1 /*
2 * XML Security Library (http://www.aleksey.com/xmlsec).
3 *
4 *
5 *
6 * This is free software; see Copyright file in the source
7 * distribution for preciese wording.
8 *
9 * Copyright (C) 2010-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
10 */
11 /**
12 * SECTION:x509utils
13 * @Short_description: X509 certificates support functions for GnuTLS.
14 * @Stability: Private
15 *
16 */
17
18 #include "globals.h"
19
20 #ifndef XMLSEC_NO_X509
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <time.h>
28
29 #include <libxml/tree.h>
30
31
32
33 #include <gnutls/gnutls.h>
34 #include <gnutls/x509.h>
35 #include <gnutls/pkcs12.h>
36
37 #include <xmlsec/xmlsec.h>
38 #include <xmlsec/xmltree.h>
39 #include <xmlsec/keys.h>
40 #include <xmlsec/keyinfo.h>
41 #include <xmlsec/keysmngr.h>
42 #include <xmlsec/x509.h>
43 #include <xmlsec/base64.h>
44 #include <xmlsec/errors.h>
45 #include <xmlsec/private.h>
46
47 #include <xmlsec/gnutls/crypto.h>
48 #include <xmlsec/gnutls/x509.h>
49
50 #include "x509utils.h"
51
52
53 /**************************************************************************
54 *
55 * X509 crt list
56 *
57 *****************************************************************************/
58 static xmlSecPtr xmlSecGnuTLSX509CrtListDuplicateItem (xmlSecPtr ptr);
59 static void xmlSecGnuTLSX509CrtListDestroyItem (xmlSecPtr ptr);
60 static void xmlSecGnuTLSX509CrtListDebugDumpItem (xmlSecPtr ptr,
61 FILE* output);
62 static void xmlSecGnuTLSX509CrtListDebugXmlDumpItem (xmlSecPtr ptr,
63 FILE* output);
64
65 static xmlSecPtrListKlass xmlSecGnuTLSX509CrtListKlass = {
66 BAD_CAST "gnutls-x509-crt-list",
67 xmlSecGnuTLSX509CrtListDuplicateItem, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
68 xmlSecGnuTLSX509CrtListDestroyItem, /* xmlSecPtrDestroyItemMethod destroyItem; */
69 xmlSecGnuTLSX509CrtListDebugDumpItem, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
70 xmlSecGnuTLSX509CrtListDebugXmlDumpItem, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
71 };
72
73 xmlSecPtrListId
xmlSecGnuTLSX509CrtListGetKlass(void)74 xmlSecGnuTLSX509CrtListGetKlass(void) {
75 return(&xmlSecGnuTLSX509CrtListKlass);
76 }
77
78 static xmlSecPtr
xmlSecGnuTLSX509CrtListDuplicateItem(xmlSecPtr ptr)79 xmlSecGnuTLSX509CrtListDuplicateItem(xmlSecPtr ptr) {
80 xmlSecAssert2(ptr != NULL, NULL);
81
82 return xmlSecGnuTLSX509CertDup((gnutls_x509_crt_t)ptr);
83 }
84
85 static void
xmlSecGnuTLSX509CrtListDestroyItem(xmlSecPtr ptr)86 xmlSecGnuTLSX509CrtListDestroyItem(xmlSecPtr ptr) {
87 xmlSecAssert(ptr != NULL);
88
89 gnutls_x509_crt_deinit((gnutls_x509_crt_t)ptr);
90 }
91
92 static void
xmlSecGnuTLSX509CrtListDebugDumpItem(xmlSecPtr ptr,FILE * output)93 xmlSecGnuTLSX509CrtListDebugDumpItem(xmlSecPtr ptr, FILE* output) {
94 xmlSecAssert(ptr != NULL);
95 xmlSecAssert(output != NULL);
96
97 xmlSecGnuTLSX509CertDebugDump((gnutls_x509_crt_t)ptr, output);
98 }
99
100
101 static void
xmlSecGnuTLSX509CrtListDebugXmlDumpItem(xmlSecPtr ptr,FILE * output)102 xmlSecGnuTLSX509CrtListDebugXmlDumpItem(xmlSecPtr ptr, FILE* output) {
103 xmlSecAssert(ptr != NULL);
104 xmlSecAssert(output != NULL);
105
106 xmlSecGnuTLSX509CertDebugXmlDump((gnutls_x509_crt_t)ptr, output);
107 }
108
109 /**************************************************************************
110 *
111 * X509 crl list
112 *
113 *****************************************************************************/
114 static xmlSecPtr xmlSecGnuTLSX509CrlListDuplicateItem (xmlSecPtr ptr);
115 static void xmlSecGnuTLSX509CrlListDestroyItem (xmlSecPtr ptr);
116 static void xmlSecGnuTLSX509CrlListDebugDumpItem (xmlSecPtr ptr,
117 FILE* output);
118 static void xmlSecGnuTLSX509CrlListDebugXmlDumpItem (xmlSecPtr ptr,
119 FILE* output);
120
121 static xmlSecPtrListKlass xmlSecGnuTLSX509CrlListKlass = {
122 BAD_CAST "gnutls-x509-crl-list",
123 xmlSecGnuTLSX509CrlListDuplicateItem, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
124 xmlSecGnuTLSX509CrlListDestroyItem, /* xmlSecPtrDestroyItemMethod destroyItem; */
125 xmlSecGnuTLSX509CrlListDebugDumpItem, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
126 xmlSecGnuTLSX509CrlListDebugXmlDumpItem, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
127 };
128
129 xmlSecPtrListId
xmlSecGnuTLSX509CrlListGetKlass(void)130 xmlSecGnuTLSX509CrlListGetKlass(void) {
131 return(&xmlSecGnuTLSX509CrlListKlass);
132 }
133
134 static xmlSecPtr
xmlSecGnuTLSX509CrlListDuplicateItem(xmlSecPtr ptr)135 xmlSecGnuTLSX509CrlListDuplicateItem(xmlSecPtr ptr) {
136 xmlSecAssert2(ptr != NULL, NULL);
137
138 return xmlSecGnuTLSX509CrlDup((gnutls_x509_crl_t)ptr);
139 }
140
141 static void
xmlSecGnuTLSX509CrlListDestroyItem(xmlSecPtr ptr)142 xmlSecGnuTLSX509CrlListDestroyItem(xmlSecPtr ptr) {
143 xmlSecAssert(ptr != NULL);
144
145 gnutls_x509_crl_deinit((gnutls_x509_crl_t)ptr);
146 }
147
148 static void
xmlSecGnuTLSX509CrlListDebugDumpItem(xmlSecPtr ptr,FILE * output)149 xmlSecGnuTLSX509CrlListDebugDumpItem(xmlSecPtr ptr, FILE* output) {
150 xmlSecAssert(ptr != NULL);
151 xmlSecAssert(output != NULL);
152
153 xmlSecGnuTLSX509CrlDebugDump((gnutls_x509_crl_t)ptr, output);
154 }
155
156
157 static void
xmlSecGnuTLSX509CrlListDebugXmlDumpItem(xmlSecPtr ptr,FILE * output)158 xmlSecGnuTLSX509CrlListDebugXmlDumpItem(xmlSecPtr ptr, FILE* output) {
159 xmlSecAssert(ptr != NULL);
160 xmlSecAssert(output != NULL);
161
162 xmlSecGnuTLSX509CrlDebugXmlDump((gnutls_x509_crl_t)ptr, output);
163 }
164
165 /*************************************************************************
166 *
167 * x509 certs utils/helpers
168 *
169 ************************************************************************/
170
171 /* HACK: gnutls doesn't have cert duplicate function, so we simply
172 write cert out and then read it back */
173 gnutls_x509_crt_t
xmlSecGnuTLSX509CertDup(gnutls_x509_crt_t src)174 xmlSecGnuTLSX509CertDup(gnutls_x509_crt_t src) {
175 xmlChar * buf = NULL;
176 gnutls_x509_crt_t res = NULL;
177
178 xmlSecAssert2(src != NULL, NULL);
179
180 buf = xmlSecGnuTLSX509CertBase64DerWrite(src, 0);
181 if(buf == NULL) {
182 xmlSecInternalError("xmlSecGnuTLSX509CertBase64DerWrite", NULL);
183 return (NULL);
184 }
185
186 res = xmlSecGnuTLSX509CertBase64DerRead(buf);
187 if(res == NULL) {
188 xmlSecInternalError("xmlSecGnuTLSX509CertBase64DerRead", NULL);
189 xmlFree(buf);
190 return (NULL);
191 }
192
193 /* done */
194 xmlFree(buf);
195 return (res);
196 }
197
198 xmlChar *
xmlSecGnuTLSX509CertGetSubjectDN(gnutls_x509_crt_t cert)199 xmlSecGnuTLSX509CertGetSubjectDN(gnutls_x509_crt_t cert) {
200 char* buf = NULL;
201 size_t bufSize = 0;
202 int err;
203
204 xmlSecAssert2(cert != NULL, NULL);
205
206 /* get subject size */
207 err = gnutls_x509_crt_get_dn(cert, NULL, &bufSize);
208 if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
209 xmlSecGnuTLSError("gnutls_x509_crt_get_dn", err, NULL);
210 return(NULL);
211 }
212
213 /* allocate buffer */
214 buf = (char *)xmlMalloc(bufSize + 1);
215 if(buf == NULL) {
216 xmlSecMallocError(bufSize + 1, NULL);
217 return(NULL);
218 }
219
220 /* finally write it out */
221 err = gnutls_x509_crt_get_dn(cert, buf, &bufSize);
222 if(err != GNUTLS_E_SUCCESS) {
223 xmlSecGnuTLSError("gnutls_x509_crt_get_dn", err, NULL);
224 xmlFree(buf);
225 return(NULL);
226 }
227
228 /* done */
229 return(BAD_CAST buf);
230 }
231
232 xmlChar *
xmlSecGnuTLSX509CertGetIssuerDN(gnutls_x509_crt_t cert)233 xmlSecGnuTLSX509CertGetIssuerDN(gnutls_x509_crt_t cert) {
234 char* buf = NULL;
235 size_t bufSize = 0;
236 int err;
237
238 xmlSecAssert2(cert != NULL, NULL);
239
240 /* get issuer size */
241 err = gnutls_x509_crt_get_issuer_dn(cert, NULL, &bufSize);
242 if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
243 xmlSecGnuTLSError("gnutls_x509_crt_get_issuer_dn", err, NULL);
244 return(NULL);
245 }
246
247 /* allocate buffer */
248 buf = (char *)xmlMalloc(bufSize + 1);
249 if(buf == NULL) {
250 xmlSecMallocError(bufSize + 1, NULL);
251 return(NULL);
252 }
253
254 /* finally write it out */
255 err = gnutls_x509_crt_get_issuer_dn(cert, buf, &bufSize);
256 if(err != GNUTLS_E_SUCCESS) {
257 xmlSecGnuTLSError("gnutls_x509_crt_get_issuer_dn", err, NULL);
258 xmlFree(buf);
259 return(NULL);
260 }
261
262 /* done */
263 return(BAD_CAST buf);
264 }
265
266 xmlChar *
xmlSecGnuTLSX509CertGetIssuerSerial(gnutls_x509_crt_t cert)267 xmlSecGnuTLSX509CertGetIssuerSerial(gnutls_x509_crt_t cert) {
268 xmlChar * res = NULL;
269 unsigned char* buf = NULL;
270 size_t bufSize = 0;
271 int err;
272
273 xmlSecAssert2(cert != NULL, NULL);
274
275 /* get issuer serial size */
276 err = gnutls_x509_crt_get_serial(cert, NULL, &bufSize);
277 if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
278 xmlSecGnuTLSError("gnutls_x509_crt_get_serial", err, NULL);
279 return(NULL);
280 }
281
282 /* allocate buffer */
283 buf = (unsigned char *)xmlMalloc(bufSize + 1);
284 if(buf == NULL) {
285 xmlSecMallocError(bufSize + 1, NULL);
286 return(NULL);
287 }
288
289 /* write it out */
290 err = gnutls_x509_crt_get_serial(cert, buf, &bufSize);
291 if(err != GNUTLS_E_SUCCESS) {
292 xmlSecGnuTLSError("gnutls_x509_crt_get_serial", err, NULL);
293 xmlFree(buf);
294 return(NULL);
295 }
296
297 /* convert to string */
298 res = xmlSecGnuTLSASN1IntegerWrite(buf, bufSize);
299 if(res == NULL) {
300 xmlSecInternalError("xmlSecGnuTLSASN1IntegerWrite", NULL);
301 xmlFree(buf);
302 return(NULL);
303 }
304
305 /* done */
306 xmlFree(buf);
307 return(res);
308 }
309
310 xmlChar *
xmlSecGnuTLSX509CertGetSKI(gnutls_x509_crt_t cert)311 xmlSecGnuTLSX509CertGetSKI(gnutls_x509_crt_t cert) {
312 xmlChar * res = NULL;
313 xmlSecByte* buf = NULL;
314 size_t bufSize = 0;
315 unsigned int critical = 0;
316 int err;
317
318 xmlSecAssert2(cert != NULL, NULL);
319
320 /* get ski size */
321 err = gnutls_x509_crt_get_subject_key_id(cert, NULL, &bufSize, &critical);
322 if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
323 xmlSecGnuTLSError("gnutls_x509_crt_get_subject_key_id", err, NULL);
324 return(NULL);
325 }
326
327 /* allocate buffer */
328 buf = (xmlSecByte *)xmlMalloc(bufSize + 1);
329 if(buf == NULL) {
330 xmlSecMallocError(bufSize + 1, NULL);
331 return(NULL);
332 }
333
334 /* write it out */
335 err = gnutls_x509_crt_get_subject_key_id(cert, buf, &bufSize, &critical);
336 if(err != GNUTLS_E_SUCCESS) {
337 xmlSecGnuTLSError("gnutls_x509_crt_get_subject_key_id", err, NULL);
338 xmlFree(buf);
339 return(NULL);
340 }
341
342 /* convert to string */
343 res = xmlSecBase64Encode(buf, bufSize, 0);
344 if(res == NULL) {
345 xmlSecInternalError("xmlSecBase64Encode", NULL);
346 xmlFree(buf);
347 return(NULL);
348 }
349
350 /* done */
351 xmlFree(buf);
352 return(res);
353 }
354
355
356 gnutls_x509_crt_t
xmlSecGnuTLSX509CertBase64DerRead(xmlChar * buf)357 xmlSecGnuTLSX509CertBase64DerRead(xmlChar* buf) {
358 int ret;
359
360 xmlSecAssert2(buf != NULL, NULL);
361
362 /* usual trick with base64 decoding "in-place" */
363 ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf));
364 if(ret < 0) {
365 xmlSecInternalError("xmlSecBase64Decode", NULL);
366 return(NULL);
367 }
368
369 return(xmlSecGnuTLSX509CertRead((const xmlSecByte*)buf, ret, xmlSecKeyDataFormatCertDer));
370 }
371
372 gnutls_x509_crt_t
xmlSecGnuTLSX509CertRead(const xmlSecByte * buf,xmlSecSize size,xmlSecKeyDataFormat format)373 xmlSecGnuTLSX509CertRead(const xmlSecByte* buf, xmlSecSize size, xmlSecKeyDataFormat format) {
374 gnutls_x509_crt_t cert = NULL;
375 gnutls_x509_crt_fmt_t fmt;
376 gnutls_datum_t data;
377 int err;
378
379 xmlSecAssert2(buf != NULL, NULL);
380 xmlSecAssert2(size > 0, NULL);
381
382 /* figure out format */
383 switch(format) {
384 case xmlSecKeyDataFormatPem:
385 case xmlSecKeyDataFormatCertPem:
386 fmt = GNUTLS_X509_FMT_PEM;
387 break;
388 case xmlSecKeyDataFormatDer:
389 case xmlSecKeyDataFormatCertDer:
390 fmt = GNUTLS_X509_FMT_DER;
391 break;
392 default:
393 xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL,
394 "format=%d", (int)format);
395 return(NULL);
396 }
397
398 /* read cert */
399 err = gnutls_x509_crt_init(&cert);
400 if(err != GNUTLS_E_SUCCESS) {
401 xmlSecGnuTLSError("gnutls_x509_crt_init", err, NULL);
402 return(NULL);
403 }
404
405 data.data = (unsigned char*)buf;
406 data.size = size;
407 err = gnutls_x509_crt_import(cert, &data, fmt);
408 if(err != GNUTLS_E_SUCCESS) {
409 xmlSecGnuTLSError("gnutls_x509_crt_import", err, NULL);
410 gnutls_x509_crt_deinit(cert);
411 return(NULL);
412 }
413
414 return(cert);
415 }
416
417 xmlChar*
xmlSecGnuTLSX509CertBase64DerWrite(gnutls_x509_crt_t cert,int base64LineWrap)418 xmlSecGnuTLSX509CertBase64DerWrite(gnutls_x509_crt_t cert, int base64LineWrap) {
419 xmlChar * res = NULL;
420 xmlSecByte* buf = NULL;
421 size_t bufSize = 0;
422 int err;
423
424 xmlSecAssert2(cert != NULL, NULL);
425
426 /* get size */
427 err = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &bufSize);
428 if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
429 xmlSecGnuTLSError("gnutls_x509_crt_export(GNUTLS_X509_FMT_DER)", err, NULL);
430 return(NULL);
431 }
432
433 /* allocate buffer */
434 buf = (xmlSecByte *)xmlMalloc(bufSize + 1);
435 if(buf == NULL) {
436 xmlSecMallocError(bufSize + 1, NULL);
437 return(NULL);
438 }
439
440 /* write it out */
441 err = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, buf, &bufSize);
442 if(err != GNUTLS_E_SUCCESS) {
443 xmlSecGnuTLSError("gnutls_x509_crt_export(GNUTLS_X509_FMT_DER)", err, NULL);
444 xmlFree(buf);
445 return(NULL);
446 }
447
448 /* convert to string */
449 res = xmlSecBase64Encode(buf, bufSize, base64LineWrap);
450 if(res == NULL) {
451 xmlSecInternalError("xmlSecBase64Encode", NULL);
452 xmlFree(buf);
453 return(NULL);
454 }
455
456 /* done */
457 xmlFree(buf);
458 return(res);
459 }
460
461 void
xmlSecGnuTLSX509CertDebugDump(gnutls_x509_crt_t cert,FILE * output)462 xmlSecGnuTLSX509CertDebugDump(gnutls_x509_crt_t cert, FILE* output) {
463 xmlChar * buf;
464
465 xmlSecAssert(cert != NULL);
466 xmlSecAssert(output != NULL);
467
468 buf = xmlSecGnuTLSX509CertGetSubjectDN(cert);
469 if(buf != NULL) {
470 fprintf(output, "==== Subject Name: %s\n", buf);
471 xmlFree(buf);
472 } else {
473 fprintf(output, "==== Subject Name: unknown\n");
474 }
475
476 buf = xmlSecGnuTLSX509CertGetIssuerDN(cert);
477 if(buf != NULL) {
478 fprintf(output, "==== Issuer Name: %s\n", buf);
479 xmlFree(buf);
480 } else {
481 fprintf(output, "==== Issuer Name: unknown\n");
482 }
483
484 buf = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
485 if(buf != NULL) {
486 fprintf(output, "==== Issuer Serial: %s\n", buf);
487 xmlFree(buf);
488 } else {
489 fprintf(output, "==== Issuer Serial: unknown\n");
490 }
491 }
492
493 void
xmlSecGnuTLSX509CertDebugXmlDump(gnutls_x509_crt_t cert,FILE * output)494 xmlSecGnuTLSX509CertDebugXmlDump(gnutls_x509_crt_t cert, FILE* output) {
495 xmlChar * buf;
496
497 xmlSecAssert(cert != NULL);
498 xmlSecAssert(output != NULL);
499
500 buf = xmlSecGnuTLSX509CertGetSubjectDN(cert);
501 if(buf != NULL) {
502 fprintf(output, "<SubjectName>%s</SubjectName>\n", buf);
503 xmlFree(buf);
504 } else {
505 fprintf(output, "<SubjectName>unknown</SubjectName>\n");
506 }
507
508 buf = xmlSecGnuTLSX509CertGetIssuerDN(cert);
509 if(buf != NULL) {
510 fprintf(output, "<IssuerName>%s</IssuerName>\n", buf);
511 xmlFree(buf);
512 } else {
513 fprintf(output, "<IssuerName>unknown</IssuerName>\n");
514 }
515
516 buf = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
517 if(buf != NULL) {
518 fprintf(output, "<SerialNumber>%s</SerialNumber>\n", buf);
519 xmlFree(buf);
520 } else {
521 fprintf(output, "<SerialNumber>unknown</SerialNumber>\n");
522 }
523 }
524
525 /*************************************************************************
526 *
527 * x509 crls utils/helpers
528 *
529 ************************************************************************/
530
531 /* HACK: gnutls doesn't have crl duplicate function, so we simply
532 write crl out and then read it back */
533 gnutls_x509_crl_t
xmlSecGnuTLSX509CrlDup(gnutls_x509_crl_t src)534 xmlSecGnuTLSX509CrlDup(gnutls_x509_crl_t src) {
535 xmlChar * buf = NULL;
536 gnutls_x509_crl_t res = NULL;
537
538 xmlSecAssert2(src != NULL, NULL);
539
540 buf = xmlSecGnuTLSX509CrlBase64DerWrite(src, 0);
541 if(buf == NULL) {
542 xmlSecInternalError("xmlSecGnuTLSX509CrlBase64DerWrite", NULL);
543 return (NULL);
544 }
545
546 res = xmlSecGnuTLSX509CrlBase64DerRead(buf);
547 if(res == NULL) {
548 xmlSecInternalError("xmlSecGnuTLSX509CrlBase64DerRead", NULL);
549 xmlFree(buf);
550 return (NULL);
551 }
552
553 /* done */
554 xmlFree(buf);
555 return (res);
556 }
557
558 xmlChar *
xmlSecGnuTLSX509CrlGetIssuerDN(gnutls_x509_crl_t crl)559 xmlSecGnuTLSX509CrlGetIssuerDN(gnutls_x509_crl_t crl) {
560 char* buf = NULL;
561 size_t bufSize = 0;
562 int err;
563
564 xmlSecAssert2(crl != NULL, NULL);
565
566 /* get issuer size */
567 err = gnutls_x509_crl_get_issuer_dn(crl, NULL, &bufSize);
568 if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
569 xmlSecGnuTLSError("gnutls_x509_crl_get_issuer_dn", err, NULL);
570 return(NULL);
571 }
572
573 /* allocate buffer */
574 buf = (char *)xmlMalloc(bufSize + 1);
575 if(buf == NULL) {
576 xmlSecMallocError(bufSize + 1, NULL);
577 return(NULL);
578 }
579
580 /* finally write it out */
581 err = gnutls_x509_crl_get_issuer_dn(crl, buf, &bufSize);
582 if(err != GNUTLS_E_SUCCESS) {
583 xmlSecGnuTLSError("gnutls_x509_crl_get_issuer_dn", err, NULL);
584 xmlFree(buf);
585 return(NULL);
586 }
587
588 /* done */
589 return(BAD_CAST buf);
590 }
591
592 gnutls_x509_crl_t
xmlSecGnuTLSX509CrlBase64DerRead(xmlChar * buf)593 xmlSecGnuTLSX509CrlBase64DerRead(xmlChar* buf) {
594 int ret;
595
596 xmlSecAssert2(buf != NULL, NULL);
597
598 /* usual trick with base64 decoding "in-place" */
599 ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf));
600 if(ret < 0) {
601 xmlSecInternalError("xmlSecBase64Decode", NULL);
602 return(NULL);
603 }
604
605 return(xmlSecGnuTLSX509CrlRead((const xmlSecByte*)buf, ret, xmlSecKeyDataFormatCertDer));
606 }
607
608 gnutls_x509_crl_t
xmlSecGnuTLSX509CrlRead(const xmlSecByte * buf,xmlSecSize size,xmlSecKeyDataFormat format)609 xmlSecGnuTLSX509CrlRead(const xmlSecByte* buf, xmlSecSize size, xmlSecKeyDataFormat format) {
610 gnutls_x509_crl_t crl = NULL;
611 gnutls_x509_crt_fmt_t fmt;
612 gnutls_datum_t data;
613 int err;
614
615 xmlSecAssert2(buf != NULL, NULL);
616 xmlSecAssert2(size > 0, NULL);
617
618 /* figure out format */
619 switch(format) {
620 case xmlSecKeyDataFormatPem:
621 case xmlSecKeyDataFormatCertPem:
622 fmt = GNUTLS_X509_FMT_PEM;
623 break;
624 case xmlSecKeyDataFormatDer:
625 case xmlSecKeyDataFormatCertDer:
626 fmt = GNUTLS_X509_FMT_DER;
627 break;
628 default:
629 xmlSecOtherError2(XMLSEC_ERRORS_R_INVALID_FORMAT, NULL,
630 "format=%d", (int)format);
631 return(NULL);
632 }
633
634 /* read crl */
635 err = gnutls_x509_crl_init(&crl);
636 if(err != GNUTLS_E_SUCCESS) {
637 xmlSecGnuTLSError("gnutls_x509_crl_init", err, NULL);
638 return(NULL);
639 }
640
641 data.data = (unsigned char*)buf;
642 data.size = size;
643 err = gnutls_x509_crl_import(crl, &data, fmt);
644 if(err != GNUTLS_E_SUCCESS) {
645 xmlSecGnuTLSError("gnutls_x509_crl_import", err, NULL);
646 gnutls_x509_crl_deinit(crl);
647 return(NULL);
648 }
649
650 return(crl);
651 }
652
653 xmlChar*
xmlSecGnuTLSX509CrlBase64DerWrite(gnutls_x509_crl_t crl,int base64LineWrap)654 xmlSecGnuTLSX509CrlBase64DerWrite(gnutls_x509_crl_t crl, int base64LineWrap) {
655 xmlChar * res = NULL;
656 xmlSecByte* buf = NULL;
657 size_t bufSize = 0;
658 int err;
659
660 xmlSecAssert2(crl != NULL, NULL);
661
662 /* get size */
663 err = gnutls_x509_crl_export(crl, GNUTLS_X509_FMT_DER, NULL, &bufSize);
664 if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
665 xmlSecGnuTLSError("gnutls_x509_crl_export(GNUTLS_X509_FMT_DER)", err, NULL);
666 return(NULL);
667 }
668
669 /* allocate buffer */
670 buf = (xmlSecByte *)xmlMalloc(bufSize + 1);
671 if(buf == NULL) {
672 xmlSecMallocError(bufSize + 1, NULL);
673 return(NULL);
674 }
675
676 /* write it out */
677 err = gnutls_x509_crl_export(crl, GNUTLS_X509_FMT_DER, buf, &bufSize);
678 if(err != GNUTLS_E_SUCCESS) {
679 xmlSecGnuTLSError("gnutls_x509_crl_export(GNUTLS_X509_FMT_DER)", err, NULL);
680 xmlFree(buf);
681 return(NULL);
682 }
683
684 /* convert to string */
685 res = xmlSecBase64Encode(buf, bufSize, base64LineWrap);
686 if(res == NULL) {
687 xmlSecInternalError("xmlSecBase64Encode", NULL);
688 xmlFree(buf);
689 return(NULL);
690 }
691
692 /* done */
693 xmlFree(buf);
694 return(res);
695 }
696
697 void
xmlSecGnuTLSX509CrlDebugDump(gnutls_x509_crl_t crl,FILE * output)698 xmlSecGnuTLSX509CrlDebugDump(gnutls_x509_crl_t crl, FILE* output) {
699 xmlChar * buf;
700
701 xmlSecAssert(crl != NULL);
702 xmlSecAssert(output != NULL);
703
704 buf = xmlSecGnuTLSX509CrlGetIssuerDN(crl);
705 if(buf != NULL) {
706 fprintf(output, "==== Issuer Name: %s\n", buf);
707 xmlFree(buf);
708 } else {
709 fprintf(output, "==== Issuer Name: unknown\n");
710 }
711 }
712
713 void
xmlSecGnuTLSX509CrlDebugXmlDump(gnutls_x509_crl_t crl,FILE * output)714 xmlSecGnuTLSX509CrlDebugXmlDump(gnutls_x509_crl_t crl, FILE* output) {
715 xmlChar * buf;
716
717 xmlSecAssert(crl != NULL);
718 xmlSecAssert(output != NULL);
719
720 buf = xmlSecGnuTLSX509CrlGetIssuerDN(crl);
721 if(buf != NULL) {
722 fprintf(output, "<IssuerName>%s</IssuerName>\n", buf);
723 xmlFree(buf);
724 } else {
725 fprintf(output, "<IssuerName>unknown</IssuerName>\n");
726 }
727 }
728
729 /*************************************************************************
730 *
731 * Misc. utils/helpers
732 *
733 ************************************************************************/
734 xmlChar*
xmlSecGnuTLSASN1IntegerWrite(const unsigned char * data,size_t len)735 xmlSecGnuTLSASN1IntegerWrite(const unsigned char * data, size_t len) {
736 xmlChar *res = NULL;
737 int resLen = 64; /* not more than 64 chars */
738 unsigned long long int val = 0;
739 size_t ii = 0;
740 int shift = 0;
741 int ret;
742
743 xmlSecAssert2(data != NULL, NULL);
744 xmlSecAssert2(len <= 9, NULL);
745
746 /* HACK : to be fixed after GnuTLS provides a way to read opaque ASN1 integer */
747 for(ii = len; ii > 0; --ii, shift += 8) {
748 val |= ((unsigned long long)data[ii - 1]) << shift;
749 }
750
751 res = (xmlChar*)xmlMalloc(resLen + 1);
752 if(res == NULL) {
753 xmlSecMallocError(resLen + 1, NULL);
754 return(NULL);
755 }
756
757 ret = xmlStrPrintf(res, resLen, "%llu", val);
758 if(ret < 0) {
759 xmlSecXmlError("xmlStrPrintf", NULL);
760 xmlFree(res);
761 return(NULL);
762 }
763
764 return(res);
765 }
766
767 /*************************************************************************
768 *
769 * pkcs12 utils/helpers
770 *
771 ************************************************************************/
772 int
xmlSecGnuTLSPkcs12LoadMemory(const xmlSecByte * data,xmlSecSize dataSize,const char * pwd,gnutls_x509_privkey_t * priv_key,gnutls_x509_crt_t * key_cert,xmlSecPtrListPtr certsList)773 xmlSecGnuTLSPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
774 const char *pwd,
775 gnutls_x509_privkey_t * priv_key,
776 gnutls_x509_crt_t * key_cert,
777 xmlSecPtrListPtr certsList)
778 {
779 gnutls_pkcs12_t pkcs12 = NULL;
780 gnutls_pkcs12_bag_t bag = NULL;
781 gnutls_x509_crt_t cert = NULL;
782 gnutls_datum_t datum;
783 xmlSecSize certsSize;
784 int res = -1;
785 int idx;
786 int err;
787 int ret;
788
789 xmlSecAssert2(data != NULL, -1);
790 xmlSecAssert2(dataSize > 0, -1);
791 xmlSecAssert2(priv_key != NULL, -1);
792 xmlSecAssert2((*priv_key) == NULL, -1);
793 xmlSecAssert2(key_cert!= NULL, -1);
794 xmlSecAssert2((*key_cert) == NULL, -1);
795 xmlSecAssert2(certsList != NULL, -1);
796
797 /* read pkcs12 in internal structure */
798 err = gnutls_pkcs12_init(&pkcs12);
799 if(err != GNUTLS_E_SUCCESS) {
800 xmlSecGnuTLSError("gnutls_pkcs12_init", err, NULL);
801 goto done;
802 }
803
804 datum.data = (unsigned char *)data;
805 datum.size = dataSize;
806 err = gnutls_pkcs12_import(pkcs12, &datum, GNUTLS_X509_FMT_DER, 0);
807 if(err != GNUTLS_E_SUCCESS) {
808 xmlSecGnuTLSError("gnutls_pkcs12_import", err, NULL);
809 goto done;
810 }
811
812 /* verify */
813 err = gnutls_pkcs12_verify_mac(pkcs12, pwd);
814 if(err != GNUTLS_E_SUCCESS) {
815 xmlSecGnuTLSError("gnutls_pkcs12_verify_mac", err, NULL);
816 goto done;
817 }
818
819 /* scan the pkcs structure and find the first private key */
820 for(idx = 0; ; ++idx) {
821 int bag_type;
822 int elements_in_bag;
823 int ii;
824
825 err = gnutls_pkcs12_bag_init(&bag);
826 if(err != GNUTLS_E_SUCCESS) {
827 xmlSecGnuTLSError("gnutls_pkcs12_bag_init", err, NULL);
828 goto done;
829 }
830
831 err = gnutls_pkcs12_get_bag(pkcs12, idx, bag);
832 if(err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
833 /* scanned the whole pkcs12, stop */
834 break;
835 } else if(err != GNUTLS_E_SUCCESS) {
836 xmlSecGnuTLSError("gnutls_pkcs12_get_bag", err, NULL);
837 goto done;
838 }
839
840 /* check if we need to decrypt the bag */
841 bag_type = gnutls_pkcs12_bag_get_type(bag, 0);
842 if(bag_type < 0) {
843 xmlSecGnuTLSError("gnutls_pkcs12_bag_get_type", bag_type, NULL);
844 goto done;
845 }
846 if(bag_type == GNUTLS_BAG_ENCRYPTED) {
847 err = gnutls_pkcs12_bag_decrypt(bag, pwd);
848 if(err != GNUTLS_E_SUCCESS) {
849 xmlSecGnuTLSError("gnutls_pkcs12_bag_decrypt", err, NULL);
850 goto done;
851 }
852 }
853
854 /* scan elements in bag */
855 elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
856 if(elements_in_bag < 0) {
857 xmlSecGnuTLSError("gnutls_pkcs12_bag_get_count", elements_in_bag, NULL);
858 goto done;
859 }
860 for(ii = 0; ii < elements_in_bag; ++ii) {
861 bag_type = gnutls_pkcs12_bag_get_type(bag, ii);
862 if(bag_type < 0) {
863 xmlSecGnuTLSError("gnutls_pkcs12_bag_get_type", bag_type, NULL);
864 goto done;
865 }
866
867 err = gnutls_pkcs12_bag_get_data(bag, ii, &datum);
868 if(err != GNUTLS_E_SUCCESS) {
869 xmlSecGnuTLSError("gnutls_pkcs12_bag_get_data", err, NULL);
870 goto done;
871 }
872
873 switch(bag_type) {
874 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
875 case GNUTLS_BAG_PKCS8_KEY:
876 /* we want only the first private key */
877 if((*priv_key) == NULL) {
878 err = gnutls_x509_privkey_init(priv_key);
879 if(err != GNUTLS_E_SUCCESS) {
880 xmlSecGnuTLSError("gnutls_x509_privkey_init", err, NULL);
881 goto done;
882 }
883
884 err = gnutls_x509_privkey_import_pkcs8((*priv_key),
885 &datum, GNUTLS_X509_FMT_DER,
886 pwd,
887 (bag_type == GNUTLS_BAG_PKCS8_KEY) ? GNUTLS_PKCS_PLAIN : 0);
888 if(err != GNUTLS_E_SUCCESS) {
889 xmlSecGnuTLSError("gnutls_x509_privkey_import_pkcs8", err, NULL);
890 goto done;
891 }
892 }
893 break;
894 case GNUTLS_BAG_CERTIFICATE:
895 err = gnutls_x509_crt_init(&cert);
896 if(err != GNUTLS_E_SUCCESS) {
897 xmlSecGnuTLSError("gnutls_x509_crt_init", err, NULL);
898 goto done;
899 }
900
901 err = gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER);
902 if(err != GNUTLS_E_SUCCESS) {
903 xmlSecGnuTLSError("gnutls_x509_crt_import", err, NULL);
904 goto done;
905 }
906
907 ret = xmlSecPtrListAdd(certsList, cert);
908 if(ret < 0) {
909 xmlSecInternalError("xmlSecPtrListAdd(certsList)", NULL);
910 goto done;
911 }
912 cert = NULL; /* owned by certsList now */
913 break;
914 default:
915 /* ignore unknown bag element */
916 break;
917 }
918 }
919
920 /* done with bag */
921 gnutls_pkcs12_bag_deinit(bag);
922 bag = NULL;
923 }
924
925 /* check we have private key */
926 if((*priv_key) == NULL) {
927 xmlSecOtherError(XMLSEC_ERRORS_R_KEY_NOT_FOUND, NULL,
928 "Private key was not found in pkcs12 object");
929 goto done;
930 }
931
932 /* we will search for key cert using the key id */
933 certsSize = xmlSecPtrListGetSize(certsList);
934 if(certsSize > 0) {
935 size_t cert_id_size = 0;
936 size_t key_id_size = 0;
937 xmlSecByte cert_id[100];
938 xmlSecByte key_id[100];
939 xmlSecSize ii;
940
941 key_id_size = sizeof(key_id);
942 err = gnutls_x509_privkey_get_key_id((*priv_key), 0, key_id, &key_id_size);
943 if(err != GNUTLS_E_SUCCESS) {
944 xmlSecGnuTLSError("gnutls_x509_privkey_get_key_id", err, NULL);
945 goto done;
946 }
947 for(ii = 0; ii < certsSize; ++ii) {
948 gnutls_x509_crt_t tmp;
949
950 tmp = xmlSecPtrListGetItem(certsList, ii);
951 if(tmp == NULL) {
952 continue;
953 }
954
955 cert_id_size = sizeof(cert_id);
956 err = gnutls_x509_crt_get_key_id(tmp, 0, cert_id, &cert_id_size);
957 if(err != GNUTLS_E_SUCCESS) {
958 xmlSecGnuTLSError("gnutls_x509_crt_get_key_id", err, NULL);
959 goto done;
960 }
961
962 /* if key ids match, then this is THE key cert!!! */
963 if((key_id_size == cert_id_size) && (memcmp(key_id, cert_id, key_id_size) == 0)) {
964 (*key_cert) = xmlSecGnuTLSX509CertDup(tmp);
965 if((*key_cert) == NULL) {
966 xmlSecInternalError("xmlSecGnuTLSX509CertDup", NULL);
967 goto done;
968 }
969
970 break;
971 }
972 }
973
974 /* check we have key cert */
975 if((*key_cert) == NULL) {
976 xmlSecOtherError(XMLSEC_ERRORS_R_CERT_NOT_FOUND, NULL,
977 "Certificate for the private key was not found in pkcs12 object");
978 goto done;
979 }
980 }
981
982
983 /* success!!! */
984 res = 0;
985
986 done:
987 if(cert != NULL) {
988 gnutls_x509_crt_deinit(cert);
989 }
990 if(bag != NULL) {
991 gnutls_pkcs12_bag_deinit(bag);
992 }
993 if(pkcs12 != NULL) {
994 gnutls_pkcs12_deinit(pkcs12);
995 }
996 return(res);
997 }
998
999 xmlSecKeyDataPtr
xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey(gnutls_x509_privkey_t priv_key)1000 xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey(gnutls_x509_privkey_t priv_key) {
1001 xmlSecKeyDataPtr res = NULL;
1002 int key_alg;
1003 int ret;
1004
1005 xmlSecAssert2(priv_key != NULL, NULL);
1006
1007 /* create key value data */
1008 key_alg = gnutls_x509_privkey_get_pk_algorithm(priv_key);
1009 if(key_alg < 0) {
1010 xmlSecGnuTLSError("gnutls_x509_privkey_get_pk_algorithm", key_alg < 0, NULL);
1011 return (NULL);
1012 }
1013 switch(key_alg) {
1014 #ifndef XMLSEC_NO_RSA
1015 case GNUTLS_PK_RSA:
1016 res = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataRsaId);
1017 if(res == NULL) {
1018 xmlSecInternalError("xmlSecKeyDataCreate(KeyDataRsaId)", NULL);
1019 return(NULL);
1020 }
1021
1022 ret = xmlSecGnuTLSKeyDataRsaAdoptPrivateKey(res, priv_key);
1023 if(ret < 0) {
1024 xmlSecInternalError("xmlSecGnuTLSKeyDataRsaAdoptPrivateKey(KeyDataRsaId)", NULL);
1025 xmlSecKeyDataDestroy(res);
1026 return(NULL);
1027 }
1028 break;
1029 #endif /* XMLSEC_NO_RSA */
1030
1031 #ifndef XMLSEC_NO_DSA
1032 case GNUTLS_PK_DSA:
1033 res = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataDsaId);
1034 if(res == NULL) {
1035 xmlSecInternalError("xmlSecKeyDataCreate(KeyDataDsaId)", NULL);
1036 return(NULL);
1037 }
1038
1039 ret = xmlSecGnuTLSKeyDataDsaAdoptPrivateKey(res, priv_key);
1040 if(ret < 0) {
1041 xmlSecInternalError("xmlSecGnuTLSKeyDataDsaAdoptPrivateKey(KeyDataDsaId)", NULL);
1042 xmlSecKeyDataDestroy(res);
1043 return(NULL);
1044 }
1045 break;
1046 #endif /* XMLSEC_NO_DSA */
1047 default:
1048 xmlSecInvalidIntegerTypeError("key_alg", key_alg, "supported algorithm", NULL);
1049 return(NULL);
1050 }
1051
1052 /* done */
1053 return(res);
1054 }
1055
1056 /*************************************************************************
1057 *
1058 * LDAP DN parser
1059 *
1060 ************************************************************************/
1061 void
xmlSecGnuTLSDnAttrsInitialize(xmlSecGnuTLSDnAttr * attrs,xmlSecSize attrsSize)1062 xmlSecGnuTLSDnAttrsInitialize(xmlSecGnuTLSDnAttr * attrs, xmlSecSize attrsSize) {
1063 xmlSecAssert(attrs != NULL);
1064 xmlSecAssert(attrsSize > 0);
1065
1066 memset(attrs, 0, attrsSize * sizeof(xmlSecGnuTLSDnAttr));
1067 }
1068
1069 void
xmlSecGnuTLSDnAttrsDeinitialize(xmlSecGnuTLSDnAttr * attrs,xmlSecSize attrsSize)1070 xmlSecGnuTLSDnAttrsDeinitialize(xmlSecGnuTLSDnAttr * attrs, xmlSecSize attrsSize) {
1071 xmlSecSize ii;
1072
1073 xmlSecAssert(attrs != NULL);
1074 xmlSecAssert(attrsSize > 0);
1075
1076 for(ii = 0; ii < attrsSize; ++ii) {
1077 if(attrs[ii].key != NULL) {
1078 xmlFree(attrs[ii].key);
1079 }
1080 if(attrs[ii].value != NULL) {
1081 xmlFree(attrs[ii].value);
1082 }
1083 }
1084 memset(attrs, 0, attrsSize * sizeof(xmlSecGnuTLSDnAttr));
1085 }
1086
1087 const xmlSecGnuTLSDnAttr *
xmlSecGnuTLSDnAttrrsFind(const xmlSecGnuTLSDnAttr * attrs,xmlSecSize attrsSize,const xmlChar * key)1088 xmlSecGnuTLSDnAttrrsFind(const xmlSecGnuTLSDnAttr * attrs,
1089 xmlSecSize attrsSize,
1090 const xmlChar * key)
1091 {
1092 xmlSecSize ii;
1093
1094 xmlSecAssert2(attrs != NULL, NULL);
1095 xmlSecAssert2(attrsSize > 0, NULL);
1096 xmlSecAssert2(key != NULL, NULL);
1097
1098 for(ii = 0; ii < attrsSize; ++ii) {
1099 /* simple case */
1100 if(xmlStrcasecmp(key, attrs[ii].key) == 0) {
1101 return(&(attrs[ii]));
1102 }
1103
1104 /* special case for emailAddress (as usual) */
1105 if((xmlStrcasecmp(key, BAD_CAST "emailAddress") == 0) &&
1106 (xmlStrcasecmp(attrs[ii].key, BAD_CAST "email") == 0))
1107 {
1108 return(&(attrs[ii]));
1109 }
1110 if((xmlStrcasecmp(key, BAD_CAST "email") == 0) &&
1111 (xmlStrcasecmp(attrs[ii].key, BAD_CAST "emailAddress") == 0))
1112 {
1113 return(&(attrs[ii]));
1114 }
1115 }
1116
1117 /* not found :( */
1118 return(NULL);
1119 }
1120
1121 int
xmlSecGnuTLSDnAttrsEqual(const xmlSecGnuTLSDnAttr * ll,xmlSecSize llSize,const xmlSecGnuTLSDnAttr * rr,xmlSecSize rrSize)1122 xmlSecGnuTLSDnAttrsEqual(const xmlSecGnuTLSDnAttr * ll, xmlSecSize llSize,
1123 const xmlSecGnuTLSDnAttr * rr, xmlSecSize rrSize)
1124 {
1125 xmlSecSize llNum = 0;
1126 xmlSecSize rrNum = 0;
1127 const xmlSecGnuTLSDnAttr * tmp;
1128 xmlSecSize ii;
1129
1130 xmlSecAssert2(ll != NULL, -1);
1131 xmlSecAssert2(llSize > 0, -1);
1132 xmlSecAssert2(rr != NULL, -1);
1133 xmlSecAssert2(rrSize > 0, -1);
1134
1135 /* compare number of non-nullattributes */
1136 for(ii = 0; ii < llSize; ++ii) {
1137 if(ll[ii].key != NULL) {
1138 ++llNum;
1139 }
1140 }
1141 for(ii = 0; ii < rrSize; ++ii) {
1142 if(rr[ii].key != NULL) {
1143 ++rrNum;
1144 }
1145 }
1146 if(llNum != rrNum) {
1147 return(0);
1148 }
1149
1150 /* make sure that all ll attrs are equal to rr attrs */
1151 for(ii = 0; ii < llSize; ++ii) {
1152 if(ll[ii].key == NULL) {
1153 continue;
1154 }
1155
1156 tmp = xmlSecGnuTLSDnAttrrsFind(rr, rrSize, ll[ii].key);
1157 if(tmp == NULL) {
1158 return(0); /* attribute was not found */
1159 }
1160
1161 if(!xmlStrEqual(ll[ii].value, tmp->value)) {
1162 return(0); /* different values */
1163 }
1164 }
1165
1166 /* good!!! */
1167 return(1);
1168 }
1169
1170 /*
1171 Distinguished name syntax
1172
1173 The formal syntax for a Distinguished Name (DN) is based on RFC 2253.
1174 The Backus Naur Form (BNF) syntax is defined as follows:
1175
1176 <name> ::= <name-component> ( <spaced-separator> )
1177 | <name-component> <spaced-separator> <name>
1178
1179 <spaced-separator> ::= <optional-space>
1180 <separator>
1181 <optional-space>
1182
1183 <separator> ::= "," | ";"
1184
1185 <optional-space> ::= ( <CR> ) *( " " )
1186
1187 <name-component> ::= <attribute>
1188 | <attribute> <optional-space> "+"
1189 <optional-space> <name-component>
1190
1191 <attribute> ::= <string>
1192 | <key> <optional-space> "=" <optional-space> <string>
1193
1194 <key> ::= 1*( <keychar> ) | "OID." <oid> | "oid." <oid>
1195 <keychar> ::= letters, numbers, and space
1196
1197 <oid> ::= <digitstring> | <digitstring> "." <oid>
1198 <digitstring> ::= 1*<digit>
1199 <digit> ::= digits 0-9
1200
1201 <string> ::= *( <stringchar> | <pair> )
1202 | '"' *( <stringchar> | <special> | <pair> ) '"'
1203 | "#" <hex>
1204
1205
1206 <special> ::= "," | "=" | <CR> | "+" | "<" | ">"
1207 | "#" | ";"
1208
1209 <pair> ::= "\" ( <special> | "\" | '"')
1210 <stringchar> ::= any character except <special> or "\" or '"'
1211
1212
1213 <hex> ::= 2*<hexchar>
1214 <hexchar> ::= 0-9, a-f, A-F
1215
1216 A semicolon (;) character can be used to separate RDNs in a distinguished name,
1217 although the comma (,) character is the typical notation.
1218
1219 White-space characters (spaces) might be present on either side of the comma or
1220 semicolon. The white-space characters are ignored, and the semicolon is replaced
1221 with a comma.
1222
1223 In addition, space (' ' ASCII 32) characters may be present either before or
1224 after a '+' or '='. These space characters are ignored when parsing.
1225 */
1226 enum xmlSecGnuTLSDnParseState {
1227 xmlSecGnuTLSDnParseState_BeforeNameComponent = 0,
1228 xmlSecGnuTLSDnParseState_Key,
1229 xmlSecGnuTLSDnParseState_BeforeString,
1230 xmlSecGnuTLSDnParseState_String,
1231 xmlSecGnuTLSDnParseState_QuotedString,
1232 xmlSecGnuTLSDnParseState_AfterQuotedString
1233 };
1234
1235 #define XMLSEC_GNUTLS_IS_SPACE(ch) \
1236 (((ch) == ' ') || ((ch) == '\n') || ((ch) == '\r'))
1237
1238 int
xmlSecGnuTLSDnAttrsParse(const xmlChar * dn,xmlSecGnuTLSDnAttr * attrs,xmlSecSize attrsSize)1239 xmlSecGnuTLSDnAttrsParse(const xmlChar * dn,
1240 xmlSecGnuTLSDnAttr * attrs, xmlSecSize attrsSize)
1241 {
1242 xmlChar * tmp = NULL;
1243 xmlChar * p;
1244 xmlChar ch;
1245 enum xmlSecGnuTLSDnParseState state;
1246 int slash;
1247 xmlSecSize pos;
1248 int res = -1;
1249
1250 xmlSecAssert2(dn != NULL, -1);
1251 xmlSecAssert2(attrs != NULL, -1);
1252 xmlSecAssert2(attrsSize > 0, -1);
1253
1254 /* allocate buffer, we don't need more than string */
1255 tmp = (xmlChar *)xmlMalloc(xmlStrlen(dn) + 1);
1256 if(tmp == NULL) {
1257 xmlSecMallocError(xmlStrlen(dn) + 1, NULL);
1258 goto done;
1259 }
1260
1261 /* state machine */
1262 state = xmlSecGnuTLSDnParseState_BeforeNameComponent;
1263 slash = 0;
1264 pos = 0;
1265 p = tmp;
1266 for(ch = (*dn); ; ch = *(++dn)) {
1267 switch(state) {
1268 case xmlSecGnuTLSDnParseState_BeforeNameComponent:
1269 if(!XMLSEC_GNUTLS_IS_SPACE(ch)) {
1270 *(p++) = ch; /* we are sure we have enough buffer */
1271 state = xmlSecGnuTLSDnParseState_Key;
1272 } else {
1273 /* just skip space */
1274 }
1275 break;
1276 case xmlSecGnuTLSDnParseState_Key:
1277 /* we don't support
1278 1) <attribute><optional-space>"+"<optional-space><name-component>
1279 2) <attribute> ::= <string>
1280 */
1281 if(ch != '=') {
1282 *(p++) = ch; /* we are sure we have enough buffer */
1283 } else {
1284 *(p) = '\0';
1285 /* remove spaces back */
1286 while((p > tmp) && (XMLSEC_GNUTLS_IS_SPACE(*(p - 1)))) {
1287 *(--p) = '\0';
1288 }
1289
1290 /* insert into the attrs */
1291 if(pos >= attrsSize) {
1292 xmlSecInvalidSizeLessThanError("Attributes",
1293 attrsSize, pos, NULL);
1294 goto done;
1295 }
1296 attrs[pos].key = xmlStrdup(tmp);
1297 if(attrs[pos].key == NULL) {
1298 xmlSecStrdupError(tmp, NULL);
1299 goto done;
1300 }
1301
1302 state = xmlSecGnuTLSDnParseState_BeforeString;
1303 p = tmp;
1304 }
1305 break;
1306 case xmlSecGnuTLSDnParseState_BeforeString:
1307 if(!XMLSEC_GNUTLS_IS_SPACE(ch)) {
1308 if(ch != '\"') {
1309 state = xmlSecGnuTLSDnParseState_String;
1310 slash = 0;
1311 --dn; /* small hack, so we can look at the same char
1312 again with the correct state */
1313 } else {
1314 state = xmlSecGnuTLSDnParseState_QuotedString;
1315 slash = 0;
1316 }
1317 } else {
1318 /* just skip space */
1319 }
1320 break;
1321 case xmlSecGnuTLSDnParseState_String:
1322 if(slash == 1) {
1323 *(p++) = ch; /* we are sure we have enough buffer */
1324 slash = 0;
1325 } else if(ch == '\\') {
1326 slash = 1;
1327 } else if((ch == ',') || (ch == ';') || (ch == '\0')) {
1328 *(p) = '\0';
1329 /* remove spaces back */
1330 while((p > tmp) && (XMLSEC_GNUTLS_IS_SPACE(*(p - 1)))) {
1331 *(--p) = '\0';
1332 }
1333
1334 attrs[pos].value = xmlStrdup(tmp);
1335 if(attrs[pos].value == NULL) {
1336 xmlSecStrdupError(tmp, NULL);
1337 goto done;
1338 }
1339 state = xmlSecGnuTLSDnParseState_BeforeNameComponent;
1340 ++pos;
1341 p = tmp;
1342 } else {
1343 *(p++) = ch; /* we are sure we have enough buffer */
1344 }
1345 break;
1346 case xmlSecGnuTLSDnParseState_QuotedString:
1347 if(slash == 1) {
1348 *(p++) = ch; /* we are sure we have enough buffer */
1349 slash = 0;
1350 } else if(ch == '\\') {
1351 slash = 1;
1352 } else if(ch == '\"') {
1353 *(p) = '\0';
1354 /* don't remove spaces for quoted string */
1355
1356 attrs[pos].value = xmlStrdup(tmp);
1357 if(attrs[pos].value == NULL) {
1358 xmlSecStrdupError(tmp, NULL);
1359 goto done;
1360 }
1361 state = xmlSecGnuTLSDnParseState_AfterQuotedString;
1362 ++pos;
1363 p = tmp;
1364 } else {
1365 *(p++) = ch; /* we are sure we have enough buffer */
1366 }
1367 break;
1368 case xmlSecGnuTLSDnParseState_AfterQuotedString:
1369 if(!XMLSEC_GNUTLS_IS_SPACE(ch)) {
1370 if((ch == ',') || (ch == ';') || (ch == '\0')) {
1371 state = xmlSecGnuTLSDnParseState_BeforeNameComponent;
1372 } else {
1373 xmlSecInvalidIntegerDataError("ch", ch, "space,',',';','\\0'", NULL);
1374 goto done;
1375 }
1376 } else {
1377 /* just skip space */
1378 }
1379 break;
1380 }
1381
1382 if(ch == '\0') {
1383 /* done */
1384 break;
1385 }
1386 }
1387
1388 /* check end state */
1389 if(state != xmlSecGnuTLSDnParseState_BeforeNameComponent) {
1390 xmlSecInvalidIntegerDataError("state", state, "xmlSecGnuTLSDnParseState_BeforeNameComponent", NULL);
1391 goto done;
1392 }
1393
1394 /* debug
1395 {
1396 xmlSecSize ii;
1397 for(ii = 0; ii < attrsSize; ++ii) {
1398 if(attrs[ii].key != NULL) {
1399 printf("DEBUG: attrs - %s=>%s\n", attrs[ii].key, attrs[ii].value);
1400 }
1401 }
1402 }
1403 */
1404
1405 /* done */
1406 res = 0;
1407
1408 done:
1409 if(tmp != NULL) {
1410 xmlFree(tmp);
1411 }
1412 return(res);
1413 }
1414
1415
1416 #endif /* XMLSEC_NO_X509 */
1417
1418
1419
1420