1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "secerr.h"
25 #include "sslerr.h"
26 #include "nspr.h"
27 #include "certt.h"
28 
29 #include "../diagnose.hxx"
30 
31 using namespace xmlsecurity;
32 
33 struct ErrDesc {
34     PRErrorCode	 errNum;
35     const char * errString;
36 };
37 
38 
39 
40 const ErrDesc allDesc[] = {
41 
42 #include "certerrors.h"
43 
44 };
45 
46 
47 
48 /* Returns a UTF-8 encoded constant error string for "errNum".
49  * Returns NULL of errNum is unknown.
50  */
51 const char *
getCertError(PRErrorCode errNum)52 getCertError(PRErrorCode errNum)
53 {
54     static char sEmpty[] = "";
55     const int numDesc = sizeof(allDesc) / sizeof(ErrDesc);
56     for (int i = 0; i < numDesc; i++)
57     {
58         if (allDesc[i].errNum == errNum)
59             return  allDesc[i].errString;
60     }
61 
62     return sEmpty;
63 }
64 
65 void
printChainFailure(CERTVerifyLog * log)66 printChainFailure(CERTVerifyLog *log)
67 {
68     unsigned long errorFlags  = 0;
69     unsigned int       depth  = (unsigned int)-1;
70     const char * specificError = NULL;
71     const char * issuer = NULL;
72     CERTVerifyLogNode *node   = NULL;
73 
74     if (log->count > 0)
75     {
76         xmlsec_trace("Bad certification path:");
77         for (node = log->head; node; node = node->next)
78         {
79             if (depth != node->depth)
80             {
81                 depth = node->depth;
82                 xmlsec_trace("Certificate:  %d. %s %s:", depth,
83                         node->cert->subjectName,
84                         depth ? "[Certificate Authority]": "");
85             }
86             xmlsec_trace("  ERROR %ld: %s", node->error,
87                     getCertError(node->error));
88             specificError = NULL;
89             issuer = NULL;
90             switch (node->error)
91             {
92             case SEC_ERROR_INADEQUATE_KEY_USAGE:
93                 errorFlags = (unsigned long)node->arg;
94                 switch (errorFlags)
95                 {
96                 case KU_DIGITAL_SIGNATURE:
97                     specificError = "Certificate cannot sign.";
98                     break;
99                 case KU_KEY_ENCIPHERMENT:
100                     specificError = "Certificate cannot encrypt.";
101                     break;
102                 case KU_KEY_CERT_SIGN:
103                     specificError = "Certificate cannot sign other certs.";
104                     break;
105                 default:
106                     specificError = "[unknown usage].";
107                     break;
108                 }
109             case SEC_ERROR_INADEQUATE_CERT_TYPE:
110                 errorFlags = (unsigned long)node->arg;
111                 switch (errorFlags)
112                 {
113                 case NS_CERT_TYPE_SSL_CLIENT:
114                 case NS_CERT_TYPE_SSL_SERVER:
115                     specificError = "Certificate cannot be used for SSL.";
116                     break;
117                 case NS_CERT_TYPE_SSL_CA:
118                     specificError = "Certificate cannot be used as an SSL CA.";
119                     break;
120                 case NS_CERT_TYPE_EMAIL:
121                     specificError = "Certificate cannot be used for SMIME.";
122                     break;
123                 case NS_CERT_TYPE_EMAIL_CA:
124                     specificError = "Certificate cannot be used as an SMIME CA.";
125                     break;
126                 case NS_CERT_TYPE_OBJECT_SIGNING:
127                     specificError = "Certificate cannot be used for object signing.";
128                     break;
129                 case NS_CERT_TYPE_OBJECT_SIGNING_CA:
130                     specificError = "Certificate cannot be used as an object signing CA.";
131                     break;
132                 default:
133                     specificError = "[unknown usage].";
134                     break;
135                 }
136             case SEC_ERROR_UNKNOWN_ISSUER:
137                 specificError = "Unknown issuer:";
138                 issuer = node->cert->issuerName;
139                 break;
140             case SEC_ERROR_UNTRUSTED_ISSUER:
141                 specificError = "Untrusted issuer:";
142                 issuer = node->cert->issuerName;
143                 break;
144             case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
145                 specificError = "Expired issuer certificate:";
146                 issuer = node->cert->issuerName;
147                 break;
148             default:
149                 break;
150             }
151             if (specificError)
152                 xmlsec_trace("%s", specificError);
153             if (issuer)
154                 xmlsec_trace("%s", issuer);
155         }
156     }
157 }
158