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