3 #include "ssl/ErrorDetail.h"
11 struct SslErrorEntry
{
12 Ssl::ssl_error_t value
;
16 static const char *SslErrorDetailDefaultStr
= "SSL handshake error (%err_name)";
17 //Use std::map to optimize search
18 typedef std::map
<Ssl::ssl_error_t
, const SslErrorEntry
*> SslErrors
;
19 SslErrors TheSslErrors
;
21 static SslErrorEntry TheSslErrorArray
[] = {
22 {SQUID_X509_V_ERR_INFINITE_VALIDATION
,
23 "SQUID_X509_V_ERR_INFINITE_VALIDATION"},
24 {SQUID_X509_V_ERR_CERT_CHANGE
,
25 "SQUID_X509_V_ERR_CERT_CHANGE"},
26 {SQUID_ERR_SSL_HANDSHAKE
,
27 "SQUID_ERR_SSL_HANDSHAKE"},
28 {SQUID_X509_V_ERR_DOMAIN_MISMATCH
,
29 "SQUID_X509_V_ERR_DOMAIN_MISMATCH"},
30 {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
,
31 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"},
32 {X509_V_ERR_UNABLE_TO_GET_CRL
,
33 "X509_V_ERR_UNABLE_TO_GET_CRL"},
34 {X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE
,
35 "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE"},
36 {X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE
,
37 "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE"},
38 {X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
,
39 "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY"},
40 {X509_V_ERR_CERT_SIGNATURE_FAILURE
,
41 "X509_V_ERR_CERT_SIGNATURE_FAILURE"},
42 {X509_V_ERR_CRL_SIGNATURE_FAILURE
,
43 "X509_V_ERR_CRL_SIGNATURE_FAILURE"},
44 {X509_V_ERR_CERT_NOT_YET_VALID
,
45 "X509_V_ERR_CERT_NOT_YET_VALID"},
46 {X509_V_ERR_CERT_HAS_EXPIRED
,
47 "X509_V_ERR_CERT_HAS_EXPIRED"},
48 {X509_V_ERR_CRL_NOT_YET_VALID
,
49 "X509_V_ERR_CRL_NOT_YET_VALID"},
50 {X509_V_ERR_CRL_HAS_EXPIRED
,
51 "X509_V_ERR_CRL_HAS_EXPIRED"},
52 {X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
,
53 "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"},
54 {X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
,
55 "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"},
56 {X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD
,
57 "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD"},
58 {X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD
,
59 "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD"},
60 {X509_V_ERR_OUT_OF_MEM
,
61 "X509_V_ERR_OUT_OF_MEM"},
62 {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
,
63 "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT"},
64 {X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
,
65 "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN"},
66 {X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
,
67 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY"},
68 {X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
,
69 "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE"},
70 {X509_V_ERR_CERT_CHAIN_TOO_LONG
,
71 "X509_V_ERR_CERT_CHAIN_TOO_LONG"},
72 {X509_V_ERR_CERT_REVOKED
,
73 "X509_V_ERR_CERT_REVOKED"},
74 {X509_V_ERR_INVALID_CA
,
75 "X509_V_ERR_INVALID_CA"},
76 {X509_V_ERR_PATH_LENGTH_EXCEEDED
,
77 "X509_V_ERR_PATH_LENGTH_EXCEEDED"},
78 {X509_V_ERR_INVALID_PURPOSE
,
79 "X509_V_ERR_INVALID_PURPOSE"},
80 {X509_V_ERR_CERT_UNTRUSTED
,
81 "X509_V_ERR_CERT_UNTRUSTED"},
82 {X509_V_ERR_CERT_REJECTED
,
83 "X509_V_ERR_CERT_REJECTED"},
84 {X509_V_ERR_SUBJECT_ISSUER_MISMATCH
,
85 "X509_V_ERR_SUBJECT_ISSUER_MISMATCH"},
86 {X509_V_ERR_AKID_SKID_MISMATCH
,
87 "X509_V_ERR_AKID_SKID_MISMATCH"},
88 {X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH
,
89 "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH"},
90 {X509_V_ERR_KEYUSAGE_NO_CERTSIGN
,
91 "X509_V_ERR_KEYUSAGE_NO_CERTSIGN"},
92 #if defined(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER)
94 X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
, //33
95 "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER"
98 #if defined(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
100 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
, //34
101 "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION"
104 #if defined(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN)
106 X509_V_ERR_KEYUSAGE_NO_CRL_SIGN
, //35
107 "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN"
110 #if defined(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION)
112 X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION
, //36
113 "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION"
116 #if defined(X509_V_ERR_INVALID_NON_CA)
118 X509_V_ERR_INVALID_NON_CA
, //37
119 "X509_V_ERR_INVALID_NON_CA"
122 #if defined(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED)
124 X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED
, //38
125 "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED"
128 #if defined(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE)
130 X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE
, //39
131 "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE"
134 #if defined(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED)
136 X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED
, //40
137 "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED"
140 #if defined(X509_V_ERR_INVALID_EXTENSION)
142 X509_V_ERR_INVALID_EXTENSION
, //41
143 "X509_V_ERR_INVALID_EXTENSION"
146 #if defined(X509_V_ERR_INVALID_POLICY_EXTENSION)
148 X509_V_ERR_INVALID_POLICY_EXTENSION
, //42
149 "X509_V_ERR_INVALID_POLICY_EXTENSION"
152 #if defined(X509_V_ERR_NO_EXPLICIT_POLICY)
154 X509_V_ERR_NO_EXPLICIT_POLICY
, //43
155 "X509_V_ERR_NO_EXPLICIT_POLICY"
158 #if defined(X509_V_ERR_DIFFERENT_CRL_SCOPE)
160 X509_V_ERR_DIFFERENT_CRL_SCOPE
, //44
161 "X509_V_ERR_DIFFERENT_CRL_SCOPE"
164 #if defined(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE)
166 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE
, //45
167 "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE"
170 #if defined(X509_V_ERR_UNNESTED_RESOURCE)
172 X509_V_ERR_UNNESTED_RESOURCE
, //46
173 "X509_V_ERR_UNNESTED_RESOURCE"
176 #if defined(X509_V_ERR_PERMITTED_VIOLATION)
178 X509_V_ERR_PERMITTED_VIOLATION
, //47
179 "X509_V_ERR_PERMITTED_VIOLATION"
182 #if defined(X509_V_ERR_EXCLUDED_VIOLATION)
184 X509_V_ERR_EXCLUDED_VIOLATION
, //48
185 "X509_V_ERR_EXCLUDED_VIOLATION"
188 #if defined(X509_V_ERR_SUBTREE_MINMAX)
190 X509_V_ERR_SUBTREE_MINMAX
, //49
191 "X509_V_ERR_SUBTREE_MINMAX"
194 #if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE)
196 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE
, //51
197 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE"
200 #if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX)
202 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX
, //52
203 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX"
206 #if defined(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX)
208 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX
, //53
209 "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX"
212 #if defined(X509_V_ERR_CRL_PATH_VALIDATION_ERROR)
214 X509_V_ERR_CRL_PATH_VALIDATION_ERROR
, //54
215 "X509_V_ERR_CRL_PATH_VALIDATION_ERROR"
218 {X509_V_ERR_APPLICATION_VERIFICATION
,
219 "X509_V_ERR_APPLICATION_VERIFICATION"},
220 { SSL_ERROR_NONE
, "SSL_ERROR_NONE"},
221 {SSL_ERROR_NONE
, NULL
}
224 static const char *OptionalSslErrors
[] = {
225 "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER",
226 "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION",
227 "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN",
228 "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION",
229 "X509_V_ERR_INVALID_NON_CA",
230 "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED",
231 "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE",
232 "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED",
233 "X509_V_ERR_INVALID_EXTENSION",
234 "X509_V_ERR_INVALID_POLICY_EXTENSION",
235 "X509_V_ERR_NO_EXPLICIT_POLICY",
236 "X509_V_ERR_DIFFERENT_CRL_SCOPE",
237 "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE",
238 "X509_V_ERR_UNNESTED_RESOURCE",
239 "X509_V_ERR_PERMITTED_VIOLATION",
240 "X509_V_ERR_EXCLUDED_VIOLATION",
241 "X509_V_ERR_SUBTREE_MINMAX",
242 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE",
243 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX",
244 "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX",
245 "X509_V_ERR_CRL_PATH_VALIDATION_ERROR",
249 struct SslErrorAlias
{
251 const Ssl::ssl_error_t
*errors
;
254 static const Ssl::ssl_error_t hasExpired
[] = {X509_V_ERR_CERT_HAS_EXPIRED
, SSL_ERROR_NONE
};
255 static const Ssl::ssl_error_t notYetValid
[] = {X509_V_ERR_CERT_NOT_YET_VALID
, SSL_ERROR_NONE
};
256 static const Ssl::ssl_error_t domainMismatch
[] = {SQUID_X509_V_ERR_DOMAIN_MISMATCH
, SSL_ERROR_NONE
};
257 static const Ssl::ssl_error_t certUntrusted
[] = {X509_V_ERR_INVALID_CA
,
258 X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
,
259 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
,
260 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
,
261 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
,
262 X509_V_ERR_CERT_UNTRUSTED
, SSL_ERROR_NONE
264 static const Ssl::ssl_error_t certSelfSigned
[] = {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
, SSL_ERROR_NONE
};
266 // The list of error name shortcuts for use with ssl_error acls.
267 // The keys without the "ssl::" scope prefix allow shorter error
268 // names within the SSL options scope. This is easier than
269 // carefully stripping the scope prefix in Ssl::ParseErrorString().
270 static SslErrorAlias TheSslErrorShortcutsArray
[] = {
271 {"ssl::certHasExpired", hasExpired
},
272 {"certHasExpired", hasExpired
},
273 {"ssl::certNotYetValid", notYetValid
},
274 {"certNotYetValid", notYetValid
},
275 {"ssl::certDomainMismatch", domainMismatch
},
276 {"certDomainMismatch", domainMismatch
},
277 {"ssl::certUntrusted", certUntrusted
},
278 {"certUntrusted", certUntrusted
},
279 {"ssl::certSelfSigned", certSelfSigned
},
280 {"certSelfSigned", certSelfSigned
},
284 // Use std::map to optimize search.
285 typedef std::map
<std::string
, const Ssl::ssl_error_t
*> SslErrorShortcuts
;
286 SslErrorShortcuts TheSslErrorShortcuts
;
288 static void loadSslErrorMap()
290 assert(TheSslErrors
.empty());
291 for (int i
= 0; TheSslErrorArray
[i
].name
; ++i
) {
292 TheSslErrors
[TheSslErrorArray
[i
].value
] = &TheSslErrorArray
[i
];
296 static void loadSslErrorShortcutsMap()
298 assert(TheSslErrorShortcuts
.empty());
299 for (int i
= 0; TheSslErrorShortcutsArray
[i
].name
; ++i
)
300 TheSslErrorShortcuts
[TheSslErrorShortcutsArray
[i
].name
] = TheSslErrorShortcutsArray
[i
].errors
;
303 Ssl::ssl_error_t
Ssl::GetErrorCode(const char *name
)
305 //TODO: use a std::map?
306 for (int i
= 0; TheSslErrorArray
[i
].name
!= NULL
; ++i
) {
307 if (strcmp(name
, TheSslErrorArray
[i
].name
) == 0)
308 return TheSslErrorArray
[i
].value
;
310 return SSL_ERROR_NONE
;
314 Ssl::ParseErrorString(const char *name
)
318 const Ssl::ssl_error_t ssl_error
= GetErrorCode(name
);
319 if (ssl_error
!= SSL_ERROR_NONE
)
320 return new Ssl::Errors(ssl_error
);
322 if (xisdigit(*name
)) {
323 const long int value
= strtol(name
, NULL
, 0);
324 if (SQUID_SSL_ERROR_MIN
<= value
&& value
<= SQUID_SSL_ERROR_MAX
)
325 return new Ssl::Errors(value
);
326 fatalf("Too small or too bug SSL error code '%s'", name
);
329 if (TheSslErrorShortcuts
.empty())
330 loadSslErrorShortcutsMap();
332 const SslErrorShortcuts::const_iterator it
= TheSslErrorShortcuts
.find(name
);
333 if (it
!= TheSslErrorShortcuts
.end()) {
334 // Should not be empty...
335 assert(it
->second
[0] != SSL_ERROR_NONE
);
336 Ssl::Errors
*errors
= new Ssl::Errors(it
->second
[0]);
337 for (int i
=1; it
->second
[i
] != SSL_ERROR_NONE
; ++i
) {
338 errors
->push_back_unique(it
->second
[i
]);
343 fatalf("Unknown SSL error name '%s'", name
);
344 return NULL
; // not reached
347 const char *Ssl::GetErrorName(Ssl::ssl_error_t value
)
349 if (TheSslErrors
.empty())
352 const SslErrors::const_iterator it
= TheSslErrors
.find(value
);
353 if (it
!= TheSslErrors
.end())
354 return it
->second
->name
;
360 Ssl::ErrorIsOptional(const char *name
)
362 for (int i
= 0; OptionalSslErrors
[i
] != NULL
; ++i
) {
363 if (strcmp(name
, OptionalSslErrors
[i
]) == 0)
370 Ssl::GetErrorDescr(Ssl::ssl_error_t value
)
372 return ErrorDetailsManager::GetInstance().getDefaultErrorDescr(value
);
375 Ssl::ErrorDetail::err_frm_code
Ssl::ErrorDetail::ErrorFormatingCodes
[] = {
376 {"ssl_subject", &Ssl::ErrorDetail::subject
},
377 {"ssl_ca_name", &Ssl::ErrorDetail::ca_name
},
378 {"ssl_cn", &Ssl::ErrorDetail::cn
},
379 {"ssl_notbefore", &Ssl::ErrorDetail::notbefore
},
380 {"ssl_notafter", &Ssl::ErrorDetail::notafter
},
381 {"err_name", &Ssl::ErrorDetail::err_code
},
382 {"ssl_error_descr", &Ssl::ErrorDetail::err_descr
},
383 {"ssl_lib_error", &Ssl::ErrorDetail::err_lib_error
},
388 * The subject of the current certification in text form
390 const char *Ssl::ErrorDetail::subject() const
393 return "[Not available]";
395 static char tmpBuffer
[256]; // A temporary buffer
396 X509_NAME_oneline(X509_get_subject_name(broken_cert
.get()), tmpBuffer
,
401 // helper function to be used with Ssl::matchX509CommonNames
402 static int copy_cn(void *check_data
, ASN1_STRING
*cn_data
)
404 String
*str
= (String
*)check_data
;
405 if (!str
) // no data? abort
409 str
->append((const char *)cn_data
->data
, cn_data
->length
);
414 * The list with certificates cn and alternate names
416 const char *Ssl::ErrorDetail::cn() const
419 return "[Not available]";
421 static String tmpStr
; ///< A temporary string buffer
423 Ssl::matchX509CommonNames(broken_cert
.get(), &tmpStr
, copy_cn
);
424 return tmpStr
.termedBuf();
430 const char *Ssl::ErrorDetail::ca_name() const
433 return "[Not available]";
435 static char tmpBuffer
[256]; // A temporary buffer
436 X509_NAME_oneline(X509_get_issuer_name(broken_cert
.get()), tmpBuffer
, sizeof(tmpBuffer
));
441 * The certificate "not before" field
443 const char *Ssl::ErrorDetail::notbefore() const
446 return "[Not available]";
448 static char tmpBuffer
[256]; // A temporary buffer
449 ASN1_UTCTIME
* tm
= X509_get_notBefore(broken_cert
.get());
450 Ssl::asn1timeToString(tm
, tmpBuffer
, sizeof(tmpBuffer
));
455 * The certificate "not after" field
457 const char *Ssl::ErrorDetail::notafter() const
460 return "[Not available]";
462 static char tmpBuffer
[256]; // A temporary buffer
463 ASN1_UTCTIME
* tm
= X509_get_notAfter(broken_cert
.get());
464 Ssl::asn1timeToString(tm
, tmpBuffer
, sizeof(tmpBuffer
));
469 * The string representation of the error_no
471 const char *Ssl::ErrorDetail::err_code() const
473 static char tmpBuffer
[64];
474 // We can use the GetErrorName but using the detailEntry is faster,
476 const char *err
= detailEntry
.name
.termedBuf();
478 // error details not loaded yet or not defined in error_details.txt,
479 // try the GetErrorName...
481 err
= GetErrorName(error_no
);
484 snprintf(tmpBuffer
, 64, "%d", (int)error_no
);
491 * A short description of the error_no
493 const char *Ssl::ErrorDetail::err_descr() const
495 if (error_no
== SSL_ERROR_NONE
)
497 if (const char *err
= detailEntry
.descr
.termedBuf())
499 return "[Not available]";
502 const char *Ssl::ErrorDetail::err_lib_error() const
504 if (errReason
.size() > 0)
505 return errReason
.termedBuf();
506 else if (lib_error_no
!= SSL_ERROR_NONE
)
507 return ERR_error_string(lib_error_no
, NULL
);
513 * Converts the code to a string value. Supported formating codes are:
515 * Error meta information:
516 * %err_name: The name of a high-level SSL error (e.g., X509_V_ERR_*)
517 * %ssl_error_descr: A short description of the SSL error
518 * %ssl_lib_error: human-readable low-level error string by ERR_error_string(3SSL)
520 * Certificate information extracted from broken (not necessarily peer!) cert
521 * %ssl_cn: The comma-separated list of common and alternate names
522 * %ssl_subject: The certificate subject
523 * %ssl_ca_name: The certificate issuer name
524 * %ssl_notbefore: The certificate "not before" field
525 * %ssl_notafter: The certificate "not after" field
527 \retval the length of the code (the number of characters will be replaced by value)
529 int Ssl::ErrorDetail::convert(const char *code
, const char **value
) const
532 for (int i
=0; ErrorFormatingCodes
[i
].code
!=NULL
; ++i
) {
533 const int len
= strlen(ErrorFormatingCodes
[i
].code
);
534 if (strncmp(code
,ErrorFormatingCodes
[i
].code
, len
)==0) {
535 ErrorDetail::fmt_action_t action
= ErrorFormatingCodes
[i
].fmt_action
;
536 *value
= (this->*action
)();
544 * It uses the convert method to build the string errDetailStr using
545 * a template message for the current SSL error. The template messages
546 * can also contain normal error pages formating codes.
547 * Currently the error template messages are hard-coded
549 void Ssl::ErrorDetail::buildDetail() const
551 char const *s
= NULL
;
556 if (ErrorDetailsManager::GetInstance().getErrorDetail(error_no
, request
, detailEntry
))
557 s
= detailEntry
.detail
.termedBuf();
560 s
= SslErrorDetailDefaultStr
;
563 while ((p
= strchr(s
, '%'))) {
564 errDetailStr
.append(s
, p
- s
);
565 code_len
= convert(++p
, &t
);
567 errDetailStr
.append(t
);
569 errDetailStr
.append("%");
572 errDetailStr
.append(s
, strlen(s
));
575 const String
&Ssl::ErrorDetail::toString() const
577 if (errDetailStr
.size() == 0)
582 Ssl::ErrorDetail::ErrorDetail( Ssl::ssl_error_t err_no
, X509
*cert
, X509
*broken
, const char *aReason
): error_no (err_no
), lib_error_no(SSL_ERROR_NONE
), errReason(aReason
)
585 peer_cert
.resetAndLock(cert
);
588 broken_cert
.resetAndLock(broken
);
590 broken_cert
.resetAndLock(cert
);
592 detailEntry
.error_no
= SSL_ERROR_NONE
;
595 Ssl::ErrorDetail::ErrorDetail(Ssl::ErrorDetail
const &anErrDetail
)
597 error_no
= anErrDetail
.error_no
;
598 request
= anErrDetail
.request
;
600 if (anErrDetail
.peer_cert
.get()) {
601 peer_cert
.resetAndLock(anErrDetail
.peer_cert
.get());
604 if (anErrDetail
.broken_cert
.get()) {
605 broken_cert
.resetAndLock(anErrDetail
.broken_cert
.get());
608 detailEntry
= anErrDetail
.detailEntry
;
610 lib_error_no
= anErrDetail
.lib_error_no
;