fixed all pluto compiler warnings
[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$
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 int objectID = 0;
464 int type = OID_UNKNOWN;
465 int extn_oid = OID_UNKNOWN;
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 * release an ietfAttribute, free it if count reaches zero
603 */
604 static void
605 release_ietfAttr(ietfAttr_t* attr)
606 {
607 if (--attr->count == 0)
608 {
609 ietfAttrList_t **plist = &ietfAttributes;
610 ietfAttrList_t *list = *plist;
611
612 while (list->attr != attr)
613 {
614 plist = &list->next;
615 list = *plist;
616 }
617 *plist = list->next;
618
619 pfree(attr->value.ptr);
620 pfree(attr);
621 pfree(list);
622 }
623 }
624
625 /*
626 * free an ietfAttrList
627 */
628 void
629 free_ietfAttrList(ietfAttrList_t* list)
630 {
631 while (list != NULL)
632 {
633 ietfAttrList_t *el = list;
634
635 release_ietfAttr(el->attr);
636 list = list->next;
637 pfree(el);
638 }
639 }
640
641 /*
642 * free a X.509 attribute certificate
643 */
644 void
645 free_acert(x509acert_t *ac)
646 {
647 if (ac != NULL)
648 {
649 free_ietfAttrList(ac->charging);
650 free_ietfAttrList(ac->groups);
651 pfreeany(ac->certificate.ptr);
652 pfree(ac);
653 }
654 }
655
656 /*
657 * free first X.509 attribute certificate in the chained list
658 */
659 static void
660 free_first_acert(void)
661 {
662 x509acert_t *first = x509acerts;
663 x509acerts = first->next;
664 free_acert(first);
665 }
666
667 /*
668 * Free all attribute certificates in the chained list
669 */
670 void
671 free_acerts(void)
672 {
673 while (x509acerts != NULL)
674 free_first_acert();
675 }
676
677 /*
678 * get a X.509 attribute certificate for a given holder
679 */
680 x509acert_t*
681 get_x509acert(chunk_t issuer, chunk_t serial)
682 {
683 x509acert_t *ac = x509acerts;
684 x509acert_t *prev_ac = NULL;
685
686 while (ac != NULL)
687 {
688 if (same_dn(issuer, ac->holderIssuer)
689 && same_serial(serial, ac->holderSerial))
690 {
691 if (ac!= x509acerts)
692 {
693 /* bring the certificate up front */
694 prev_ac->next = ac->next;
695 ac->next = x509acerts;
696 x509acerts = ac;
697 }
698 return ac;
699 }
700 prev_ac = ac;
701 ac = ac->next;
702 }
703 return NULL;
704 }
705
706 /*
707 * add a X.509 attribute certificate to the chained list
708 */
709 static void
710 add_acert(x509acert_t *ac)
711 {
712 x509acert_t *old_ac = get_x509acert(ac->holderIssuer, ac->holderSerial);
713
714 if (old_ac != NULL)
715 {
716 if (ac->notBefore >old_ac->notBefore)
717 {
718 /* delete the old attribute cert */
719 free_first_acert();
720 DBG(DBG_CONTROL,
721 DBG_log("attribute cert is newer - existing cert deleted")
722 )
723 }
724 else
725 {
726 DBG(DBG_CONTROL,
727 DBG_log("attribute cert is not newer - existing cert kept");
728 )
729 free_acert(ac);
730 return;
731 }
732 }
733 plog("attribute cert added");
734
735 /* insert new attribute cert at the root of the chain */
736 ac->next = x509acerts;
737 x509acerts = ac;
738 }
739
740 /* verify the validity of an attribute certificate by
741 * checking the notBefore and notAfter dates
742 */
743 static err_t
744 check_ac_validity(const x509acert_t *ac)
745 {
746 time_t current_time;
747
748 time(&current_time);
749 DBG(DBG_CONTROL | DBG_PARSING,
750 DBG_log(" not before : %s", timetoa(&ac->notBefore, TRUE));
751 DBG_log(" current time: %s", timetoa(&current_time, TRUE));
752 DBG_log(" not after : %s", timetoa(&ac->notAfter, TRUE));
753 )
754
755 if (current_time < ac->notBefore)
756 return "attribute certificate is not valid yet";
757 if (current_time > ac->notAfter)
758 return "attribute certificate has expired";
759 else
760 return NULL;
761 }
762
763 /*
764 * verifies a X.509 attribute certificate
765 */
766 bool
767 verify_x509acert(x509acert_t *ac, bool strict)
768 {
769 u_char buf[BUF_LEN];
770 x509cert_t *aacert;
771 err_t ugh = NULL;
772 time_t valid_until = ac->notAfter;
773
774 DBG(DBG_CONTROL,
775 dntoa(buf, BUF_LEN, ac->entityName);
776 DBG_log("holder: '%s'",buf);
777 dntoa(buf, BUF_LEN, ac->issuerName);
778 DBG_log("issuer: '%s'",buf);
779 )
780
781 ugh = check_ac_validity(ac);
782
783 if (ugh != NULL)
784 {
785 plog("%s", ugh);
786 return FALSE;
787 }
788 DBG(DBG_CONTROL,
789 DBG_log("attribute certificate is valid")
790 )
791
792 lock_authcert_list("verify_x509acert");
793 aacert = get_authcert(ac->issuerName, ac->authKeySerialNumber
794 , ac->authKeyID, AUTH_AA);
795 unlock_authcert_list("verify_x509acert");
796
797 if (aacert == NULL)
798 {
799 plog("issuer aacert not found");
800 return FALSE;
801 }
802 DBG(DBG_CONTROL,
803 DBG_log("issuer aacert found")
804 )
805
806 if (!check_signature(ac->certificateInfo, ac->signature
807 , ac->algorithm, ac->algorithm, aacert))
808 {
809 plog("attribute certificate signature is invalid");
810 return FALSE;
811 }
812 DBG(DBG_CONTROL,
813 DBG_log("attribute certificate signature is valid");
814 )
815
816 return verify_x509cert(aacert, strict, &valid_until);
817 }
818
819 /*
820 * Loads X.509 attribute certificates
821 */
822 void
823 load_acerts(void)
824 {
825 u_char buf[BUF_LEN];
826
827 /* change directory to specified path */
828 u_char *save_dir = getcwd(buf, BUF_LEN);
829
830 if (!chdir(A_CERT_PATH))
831 {
832 struct dirent **filelist;
833 int n;
834
835 plog("Changing to directory '%s'",A_CERT_PATH);
836 n = scandir(A_CERT_PATH, &filelist, file_select, alphasort);
837
838 if (n > 0)
839 {
840 while (n--)
841 {
842 chunk_t blob = empty_chunk;
843 bool pgp = FALSE;
844
845 if (load_coded_file(filelist[n]->d_name, NULL, "acert", &blob, &pgp))
846 {
847 x509acert_t *ac = alloc_thing(x509acert_t, "x509acert");
848
849 *ac = empty_ac;
850
851 if (parse_ac(blob, ac)
852 && verify_x509acert(ac, FALSE))
853 add_acert(ac);
854 else
855 free_acert(ac);
856 }
857 free(filelist[n]);
858 }
859 free(filelist);
860 }
861 }
862 /* restore directory path */
863 chdir(save_dir);
864 }
865
866 /*
867 * lists group attributes separated by commas on a single line
868 */
869 void
870 format_groups(const ietfAttrList_t *list, char *buf, int len)
871 {
872 bool first_group = TRUE;
873
874 while (list != NULL && len > 0)
875 {
876 ietfAttr_t *attr = list->attr;
877
878 if (attr->kind == IETF_ATTRIBUTE_OCTETS
879 || attr->kind == IETF_ATTRIBUTE_STRING)
880 {
881 int written = snprintf(buf, len, "%s%.*s"
882 , (first_group)? "" : ", "
883 , (int)attr->value.len, attr->value.ptr);
884
885 first_group = FALSE;
886
887 /* return value of snprintf() up to glibc 2.0.6 */
888 if (written < 0)
889 break;
890
891 buf += written;
892 len -= written;
893 }
894 list = list->next;
895 }
896 }
897
898 /*
899 * list all X.509 attribute certificates in the chained list
900 */
901 void
902 list_acerts(bool utc)
903 {
904 x509acert_t *ac = x509acerts;
905 time_t now;
906
907 /* determine the current time */
908 time(&now);
909
910 if (ac != NULL)
911 {
912 whack_log(RC_COMMENT, " ");
913 whack_log(RC_COMMENT, "List of X.509 Attribute Certificates:");
914 whack_log(RC_COMMENT, " ");
915 }
916
917 while (ac != NULL)
918 {
919 u_char buf[BUF_LEN];
920
921 whack_log(RC_COMMENT, "%s",timetoa(&ac->installed, utc));
922 if (ac->entityName.ptr != NULL)
923 {
924 dntoa(buf, BUF_LEN, ac->entityName);
925 whack_log(RC_COMMENT, " holder: '%s'", buf);
926 }
927 if (ac->holderIssuer.ptr != NULL)
928 {
929 dntoa(buf, BUF_LEN, ac->holderIssuer);
930 whack_log(RC_COMMENT, " hissuer: '%s'", buf);
931 }
932 if (ac->holderSerial.ptr != NULL)
933 {
934 datatot(ac->holderSerial.ptr, ac->holderSerial.len, ':'
935 , buf, BUF_LEN);
936 whack_log(RC_COMMENT, " hserial: %s", buf);
937 }
938 if (ac->groups != NULL)
939 {
940 format_groups(ac->groups, buf, BUF_LEN);
941 whack_log(RC_COMMENT, " groups: %s", buf);
942 }
943 dntoa(buf, BUF_LEN, ac->issuerName);
944 whack_log(RC_COMMENT, " issuer: '%s'", buf);
945 datatot(ac->serialNumber.ptr, ac->serialNumber.len, ':'
946 , buf, BUF_LEN);
947 whack_log(RC_COMMENT, " serial: %s", buf);
948 whack_log(RC_COMMENT, " validity: not before %s %s",
949 timetoa(&ac->notBefore, utc),
950 (ac->notBefore < now)?"ok":"fatal (not valid yet)");
951 whack_log(RC_COMMENT, " not after %s %s",
952 timetoa(&ac->notAfter, utc),
953 check_expiry(ac->notAfter, ACERT_WARNING_INTERVAL, TRUE));
954 if (ac->authKeyID.ptr != NULL)
955 {
956 datatot(ac->authKeyID.ptr, ac->authKeyID.len, ':'
957 , buf, BUF_LEN);
958 whack_log(RC_COMMENT, " authkey: %s", buf);
959 }
960 if (ac->authKeySerialNumber.ptr != NULL)
961 {
962 datatot(ac->authKeySerialNumber.ptr, ac->authKeySerialNumber.len, ':'
963 , buf, BUF_LEN);
964 whack_log(RC_COMMENT, " aserial: %s", buf);
965 }
966
967 ac = ac->next;
968 }
969 }
970
971 /*
972 * list all group attributes in alphabetical order
973 */
974 void
975 list_groups(bool utc)
976 {
977 ietfAttrList_t *list = ietfAttributes;
978
979 if (list != NULL)
980 {
981 whack_log(RC_COMMENT, " ");
982 whack_log(RC_COMMENT, "List of Group Attributes:");
983 whack_log(RC_COMMENT, " ");
984 }
985
986 while (list != NULL)
987 {
988 ietfAttr_t *attr = list->attr;
989
990 whack_log(RC_COMMENT, "%s, count: %d", timetoa(&attr->installed, utc),
991 attr->count);
992
993 switch (attr->kind)
994 {
995 case IETF_ATTRIBUTE_OCTETS:
996 case IETF_ATTRIBUTE_STRING:
997 whack_log(RC_COMMENT, " %.*s", (int)attr->value.len, attr->value.ptr);
998 break;
999 case IETF_ATTRIBUTE_OID:
1000 whack_log(RC_COMMENT, " OID");
1001 break;
1002 default:
1003 break;
1004 }
1005
1006 list = list->next;
1007 }
1008 }