1 /* Support of X.509 attribute certificates
2 * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
3 * Copyright (C) 2003 Martin Berner, Lukas Suter
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>.
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
15 * RCSID $Id: ac.c,v 1.12 2005/12/06 22:49:32 as Exp $
24 #include <sys/types.h>
28 #include "constants.h"
41 /* chained list of X.509 attribute certificates */
43 static x509acert_t
*x509acerts
= NULL
;
45 /* chained list of ietfAttributes */
47 static ietfAttrList_t
*ietfAttributes
= NULL
;
49 /* ASN.1 definition of ietfAttrSyntax */
51 static const asn1Object_t ietfAttrSyntaxObjects
[] =
53 { 0, "ietfAttrSyntax", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
54 { 1, "policyAuthority", ASN1_CONTEXT_C_0
, ASN1_OPT
|
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
|
60 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 5 */
61 { 2, "oid", ASN1_OID
, ASN1_OPT
|
63 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 7 */
64 { 2, "string", ASN1_UTF8STRING
, ASN1_OPT
|
66 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
67 { 1, "end loop", ASN1_EOC
, ASN1_END
} /* 10 */
70 #define IETF_ATTR_OCTETS 4
71 #define IETF_ATTR_OID 6
72 #define IETF_ATTR_STRING 8
73 #define IETF_ATTR_ROOF 11
75 /* ASN.1 definition of roleSyntax */
77 static const asn1Object_t roleSyntaxObjects
[] =
79 { 0, "roleSyntax", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
80 { 1, "roleAuthority", ASN1_CONTEXT_C_0
, ASN1_OPT
|
82 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 2 */
83 { 1, "roleName", ASN1_CONTEXT_C_1
, ASN1_OBJ
} /* 3 */
88 /* ASN.1 definition of an X509 attribute certificate */
90 static const asn1Object_t acObjects
[] =
92 { 0, "AttributeCertificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
93 { 1, "AttributeCertificateInfo", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
94 { 2, "version", ASN1_INTEGER
, ASN1_DEF
|
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
|
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
|
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
|
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 */
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
178 const x509acert_t empty_ac
= {
181 { NULL
, 0 }, /* certificate */
182 { NULL
, 0 }, /* certificateInfo */
185 /* baseCertificateID */
186 { NULL
, 0 }, /* holderIssuer */
187 { NULL
, 0 }, /* holderSerial */
189 { NULL
, 0 }, /* generalNames */
191 { NULL
, 0 }, /* issuerName */
193 OID_UNKNOWN
, /* sigAlg */
194 { NULL
, 0 }, /* serialNumber */
195 /* attrCertValidityPeriod */
199 NULL
, /* charging */
202 { NULL
, 0 }, /* authKeyID */
203 { NULL
, 0 }, /* authKeySerialNumber */
204 FALSE
, /* noRevAvail */
205 /* signatureAlgorithm */
206 OID_UNKNOWN
, /* algorithm */
207 { NULL
, 0 }, /* signature */
211 /* compare two ietfAttributes, returns zero if a equals b
212 * negative/positive if a is earlier/later in the alphabet than b
215 cmp_ietfAttr(ietfAttr_t
*a
,ietfAttr_t
*b
)
217 int cmp_len
, len
, cmp_value
;
219 /* cannot compare OID with STRING or OCTETS attributes */
220 if (a
->kind
== IETF_ATTRIBUTE_OID
&& b
->kind
!= IETF_ATTRIBUTE_OID
)
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
);
227 return (cmp_value
== 0)? cmp_len
: cmp_value
;
231 * add an ietfAttribute to the chained list
234 add_ietfAttr(ietfAttr_t
*attr
)
236 ietfAttrList_t
**listp
= &ietfAttributes
;
237 ietfAttrList_t
*list
= *listp
;
242 cmp
= cmp_ietfAttr(attr
, list
->attr
);
251 /* attribute already exists, increase count */
258 ietfAttrList_t
*el
= alloc_thing(ietfAttrList_t
, "ietfAttrList");
260 /* new attribute, unshare value */
261 attr
->value
.ptr
= clone_bytes(attr
->value
.ptr
, attr
->value
.len
264 time(&attr
->installed
);
275 * decodes a comma separated list of group attributes
278 decode_groups(char *groups
, ietfAttrList_t
**listp
)
283 while (strlen(groups
) > 0)
286 char *next
= strchr(groups
, ',');
289 end
= next
= groups
+ strlen(groups
);
293 /* eat preceeding whitespace */
294 while (groups
< end
&& *groups
== ' ')
297 /* eat trailing whitespace */
298 while (end
> groups
&& *(end
-1) == ' ')
303 ietfAttr_t
*attr
= alloc_thing(ietfAttr_t
, "ietfAttr");
304 ietfAttrList_t
*el
= alloc_thing(ietfAttrList_t
, "ietfAttrList");
306 attr
->kind
= IETF_ATTRIBUTE_STRING
;
307 attr
->value
.ptr
= groups
;
308 attr
->value
.len
= end
- groups
;
311 el
->attr
= add_ietfAttr(attr
);
321 same_attribute(const ietfAttr_t
*a
, const ietfAttr_t
*b
)
323 return (a
->kind
== b
->kind
&& a
->value
.len
== b
->value
.len
324 && memcmp(a
->value
.ptr
, b
->value
.ptr
, b
->value
.len
) == 0);
328 group_membership(const ietfAttrList_t
*peer_list
330 , const ietfAttrList_t
*conn_list
)
332 if (conn_list
== NULL
)
335 while (peer_list
!= NULL
)
337 const ietfAttr_t
*peer_attr
= peer_list
->attr
;
338 const ietfAttrList_t
*list
= conn_list
;
342 ietfAttr_t
*conn_attr
= list
->attr
;
344 if (same_attribute(conn_attr
, peer_attr
))
347 DBG_log("%s: peer matches group '%.*s'"
349 , (int)peer_attr
->value
.len
, peer_attr
->value
.ptr
)
355 peer_list
= peer_list
->next
;
358 DBG_log("%s: peer doesn't match any group", conn
)
365 unshare_ietfAttrList(ietfAttrList_t
**listp
)
367 ietfAttrList_t
*list
= *listp
;
371 ietfAttrList_t
*el
= alloc_thing(ietfAttrList_t
, "ietfAttrList");
373 el
->attr
= list
->attr
;
383 * parses ietfAttrSyntax
385 static ietfAttrList_t
*
386 parse_ietfAttrSyntax(chunk_t blob
, int level0
)
393 ietfAttrList_t
*list
= NULL
;
395 asn1_init(&ctx
, blob
, level0
, FALSE
, DBG_RAW
);
397 while (objectID
< IETF_ATTR_ROOF
)
399 if (!extract_object(ietfAttrSyntaxObjects
, &objectID
, &object
, &level
, &ctx
))
404 case IETF_ATTR_OCTETS
:
406 case IETF_ATTR_STRING
:
408 ietfAttr_t
*attr
= alloc_thing(ietfAttr_t
, "ietfAttr");
409 ietfAttrList_t
*el
= alloc_thing(ietfAttrList_t
, "ietfAttrList");
411 attr
->kind
= (objectID
- IETF_ATTR_OCTETS
) / 2;
412 attr
->value
= object
;
415 el
->attr
= add_ietfAttr(attr
);
431 parse_roleSyntax(chunk_t blob
, int level0
)
438 asn1_init(&ctx
, blob
, level0
, FALSE
, DBG_RAW
);
440 while (objectID
< ROLE_ROOF
)
442 if (!extract_object(roleSyntaxObjects
, &objectID
, &object
, &level
, &ctx
))
454 * Parses an X.509 attribute certificate
457 parse_ac(chunk_t blob
, x509acert_t
*ac
)
463 u_int type
= OID_UNKNOWN
;
464 u_int extn_oid
= OID_UNKNOWN
;
467 asn1_init(&ctx
, blob
, 0, FALSE
, DBG_RAW
);
469 while (objectID
< AC_OBJ_ROOF
) {
471 if (!extract_object(acObjects
, &objectID
, &object
, &level
, &ctx
))
474 /* those objects which will parsed further need the next higher level */
479 case AC_OBJ_CERTIFICATE
:
480 ac
->certificate
= object
;
482 case AC_OBJ_CERTIFICATE_INFO
:
483 ac
->certificateInfo
= object
;
486 ac
->version
= (object
.len
) ?
(1 + (u_int
)*object
.ptr
) : 1;
488 DBG_log(" v%d", ac
->version
);
490 if (ac
->version
!= 2)
492 plog("v%d attribute certificates are not supported"
497 case AC_OBJ_HOLDER_ISSUER
:
498 ac
->holderIssuer
= get_directoryName(object
, level
, FALSE
);
500 case AC_OBJ_HOLDER_SERIAL
:
501 ac
->holderSerial
= object
;
503 case AC_OBJ_ENTITY_NAME
:
504 ac
->entityName
= get_directoryName(object
, level
, TRUE
);
506 case AC_OBJ_ISSUER_NAME
:
507 ac
->issuerName
= get_directoryName(object
, level
, FALSE
);
510 ac
->sigAlg
= parse_algorithmIdentifier(object
, level
, NULL
);
512 case AC_OBJ_SERIAL_NUMBER
:
513 ac
->serialNumber
= object
;
515 case AC_OBJ_NOT_BEFORE
:
516 ac
->notBefore
= asn1totime(&object
, ASN1_GENERALIZEDTIME
);
518 case AC_OBJ_NOT_AFTER
:
519 ac
->notAfter
= asn1totime(&object
, ASN1_GENERALIZEDTIME
);
521 case AC_OBJ_ATTRIBUTE_TYPE
:
522 type
= known_oid(object
);
524 case AC_OBJ_ATTRIBUTE_VALUE
:
527 case OID_AUTHENTICATION_INFO
:
529 DBG_log(" need to parse authenticationInfo")
532 case OID_ACCESS_IDENTITY
:
534 DBG_log(" need to parse accessIdentity")
537 case OID_CHARGING_IDENTITY
:
538 ac
->charging
= parse_ietfAttrSyntax(object
, level
);
541 ac
->groups
= parse_ietfAttrSyntax(object
, level
);
544 parse_roleSyntax(object
, level
);
552 extn_oid
= known_oid(object
);
554 case AC_OBJ_CRITICAL
:
555 critical
= object
.len
&& *object
.ptr
;
557 DBG_log(" %s",(critical
)?
"TRUE":"FALSE");
560 case AC_OBJ_EXTN_VALUE
:
563 case OID_CRL_DISTRIBUTION_POINTS
:
565 DBG_log(" need to parse crlDistributionPoints")
568 case OID_AUTHORITY_KEY_ID
:
569 parse_authorityKeyIdentifier(object
, level
570 , &ac
->authKeyID
, &ac
->authKeySerialNumber
);
572 case OID_TARGET_INFORMATION
:
574 DBG_log(" need to parse targetInformation")
577 case OID_NO_REV_AVAIL
:
578 ac
->noRevAvail
= TRUE
;
585 case AC_OBJ_ALGORITHM
:
586 ac
->algorithm
= parse_algorithmIdentifier(object
, level
, NULL
);
588 case AC_OBJ_SIGNATURE
:
589 ac
->signature
= object
;
597 time(&ac
->installed
);
602 * compare two X.509 attribute certificates by comparing their signatures
605 same_x509acert(x509acert_t
*a
, x509acert_t
*b
)
607 return a
->signature
.len
== b
->signature
.len
&&
608 memcmp(a
->signature
.ptr
, b
->signature
.ptr
, b
->signature
.len
) == 0;
612 * release an ietfAttribute, free it if count reaches zero
615 release_ietfAttr(ietfAttr_t
* attr
)
617 if (--attr
->count
== 0)
619 ietfAttrList_t
**plist
= &ietfAttributes
;
620 ietfAttrList_t
*list
= *plist
;
622 while (list
->attr
!= attr
)
629 pfree(attr
->value
.ptr
);
636 * free an ietfAttrList
639 free_ietfAttrList(ietfAttrList_t
* list
)
643 ietfAttrList_t
*el
= list
;
645 release_ietfAttr(el
->attr
);
652 * free a X.509 attribute certificate
655 free_acert(x509acert_t
*ac
)
659 free_ietfAttrList(ac
->charging
);
660 free_ietfAttrList(ac
->groups
);
661 pfreeany(ac
->certificate
.ptr
);
667 * free first X.509 attribute certificate in the chained list
670 free_first_acert(void)
672 x509acert_t
*first
= x509acerts
;
673 x509acerts
= first
->next
;
678 * Free all attribute certificates in the chained list
683 while (x509acerts
!= NULL
)
688 * get a X.509 attribute certificate for a given holder
691 get_x509acert(chunk_t issuer
, chunk_t serial
)
693 x509acert_t
*ac
= x509acerts
;
694 x509acert_t
*prev_ac
= NULL
;
698 if (same_dn(issuer
, ac
->holderIssuer
)
699 && same_serial(serial
, ac
->holderSerial
))
703 /* bring the certificate up front */
704 prev_ac
->next
= ac
->next
;
705 ac
->next
= x509acerts
;
717 * add a X.509 attribute certificate to the chained list
720 add_acert(x509acert_t
*ac
)
722 x509acert_t
*old_ac
= get_x509acert(ac
->holderIssuer
, ac
->holderSerial
);
726 if (ac
->notBefore
>old_ac
->notBefore
)
728 /* delete the old attribute cert */
731 DBG_log("attribute cert is newer - existing cert deleted")
737 DBG_log("attribute cert is not newer - existing cert kept");
743 plog("attribute cert added");
745 /* insert new attribute cert at the root of the chain */
746 ac
->next
= x509acerts
;
750 /* verify the validity of an attribute certificate by
751 * checking the notBefore and notAfter dates
754 check_ac_validity(const x509acert_t
*ac
)
759 DBG(DBG_CONTROL
| DBG_PARSING
,
760 DBG_log(" not before : %s", timetoa(&ac
->notBefore
, TRUE
));
761 DBG_log(" current time: %s", timetoa(¤t_time
, TRUE
));
762 DBG_log(" not after : %s", timetoa(&ac
->notAfter
, TRUE
));
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";
774 * verifies a X.509 attribute certificate
777 verify_x509acert(x509acert_t
*ac
, bool strict
)
782 time_t valid_until
= ac
->notAfter
;
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
);
791 ugh
= check_ac_validity(ac
);
799 DBG_log("attribute certificate is valid")
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");
809 plog("issuer aacert not found");
813 DBG_log("issuer aacert found")
816 if (!check_signature(ac
->certificateInfo
, ac
->signature
817 , ac
->algorithm
, ac
->algorithm
, aacert
))
819 plog("attribute certificate signature is invalid");
823 DBG_log("attribute certificate signature is valid");
826 return verify_x509cert(aacert
, strict
, &valid_until
);
830 * Loads X.509 attribute certificates
837 /* change directory to specified path */
838 u_char
*save_dir
= getcwd(buf
, BUF_LEN
);
840 if (!chdir(A_CERT_PATH
))
842 struct dirent
**filelist
;
845 plog("Changing to directory '%s'",A_CERT_PATH
);
846 n
= scandir(A_CERT_PATH
, &filelist
, file_select
, alphasort
);
852 chunk_t blob
= empty_chunk
;
855 if (load_coded_file(filelist
[n
]->d_name
, NULL
, "acert", &blob
, &pgp
))
857 x509acert_t
*ac
= alloc_thing(x509acert_t
, "x509acert");
861 if (parse_ac(blob
, ac
)
862 && verify_x509acert(ac
, FALSE
))
872 /* restore directory path */
877 * lists group attributes separated by commas on a single line
880 format_groups(const ietfAttrList_t
*list
, char *buf
, int len
)
882 bool first_group
= TRUE
;
884 while (list
!= NULL
&& len
> 0)
886 ietfAttr_t
*attr
= list
->attr
;
888 if (attr
->kind
== IETF_ATTRIBUTE_OCTETS
889 || attr
->kind
== IETF_ATTRIBUTE_STRING
)
891 int written
= snprintf(buf
, len
, "%s%.*s"
892 , (first_group
)?
"" : ", "
893 , (int)attr
->value
.len
, attr
->value
.ptr
);
897 /* return value of snprintf() up to glibc 2.0.6 */
909 * list all X.509 attribute certificates in the chained list
912 list_acerts(bool utc
)
914 x509acert_t
*ac
= x509acerts
;
917 /* determine the current time */
922 whack_log(RC_COMMENT
, " ");
923 whack_log(RC_COMMENT
, "List of X.509 Attribute Certificates:");
924 whack_log(RC_COMMENT
, " ");
931 whack_log(RC_COMMENT
, "%s",timetoa(&ac
->installed
, utc
));
932 if (ac
->entityName
.ptr
!= NULL
)
934 dntoa(buf
, BUF_LEN
, ac
->entityName
);
935 whack_log(RC_COMMENT
, " holder: '%s'", buf
);
937 if (ac
->holderIssuer
.ptr
!= NULL
)
939 dntoa(buf
, BUF_LEN
, ac
->holderIssuer
);
940 whack_log(RC_COMMENT
, " hissuer: '%s'", buf
);
942 if (ac
->holderSerial
.ptr
!= NULL
)
944 datatot(ac
->holderSerial
.ptr
, ac
->holderSerial
.len
, ':'
946 whack_log(RC_COMMENT
, " hserial: %s", buf
);
948 if (ac
->groups
!= NULL
)
950 format_groups(ac
->groups
, buf
, BUF_LEN
);
951 whack_log(RC_COMMENT
, " groups: %s", buf
);
953 dntoa(buf
, BUF_LEN
, ac
->issuerName
);
954 whack_log(RC_COMMENT
, " issuer: '%s'", buf
);
955 datatot(ac
->serialNumber
.ptr
, ac
->serialNumber
.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
)
966 datatot(ac
->authKeyID
.ptr
, ac
->authKeyID
.len
, ':'
968 whack_log(RC_COMMENT
, " authkey: %s", buf
);
970 if (ac
->authKeySerialNumber
.ptr
!= NULL
)
972 datatot(ac
->authKeySerialNumber
.ptr
, ac
->authKeySerialNumber
.len
, ':'
974 whack_log(RC_COMMENT
, " aserial: %s", buf
);
982 * list all group attributes in alphabetical order
985 list_groups(bool utc
)
987 ietfAttrList_t
*list
= ietfAttributes
;
991 whack_log(RC_COMMENT
, " ");
992 whack_log(RC_COMMENT
, "List of Group Attributes:");
993 whack_log(RC_COMMENT
, " ");
998 ietfAttr_t
*attr
= list
->attr
;
1000 whack_log(RC_COMMENT
, "%s, count: %d", timetoa(&attr
->installed
, utc
),
1005 case IETF_ATTRIBUTE_OCTETS
:
1006 case IETF_ATTRIBUTE_STRING
:
1007 whack_log(RC_COMMENT
, " %.*s", (int)attr
->value
.len
, attr
->value
.ptr
);
1009 case IETF_ATTRIBUTE_OID
:
1010 whack_log(RC_COMMENT
, " OID");