streamlined file loading labels
[strongswan.git] / src / pluto / ac.c
1 /* Support of X.509 attribute certificates
2 * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
3 * Copyright (C) 2003 Martin Berner, Lukas Suter
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <dirent.h>
21 #include <time.h>
22 #include <sys/types.h>
23
24 #include <freeswan.h>
25
26 #include <utils.h>
27 #include <asn1/asn1.h>
28 #include <asn1/asn1_parser.h>
29 #include <asn1/oid.h>
30 #include <credentials/certificates/certificate.h>
31
32 #include "ac.h"
33 #include "x509.h"
34 #include "crl.h"
35 #include "ca.h"
36 #include "certs.h"
37 #include "log.h"
38 #include "whack.h"
39 #include "fetch.h"
40 #include "builder.h"
41
42 /**
43 * Chained list of X.509 attribute certificates
44 */
45 static x509acert_t *x509acerts = NULL;
46
47 /**
48 * Chained list of ietfAttributes
49 */
50 static ietfAttrList_t *ietfAttributes = NULL;
51
52 /**
53 * ASN.1 definition of ietfAttrSyntax
54 */
55 static const asn1Object_t ietfAttrSyntaxObjects[] =
56 {
57 { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
58 { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
59 ASN1_BODY }, /* 1 */
60 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
61 { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */
62 { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT |
63 ASN1_BODY }, /* 4 */
64 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
65 { 2, "oid", ASN1_OID, ASN1_OPT |
66 ASN1_BODY }, /* 6 */
67 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
68 { 2, "string", ASN1_UTF8STRING, ASN1_OPT |
69 ASN1_BODY }, /* 8 */
70 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
71 { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
72 { 0, "exit", ASN1_EOC, ASN1_EXIT }
73 };
74
75 #define IETF_ATTR_OCTETS 4
76 #define IETF_ATTR_OID 6
77 #define IETF_ATTR_STRING 8
78
79 /**
80 * ASN.1 definition of roleSyntax
81 */
82 static const asn1Object_t roleSyntaxObjects[] =
83 {
84 { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
85 { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
86 ASN1_OBJ }, /* 1 */
87 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
88 { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ }, /* 3 */
89 { 0, "exit", ASN1_EOC, ASN1_EXIT }
90 };
91
92 /**
93 * ASN.1 definition of an X509 attribute certificate
94 */
95 static const asn1Object_t acObjects[] =
96 {
97 { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
98 { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
99 { 2, "version", ASN1_INTEGER, ASN1_DEF |
100 ASN1_BODY }, /* 2 */
101 { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
102 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
103 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
104 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
105 { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
106 ASN1_BODY }, /* 7 */
107 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
108 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
109 { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
110 ASN1_OBJ }, /* 10 */
111 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
112 { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
113 { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */
114 { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
115 ASN1_BODY }, /* 14 */
116 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
117 { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
118 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
119 { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
120 { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
121 ASN1_OBJ }, /* 19 */
122 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
123 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
124 { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
125 { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
126 { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
127 { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
128 ASN1_BODY }, /* 25 */
129 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
130 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
131 { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
132 { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
133 { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
134 { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
135 ASN1_BODY }, /* 31 */
136 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
137 { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
138 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
139 { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
140 { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
141 { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
142 { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
143 { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
144 { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
145 { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
146 { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
147 { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
148 { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
149 { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
150 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
151 { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
152 { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
153 { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */
154 { 4, "critical", ASN1_BOOLEAN, ASN1_DEF |
155 ASN1_BODY }, /* 50 */
156 { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */
157 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */
158 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */
159 { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 54 */
160 { 0, "exit", ASN1_EOC, ASN1_EXIT }
161 };
162
163 #define AC_OBJ_CERTIFICATE 0
164 #define AC_OBJ_CERTIFICATE_INFO 1
165 #define AC_OBJ_VERSION 2
166 #define AC_OBJ_HOLDER_ISSUER 5
167 #define AC_OBJ_HOLDER_SERIAL 6
168 #define AC_OBJ_ENTITY_NAME 10
169 #define AC_OBJ_ISSUER_NAME 19
170 #define AC_OBJ_ISSUER 23
171 #define AC_OBJ_SIG_ALG 35
172 #define AC_OBJ_SERIAL_NUMBER 36
173 #define AC_OBJ_NOT_BEFORE 38
174 #define AC_OBJ_NOT_AFTER 39
175 #define AC_OBJ_ATTRIBUTE_TYPE 42
176 #define AC_OBJ_ATTRIBUTE_VALUE 44
177 #define AC_OBJ_EXTN_ID 49
178 #define AC_OBJ_CRITICAL 50
179 #define AC_OBJ_EXTN_VALUE 51
180 #define AC_OBJ_ALGORITHM 53
181 #define AC_OBJ_SIGNATURE 54
182
183 const x509acert_t empty_ac = {
184 NULL , /* *next */
185 0 , /* installed */
186 { NULL, 0 }, /* certificate */
187 { NULL, 0 }, /* certificateInfo */
188 1 , /* version */
189 /* holder */
190 /* baseCertificateID */
191 { NULL, 0 }, /* holderIssuer */
192 { NULL, 0 }, /* holderSerial */
193 /* entityName */
194 { NULL, 0 }, /* generalNames */
195 /* v2Form */
196 { NULL, 0 }, /* issuerName */
197 /* signature */
198 OID_UNKNOWN, /* sigAlg */
199 { NULL, 0 }, /* serialNumber */
200 /* attrCertValidityPeriod */
201 0 , /* notBefore */
202 0 , /* notAfter */
203 /* attributes */
204 NULL , /* charging */
205 NULL , /* groups */
206 /* extensions */
207 { NULL, 0 }, /* authKeyID */
208 { NULL, 0 }, /* authKeySerialNumber */
209 FALSE , /* noRevAvail */
210 /* signatureAlgorithm */
211 OID_UNKNOWN, /* algorithm */
212 { NULL, 0 }, /* signature */
213 };
214
215
216 /**
217 * compare two ietfAttributes, returns zero if a equals b
218 * negative/positive if a is earlier/later in the alphabet than b
219 */
220 static int cmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b)
221 {
222 int cmp_len, len, cmp_value;
223
224 /* cannot compare OID with STRING or OCTETS attributes */
225 if (a->kind == IETF_ATTRIBUTE_OID && b->kind != IETF_ATTRIBUTE_OID)
226 return 1;
227
228 cmp_len = a->value.len - b->value.len;
229 len = (cmp_len < 0)? a->value.len : b->value.len;
230 cmp_value = memcmp(a->value.ptr, b->value.ptr, len);
231
232 return (cmp_value == 0)? cmp_len : cmp_value;
233 }
234
235 /**
236 * add an ietfAttribute to the chained list
237 */
238 static ietfAttr_t* add_ietfAttr(ietfAttr_t *attr)
239 {
240 ietfAttrList_t **listp = &ietfAttributes;
241 ietfAttrList_t *list = *listp;
242 int cmp = -1;
243
244 while (list != NULL)
245 {
246 cmp = cmp_ietfAttr(attr, list->attr);
247 if (cmp <= 0)
248 break;
249 listp = &list->next;
250 list = *listp;
251 }
252
253 if (cmp == 0)
254 {
255 /* attribute already exists, increase count */
256 free(attr);
257 list->attr->count++;
258 return list->attr;
259 }
260 else
261 {
262 ietfAttrList_t *el = malloc_thing(ietfAttrList_t);
263
264 /* new attribute, unshare value */
265 attr->value = chunk_clone(attr->value);
266 attr->count = 1;
267 time(&attr->installed);
268
269 el->attr = attr;
270 el->next = list;
271 *listp = el;
272
273 return attr;
274 }
275 }
276
277 /**
278 * decodes a comma separated list of group attributes
279 */
280 void decode_groups(char *groups, ietfAttrList_t **listp)
281 {
282 if (groups == NULL)
283 return;
284
285 while (strlen(groups) > 0)
286 {
287 char *end;
288 char *next = strchr(groups, ',');
289
290 if (next == NULL)
291 end = next = groups + strlen(groups);
292 else
293 end = next++;
294
295 /* eat preceeding whitespace */
296 while (groups < end && *groups == ' ')
297 groups++;
298
299 /* eat trailing whitespace */
300 while (end > groups && *(end-1) == ' ')
301 end--;
302
303 if (groups < end)
304 {
305 ietfAttr_t *attr = malloc_thing(ietfAttr_t);
306 ietfAttrList_t *el = malloc_thing(ietfAttrList_t);
307
308 attr->kind = IETF_ATTRIBUTE_STRING;
309 attr->value.ptr = groups;
310 attr->value.len = end - groups;
311 attr->count = 0;
312
313 el->attr = add_ietfAttr(attr);
314 el->next = *listp;
315 *listp = el;
316 }
317
318 groups = next;
319 }
320 }
321
322 static bool same_attribute(const ietfAttr_t *a, const ietfAttr_t *b)
323 {
324 return (a->kind == b->kind && a->value.len == b->value.len
325 && memeq(a->value.ptr, b->value.ptr, b->value.len));
326 }
327
328 bool group_membership(const ietfAttrList_t *peer_list
329 , const char *conn
330 , const ietfAttrList_t *conn_list)
331 {
332 if (conn_list == NULL)
333 return TRUE;
334
335 while (peer_list != NULL)
336 {
337 const ietfAttr_t *peer_attr = peer_list->attr;
338 const ietfAttrList_t *list = conn_list;
339
340 while (list != NULL)
341 {
342 ietfAttr_t *conn_attr = list->attr;
343
344 if (same_attribute(conn_attr, peer_attr))
345 {
346 DBG(DBG_CONTROL,
347 DBG_log("%s: peer matches group '%.*s'"
348 , conn
349 , (int)peer_attr->value.len, peer_attr->value.ptr)
350 )
351 return TRUE;
352 }
353 list = list->next;
354 }
355 peer_list = peer_list->next;
356 }
357 DBG(DBG_CONTROL,
358 DBG_log("%s: peer doesn't match any group", conn)
359 )
360 return FALSE;
361 }
362
363 void unshare_ietfAttrList(ietfAttrList_t **listp)
364 {
365 ietfAttrList_t *list = *listp;
366
367 while (list != NULL)
368 {
369 ietfAttrList_t *el = malloc_thing(ietfAttrList_t);
370
371 el->attr = list->attr;
372 el->attr->count++;
373 el->next = NULL;
374 *listp = el;
375 listp = &el->next;
376 list = list->next;
377 }
378 }
379
380 /**
381 * Parses ietfAttrSyntax
382 */
383 static ietfAttrList_t* parse_ietfAttrSyntax(chunk_t blob, int level0)
384 {
385 asn1_parser_t *parser;
386 chunk_t object;
387 int objectID;
388
389 ietfAttrList_t *list = NULL;
390
391 parser = asn1_parser_create(ietfAttrSyntaxObjects, blob);
392 parser->set_top_level(parser, level0);
393
394 while (parser->iterate(parser, &objectID, &object))
395 {
396 switch (objectID)
397 {
398 case IETF_ATTR_OCTETS:
399 case IETF_ATTR_OID:
400 case IETF_ATTR_STRING:
401 {
402 ietfAttr_t *attr = malloc_thing(ietfAttr_t);
403 ietfAttrList_t *el = malloc_thing(ietfAttrList_t);
404
405 attr->kind = (objectID - IETF_ATTR_OCTETS) / 2;
406 attr->value = object;
407 attr->count = 0;
408
409 el->attr = add_ietfAttr(attr);
410 el->next = list;
411 list = el;
412 }
413 break;
414 default:
415 break;
416 }
417 }
418 parser->destroy(parser);
419 return list;
420 }
421
422 /**
423 * Parses roleSyntax
424 */
425 static void parse_roleSyntax(chunk_t blob, int level0)
426 {
427 asn1_parser_t *parser;
428 chunk_t object;
429 int objectID;
430
431 parser = asn1_parser_create(roleSyntaxObjects, blob);
432 parser->set_top_level(parser, level0);
433
434 while (parser->iterate(parser, &objectID, &object))
435 {
436 switch (objectID)
437 {
438 default:
439 break;
440 }
441 }
442 parser->destroy(parser);
443 }
444
445 /**
446 * Parses an X.509 attribute certificate
447 */
448 bool parse_ac(chunk_t blob, x509acert_t *ac)
449 {
450 asn1_parser_t *parser;
451 chunk_t object;
452 int objectID;
453 int type = OID_UNKNOWN;
454 int extn_oid = OID_UNKNOWN;
455 bool success = FALSE;
456 bool critical;
457
458 parser = asn1_parser_create(acObjects, blob);
459
460 while (parser->iterate(parser, &objectID, &object))
461 {
462 u_int level = parser->get_level(parser)+1;
463
464 switch (objectID)
465 {
466 case AC_OBJ_CERTIFICATE:
467 ac->certificate = object;
468 break;
469 case AC_OBJ_CERTIFICATE_INFO:
470 ac->certificateInfo = object;
471 break;
472 case AC_OBJ_VERSION:
473 ac->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
474 DBG(DBG_PARSING,
475 DBG_log(" v%d", ac->version);
476 )
477 if (ac->version != 2)
478 {
479 plog("v%d attribute certificates are not supported"
480 , ac->version);
481 goto end;
482 }
483 break;
484 case AC_OBJ_HOLDER_ISSUER:
485 ac->holderIssuer = get_directoryName(object, level, FALSE);
486 break;
487 case AC_OBJ_HOLDER_SERIAL:
488 ac->holderSerial = object;
489 break;
490 case AC_OBJ_ENTITY_NAME:
491 ac->entityName = get_directoryName(object, level, TRUE);
492 break;
493 case AC_OBJ_ISSUER_NAME:
494 ac->issuerName = get_directoryName(object, level, FALSE);
495 break;
496 case AC_OBJ_SIG_ALG:
497 ac->sigAlg = asn1_parse_algorithmIdentifier(object, level, NULL);
498 break;
499 case AC_OBJ_SERIAL_NUMBER:
500 ac->serialNumber = object;
501 break;
502 case AC_OBJ_NOT_BEFORE:
503 ac->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
504 break;
505 case AC_OBJ_NOT_AFTER:
506 ac->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
507 break;
508 case AC_OBJ_ATTRIBUTE_TYPE:
509 type = asn1_known_oid(object);
510 break;
511 case AC_OBJ_ATTRIBUTE_VALUE:
512 {
513 switch (type) {
514 case OID_AUTHENTICATION_INFO:
515 DBG(DBG_PARSING,
516 DBG_log(" need to parse authenticationInfo")
517 )
518 break;
519 case OID_ACCESS_IDENTITY:
520 DBG(DBG_PARSING,
521 DBG_log(" need to parse accessIdentity")
522 )
523 break;
524 case OID_CHARGING_IDENTITY:
525 ac->charging = parse_ietfAttrSyntax(object, level);
526 break;
527 case OID_GROUP:
528 ac->groups = parse_ietfAttrSyntax(object, level);
529 break;
530 case OID_ROLE:
531 parse_roleSyntax(object, level);
532 break;
533 default:
534 break;
535 }
536 }
537 break;
538 case AC_OBJ_EXTN_ID:
539 extn_oid = asn1_known_oid(object);
540 break;
541 case AC_OBJ_CRITICAL:
542 critical = object.len && *object.ptr;
543 DBG(DBG_PARSING,
544 DBG_log(" %s",(critical)?"TRUE":"FALSE");
545 )
546 break;
547 case AC_OBJ_EXTN_VALUE:
548 {
549 switch (extn_oid) {
550 case OID_CRL_DISTRIBUTION_POINTS:
551 DBG(DBG_PARSING,
552 DBG_log(" need to parse crlDistributionPoints")
553 )
554 break;
555 case OID_AUTHORITY_KEY_ID:
556 parse_authorityKeyIdentifier(object, level
557 , &ac->authKeyID, &ac->authKeySerialNumber);
558 break;
559 case OID_TARGET_INFORMATION:
560 DBG(DBG_PARSING,
561 DBG_log(" need to parse targetInformation")
562 )
563 break;
564 case OID_NO_REV_AVAIL:
565 ac->noRevAvail = TRUE;
566 break;
567 default:
568 break;
569 }
570 }
571 break;
572 case AC_OBJ_ALGORITHM:
573 ac->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
574 break;
575 case AC_OBJ_SIGNATURE:
576 ac->signature = object;
577 break;
578
579 default:
580 break;
581 }
582 }
583 success = parser->success(parser);
584 time(&ac->installed);
585
586 end:
587 parser->destroy(parser);
588 return success;
589 }
590
591 /**
592 * Release an ietfAttribute, free it if count reaches zero
593 */
594 static void release_ietfAttr(ietfAttr_t* attr)
595 {
596 if (--attr->count == 0)
597 {
598 ietfAttrList_t **plist = &ietfAttributes;
599 ietfAttrList_t *list = *plist;
600
601 while (list->attr != attr)
602 {
603 plist = &list->next;
604 list = *plist;
605 }
606 *plist = list->next;
607
608 free(attr->value.ptr);
609 free(attr);
610 free(list);
611 }
612 }
613
614 /**
615 * Free an ietfAttrList
616 */
617 void free_ietfAttrList(ietfAttrList_t* list)
618 {
619 while (list != NULL)
620 {
621 ietfAttrList_t *el = list;
622
623 release_ietfAttr(el->attr);
624 list = list->next;
625 free(el);
626 }
627 }
628
629 /**
630 * Free a X.509 attribute certificate
631 */
632 void free_acert(x509acert_t *ac)
633 {
634 if (ac != NULL)
635 {
636 free_ietfAttrList(ac->charging);
637 free_ietfAttrList(ac->groups);
638 free(ac->certificate.ptr);
639 free(ac);
640 }
641 }
642
643 /**
644 * Free first X.509 attribute certificate in the chained list
645 */
646 static void free_first_acert(void)
647 {
648 x509acert_t *first = x509acerts;
649 x509acerts = first->next;
650 free_acert(first);
651 }
652
653 /**
654 * Free all attribute certificates in the chained list
655 */
656 void free_acerts(void)
657 {
658 while (x509acerts != NULL)
659 free_first_acert();
660 }
661
662 /**
663 * Get a X.509 attribute certificate for a given holder
664 */
665 x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial)
666 {
667 x509acert_t *ac = x509acerts;
668 x509acert_t *prev_ac = NULL;
669
670 while (ac != NULL)
671 {
672 if (same_dn(issuer, ac->holderIssuer)
673 && same_serial(serial, ac->holderSerial))
674 {
675 if (ac!= x509acerts)
676 {
677 /* bring the certificate up front */
678 prev_ac->next = ac->next;
679 ac->next = x509acerts;
680 x509acerts = ac;
681 }
682 return ac;
683 }
684 prev_ac = ac;
685 ac = ac->next;
686 }
687 return NULL;
688 }
689
690 /**
691 * Add a X.509 attribute certificate to the chained list
692 */
693 static void add_acert(x509acert_t *ac)
694 {
695 x509acert_t *old_ac = get_x509acert(ac->holderIssuer, ac->holderSerial);
696
697 if (old_ac != NULL)
698 {
699 if (ac->notBefore >old_ac->notBefore)
700 {
701 /* delete the old attribute cert */
702 free_first_acert();
703 DBG(DBG_CONTROL,
704 DBG_log("attribute cert is newer - existing cert deleted")
705 )
706 }
707 else
708 {
709 DBG(DBG_CONTROL,
710 DBG_log("attribute cert is not newer - existing cert kept");
711 )
712 free_acert(ac);
713 return;
714 }
715 }
716 plog("attribute cert added");
717
718 /* insert new attribute cert at the root of the chain */
719 ac->next = x509acerts;
720 x509acerts = ac;
721 }
722
723 /**
724 * Verify the validity of an attribute certificate by
725 * checking the notBefore and notAfter dates
726 */
727 static err_t check_ac_validity(const x509acert_t *ac)
728 {
729 time_t current_time;
730
731 time(&current_time);
732 DBG(DBG_CONTROL | DBG_PARSING,
733 DBG_log(" not before : %T", &ac->notBefore, TRUE);
734 DBG_log(" current time: %T", &current_time, TRUE);
735 DBG_log(" not after : %T", &ac->notAfter, TRUE);
736 )
737
738 if (current_time < ac->notBefore)
739 return "attribute certificate is not valid yet";
740 if (current_time > ac->notAfter)
741 return "attribute certificate has expired";
742 else
743 return NULL;
744 }
745
746 /**
747 * verifies a X.509 attribute certificate
748 */
749 bool verify_x509acert(x509acert_t *ac, bool strict)
750 {
751 u_char buf[BUF_LEN];
752 x509cert_t *aacert;
753 err_t ugh = NULL;
754 time_t valid_until = ac->notAfter;
755
756 DBG(DBG_CONTROL,
757 dntoa(buf, BUF_LEN, ac->entityName);
758 DBG_log("holder: '%s'",buf);
759 dntoa(buf, BUF_LEN, ac->issuerName);
760 DBG_log("issuer: '%s'",buf);
761 )
762
763 ugh = check_ac_validity(ac);
764
765 if (ugh != NULL)
766 {
767 plog("%s", ugh);
768 return FALSE;
769 }
770 DBG(DBG_CONTROL,
771 DBG_log("attribute certificate is valid")
772 )
773
774 lock_authcert_list("verify_x509acert");
775 aacert = get_authcert(ac->issuerName, ac->authKeySerialNumber
776 , ac->authKeyID, AUTH_AA);
777 unlock_authcert_list("verify_x509acert");
778
779 if (aacert == NULL)
780 {
781 plog("issuer aacert not found");
782 return FALSE;
783 }
784 DBG(DBG_CONTROL,
785 DBG_log("issuer aacert found")
786 )
787
788 if (!x509_check_signature(ac->certificateInfo, ac->signature, ac->algorithm,
789 aacert))
790 {
791 plog("attribute certificate signature is invalid");
792 return FALSE;
793 }
794 DBG(DBG_CONTROL,
795 DBG_log("attribute certificate signature is valid");
796 )
797
798 return verify_x509cert(aacert, strict, &valid_until);
799 }
800
801 /**
802 * Loads X.509 attribute certificates
803 */
804 void load_acerts(void)
805 {
806 u_char buf[BUF_LEN];
807
808 /* change directory to specified path */
809 u_char *save_dir = getcwd(buf, BUF_LEN);
810
811 if (!chdir(A_CERT_PATH))
812 {
813 struct dirent **filelist;
814 int n;
815
816 plog("Changing to directory '%s'",A_CERT_PATH);
817 n = scandir(A_CERT_PATH, &filelist, file_select, alphasort);
818
819 if (n > 0)
820 {
821 while (n--)
822 {
823 char *filename = filelist[n]->d_name;
824 x509acert_t *ac;
825
826 ac = lib->creds->create(lib->creds, CRED_CERTIFICATE,
827 CERT_PLUTO_AC, BUILD_FROM_FILE, filename,
828 BUILD_END);
829 if (ac)
830 {
831 plog(" loaded attribute certificate from '%s'", filename);
832 add_acert(ac);
833 }
834 free(filelist[n]);
835 }
836 free(filelist);
837 }
838 }
839 /* restore directory path */
840 ignore_result(chdir(save_dir));
841 }
842
843 /**
844 * lists group attributes separated by commas on a single line
845 */
846 void format_groups(const ietfAttrList_t *list, char *buf, int len)
847 {
848 bool first_group = TRUE;
849
850 while (list != NULL && len > 0)
851 {
852 ietfAttr_t *attr = list->attr;
853
854 if (attr->kind == IETF_ATTRIBUTE_OCTETS
855 || attr->kind == IETF_ATTRIBUTE_STRING)
856 {
857 int written = snprintf(buf, len, "%s%.*s"
858 , (first_group)? "" : ", "
859 , (int)attr->value.len, attr->value.ptr);
860
861 first_group = FALSE;
862
863 /* return value of snprintf() up to glibc 2.0.6 */
864 if (written < 0)
865 break;
866
867 buf += written;
868 len -= written;
869 }
870 list = list->next;
871 }
872 }
873
874 /**
875 * list all X.509 attribute certificates in the chained list
876 */
877 void list_acerts(bool utc)
878 {
879 x509acert_t *ac = x509acerts;
880 time_t now;
881
882 /* determine the current time */
883 time(&now);
884
885 if (ac != NULL)
886 {
887 whack_log(RC_COMMENT, " ");
888 whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:");
889 whack_log(RC_COMMENT, " ");
890 }
891
892 while (ac != NULL)
893 {
894 u_char buf[BUF_LEN];
895
896 whack_log(RC_COMMENT, "%T", &ac->installed, utc);
897 if (ac->entityName.ptr != NULL)
898 {
899 dntoa(buf, BUF_LEN, ac->entityName);
900 whack_log(RC_COMMENT, " holder: '%s'", buf);
901 }
902 if (ac->holderIssuer.ptr != NULL)
903 {
904 dntoa(buf, BUF_LEN, ac->holderIssuer);
905 whack_log(RC_COMMENT, " hissuer: '%s'", buf);
906 }
907 if (ac->holderSerial.ptr != NULL)
908 {
909 datatot(ac->holderSerial.ptr, ac->holderSerial.len, ':'
910 , buf, BUF_LEN);
911 whack_log(RC_COMMENT, " hserial: %s", buf);
912 }
913 if (ac->groups != NULL)
914 {
915 format_groups(ac->groups, buf, BUF_LEN);
916 whack_log(RC_COMMENT, " groups: %s", buf);
917 }
918 dntoa(buf, BUF_LEN, ac->issuerName);
919 whack_log(RC_COMMENT, " issuer: '%s'", buf);
920 datatot(ac->serialNumber.ptr, ac->serialNumber.len, ':'
921 , buf, BUF_LEN);
922 whack_log(RC_COMMENT, " serial: %s", buf);
923 whack_log(RC_COMMENT, " validity: not before %T %s",
924 &ac->notBefore, utc,
925 (ac->notBefore < now)?"ok":"fatal (not valid yet)");
926 whack_log(RC_COMMENT, " not after %T %s",
927 &ac->notAfter, utc,
928 check_expiry(ac->notAfter, ACERT_WARNING_INTERVAL, TRUE));
929 if (ac->authKeyID.ptr != NULL)
930 {
931 datatot(ac->authKeyID.ptr, ac->authKeyID.len, ':'
932 , buf, BUF_LEN);
933 whack_log(RC_COMMENT, " authkey: %s", buf);
934 }
935 if (ac->authKeySerialNumber.ptr != NULL)
936 {
937 datatot(ac->authKeySerialNumber.ptr, ac->authKeySerialNumber.len, ':'
938 , buf, BUF_LEN);
939 whack_log(RC_COMMENT, " aserial: %s", buf);
940 }
941
942 ac = ac->next;
943 }
944 }
945
946 /**
947 * list all group attributes in alphabetical order
948 */
949 void list_groups(bool utc)
950 {
951 ietfAttrList_t *list = ietfAttributes;
952
953 if (list != NULL)
954 {
955 whack_log(RC_COMMENT, " ");
956 whack_log(RC_COMMENT, "List of Group Attributes:");
957 whack_log(RC_COMMENT, " ");
958 }
959
960 while (list != NULL)
961 {
962 ietfAttr_t *attr = list->attr;
963
964 whack_log(RC_COMMENT, "%T, count: %d", &attr->installed, utc, attr->count);
965
966 switch (attr->kind)
967 {
968 case IETF_ATTRIBUTE_OCTETS:
969 case IETF_ATTRIBUTE_STRING:
970 whack_log(RC_COMMENT, " %.*s", (int)attr->value.len, attr->value.ptr);
971 break;
972 case IETF_ATTRIBUTE_OID:
973 whack_log(RC_COMMENT, " OID");
974 break;
975 default:
976 break;
977 }
978
979 list = list->next;
980 }
981 }