2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 #include "errorpage.h"
12 #include "ssl/ErrorDetail.h"
17 struct SslErrorEntry
{
18 Ssl::ssl_error_t value
;
22 static const char *SslErrorDetailDefaultStr
= "SSL handshake error (%err_name)";
23 //Use std::map to optimize search
24 typedef std::map
<Ssl::ssl_error_t
, const SslErrorEntry
*> SslErrors
;
25 SslErrors TheSslErrors
;
27 static SslErrorEntry TheSslErrorArray
[] = {
28 { SQUID_X509_V_ERR_INFINITE_VALIDATION
,
29 "SQUID_X509_V_ERR_INFINITE_VALIDATION"
31 { SQUID_X509_V_ERR_CERT_CHANGE
,
32 "SQUID_X509_V_ERR_CERT_CHANGE"
34 { SQUID_ERR_SSL_HANDSHAKE
,
35 "SQUID_ERR_SSL_HANDSHAKE"
37 { SQUID_X509_V_ERR_DOMAIN_MISMATCH
,
38 "SQUID_X509_V_ERR_DOMAIN_MISMATCH"
40 { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
,
41 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"
43 { X509_V_ERR_UNABLE_TO_GET_CRL
,
44 "X509_V_ERR_UNABLE_TO_GET_CRL"
46 { X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE
,
47 "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE"
49 { X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE
,
50 "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE"
52 { X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
,
53 "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY"
55 { X509_V_ERR_CERT_SIGNATURE_FAILURE
,
56 "X509_V_ERR_CERT_SIGNATURE_FAILURE"
58 { X509_V_ERR_CRL_SIGNATURE_FAILURE
,
59 "X509_V_ERR_CRL_SIGNATURE_FAILURE"
61 { X509_V_ERR_CERT_NOT_YET_VALID
,
62 "X509_V_ERR_CERT_NOT_YET_VALID"
64 { X509_V_ERR_CERT_HAS_EXPIRED
,
65 "X509_V_ERR_CERT_HAS_EXPIRED"
67 { X509_V_ERR_CRL_NOT_YET_VALID
,
68 "X509_V_ERR_CRL_NOT_YET_VALID"
70 { X509_V_ERR_CRL_HAS_EXPIRED
,
71 "X509_V_ERR_CRL_HAS_EXPIRED"
73 { X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
,
74 "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"
76 { X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
,
77 "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"
79 { X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD
,
80 "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD"
82 { X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD
,
83 "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD"
85 { X509_V_ERR_OUT_OF_MEM
,
86 "X509_V_ERR_OUT_OF_MEM"
88 { X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
,
89 "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT"
91 { X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
,
92 "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN"
94 { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
,
95 "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
97 { X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
,
98 "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE"
100 { X509_V_ERR_CERT_CHAIN_TOO_LONG
,
101 "X509_V_ERR_CERT_CHAIN_TOO_LONG"
103 { X509_V_ERR_CERT_REVOKED
,
104 "X509_V_ERR_CERT_REVOKED"
106 { X509_V_ERR_INVALID_CA
,
107 "X509_V_ERR_INVALID_CA"
109 { X509_V_ERR_PATH_LENGTH_EXCEEDED
,
110 "X509_V_ERR_PATH_LENGTH_EXCEEDED"
112 { X509_V_ERR_INVALID_PURPOSE
,
113 "X509_V_ERR_INVALID_PURPOSE"
115 { X509_V_ERR_CERT_UNTRUSTED
,
116 "X509_V_ERR_CERT_UNTRUSTED"
118 { X509_V_ERR_CERT_REJECTED
,
119 "X509_V_ERR_CERT_REJECTED"
121 { X509_V_ERR_SUBJECT_ISSUER_MISMATCH
,
122 "X509_V_ERR_SUBJECT_ISSUER_MISMATCH"
124 { X509_V_ERR_AKID_SKID_MISMATCH
,
125 "X509_V_ERR_AKID_SKID_MISMATCH"
127 { X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH
,
128 "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH"
130 { X509_V_ERR_KEYUSAGE_NO_CERTSIGN
,
131 "X509_V_ERR_KEYUSAGE_NO_CERTSIGN"
133 #if defined(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER)
135 X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
, //33
136 "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER"
139 #if defined(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
141 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
, //34
142 "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION"
145 #if defined(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN)
147 X509_V_ERR_KEYUSAGE_NO_CRL_SIGN
, //35
148 "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN"
151 #if defined(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION)
153 X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION
, //36
154 "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION"
157 #if defined(X509_V_ERR_INVALID_NON_CA)
159 X509_V_ERR_INVALID_NON_CA
, //37
160 "X509_V_ERR_INVALID_NON_CA"
163 #if defined(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED)
165 X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED
, //38
166 "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED"
169 #if defined(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE)
171 X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE
, //39
172 "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE"
175 #if defined(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED)
177 X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED
, //40
178 "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED"
181 #if defined(X509_V_ERR_INVALID_EXTENSION)
183 X509_V_ERR_INVALID_EXTENSION
, //41
184 "X509_V_ERR_INVALID_EXTENSION"
187 #if defined(X509_V_ERR_INVALID_POLICY_EXTENSION)
189 X509_V_ERR_INVALID_POLICY_EXTENSION
, //42
190 "X509_V_ERR_INVALID_POLICY_EXTENSION"
193 #if defined(X509_V_ERR_NO_EXPLICIT_POLICY)
195 X509_V_ERR_NO_EXPLICIT_POLICY
, //43
196 "X509_V_ERR_NO_EXPLICIT_POLICY"
199 #if defined(X509_V_ERR_DIFFERENT_CRL_SCOPE)
201 X509_V_ERR_DIFFERENT_CRL_SCOPE
, //44
202 "X509_V_ERR_DIFFERENT_CRL_SCOPE"
205 #if defined(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE)
207 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE
, //45
208 "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE"
211 #if defined(X509_V_ERR_UNNESTED_RESOURCE)
213 X509_V_ERR_UNNESTED_RESOURCE
, //46
214 "X509_V_ERR_UNNESTED_RESOURCE"
217 #if defined(X509_V_ERR_PERMITTED_VIOLATION)
219 X509_V_ERR_PERMITTED_VIOLATION
, //47
220 "X509_V_ERR_PERMITTED_VIOLATION"
223 #if defined(X509_V_ERR_EXCLUDED_VIOLATION)
225 X509_V_ERR_EXCLUDED_VIOLATION
, //48
226 "X509_V_ERR_EXCLUDED_VIOLATION"
229 #if defined(X509_V_ERR_SUBTREE_MINMAX)
231 X509_V_ERR_SUBTREE_MINMAX
, //49
232 "X509_V_ERR_SUBTREE_MINMAX"
235 #if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE)
237 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE
, //51
238 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE"
241 #if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX)
243 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX
, //52
244 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX"
247 #if defined(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX)
249 X509_V_ERR_UNSUPPORTED_NAME_SYNTAX
, //53
250 "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX"
253 #if defined(X509_V_ERR_CRL_PATH_VALIDATION_ERROR)
255 X509_V_ERR_CRL_PATH_VALIDATION_ERROR
, //54
256 "X509_V_ERR_CRL_PATH_VALIDATION_ERROR"
259 { X509_V_ERR_APPLICATION_VERIFICATION
,
260 "X509_V_ERR_APPLICATION_VERIFICATION"
262 { SSL_ERROR_NONE
, "SSL_ERROR_NONE"},
263 {SSL_ERROR_NONE
, NULL
}
266 static const char *OptionalSslErrors
[] = {
267 "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER",
268 "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION",
269 "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN",
270 "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION",
271 "X509_V_ERR_INVALID_NON_CA",
272 "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED",
273 "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE",
274 "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED",
275 "X509_V_ERR_INVALID_EXTENSION",
276 "X509_V_ERR_INVALID_POLICY_EXTENSION",
277 "X509_V_ERR_NO_EXPLICIT_POLICY",
278 "X509_V_ERR_DIFFERENT_CRL_SCOPE",
279 "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE",
280 "X509_V_ERR_UNNESTED_RESOURCE",
281 "X509_V_ERR_PERMITTED_VIOLATION",
282 "X509_V_ERR_EXCLUDED_VIOLATION",
283 "X509_V_ERR_SUBTREE_MINMAX",
284 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE",
285 "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX",
286 "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX",
287 "X509_V_ERR_CRL_PATH_VALIDATION_ERROR",
291 struct SslErrorAlias
{
293 const Ssl::ssl_error_t
*errors
;
296 static const Ssl::ssl_error_t hasExpired
[] = {X509_V_ERR_CERT_HAS_EXPIRED
, SSL_ERROR_NONE
};
297 static const Ssl::ssl_error_t notYetValid
[] = {X509_V_ERR_CERT_NOT_YET_VALID
, SSL_ERROR_NONE
};
298 static const Ssl::ssl_error_t domainMismatch
[] = {SQUID_X509_V_ERR_DOMAIN_MISMATCH
, SSL_ERROR_NONE
};
299 static const Ssl::ssl_error_t certUntrusted
[] = {X509_V_ERR_INVALID_CA
,
300 X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
,
301 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
,
302 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
,
303 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
,
304 X509_V_ERR_CERT_UNTRUSTED
, SSL_ERROR_NONE
306 static const Ssl::ssl_error_t certSelfSigned
[] = {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
, SSL_ERROR_NONE
};
308 // The list of error name shortcuts for use with ssl_error acls.
309 // The keys without the "ssl::" scope prefix allow shorter error
310 // names within the SSL options scope. This is easier than
311 // carefully stripping the scope prefix in Ssl::ParseErrorString().
312 static SslErrorAlias TheSslErrorShortcutsArray
[] = {
313 {"ssl::certHasExpired", hasExpired
},
314 {"certHasExpired", hasExpired
},
315 {"ssl::certNotYetValid", notYetValid
},
316 {"certNotYetValid", notYetValid
},
317 {"ssl::certDomainMismatch", domainMismatch
},
318 {"certDomainMismatch", domainMismatch
},
319 {"ssl::certUntrusted", certUntrusted
},
320 {"certUntrusted", certUntrusted
},
321 {"ssl::certSelfSigned", certSelfSigned
},
322 {"certSelfSigned", certSelfSigned
},
326 // Use std::map to optimize search.
327 typedef std::map
<std::string
, const Ssl::ssl_error_t
*> SslErrorShortcuts
;
328 SslErrorShortcuts TheSslErrorShortcuts
;
330 static void loadSslErrorMap()
332 assert(TheSslErrors
.empty());
333 for (int i
= 0; TheSslErrorArray
[i
].name
; ++i
) {
334 TheSslErrors
[TheSslErrorArray
[i
].value
] = &TheSslErrorArray
[i
];
338 static void loadSslErrorShortcutsMap()
340 assert(TheSslErrorShortcuts
.empty());
341 for (int i
= 0; TheSslErrorShortcutsArray
[i
].name
; ++i
)
342 TheSslErrorShortcuts
[TheSslErrorShortcutsArray
[i
].name
] = TheSslErrorShortcutsArray
[i
].errors
;
345 Ssl::ssl_error_t
Ssl::GetErrorCode(const char *name
)
347 //TODO: use a std::map?
348 for (int i
= 0; TheSslErrorArray
[i
].name
!= NULL
; ++i
) {
349 if (strcmp(name
, TheSslErrorArray
[i
].name
) == 0)
350 return TheSslErrorArray
[i
].value
;
352 return SSL_ERROR_NONE
;
356 Ssl::ParseErrorString(const char *name
)
360 const Ssl::ssl_error_t ssl_error
= GetErrorCode(name
);
361 if (ssl_error
!= SSL_ERROR_NONE
)
362 return new Ssl::Errors(ssl_error
);
364 if (xisdigit(*name
)) {
365 const long int value
= strtol(name
, NULL
, 0);
366 if (SQUID_SSL_ERROR_MIN
<= value
&& value
<= SQUID_SSL_ERROR_MAX
)
367 return new Ssl::Errors(value
);
368 fatalf("Too small or too bug SSL error code '%s'", name
);
371 if (TheSslErrorShortcuts
.empty())
372 loadSslErrorShortcutsMap();
374 const SslErrorShortcuts::const_iterator it
= TheSslErrorShortcuts
.find(name
);
375 if (it
!= TheSslErrorShortcuts
.end()) {
376 // Should not be empty...
377 assert(it
->second
[0] != SSL_ERROR_NONE
);
378 Ssl::Errors
*errors
= new Ssl::Errors(it
->second
[0]);
379 for (int i
=1; it
->second
[i
] != SSL_ERROR_NONE
; ++i
) {
380 errors
->push_back_unique(it
->second
[i
]);
385 fatalf("Unknown SSL error name '%s'", name
);
386 return NULL
; // not reached
389 const char *Ssl::GetErrorName(Ssl::ssl_error_t value
)
391 if (TheSslErrors
.empty())
394 const SslErrors::const_iterator it
= TheSslErrors
.find(value
);
395 if (it
!= TheSslErrors
.end())
396 return it
->second
->name
;
402 Ssl::ErrorIsOptional(const char *name
)
404 for (int i
= 0; OptionalSslErrors
[i
] != NULL
; ++i
) {
405 if (strcmp(name
, OptionalSslErrors
[i
]) == 0)
412 Ssl::GetErrorDescr(Ssl::ssl_error_t value
)
414 return ErrorDetailsManager::GetInstance().getDefaultErrorDescr(value
);
417 Ssl::ErrorDetail::err_frm_code
Ssl::ErrorDetail::ErrorFormatingCodes
[] = {
418 {"ssl_subject", &Ssl::ErrorDetail::subject
},
419 {"ssl_ca_name", &Ssl::ErrorDetail::ca_name
},
420 {"ssl_cn", &Ssl::ErrorDetail::cn
},
421 {"ssl_notbefore", &Ssl::ErrorDetail::notbefore
},
422 {"ssl_notafter", &Ssl::ErrorDetail::notafter
},
423 {"err_name", &Ssl::ErrorDetail::err_code
},
424 {"ssl_error_descr", &Ssl::ErrorDetail::err_descr
},
425 {"ssl_lib_error", &Ssl::ErrorDetail::err_lib_error
},
430 * The subject of the current certification in text form
432 const char *Ssl::ErrorDetail::subject() const
434 if (broken_cert
.get()) {
435 static char tmpBuffer
[256]; // A temporary buffer
436 if (X509_NAME_oneline(X509_get_subject_name(broken_cert
.get()), tmpBuffer
, sizeof(tmpBuffer
)))
439 return "[Not available]";
442 // helper function to be used with Ssl::matchX509CommonNames
443 static int copy_cn(void *check_data
, ASN1_STRING
*cn_data
)
445 String
*str
= (String
*)check_data
;
446 if (!str
) // no data? abort
448 if (cn_data
&& cn_data
->length
) {
451 str
->append((const char *)cn_data
->data
, cn_data
->length
);
457 * The list with certificates cn and alternate names
459 const char *Ssl::ErrorDetail::cn() const
461 if (broken_cert
.get()) {
462 static String tmpStr
; ///< A temporary string buffer
464 Ssl::matchX509CommonNames(broken_cert
.get(), &tmpStr
, copy_cn
);
466 return tmpStr
.termedBuf();
468 return "[Not available]";
474 const char *Ssl::ErrorDetail::ca_name() const
476 if (broken_cert
.get()) {
477 static char tmpBuffer
[256]; // A temporary buffer
478 if (X509_NAME_oneline(X509_get_issuer_name(broken_cert
.get()), tmpBuffer
, sizeof(tmpBuffer
)))
481 return "[Not available]";
485 * The certificate "not before" field
487 const char *Ssl::ErrorDetail::notbefore() const
489 if (broken_cert
.get()) {
490 if (ASN1_UTCTIME
* tm
= X509_get_notBefore(broken_cert
.get())) {
491 static char tmpBuffer
[256]; // A temporary buffer
492 Ssl::asn1timeToString(tm
, tmpBuffer
, sizeof(tmpBuffer
));
496 return "[Not available]";
500 * The certificate "not after" field
502 const char *Ssl::ErrorDetail::notafter() const
504 if (broken_cert
.get()) {
505 if (ASN1_UTCTIME
* tm
= X509_get_notAfter(broken_cert
.get())) {
506 static char tmpBuffer
[256]; // A temporary buffer
507 Ssl::asn1timeToString(tm
, tmpBuffer
, sizeof(tmpBuffer
));
511 return "[Not available]";
515 * The string representation of the error_no
517 const char *Ssl::ErrorDetail::err_code() const
519 static char tmpBuffer
[64];
520 // We can use the GetErrorName but using the detailEntry is faster,
522 const char *err
= detailEntry
.name
.termedBuf();
524 // error details not loaded yet or not defined in error_details.txt,
525 // try the GetErrorName...
527 err
= GetErrorName(error_no
);
530 snprintf(tmpBuffer
, 64, "%d", (int)error_no
);
537 * A short description of the error_no
539 const char *Ssl::ErrorDetail::err_descr() const
541 if (error_no
== SSL_ERROR_NONE
)
543 if (const char *err
= detailEntry
.descr
.termedBuf())
545 return "[Not available]";
548 const char *Ssl::ErrorDetail::err_lib_error() const
550 if (errReason
.size() > 0)
551 return errReason
.termedBuf();
552 else if (lib_error_no
!= SSL_ERROR_NONE
)
553 return ERR_error_string(lib_error_no
, NULL
);
559 * Converts the code to a string value. Supported formating codes are:
561 * Error meta information:
562 * %err_name: The name of a high-level SSL error (e.g., X509_V_ERR_*)
563 * %ssl_error_descr: A short description of the SSL error
564 * %ssl_lib_error: human-readable low-level error string by ERR_error_string(3SSL)
566 * Certificate information extracted from broken (not necessarily peer!) cert
567 * %ssl_cn: The comma-separated list of common and alternate names
568 * %ssl_subject: The certificate subject
569 * %ssl_ca_name: The certificate issuer name
570 * %ssl_notbefore: The certificate "not before" field
571 * %ssl_notafter: The certificate "not after" field
573 \retval the length of the code (the number of characters will be replaced by value)
575 int Ssl::ErrorDetail::convert(const char *code
, const char **value
) const
578 for (int i
=0; ErrorFormatingCodes
[i
].code
!=NULL
; ++i
) {
579 const int len
= strlen(ErrorFormatingCodes
[i
].code
);
580 if (strncmp(code
,ErrorFormatingCodes
[i
].code
, len
)==0) {
581 ErrorDetail::fmt_action_t action
= ErrorFormatingCodes
[i
].fmt_action
;
582 *value
= (this->*action
)();
590 * It uses the convert method to build the string errDetailStr using
591 * a template message for the current SSL error. The template messages
592 * can also contain normal error pages formating codes.
593 * Currently the error template messages are hard-coded
595 void Ssl::ErrorDetail::buildDetail() const
597 char const *s
= NULL
;
602 if (ErrorDetailsManager::GetInstance().getErrorDetail(error_no
, request
, detailEntry
))
603 s
= detailEntry
.detail
.termedBuf();
606 s
= SslErrorDetailDefaultStr
;
609 while ((p
= strchr(s
, '%'))) {
610 errDetailStr
.append(s
, p
- s
);
611 code_len
= convert(++p
, &t
);
613 errDetailStr
.append(t
);
615 errDetailStr
.append("%");
618 errDetailStr
.append(s
, strlen(s
));
621 const String
&Ssl::ErrorDetail::toString() const
623 if (errDetailStr
.size() == 0)
628 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
)
631 peer_cert
.reset(cert
);
634 broken_cert
.reset(broken
);
636 broken_cert
.reset(cert
);
638 detailEntry
.error_no
= SSL_ERROR_NONE
;
641 Ssl::ErrorDetail::ErrorDetail(Ssl::ErrorDetail
const &anErrDetail
)
643 error_no
= anErrDetail
.error_no
;
644 request
= anErrDetail
.request
;
646 if (anErrDetail
.peer_cert
.get()) {
647 peer_cert
.reset(anErrDetail
.peer_cert
.get());
650 if (anErrDetail
.broken_cert
.get()) {
651 broken_cert
.reset(anErrDetail
.broken_cert
.get());
654 detailEntry
= anErrDetail
.detailEntry
;
656 lib_error_no
= anErrDetail
.lib_error_no
;