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 
25 #include "secerr.h"
26 #include "sslerr.h"
27 #include "nspr.h"
28 #include "certt.h"
29 
30 #include "../diagnose.hxx"
31 
32 using namespace xmlsecurity;
33 
34 struct ErrDesc {
35     PRErrorCode	 errNum;
36     const char * errString;
37 };
38 
39 
40 
41 const ErrDesc allDesc[] = {
42 
43 #include "certerrors.h"
44 
45 };
46 
47 
48 
49 /* Returns a UTF-8 encoded constant error string for "errNum".
50  * Returns NULL of errNum is unknown.
51  */
52 const char *
53 getCertError(PRErrorCode errNum)
54 {
55     static char sEmpty[] = "";
56     const int numDesc = sizeof(allDesc) / sizeof(ErrDesc);
57     for (int i = 0; i < numDesc; i++)
58     {
59         if (allDesc[i].errNum == errNum)
60             return  allDesc[i].errString;
61     }
62 
63     return sEmpty;
64 }
65 
66 void
67 printChainFailure(CERTVerifyLog *log)
68 {
69     unsigned long errorFlags  = 0;
70     unsigned int       depth  = (unsigned int)-1;
71     const char * specificError = NULL;
72     const char * issuer = NULL;
73     CERTVerifyLogNode *node   = NULL;
74 
75     if (log->count > 0)
76     {
77         xmlsec_trace("Bad certifcation path:");
78         for (node = log->head; node; node = node->next)
79         {
80             if (depth != node->depth)
81             {
82                 depth = node->depth;
83                 xmlsec_trace("Certificate:  %d. %s %s:", depth,
84                         node->cert->subjectName,
85                         depth ? "[Certificate Authority]": "");
86             }
87             xmlsec_trace("  ERROR %ld: %s", node->error,
88                     getCertError(node->error));
89             specificError = NULL;
90             issuer = NULL;
91             switch (node->error)
92             {
93             case SEC_ERROR_INADEQUATE_KEY_USAGE:
94                 errorFlags = (unsigned long)node->arg;
95                 switch (errorFlags)
96                 {
97                 case KU_DIGITAL_SIGNATURE:
98                     specificError = "Certificate cannot sign.";
99                     break;
100                 case KU_KEY_ENCIPHERMENT:
101                     specificError = "Certificate cannot encrypt.";
102                     break;
103                 case KU_KEY_CERT_SIGN:
104                     specificError = "Certificate cannot sign other certs.";
105                     break;
106                 default:
107                     specificError = "[unknown usage].";
108                     break;
109                 }
110             case SEC_ERROR_INADEQUATE_CERT_TYPE:
111                 errorFlags = (unsigned long)node->arg;
112                 switch (errorFlags)
113                 {
114                 case NS_CERT_TYPE_SSL_CLIENT:
115                 case NS_CERT_TYPE_SSL_SERVER:
116                     specificError = "Certificate cannot be used for SSL.";
117                     break;
118                 case NS_CERT_TYPE_SSL_CA:
119                     specificError = "Certificate cannot be used as an SSL CA.";
120                     break;
121                 case NS_CERT_TYPE_EMAIL:
122                     specificError = "Certificate cannot be used for SMIME.";
123                     break;
124                 case NS_CERT_TYPE_EMAIL_CA:
125                     specificError = "Certificate cannot be used as an SMIME CA.";
126                     break;
127                 case NS_CERT_TYPE_OBJECT_SIGNING:
128                     specificError = "Certificate cannot be used for object signing.";
129                     break;
130                 case NS_CERT_TYPE_OBJECT_SIGNING_CA:
131                     specificError = "Certificate cannot be used as an object signing CA.";
132                     break;
133                 default:
134                     specificError = "[unknown usage].";
135                     break;
136                 }
137             case SEC_ERROR_UNKNOWN_ISSUER:
138                 specificError = "Unknown issuer:";
139                 issuer = node->cert->issuerName;
140                 break;
141             case SEC_ERROR_UNTRUSTED_ISSUER:
142                 specificError = "Untrusted issuer:";
143                 issuer = node->cert->issuerName;
144                 break;
145             case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
146                 specificError = "Expired issuer certificate:";
147                 issuer = node->cert->issuerName;
148                 break;
149             default:
150                 break;
151             }
152             if (specificError)
153                 xmlsec_trace("%s", specificError);
154             if (issuer)
155                 xmlsec_trace("%s", issuer);
156         }
157     }
158 }
159