📄 ac.c
字号:
/* Support of X.509 attribute certificates * Copyright (C) 2002 Ueli Gallizzi, Ariane Seiler * Copyright (C) 2003 Martin Berner, Lukas Suter * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * RCSID $Id: ac.c,v 1.7 2004/06/14 01:46:02 mcr Exp $ */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <dirent.h>#include <time.h>#include <sys/types.h>#include <openswan.h>#include "constants.h"#include "oswlog.h"#include "defs.h"#include "asn1.h"#include "oid.h"#include "ac.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "log.h"#include "paths.h"#include "whack.h"#include "fetch.h"/* chained list of X.509 attribute certificates */ static x509acert_t *x509acerts = NULL; /* chained list of ietfAttributes */ static ietfAttrList_t *ietfAttributes = NULL;/* ASN.1 definition of ietfAttrSyntax */static const asn1Object_t ietfAttrSyntaxObjects[] ={ { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | ASN1_BODY }, /* 1 */ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | ASN1_BODY }, /* 4 */ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ { 2, "oid", ASN1_OID, ASN1_OPT | ASN1_BODY }, /* 6 */ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ { 2, "string", ASN1_UTF8STRING, ASN1_OPT | ASN1_BODY }, /* 8 */ { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ { 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */};#define IETF_ATTR_OCTETS 4#define IETF_ATTR_OID 6#define IETF_ATTR_STRING 8#define IETF_ATTR_ROOF 11/* ASN.1 definition of roleSyntax */static const asn1Object_t roleSyntaxObjects[] ={ { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | ASN1_OBJ }, /* 1 */ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */};#define ROLE_ROOF 4/* ASN.1 definition of an X509 attribute certificate */static const asn1Object_t acObjects[] ={ { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ { 2, "version", ASN1_INTEGER, ASN1_DEF | ASN1_BODY }, /* 2 */ { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | ASN1_BODY }, /* 7 */ { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | ASN1_OBJ }, /* 10 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/ { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | ASN1_BODY }, /* 14 */ { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/ { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | ASN1_OBJ }, /* 19 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | ASN1_BODY }, /* 25 */ { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | ASN1_BODY }, /* 31 */ { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ { 5, "value", ASN1_SEQUENCE, ASN1_OBJ }, /* 44 */ { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */ { 4, "critical", ASN1_BOOLEAN, ASN1_DEF | ASN1_BODY }, /* 50 */ { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */ { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */ { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */};#define AC_OBJ_CERTIFICATE 0#define AC_OBJ_CERTIFICATE_INFO 1#define AC_OBJ_VERSION 2#define AC_OBJ_HOLDER_ISSUER 5#define AC_OBJ_HOLDER_SERIAL 6#define AC_OBJ_ENTITY_NAME 10#define AC_OBJ_ISSUER_NAME 19#define AC_OBJ_ISSUER 23#define AC_OBJ_SIG_ALG 35#define AC_OBJ_SERIAL_NUMBER 36#define AC_OBJ_NOT_BEFORE 38#define AC_OBJ_NOT_AFTER 39#define AC_OBJ_ATTRIBUTE_TYPE 40#define AC_OBJ_ATTRIBUTE_VALUE 44#define AC_OBJ_EXTN_ID 49#define AC_OBJ_CRITICAL 50#define AC_OBJ_EXTN_VALUE 51#define AC_OBJ_ALGORITHM 53#define AC_OBJ_SIGNATURE 54#define AC_OBJ_ROOF 55const x509acert_t empty_ac = { NULL , /* *next */ 0 , /* installed */ { NULL, 0 }, /* certificate */ { NULL, 0 }, /* certificateInfo */ 1 , /* version */ /* holder */ /* baseCertificateID */ { NULL, 0 }, /* holderIssuer */ { NULL, 0 }, /* holderSerial */ /* entityName */ { NULL, 0 }, /* generalNames */ /* v2Form */ { NULL, 0 }, /* issuerName */ /* signature */ OID_UNKNOWN, /* sigAlg */ { NULL, 0 }, /* serialNumber */ /* attrCertValidityPeriod */ 0 , /* notBefore */ 0 , /* notAfter */ /* attributes */ NULL , /* charging */ NULL , /* groups */ /* extensions */ { NULL, 0 }, /* authKeyID */ { NULL, 0 }, /* authKeySerialNumber */ FALSE , /* noRevAvail */ /* signatureAlgorithm */ OID_UNKNOWN, /* algorithm */ { NULL, 0 }, /* signature */};/* Maximum length of ASN.1 distinquished name */#define BUF_LEN 512/* compare two ietfAttributes, returns zero if a equals b * negative/positive if a is earlier/later in the alphabet than b */static intcmp_ietfAttr(ietfAttr_t *a,ietfAttr_t *b){ int cmp_len, len, cmp_value; /* cannot compare OID with STRING or OCTETS attributes */ if (a->kind == IETF_ATTRIBUTE_OID && b->kind != IETF_ATTRIBUTE_OID) return 1; cmp_len = a->value.len - b->value.len; len = (cmp_len < 0)? a->value.len : b->value.len; cmp_value = memcmp(a->value.ptr, b->value.ptr, len); return (cmp_value == 0)? cmp_len : cmp_value;} /* * add an ietfAttribute to the chained list */static ietfAttr_t*add_ietfAttr(ietfAttr_t *attr){ ietfAttrList_t **listp = &ietfAttributes; ietfAttrList_t *list = *listp; int cmp = -1; while (list != NULL) { cmp = cmp_ietfAttr(attr, list->attr); if (cmp <= 0) break; listp = &list->next; list = *listp; } if (cmp == 0) { /* attribute already exists, increase count */ pfree(attr); list->attr->count++; return list->attr; } else { ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList"); /* new attribute, unshare value */ attr->value.ptr = clone_bytes(attr->value.ptr, attr->value.len , "attr value"); attr->count = 1; time(&attr->installed); el->attr = attr; el->next = list; *listp = el; return attr; }} /* * decodes a comma separated list of group attributes */voiddecode_groups(char *groups, ietfAttrList_t **listp){ if (groups == NULL) return; while (strlen(groups) > 0) { char *end; char *next = strchr(groups, ','); if (next == NULL) end = next = groups + strlen(groups); else end = next++; /* eat preceeding whitespace */ while (groups < end && *groups == ' ') groups++; /* eat trailing whitespace */ while (end > groups && *(end-1) == ' ') end--; if (groups < end) { ietfAttr_t *attr = alloc_thing(ietfAttr_t, "ietfAttr"); ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList"); attr->kind = IETF_ATTRIBUTE_STRING; attr->value.ptr = groups; attr->value.len = end - groups; attr->count = 0; el->attr = add_ietfAttr(attr); el->next = *listp; *listp = el; } groups = next; }} void unshare_ietfAttrList(ietfAttrList_t **listp){ ietfAttrList_t *list = *listp; while (list != NULL) { ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList"); el->attr = list->attr; el->attr->count++; el->next = NULL; *listp = el; listp = &el->next; list = list->next; }} /* * parses ietfAttrSyntax */static ietfAttrList_t*parse_ietfAttrSyntax(chunk_t blob, int level0){ asn1_ctx_t ctx; chunk_t object; u_int level; int objectID = 0; ietfAttrList_t *list = NULL; asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < IETF_ATTR_ROOF) { if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx)) return NULL; switch (objectID) { case IETF_ATTR_OCTETS: case IETF_ATTR_OID: case IETF_ATTR_STRING: { ietfAttr_t *attr = alloc_thing(ietfAttr_t, "ietfAttr"); ietfAttrList_t *el = alloc_thing(ietfAttrList_t, "ietfAttrList"); attr->kind = (objectID - IETF_ATTR_OCTETS) / 2; attr->value = object; attr->count = 0; el->attr = add_ietfAttr(attr); el->next = list; list = el; } break; default: break; } objectID++; } return list;}/* * parses roleSyntax */static voidparse_roleSyntax(chunk_t blob, int level0){ asn1_ctx_t ctx; chunk_t object; u_int level; int objectID = 0; asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < ROLE_ROOF) { if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx)) return; switch (objectID) { default: break; } objectID++; }}/* * Parses an X.509 attribute certificate */static boolparse_ac(chunk_t blob, x509acert_t *ac){ asn1_ctx_t ctx; bool critical; chunk_t extnID; chunk_t type; chunk_t object; u_int level; int objectID = 0; asn1_init(&ctx, blob, 0, FALSE, DBG_RAW); while (objectID < AC_OBJ_ROOF) { if (!extract_object(acObjects, &objectID, &object, &level, &ctx)) return FALSE; /* those objects which will parsed further need the next higher level */ level++; switch (objectID) { case AC_OBJ_CERTIFICATE: ac->certificate = object; break; case AC_OBJ_CERTIFICATE_INFO: ac->certificateInfo = object; break; case AC_OBJ_VERSION: ac->version = (object.len) ? (1 + (u_int)*object.ptr) : 1; DBG(DBG_PARSING, DBG_log(" v%d", ac->version); ) if (ac->version != 2) { openswan_log("v%d attribute certificates are not supported" , ac->version); return FALSE; } break; case AC_OBJ_HOLDER_ISSUER:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -