1 /*
2  * XML Security Library (http://www.aleksey.com/xmlsec).
3  *
4  *
5  * This is free software; see Copyright file in the source
6  * distribution for preciese wording.
7  *
8  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9  */
10 /**
11  * SECTION:x509vfy
12  * @Short_description: X509 certificates verification support functions for OpenSSL.
13  * @Stability: Private
14  *
15  */
16 
17 #include "globals.h"
18 
19 #ifndef XMLSEC_NO_X509
20 
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <errno.h>
26 
27 #include <libxml/tree.h>
28 
29 #include <xmlsec/xmlsec.h>
30 #include <xmlsec/xmltree.h>
31 #include <xmlsec/keys.h>
32 #include <xmlsec/keyinfo.h>
33 #include <xmlsec/keysmngr.h>
34 #include <xmlsec/base64.h>
35 #include <xmlsec/errors.h>
36 
37 #include <xmlsec/openssl/crypto.h>
38 #include <xmlsec/openssl/evp.h>
39 #include <xmlsec/openssl/x509.h>
40 #include "openssl_compat.h"
41 
42 #include <openssl/evp.h>
43 #include <openssl/x509.h>
44 #include <openssl/x509_vfy.h>
45 #include <openssl/x509v3.h>
46 
47 #ifdef OPENSSL_IS_BORINGSSL
48 typedef size_t x509_size_t;
49 #else /* OPENSSL_IS_BORINGSSL */
50 typedef int x509_size_t;
51 #endif /* OPENSSL_IS_BORINGSSL */
52 
53 /**************************************************************************
54  *
55  * Internal OpenSSL X509 store CTX
56  *
57  *************************************************************************/
58 typedef struct _xmlSecOpenSSLX509StoreCtx               xmlSecOpenSSLX509StoreCtx,
59                                                         *xmlSecOpenSSLX509StoreCtxPtr;
60 struct _xmlSecOpenSSLX509StoreCtx {
61     X509_STORE*         xst;
62     STACK_OF(X509)*     untrusted;
63     STACK_OF(X509_CRL)* crls;
64     X509_VERIFY_PARAM * vpm;
65 };
66 
67 /****************************************************************************
68  *
69  * xmlSecOpenSSLKeyDataStoreX509Id:
70  *
71  * xmlSecOpenSSLX509StoreCtx is located after xmlSecTransform
72  *
73  ***************************************************************************/
74 #define xmlSecOpenSSLX509StoreGetCtx(store) \
75     ((xmlSecOpenSSLX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
76                                     sizeof(xmlSecKeyDataStoreKlass)))
77 #define xmlSecOpenSSLX509StoreSize      \
78     (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecOpenSSLX509StoreCtx))
79 
80 static int              xmlSecOpenSSLX509StoreInitialize        (xmlSecKeyDataStorePtr store);
81 static void             xmlSecOpenSSLX509StoreFinalize          (xmlSecKeyDataStorePtr store);
82 
83 static xmlSecKeyDataStoreKlass xmlSecOpenSSLX509StoreKlass = {
84     sizeof(xmlSecKeyDataStoreKlass),
85     xmlSecOpenSSLX509StoreSize,
86 
87     /* data */
88     xmlSecNameX509Store,                        /* const xmlChar* name; */
89 
90     /* constructors/destructor */
91     xmlSecOpenSSLX509StoreInitialize,           /* xmlSecKeyDataStoreInitializeMethod initialize; */
92     xmlSecOpenSSLX509StoreFinalize,             /* xmlSecKeyDataStoreFinalizeMethod finalize; */
93 
94     /* reserved for the future */
95     NULL,                                       /* void* reserved0; */
96     NULL,                                       /* void* reserved1; */
97 };
98 
99 static int              xmlSecOpenSSLX509VerifyCRL                      (X509_STORE* xst,
100                                                                          X509_CRL *crl );
101 static X509*            xmlSecOpenSSLX509FindCert                       (STACK_OF(X509) *certs,
102                                                                          xmlChar *subjectName,
103                                                                          xmlChar *issuerName,
104                                                                          xmlChar *issuerSerial,
105                                                                          xmlChar *ski);
106 static X509*            xmlSecOpenSSLX509FindNextChainCert              (STACK_OF(X509) *chain,
107                                                                          X509 *cert);
108 static int              xmlSecOpenSSLX509VerifyCertAgainstCrls          (STACK_OF(X509_CRL) *crls,
109                                                                          X509* cert);
110 static X509_NAME*       xmlSecOpenSSLX509NameRead                       (xmlSecByte *str,
111                                                                          int len);
112 static int              xmlSecOpenSSLX509NameStringRead                 (xmlSecByte **str,
113                                                                          int *strLen,
114                                                                          xmlSecByte *res,
115                                                                          int resLen,
116                                                                          xmlSecByte delim,
117                                                                          int ingoreTrailingSpaces);
118 static int              xmlSecOpenSSLX509NamesCompare                   (X509_NAME *a,
119                                                                          X509_NAME *b);
120 static STACK_OF(X509_NAME_ENTRY)*  xmlSecOpenSSLX509_NAME_ENTRIES_copy  (X509_NAME *a);
121 static int              xmlSecOpenSSLX509_NAME_ENTRIES_cmp              (STACK_OF(X509_NAME_ENTRY) * a,
122                                                                          STACK_OF(X509_NAME_ENTRY) * b);
123 static int              xmlSecOpenSSLX509_NAME_ENTRY_cmp                (const X509_NAME_ENTRY * const *a,
124                                                                          const X509_NAME_ENTRY * const *b);
125 
126 
127 /**
128  * xmlSecOpenSSLX509StoreGetKlass:
129  *
130  * The OpenSSL X509 certificates key data store klass.
131  *
132  * Returns: pointer to OpenSSL X509 certificates key data store klass.
133  */
134 xmlSecKeyDataStoreId
xmlSecOpenSSLX509StoreGetKlass(void)135 xmlSecOpenSSLX509StoreGetKlass(void) {
136     return(&xmlSecOpenSSLX509StoreKlass);
137 }
138 
139 /**
140  * xmlSecOpenSSLX509StoreFindCert:
141  * @store:              the pointer to X509 key data store klass.
142  * @subjectName:        the desired certificate name.
143  * @issuerName:         the desired certificate issuer name.
144  * @issuerSerial:       the desired certificate issuer serial number.
145  * @ski:                the desired certificate SKI.
146  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
147  *
148  * Searches @store for a certificate that matches given criteria.
149  *
150  * Returns: pointer to found certificate or NULL if certificate is not found
151  * or an error occurs.
152  */
153 X509*
xmlSecOpenSSLX509StoreFindCert(xmlSecKeyDataStorePtr store,xmlChar * subjectName,xmlChar * issuerName,xmlChar * issuerSerial,xmlChar * ski,xmlSecKeyInfoCtx * keyInfoCtx)154 xmlSecOpenSSLX509StoreFindCert(xmlSecKeyDataStorePtr store, xmlChar *subjectName,
155                                 xmlChar *issuerName, xmlChar *issuerSerial,
156                                 xmlChar *ski, xmlSecKeyInfoCtx* keyInfoCtx) {
157     xmlSecOpenSSLX509StoreCtxPtr ctx;
158     X509* res = NULL;
159 
160     xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
161     xmlSecAssert2(keyInfoCtx != NULL, NULL);
162 
163     ctx = xmlSecOpenSSLX509StoreGetCtx(store);
164     xmlSecAssert2(ctx != NULL, NULL);
165 
166     if((res == NULL) && (ctx->untrusted != NULL)) {
167         res = xmlSecOpenSSLX509FindCert(ctx->untrusted, subjectName, issuerName, issuerSerial, ski);
168     }
169     return(res);
170 }
171 
172 /**
173  * xmlSecOpenSSLX509StoreVerify:
174  * @store:              the pointer to X509 key data store klass.
175  * @certs:              the untrusted certificates stack.
176  * @crls:               the crls stack.
177  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
178  *
179  * Verifies @certs list.
180  *
181  * Returns: pointer to the first verified certificate from @certs.
182  */
183 X509*
xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store,XMLSEC_STACK_OF_X509 * certs,XMLSEC_STACK_OF_X509_CRL * crls,xmlSecKeyInfoCtx * keyInfoCtx)184 xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs,
185                              XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) {
186     xmlSecOpenSSLX509StoreCtxPtr ctx;
187     STACK_OF(X509)* certs2 = NULL;
188     STACK_OF(X509_CRL)* crls2 = NULL;
189     X509 * res = NULL;
190     X509 * cert;
191     X509 * err_cert = NULL;
192     X509_STORE_CTX *xsc;
193     int err = 0;
194     x509_size_t i;
195     int ret;
196 
197     xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
198     xmlSecAssert2(certs != NULL, NULL);
199     xmlSecAssert2(keyInfoCtx != NULL, NULL);
200 
201     xsc = X509_STORE_CTX_new();
202     if(xsc == NULL) {
203         xmlSecOpenSSLError("X509_STORE_CTX_new",
204                            xmlSecKeyDataStoreGetName(store));
205         goto done;
206     }
207 
208     ctx = xmlSecOpenSSLX509StoreGetCtx(store);
209     xmlSecAssert2(ctx != NULL, NULL);
210     xmlSecAssert2(ctx->xst != NULL, NULL);
211 
212     /* dup certs */
213     certs2 = sk_X509_dup(certs);
214     if(certs2 == NULL) {
215         xmlSecOpenSSLError("sk_X509_dup",
216                            xmlSecKeyDataStoreGetName(store));
217         goto done;
218     }
219 
220     /* add untrusted certs from the store */
221     if(ctx->untrusted != NULL) {
222         for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) {
223             ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i));
224             if(ret < 1) {
225                 xmlSecOpenSSLError("sk_X509_push",
226                                    xmlSecKeyDataStoreGetName(store));
227                 goto done;
228             }
229         }
230     }
231 
232     /* dup crls but remove all non-verified */
233     if(crls != NULL) {
234         crls2 = sk_X509_CRL_dup(crls);
235         if(crls2 == NULL) {
236             xmlSecOpenSSLError("sk_X509_CRL_dup",
237                                xmlSecKeyDataStoreGetName(store));
238             goto done;
239         }
240 
241         for(i = 0; i < sk_X509_CRL_num(crls2); ) {
242             ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i));
243             if(ret == 1) {
244                 ++i;
245             } else if(ret == 0) {
246                 (void)sk_X509_CRL_delete(crls2, i);
247             } else {
248                 xmlSecInternalError("xmlSecOpenSSLX509VerifyCRL",
249                                     xmlSecKeyDataStoreGetName(store));
250                 goto done;
251             }
252         }
253     }
254 
255     /* remove all revoked certs */
256     for(i = 0; i < sk_X509_num(certs2);) {
257         cert = sk_X509_value(certs2, i);
258 
259         if(crls2 != NULL) {
260             ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert);
261             if(ret == 0) {
262                 (void)sk_X509_delete(certs2, i);
263                 continue;
264             } else if(ret != 1) {
265                 xmlSecInternalError("xmlSecOpenSSLX509VerifyCertAgainstCrls",
266                                     xmlSecKeyDataStoreGetName(store));
267                 goto done;
268             }
269         }
270 
271         if(ctx->crls != NULL) {
272             ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert);
273             if(ret == 0) {
274                 (void)sk_X509_delete(certs2, i);
275                 continue;
276             } else if(ret != 1) {
277                 xmlSecInternalError("xmlSecOpenSSLX509VerifyCertAgainstCrls",
278                                     xmlSecKeyDataStoreGetName(store));
279                 goto done;
280             }
281         }
282         ++i;
283     }
284 
285     /* get one cert after another and try to verify */
286     for(i = 0; i < sk_X509_num(certs2); ++i) {
287         cert = sk_X509_value(certs2, i);
288         if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) {
289 
290             ret = X509_STORE_CTX_init(xsc, ctx->xst, cert, certs2);
291             if(ret != 1) {
292                 xmlSecOpenSSLError("X509_STORE_CTX_init",
293                                    xmlSecKeyDataStoreGetName(store));
294                 goto done;
295             }
296 
297             if(keyInfoCtx->certsVerificationTime > 0) {
298                 X509_STORE_CTX_set_time(xsc, 0, keyInfoCtx->certsVerificationTime);
299             }
300 
301             {
302                 X509_VERIFY_PARAM * vpm = NULL;
303                 unsigned long vpm_flags = 0;
304 
305                 vpm = X509_VERIFY_PARAM_new();
306                 if(vpm == NULL) {
307                     xmlSecOpenSSLError("X509_VERIFY_PARAM_new",
308                                        xmlSecKeyDataStoreGetName(store));
309                     goto done;
310                 }
311                 vpm_flags = X509_VERIFY_PARAM_get_flags(vpm);
312                 vpm_flags &= (~X509_V_FLAG_CRL_CHECK);
313 
314                 if(keyInfoCtx->certsVerificationTime > 0) {
315                     vpm_flags |= X509_V_FLAG_USE_CHECK_TIME;
316                     X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime);
317                 }
318 
319                 X509_VERIFY_PARAM_set_depth(vpm, keyInfoCtx->certsVerificationDepth);
320                 X509_VERIFY_PARAM_set_flags(vpm, vpm_flags);
321                 X509_STORE_CTX_set0_param(xsc, vpm);
322             }
323 
324 
325             if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) {
326                 ret         = X509_verify_cert(xsc);
327             } else {
328                 ret = 1;
329             }
330             err_cert    = X509_STORE_CTX_get_current_cert(xsc);
331             err         = X509_STORE_CTX_get_error(xsc);
332 
333             X509_STORE_CTX_cleanup (xsc);
334 
335             if(ret == 1) {
336                 res = cert;
337                 goto done;
338             } else if(ret < 0) {
339                 /* real error */
340                 xmlSecOpenSSLError("X509_verify_cert", xmlSecKeyDataStoreGetName(store));
341                 goto done;
342             } else if(ret == 0) {
343                 const char* err_msg;
344                 char subject[256], issuer[256];
345 
346                 X509_NAME_oneline(X509_get_subject_name(err_cert), subject, sizeof(subject));
347                 X509_NAME_oneline(X509_get_issuer_name(err_cert), issuer, sizeof(issuer));
348                 err_msg = X509_verify_cert_error_string(err);
349 
350                 xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
351                                   xmlSecKeyDataStoreGetName(store),
352                                   "X509_verify_cert: subject=%s; issuer=%s; err=%d; msg=%s",
353                                   subject, issuer, err, xmlSecErrorsSafeString(err_msg));
354             }
355         }
356     }
357 
358     /* if we came here then we found nothing. do we have any error? */
359     if((err != 0) && (err_cert != NULL)) {
360         const char* err_msg;
361         char subject[256], issuer[256];
362 
363         X509_NAME_oneline(X509_get_subject_name(err_cert), subject, sizeof(subject));
364         X509_NAME_oneline(X509_get_issuer_name(err_cert), issuer, sizeof(issuer));
365         err_msg = X509_verify_cert_error_string(err);
366 
367         switch (err) {
368         case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
369             xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,
370                               xmlSecKeyDataStoreGetName(store),
371                               "subject=%s; issuer=%s; err=%d; msg=%s",
372                               subject, issuer, err, xmlSecErrorsSafeString(err_msg));
373             break;
374         case X509_V_ERR_CERT_NOT_YET_VALID:
375         case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
376             xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,
377                               xmlSecKeyDataStoreGetName(store),
378                               "subject=%s; issuer=%s; err=%d; msg=%s",
379                               subject, issuer, err, xmlSecErrorsSafeString(err_msg));
380             break;
381         case X509_V_ERR_CERT_HAS_EXPIRED:
382         case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
383             xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
384                               xmlSecKeyDataStoreGetName(store),
385                               "subject=%s; issuer=%s; err=%d; msg=%s",
386                               subject, issuer, err, xmlSecErrorsSafeString(err_msg));
387             break;
388         default:
389             xmlSecOtherError5(XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
390                               xmlSecKeyDataStoreGetName(store),
391                               "subject=%s; issuer=%s; err=%d; msg=%s",
392                               subject, issuer, err, xmlSecErrorsSafeString(err_msg));
393             break;
394         }
395     }
396 
397 done:
398     if(certs2 != NULL) {
399         sk_X509_free(certs2);
400     }
401     if(crls2 != NULL) {
402         sk_X509_CRL_free(crls2);
403     }
404     if(xsc != NULL) {
405         X509_STORE_CTX_free(xsc);
406     }
407     return(res);
408 }
409 
410 /**
411  * xmlSecOpenSSLX509StoreAdoptCert:
412  * @store:              the pointer to X509 key data store klass.
413  * @cert:               the pointer to OpenSSL X509 certificate.
414  * @type:               the certificate type (trusted/untrusted).
415  *
416  * Adds trusted (root) or untrusted certificate to the store.
417  *
418  * Returns: 0 on success or a negative value if an error occurs.
419  */
420 int
xmlSecOpenSSLX509StoreAdoptCert(xmlSecKeyDataStorePtr store,X509 * cert,xmlSecKeyDataType type)421 xmlSecOpenSSLX509StoreAdoptCert(xmlSecKeyDataStorePtr store, X509* cert, xmlSecKeyDataType type) {
422     xmlSecOpenSSLX509StoreCtxPtr ctx;
423     int ret;
424 
425     xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
426     xmlSecAssert2(cert != NULL, -1);
427 
428     ctx = xmlSecOpenSSLX509StoreGetCtx(store);
429     xmlSecAssert2(ctx != NULL, -1);
430 
431     if((type & xmlSecKeyDataTypeTrusted) != 0) {
432         xmlSecAssert2(ctx->xst != NULL, -1);
433 
434         ret = X509_STORE_add_cert(ctx->xst, cert);
435         if(ret != 1) {
436             xmlSecOpenSSLError("X509_STORE_add_cert",
437                                xmlSecKeyDataStoreGetName(store));
438             return(-1);
439         }
440         /* add cert increments the reference */
441         X509_free(cert);
442     } else {
443         xmlSecAssert2(ctx->untrusted != NULL, -1);
444 
445         ret = sk_X509_push(ctx->untrusted, cert);
446         if(ret < 1) {
447             xmlSecOpenSSLError("sk_X509_push",
448                                xmlSecKeyDataStoreGetName(store));
449             return(-1);
450         }
451     }
452     return(0);
453 }
454 
455 /**
456  * xmlSecOpenSSLX509StoreAdoptCrl:
457  * @store:              the pointer to X509 key data store klass.
458  * @crl:                the pointer to OpenSSL X509_CRL.
459  *
460  * Adds X509 CRL to the store.
461  *
462  * Returns: 0 on success or a negative value if an error occurs.
463  */
464 int
xmlSecOpenSSLX509StoreAdoptCrl(xmlSecKeyDataStorePtr store,X509_CRL * crl)465 xmlSecOpenSSLX509StoreAdoptCrl(xmlSecKeyDataStorePtr store, X509_CRL* crl) {
466     xmlSecOpenSSLX509StoreCtxPtr ctx;
467     int ret;
468 
469     xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
470     xmlSecAssert2(crl != NULL, -1);
471 
472     ctx = xmlSecOpenSSLX509StoreGetCtx(store);
473     xmlSecAssert2(ctx != NULL, -1);
474         xmlSecAssert2(ctx->crls != NULL, -1);
475 
476         ret = sk_X509_CRL_push(ctx->crls, crl);
477         if(ret < 1) {
478             xmlSecOpenSSLError("sk_X509_CRL_push",
479                                xmlSecKeyDataStoreGetName(store));
480             return(-1);
481         }
482 
483     return (0);
484 }
485 
486 /**
487  * xmlSecOpenSSLX509StoreAddCertsPath:
488  * @store: the pointer to OpenSSL x509 store.
489  * @path: the path to the certs dir.
490  *
491  * Adds all certs in the @path to the list of trusted certs
492  * in @store.
493  *
494  * Returns: 0 on success or a negative value otherwise.
495  */
496 int
xmlSecOpenSSLX509StoreAddCertsPath(xmlSecKeyDataStorePtr store,const char * path)497 xmlSecOpenSSLX509StoreAddCertsPath(xmlSecKeyDataStorePtr store, const char *path) {
498     xmlSecOpenSSLX509StoreCtxPtr ctx;
499     X509_LOOKUP *lookup = NULL;
500 
501     xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
502     xmlSecAssert2(path != NULL, -1);
503 
504     ctx = xmlSecOpenSSLX509StoreGetCtx(store);
505     xmlSecAssert2(ctx != NULL, -1);
506     xmlSecAssert2(ctx->xst != NULL, -1);
507 
508     lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir());
509     if(lookup == NULL) {
510         xmlSecOpenSSLError("X509_STORE_add_lookup",
511                            xmlSecKeyDataStoreGetName(store));
512         return(-1);
513     }
514     if(!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) {
515         xmlSecOpenSSLError2("X509_LOOKUP_add_dir",
516                             xmlSecKeyDataStoreGetName(store),
517                             "path='%s'",
518                             xmlSecErrorsSafeString(path));
519         return(-1);
520     }
521     return(0);
522 }
523 
524 /**
525  * xmlSecOpenSSLX509StoreAddCertsFile:
526  * @store: the pointer to OpenSSL x509 store.
527  * @filename: the certs file.
528  *
529  * Adds all certs in @file to the list of trusted certs
530  * in @store. It is possible for @file to contain multiple certs.
531  *
532  * Returns: 0 on success or a negative value otherwise.
533  */
534 int
xmlSecOpenSSLX509StoreAddCertsFile(xmlSecKeyDataStorePtr store,const char * filename)535 xmlSecOpenSSLX509StoreAddCertsFile(xmlSecKeyDataStorePtr store, const char *filename) {
536     xmlSecOpenSSLX509StoreCtxPtr ctx;
537     X509_LOOKUP *lookup = NULL;
538 
539     xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
540     xmlSecAssert2(filename != NULL, -1);
541 
542     ctx = xmlSecOpenSSLX509StoreGetCtx(store);
543     xmlSecAssert2(ctx != NULL, -1);
544     xmlSecAssert2(ctx->xst != NULL, -1);
545 
546     lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_file());
547     if(lookup == NULL) {
548         xmlSecOpenSSLError("X509_STORE_add_lookup",
549                            xmlSecKeyDataStoreGetName(store));
550         return(-1);
551     }
552     if(!X509_LOOKUP_load_file(lookup, filename, X509_FILETYPE_PEM)) {
553         xmlSecOpenSSLError2("X509_LOOKUP_load_file",
554                             xmlSecKeyDataStoreGetName(store),
555                             "filename='%s'",
556                             xmlSecErrorsSafeString(filename));
557         return(-1);
558     }
559     return(0);
560 }
561 
562 static int
xmlSecOpenSSLX509StoreInitialize(xmlSecKeyDataStorePtr store)563 xmlSecOpenSSLX509StoreInitialize(xmlSecKeyDataStorePtr store) {
564     const xmlChar* path;
565     X509_LOOKUP *lookup = NULL;
566 
567     xmlSecOpenSSLX509StoreCtxPtr ctx;
568     xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), -1);
569 
570     ctx = xmlSecOpenSSLX509StoreGetCtx(store);
571     xmlSecAssert2(ctx != NULL, -1);
572 
573     memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx));
574 
575     ctx->xst = X509_STORE_new();
576     if(ctx->xst == NULL) {
577         xmlSecOpenSSLError("X509_STORE_new",
578                            xmlSecKeyDataStoreGetName(store));
579         return(-1);
580     }
581 
582     if(!X509_STORE_set_default_paths(ctx->xst)) {
583         xmlSecOpenSSLError("X509_STORE_set_default_paths",
584                            xmlSecKeyDataStoreGetName(store));
585         return(-1);
586     }
587 
588 
589     lookup = X509_STORE_add_lookup(ctx->xst, X509_LOOKUP_hash_dir());
590     if(lookup == NULL) {
591         xmlSecOpenSSLError("X509_STORE_add_lookup",
592                            xmlSecKeyDataStoreGetName(store));
593          return(-1);
594     }
595 
596     path = xmlSecOpenSSLGetDefaultTrustedCertsFolder();
597     if(path != NULL) {
598         if(!X509_LOOKUP_add_dir(lookup, (char*)path, X509_FILETYPE_PEM)) {
599             xmlSecOpenSSLError2("X509_LOOKUP_add_dir",
600                                 xmlSecKeyDataStoreGetName(store),
601                                 "path='%s'",
602                                 xmlSecErrorsSafeString(path));
603             return(-1);
604         }
605     } else {
606         if(!X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT)) {
607             xmlSecOpenSSLError("X509_LOOKUP_add_dir",
608                                xmlSecKeyDataStoreGetName(store));
609             return(-1);
610         }
611     }
612 
613     ctx->untrusted = sk_X509_new_null();
614     if(ctx->untrusted == NULL) {
615         xmlSecOpenSSLError("sk_X509_new_null",
616                            xmlSecKeyDataStoreGetName(store));
617         return(-1);
618     }
619 
620     ctx->crls = sk_X509_CRL_new_null();
621     if(ctx->crls == NULL) {
622         xmlSecOpenSSLError("sk_X509_CRL_new_null",
623                            xmlSecKeyDataStoreGetName(store));
624         return(-1);
625     }
626 
627     ctx->vpm = X509_VERIFY_PARAM_new();
628     if(ctx->vpm == NULL) {
629         xmlSecOpenSSLError("X509_VERIFY_PARAM_new",
630                            xmlSecKeyDataStoreGetName(store));
631         return(-1);
632     }
633     X509_VERIFY_PARAM_set_depth(ctx->vpm, 9); /* the default cert verification path in openssl */
634     X509_STORE_set1_param(ctx->xst, ctx->vpm);
635 
636 
637     return(0);
638 }
639 
640 static void
xmlSecOpenSSLX509StoreFinalize(xmlSecKeyDataStorePtr store)641 xmlSecOpenSSLX509StoreFinalize(xmlSecKeyDataStorePtr store) {
642     xmlSecOpenSSLX509StoreCtxPtr ctx;
643     xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId));
644 
645     ctx = xmlSecOpenSSLX509StoreGetCtx(store);
646     xmlSecAssert(ctx != NULL);
647 
648 
649     if(ctx->xst != NULL) {
650         X509_STORE_free(ctx->xst);
651     }
652     if(ctx->untrusted != NULL) {
653         sk_X509_pop_free(ctx->untrusted, X509_free);
654     }
655     if(ctx->crls != NULL) {
656         sk_X509_CRL_pop_free(ctx->crls, X509_CRL_free);
657     }
658     if(ctx->vpm != NULL) {
659         X509_VERIFY_PARAM_free(ctx->vpm);
660     }
661 
662     memset(ctx, 0, sizeof(xmlSecOpenSSLX509StoreCtx));
663 }
664 
665 
666 /*****************************************************************************
667  *
668  * Low-level x509 functions
669  *
670  *****************************************************************************/
671 static int
xmlSecOpenSSLX509VerifyCRL(X509_STORE * xst,X509_CRL * crl)672 xmlSecOpenSSLX509VerifyCRL(X509_STORE* xst, X509_CRL *crl ) {
673     X509_STORE_CTX *xsc = NULL;
674     X509_OBJECT *xobj = NULL;
675     EVP_PKEY *pkey = NULL;
676     int ret;
677 
678     xmlSecAssert2(xst != NULL, -1);
679     xmlSecAssert2(crl != NULL, -1);
680 
681     xsc = X509_STORE_CTX_new();
682     if(xsc == NULL) {
683         xmlSecOpenSSLError("X509_STORE_CTX_new", NULL);
684         goto err;
685     }
686     xobj = (X509_OBJECT *)X509_OBJECT_new();
687     if(xobj == NULL) {
688         xmlSecOpenSSLError("X509_OBJECT_new", NULL);
689         goto err;
690     }
691 
692     ret = X509_STORE_CTX_init(xsc, xst, NULL, NULL);
693     if(ret != 1) {
694         xmlSecOpenSSLError("X509_STORE_CTX_init", NULL);
695         goto err;
696     }
697     ret = X509_STORE_CTX_get_by_subject(xsc, X509_LU_X509,
698                                         X509_CRL_get_issuer(crl), xobj);
699     if(ret <= 0) {
700         xmlSecOpenSSLError("X509_STORE_CTX_get_by_subject", NULL);
701         goto err;
702     }
703     pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
704     if(pkey == NULL) {
705         xmlSecOpenSSLError("X509_get_pubkey", NULL);
706         goto err;
707     }
708     ret = X509_CRL_verify(crl, pkey);
709     EVP_PKEY_free(pkey);
710     if(ret != 1) {
711         xmlSecOpenSSLError("X509_CRL_verify", NULL);
712     }
713     X509_STORE_CTX_free(xsc);
714     X509_OBJECT_free(xobj);
715     return((ret == 1) ? 1 : 0);
716 
717 err:
718     X509_STORE_CTX_free(xsc);
719     X509_OBJECT_free(xobj);
720     return(-1);
721 }
722 
723 static X509*
xmlSecOpenSSLX509FindCert(STACK_OF (X509)* certs,xmlChar * subjectName,xmlChar * issuerName,xmlChar * issuerSerial,xmlChar * ski)724 xmlSecOpenSSLX509FindCert(STACK_OF(X509) *certs, xmlChar *subjectName,
725                         xmlChar *issuerName, xmlChar *issuerSerial,
726                         xmlChar *ski) {
727     X509 *cert = NULL;
728     x509_size_t i;
729 
730     xmlSecAssert2(certs != NULL, NULL);
731 
732     /* todo: may be this is not the fastest way to search certs */
733     if(subjectName != NULL) {
734         X509_NAME *nm;
735         X509_NAME *subj;
736 
737         nm = xmlSecOpenSSLX509NameRead(subjectName, xmlStrlen(subjectName));
738         if(nm == NULL) {
739             xmlSecInternalError2("xmlSecOpenSSLX509NameRead", NULL,
740                                  "subject=%s", xmlSecErrorsSafeString(subjectName));
741             return(NULL);
742         }
743 
744         for(i = 0; i < sk_X509_num(certs); ++i) {
745             cert = sk_X509_value(certs, i);
746             subj = X509_get_subject_name(cert);
747             if(xmlSecOpenSSLX509NamesCompare(nm, subj) == 0) {
748                 X509_NAME_free(nm);
749                 return(cert);
750             }
751         }
752         X509_NAME_free(nm);
753     } else if((issuerName != NULL) && (issuerSerial != NULL)) {
754         X509_NAME *nm;
755         X509_NAME *issuer;
756         BIGNUM *bn;
757         ASN1_INTEGER *serial;
758 
759         nm = xmlSecOpenSSLX509NameRead(issuerName, xmlStrlen(issuerName));
760         if(nm == NULL) {
761             xmlSecInternalError2("xmlSecOpenSSLX509NameRead", NULL,
762                                  "issuer=%s", xmlSecErrorsSafeString(issuerName));
763             return(NULL);
764         }
765 
766         bn = BN_new();
767         if(bn == NULL) {
768             xmlSecOpenSSLError("BN_new", NULL);
769             X509_NAME_free(nm);
770             return(NULL);
771         }
772         if(BN_dec2bn(&bn, (char*)issuerSerial) == 0) {
773             xmlSecOpenSSLError("BN_dec2bn", NULL);
774             BN_free(bn);
775             X509_NAME_free(nm);
776             return(NULL);
777         }
778 
779         serial = BN_to_ASN1_INTEGER(bn, NULL);
780         if(serial == NULL) {
781             xmlSecOpenSSLError("BN_to_ASN1_INTEGER", NULL);
782             BN_free(bn);
783             X509_NAME_free(nm);
784             return(NULL);
785         }
786         BN_free(bn);
787 
788 
789         for(i = 0; i < sk_X509_num(certs); ++i) {
790             cert = sk_X509_value(certs, i);
791             if(ASN1_INTEGER_cmp(X509_get_serialNumber(cert), serial) != 0) {
792                 continue;
793             }
794             issuer = X509_get_issuer_name(cert);
795             if(xmlSecOpenSSLX509NamesCompare(nm, issuer) == 0) {
796                 ASN1_INTEGER_free(serial);
797                 X509_NAME_free(nm);
798                 return(cert);
799             }
800         }
801 
802         X509_NAME_free(nm);
803         ASN1_INTEGER_free(serial);
804     } else if(ski != NULL) {
805         int len;
806         int index;
807         X509_EXTENSION *ext;
808         ASN1_OCTET_STRING *keyId;
809 
810         /* our usual trick with base64 decode */
811         len = xmlSecBase64Decode(ski, (xmlSecByte*)ski, xmlStrlen(ski));
812         if(len < 0) {
813             xmlSecInternalError2("xmlSecBase64Decode", NULL,
814                                  "ski=%s", xmlSecErrorsSafeString(ski));
815             return(NULL);
816         }
817         for(i = 0; i < sk_X509_num(certs); ++i) {
818             cert = sk_X509_value(certs, i);
819             index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
820             if(index < 0) {
821                 continue;
822             }
823             ext = X509_get_ext(cert, index);
824             if(ext == NULL) {
825                 continue;
826             }
827             keyId = (ASN1_OCTET_STRING *)X509V3_EXT_d2i(ext);
828             if(keyId == NULL) {
829                 continue;
830             }
831             if((keyId->length == len) && (memcmp(keyId->data, ski, len) == 0)) {
832                 ASN1_OCTET_STRING_free(keyId);
833                 return(cert);
834             }
835             ASN1_OCTET_STRING_free(keyId);
836         }
837     }
838 
839     return(NULL);
840 }
841 
842 static X509*
xmlSecOpenSSLX509FindNextChainCert(STACK_OF (X509)* chain,X509 * cert)843 xmlSecOpenSSLX509FindNextChainCert(STACK_OF(X509) *chain, X509 *cert) {
844     unsigned long certSubjHash;
845     x509_size_t i;
846 
847     xmlSecAssert2(chain != NULL, NULL);
848     xmlSecAssert2(cert != NULL, NULL);
849 
850     certSubjHash = X509_subject_name_hash(cert);
851     for(i = 0; i < sk_X509_num(chain); ++i) {
852         if((sk_X509_value(chain, i) != cert) &&
853            (X509_issuer_name_hash(sk_X509_value(chain, i)) == certSubjHash)) {
854 
855             return(sk_X509_value(chain, i));
856         }
857     }
858     return(NULL);
859 }
860 
861 static int
xmlSecOpenSSLX509VerifyCertAgainstCrls(STACK_OF (X509_CRL)* crls,X509 * cert)862 xmlSecOpenSSLX509VerifyCertAgainstCrls(STACK_OF(X509_CRL) *crls, X509* cert) {
863     X509_NAME *issuer;
864     X509_CRL *crl = NULL;
865     X509_REVOKED *revoked;
866     x509_size_t i, n;
867     int ret;
868 
869     xmlSecAssert2(crls != NULL, -1);
870     xmlSecAssert2(cert != NULL, -1);
871 
872     /*
873      * Try to retrieve a CRL corresponding to the issuer of
874      * the current certificate
875      */
876     issuer = X509_get_issuer_name(cert);
877     n = sk_X509_CRL_num(crls);
878     for(i = 0; i < n; i++) {
879         crl = sk_X509_CRL_value(crls, i);
880         if(crl == NULL) {
881             continue;
882         }
883 
884         if(xmlSecOpenSSLX509NamesCompare(X509_CRL_get_issuer(crl), issuer) == 0) {
885             break;
886         }
887     }
888     if((i >= n) || (crl == NULL)){
889         /* no crls for this issuer */
890         return(1);
891     }
892 
893     /*
894      * Check date of CRL to make sure it's not expired
895      */
896     ret = X509_cmp_current_time(X509_CRL_get0_nextUpdate(crl));
897     if (ret == 0) {
898         /* crl expired */
899         return(1);
900     }
901 
902     /*
903      * Check if the current certificate is revoked by this CRL
904      */
905     n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
906     for (i = 0; i < n; i++) {
907         revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
908         if (ASN1_INTEGER_cmp(X509_REVOKED_get0_serialNumber(revoked), X509_get_serialNumber(cert)) == 0) {
909             xmlSecOtherError(XMLSEC_ERRORS_R_CERT_REVOKED, NULL, NULL);
910             return(0);
911         }
912     }
913     return(1);
914 }
915 
916 static X509_NAME *
xmlSecOpenSSLX509NameRead(xmlSecByte * str,int len)917 xmlSecOpenSSLX509NameRead(xmlSecByte *str, int len) {
918     xmlSecByte name[256];
919     xmlSecByte value[256];
920     int nameLen, valueLen;
921     X509_NAME *nm;
922     int type = MBSTRING_ASC;
923 
924     xmlSecAssert2(str != NULL, NULL);
925 
926     nm = X509_NAME_new();
927     if(nm == NULL) {
928         xmlSecOpenSSLError("X509_NAME_new", NULL);
929         return(NULL);
930     }
931 
932     while(len > 0) {
933         /* skip spaces after comma or semicolon */
934         while((len > 0) && isspace(*str)) {
935             ++str; --len;
936         }
937 
938         nameLen = xmlSecOpenSSLX509NameStringRead(&str, &len, name, sizeof(name), '=', 0);
939         if(nameLen < 0) {
940             xmlSecInternalError("xmlSecOpenSSLX509NameStringRead", NULL);
941             X509_NAME_free(nm);
942             return(NULL);
943         }
944         name[nameLen] = '\0';
945         if(len > 0) {
946             ++str; --len;
947             if((*str) == '\"') {
948                 ++str; --len;
949                 valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len,
950                                         value, sizeof(value), '"', 1);
951                 if(valueLen < 0) {
952                     xmlSecInternalError("xmlSecOpenSSLX509NameStringRead", NULL);
953                     X509_NAME_free(nm);
954                     return(NULL);
955                 }
956 
957                 /* skip quote */
958                 if((len <= 0) || ((*str) != '\"')) {
959                     xmlSecInvalidIntegerDataError("char", (*str), "quote '\"'", NULL);
960                     X509_NAME_free(nm);
961                     return(NULL);
962                 }
963                 ++str; --len;
964 
965                 /* skip spaces before comma or semicolon */
966                 while((len > 0) && isspace(*str)) {
967                     ++str; --len;
968                 }
969                 if((len > 0) && ((*str) != ',')) {
970                     xmlSecInvalidIntegerDataError("char", (*str), "comma ','", NULL);
971                     X509_NAME_free(nm);
972                     return(NULL);
973                 }
974                 if(len > 0) {
975                     ++str; --len;
976                 }
977                 type = MBSTRING_ASC;
978             } else if((*str) == '#') {
979                 /* TODO: read octect values */
980                 xmlSecNotImplementedError("reading octect values is not implemented yet");
981                 X509_NAME_free(nm);
982                 return(NULL);
983             } else {
984                 valueLen = xmlSecOpenSSLX509NameStringRead(&str, &len,
985                                         value, sizeof(value), ',', 1);
986                 if(valueLen < 0) {
987                     xmlSecInternalError("xmlSecOpenSSLX509NameStringRead", NULL);
988                     X509_NAME_free(nm);
989                     return(NULL);
990                 }
991                 type = MBSTRING_ASC;
992             }
993         } else {
994             valueLen = 0;
995         }
996         value[valueLen] = '\0';
997         if(len > 0) {
998             ++str; --len;
999         }
1000         X509_NAME_add_entry_by_txt(nm, (char*)name, type, value, valueLen, -1, 0);
1001     }
1002 
1003     return(nm);
1004 }
1005 
1006 static int
xmlSecOpenSSLX509NameStringRead(xmlSecByte ** str,int * strLen,xmlSecByte * res,int resLen,xmlSecByte delim,int ingoreTrailingSpaces)1007 xmlSecOpenSSLX509NameStringRead(xmlSecByte **str, int *strLen,
1008                         xmlSecByte *res, int resLen,
1009                         xmlSecByte delim, int ingoreTrailingSpaces) {
1010     xmlSecByte *p, *q, *nonSpace;
1011 
1012     xmlSecAssert2(str != NULL, -1);
1013     xmlSecAssert2(strLen != NULL, -1);
1014     xmlSecAssert2(res != NULL, -1);
1015 
1016     p = (*str);
1017     nonSpace = q = res;
1018     while(((p - (*str)) < (*strLen)) && ((*p) != delim) && ((q - res) < resLen)) {
1019         if((*p) != '\\') {
1020             if(ingoreTrailingSpaces && !isspace(*p)) {
1021                 nonSpace = q;
1022             }
1023             *(q++) = *(p++);
1024         } else {
1025             ++p;
1026             nonSpace = q;
1027             if(xmlSecIsHex((*p))) {
1028                 if((p - (*str) + 1) >= (*strLen)) {
1029                     xmlSecInvalidDataError("two hex digits expected", NULL);
1030                     return(-1);
1031                 }
1032                 *(q++) = xmlSecGetHex(p[0]) * 16 + xmlSecGetHex(p[1]);
1033                 p += 2;
1034             } else {
1035                 if(((++p) - (*str)) >= (*strLen)) {
1036                     xmlSecInvalidDataError("escaped symbol missed", NULL);
1037                     return(-1);
1038                 }
1039                 *(q++) = *(p++);
1040             }
1041         }
1042     }
1043     if(((p - (*str)) < (*strLen)) && ((*p) != delim)) {
1044         xmlSecInvalidSizeOtherError("buffer is too small", NULL);
1045         return(-1);
1046     }
1047     (*strLen) -= (int)(p - (*str));
1048     (*str) = p;
1049     return(int)((ingoreTrailingSpaces) ? nonSpace - res + 1 : q - res);
1050 }
1051 
1052 /*
1053  * This function DOES NOT create duplicates for X509_NAME_ENTRY objects!
1054  */
STACK_OF(X509_NAME_ENTRY)1055 static STACK_OF(X509_NAME_ENTRY)*
1056 xmlSecOpenSSLX509_NAME_ENTRIES_copy(X509_NAME * a) {
1057     STACK_OF(X509_NAME_ENTRY) * res = NULL;
1058     int ii;
1059 
1060     res = sk_X509_NAME_ENTRY_new(xmlSecOpenSSLX509_NAME_ENTRY_cmp);
1061     if(res == NULL) {
1062         xmlSecOpenSSLError("sk_X509_NAME_ENTRY_new", NULL);
1063         return(NULL);
1064     }
1065 
1066     for (ii = X509_NAME_entry_count(a) - 1; ii >= 0; --ii) {
1067         sk_X509_NAME_ENTRY_push(res, X509_NAME_get_entry(a, ii));
1068     }
1069 
1070     return (res);
1071 }
1072 
1073 static
xmlSecOpenSSLX509_NAME_ENTRIES_cmp(STACK_OF (X509_NAME_ENTRY)* a,STACK_OF (X509_NAME_ENTRY)* b)1074 int xmlSecOpenSSLX509_NAME_ENTRIES_cmp(STACK_OF(X509_NAME_ENTRY)* a,  STACK_OF(X509_NAME_ENTRY)* b) {
1075     const X509_NAME_ENTRY *na;
1076     const X509_NAME_ENTRY *nb;
1077     int ii, ret;
1078 
1079     xmlSecAssert2(a != NULL, -1);
1080     xmlSecAssert2(b != NULL, 1);
1081 
1082     if (sk_X509_NAME_ENTRY_num(a) != sk_X509_NAME_ENTRY_num(b)) {
1083         return sk_X509_NAME_ENTRY_num(a) - sk_X509_NAME_ENTRY_num(b);
1084     }
1085 
1086     for (ii = sk_X509_NAME_ENTRY_num(a) - 1; ii >= 0; --ii) {
1087         na = sk_X509_NAME_ENTRY_value(a, ii);
1088         nb = sk_X509_NAME_ENTRY_value(b, ii);
1089 
1090         ret = xmlSecOpenSSLX509_NAME_ENTRY_cmp(&na, &nb);
1091         if(ret != 0) {
1092             return(ret);
1093         }
1094     }
1095 
1096     return(0);
1097 }
1098 
1099 
1100 /**
1101  * xmlSecOpenSSLX509NamesCompare:
1102  *
1103  * We have to sort X509_NAME entries to get correct results.
1104  * This is ugly but OpenSSL does not support it
1105  */
1106 static int
xmlSecOpenSSLX509NamesCompare(X509_NAME * a,X509_NAME * b)1107 xmlSecOpenSSLX509NamesCompare(X509_NAME *a, X509_NAME *b) {
1108     STACK_OF(X509_NAME_ENTRY) *a1 = NULL;
1109     STACK_OF(X509_NAME_ENTRY) *b1 = NULL;
1110     int ret;
1111 
1112     xmlSecAssert2(a != NULL, -1);
1113     xmlSecAssert2(b != NULL, 1);
1114 
1115     a1 = xmlSecOpenSSLX509_NAME_ENTRIES_copy(a);
1116     if(a1 == NULL) {
1117         xmlSecInternalError("xmlSecOpenSSLX509_NAME_ENTRIES_copy", NULL);
1118         return(-1);
1119     }
1120     b1 = xmlSecOpenSSLX509_NAME_ENTRIES_copy(b);
1121     if(b1 == NULL) {
1122         xmlSecInternalError("xmlSecOpenSSLX509_NAME_ENTRIES_copy", NULL);
1123         sk_X509_NAME_ENTRY_free(a1);
1124         return(1);
1125     }
1126 
1127     /* sort both */
1128     (void)sk_X509_NAME_ENTRY_set_cmp_func(a1, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
1129     sk_X509_NAME_ENTRY_sort(a1);
1130     (void)sk_X509_NAME_ENTRY_set_cmp_func(b1, xmlSecOpenSSLX509_NAME_ENTRY_cmp);
1131     sk_X509_NAME_ENTRY_sort(b1);
1132 
1133     /* actually compare */
1134     ret = xmlSecOpenSSLX509_NAME_ENTRIES_cmp(a1, b1);
1135 
1136     /* cleanup */
1137     sk_X509_NAME_ENTRY_free(a1);
1138     sk_X509_NAME_ENTRY_free(b1);
1139     return(ret);
1140 }
1141 
1142 static int
xmlSecOpenSSLX509_NAME_ENTRY_cmp(const X509_NAME_ENTRY * const * a,const X509_NAME_ENTRY * const * b)1143 xmlSecOpenSSLX509_NAME_ENTRY_cmp(const X509_NAME_ENTRY * const *a, const X509_NAME_ENTRY * const *b) {
1144     ASN1_STRING *a_value, *b_value;
1145     ASN1_OBJECT *a_name,  *b_name;
1146     int a_len, b_len;
1147     int ret;
1148 
1149     xmlSecAssert2(a != NULL, -1);
1150     xmlSecAssert2(b != NULL, 1);
1151     xmlSecAssert2((*a) != NULL, -1);
1152     xmlSecAssert2((*b) != NULL, 1);
1153 
1154 
1155     /* first compare values */
1156     a_value = X509_NAME_ENTRY_get_data((X509_NAME_ENTRY*)(*a));
1157     b_value = X509_NAME_ENTRY_get_data((X509_NAME_ENTRY*)(*b));
1158 
1159     if((a_value == NULL) && (b_value != NULL)) {
1160         return(-1);
1161     } else if((a_value != NULL) && (b_value == NULL)) {
1162         return(1);
1163     } else if((a_value == NULL) && (b_value == NULL)) {
1164         return(0);
1165     }
1166 
1167     a_len = ASN1_STRING_length(a_value);
1168     b_len = ASN1_STRING_length(b_value);
1169     ret = a_len - b_len;
1170     if(ret != 0) {
1171         return(ret);
1172     }
1173 
1174     if(a_len > 0) {
1175         ret = memcmp(ASN1_STRING_get0_data(a_value), ASN1_STRING_get0_data(b_value), a_len);
1176         if(ret != 0) {
1177             return(ret);
1178         }
1179     }
1180 
1181     /* next compare names */
1182     a_name = X509_NAME_ENTRY_get_object((X509_NAME_ENTRY*)(*a));
1183     b_name = X509_NAME_ENTRY_get_object((X509_NAME_ENTRY*)(*b));
1184 
1185     if((a_name == NULL) && (b_name != NULL)) {
1186         return(-1);
1187     } else if((a_name != NULL) && (b_name == NULL)) {
1188         return(1);
1189     } else if((a_name == NULL) && (b_name == NULL)) {
1190         return(0);
1191     }
1192 
1193     return(OBJ_cmp(a_name, b_name));
1194 }
1195 
1196 #endif /* XMLSEC_NO_X509 */
1197 
1198 
1199