📄 x509.c
字号:
*/static generalName_t*parse_generalNames(chunk_t blob, int level0, bool implicit){ asn1_ctx_t ctx; chunk_t object; u_int level; int objectID = 0; generalName_t *top_gn = NULL; asn1_init(&ctx, blob, level0, implicit, DBG_RAW); while (objectID < GENERAL_NAMES_ROOF) { if (!extract_object(generalNamesObjects, &objectID, &object, &level, &ctx)) return NULL; if (objectID == GENERAL_NAMES_GN) { generalName_t *gn = parse_generalName(object, level+1); if (gn != NULL) { gn->next = top_gn; top_gn = gn; } } objectID++; } return top_gn;}/* * returns a directoryName */chunk_t get_directoryName(chunk_t blob, int level, bool implicit){ chunk_t name = empty_chunk; generalName_t * gn = parse_generalNames(blob, level, implicit); if (gn != NULL && gn->kind == GN_DIRECTORY_NAME) name= gn->name; free_generalNames(gn, FALSE); return name;}/* * extracts and converts a UTCTIME or GENERALIZEDTIME object */static time_tparse_time(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 < TIME_ROOF) { if (!extract_object(timeObjects, &objectID, &object, &level, &ctx)) return UNDEFINED_TIME; if (objectID == TIME_UTC || objectID == TIME_GENERALIZED) { return asn1totime(&object, (objectID == TIME_UTC) ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME); } objectID++; } return UNDEFINED_TIME; }/* * extracts an algorithmIdentifier */intparse_algorithmIdentifier(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 < ALGORITHM_IDENTIFIER_ROOF) { if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx)) return OID_UNKNOWN; if (objectID == ALGORITHM_IDENTIFIER_ALG) return known_oid(object); objectID++; } return OID_UNKNOWN; }/* * extracts a keyIdentifier */static chunk_tparse_keyIdentifier(chunk_t blob, int level0, bool implicit){ asn1_ctx_t ctx; chunk_t object; u_int level; int objectID = 0; asn1_init(&ctx, blob, level0, implicit, DBG_RAW); extract_object(keyIdentifierObjects, &objectID, &object, &level, &ctx); return object;}/* * extracts an authoritykeyIdentifier */voidparse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber){ asn1_ctx_t ctx; chunk_t object; u_int level; int objectID = 0; asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < AUTH_KEY_ID_ROOF) { if (!extract_object(authorityKeyIdentifierObjects, &objectID, &object, &level, &ctx)) return; switch (objectID) { case AUTH_KEY_ID_KEY_ID: *authKeyID = parse_keyIdentifier(object, level+1, TRUE); break; case AUTH_KEY_ID_CERT_ISSUER: { generalName_t * gn = parse_generalNames(object, level+1, TRUE); free_generalNames(gn, FALSE); } break; case AUTH_KEY_ID_CERT_SERIAL: *authKeySerialNumber = object; break; default: break; } objectID++; }}/* * extracts an authorityInfoAcess location */static voidparse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation){ asn1_ctx_t ctx; chunk_t object; u_int level; int objectID = 0; u_int accessMethod = OID_UNKNOWN; asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < AUTH_INFO_ACCESS_ROOF) { if (!extract_object(authorityInfoAccessObjects, &objectID, &object, &level, &ctx)) return; switch (objectID) { case AUTH_INFO_ACCESS_METHOD: accessMethod = known_oid(object); break; case AUTH_INFO_ACCESS_LOCATION: { switch (accessMethod) { case OID_OCSP: if (*object.ptr == ASN1_CONTEXT_S_6) { if (asn1_length(&object) == ASN1_INVALID_LENGTH) return; DBG(DBG_PARSING, DBG_log(" '%.*s'",(int)object.len, object.ptr) ) /* only HTTP(S) URIs accepted */ if (strncasecmp(object.ptr, "http", 4) == 0) { *accessLocation = object; return; } } openswan_log("warning: ignoring OCSP InfoAccessLocation with unkown protocol"); break; default: /* unkown accessMethod, ignoring */ break; } } break; default: break; } objectID++; }}/* * extracts extendedKeyUsage OIDs */static boolparse_extendedKeyUsage(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 < EXT_KEY_USAGE_ROOF) { if (!extract_object(extendedKeyUsageObjects, &objectID , &object, &level, &ctx)) return FALSE; if (objectID == EXT_KEY_USAGE_PURPOSE_ID && known_oid(object) == OID_OCSP_SIGNING) return TRUE; objectID++; } return FALSE;}/* extracts one or several crlDistributionPoints and puts them into * a chained list */static generalName_t*parse_crlDistributionPoints(chunk_t blob, int level0){ asn1_ctx_t ctx; chunk_t object; u_int level; int objectID = 0; generalName_t *top_gn = NULL; /* top of the chained list */ generalName_t **tail_gn = &top_gn; /* tail of the chained list */ asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < CRL_DIST_POINTS_ROOF) { if (!extract_object(crlDistributionPointsObjects, &objectID, &object, &level, &ctx)) return NULL; if (objectID == CRL_DIST_POINTS_FULLNAME) { generalName_t *gn = parse_generalNames(object, level+1, TRUE); /* append extracted generalNames to existing chained list */ *tail_gn = gn; /* find new tail of the chained list */ while (gn != NULL) { tail_gn = &gn->next; gn = gn->next; } } objectID++; } return top_gn;}/* * Parses an X.509v3 certificate */boolparse_x509cert(chunk_t blob, u_int level0, x509cert_t *cert){ u_char buf[BUF_LEN]; asn1_ctx_t ctx; bool critical; chunk_t object; u_int level; u_int extn_oid; int objectID = 0; asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < X509_OBJ_ROOF) { if (!extract_object(certObjects, &objectID, &object, &level, &ctx)) return FALSE; /* those objects which will parsed further need the next higher level */ level++; switch (objectID) { case X509_OBJ_CERTIFICATE: cert->certificate = object; break; case X509_OBJ_TBS_CERTIFICATE: cert->tbsCertificate = object; break; case X509_OBJ_VERSION: cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1; DBG(DBG_PARSING, DBG_log(" v%d", cert->version); ) break; case X509_OBJ_SERIAL_NUMBER: cert->serialNumber = object; break; case X509_OBJ_SIG_ALG: cert->sigAlg = parse_algorithmIdentifier(object, level); break; case X509_OBJ_ISSUER: cert->issuer = object; DBG(DBG_PARSING, dntoa(buf, BUF_LEN, object); DBG_log(" '%s'",buf) ) break; case X509_OBJ_NOT_BEFORE: cert->notBefore = parse_time(object, level); break; case X509_OBJ_NOT_AFTER: cert->notAfter = parse_time(object, level); break; case X509_OBJ_SUBJECT: cert->subject = object; DBG(DBG_PARSING, dntoa(buf, BUF_LEN, object); DBG_log(" '%s'",buf) ) break; case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM: if (parse_algorithmIdentifier(object, level) == OID_RSA_ENCRYPTION) cert->subjectPublicKeyAlgorithm = PUBKEY_ALG_RSA; else { plog(" unsupported public key algorithm"); return FALSE; } break; case X509_OBJ_SUBJECT_PUBLIC_KEY: if (ctx.blobs[4].len > 0 && *ctx.blobs[4].ptr == 0x00) { /* skip initial bit string octet defining 0 unused bits */ ctx.blobs[4].ptr++; ctx.blobs[4].len--; } else { plog(" invalid RSA public key format"); return FALSE; } break; case X509_OBJ_MODULUS: if (object.len < RSA_MIN_OCTETS + 1) { plog(" " RSA_MIN_OCTETS_UGH); return FALSE; } if (object.len > RSA_MAX_OCTETS + (size_t)(*object.ptr == 0x00)) { plog(" " RSA_MAX_OCTETS_UGH); return FALSE; } cert->modulus = object; break; case X509_OBJ_PUBLIC_EXPONENT: cert->publicExponent = object; break; case X509_OBJ_EXTN_ID: extn_oid = known_oid(object); break; case X509_OBJ_CRITICAL: critical = object.len && *object.ptr; DBG(DBG_PARSING, DBG_log(" %s",(critical)?"TRUE":"FALSE"); ) break; case X509_OBJ_EXTN_VALUE: { switch (extn_oid) { case OID_SUBJECT_KEY_ID: cert->subjectKeyID = parse_keyIdentifier(object, level, FALSE); break; case OID_SUBJECT_ALT_NAME: cert->subjectAltName = parse_generalNames(object, level, FALSE); break; case OID_BASIC_CONSTRAINTS: cert->isCA = parse_basicConstraints(object, level); break; case OID_CRL_DISTRIBUTION_POINTS: cert->crlDistributionPoints = parse_crlDistributionPoints(object, level); break; case OID_AUTHORITY_KEY_ID: parse_authorityKeyIdentifier(object, level , &cert->authKeyID, &cert->authKeySerialNumber); break; case OID_AUTHORITY_INFO_ACCESS: parse_authorityInfoAccess(object, level, &cert->accessLocation); break; case OID_EXTENDED_KEY_USAGE: cert->isOcspSigner = parse_extendedKeyUsage(object, level); break; default: break; } } break; case X509_OBJ_ALGORITHM: cert->algorithm = parse_algorithmIdentifier(object, level); break; case X509_OBJ_SIGNATURE: cert->signature = object; break; default: break; } objectID++; } time(&cert->installed); return TRUE;}/* * Parses an X.509 CRL */boolparse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl){ u_char buf[BUF_LEN]; asn1_ctx_t ctx; bool critical; chunk_t extnID; chunk_t userCertificate; chunk_t object; u_int level; int objectID = 0; asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < CRL_OBJ_ROOF) { if (!extract_object(crlObjects, &objectID, &object, &level, &ctx)) return FALSE; /* those objects which will parsed further need the next higher level */ level++; switch (objectID) { case CRL_OBJ_CERTIFICATE_LIST: crl->certificateList = object; break; case CRL_OBJ_TBS_CERT_LIST: crl->tbsCertList = object; break; case CRL_OBJ_VERSION: crl->version = (object.len) ? (1+(u_int)*object.ptr) : 1; DBG(DBG_PARSING, DBG_log(" v%d", crl->version); ) break; case CRL_OBJ_SIG_ALG: crl->sigAlg = parse_algorithmIdentifier(object, level); break; case CRL_OBJ_ISSUER: crl->issuer = object; DBG(DBG_PARSING, dntoa(buf, BUF_LEN, object); DBG_log(" '%s'",buf) ) break; case CRL_OBJ_THIS_UPDATE: crl->thisUpdate = parse_time(object, level); break; case CRL_OBJ_NEXT_UPDATE: crl->nextUpdate = parse_time(object, level); break; case CRL_OBJ_USER_CERTIFICATE: userCertificate = object; break; case CRL_OBJ_REVOCATION_DATE: { /* put all the serial numbers and the revocation date in a chained list with revocedCertificates pointing to the first revoked certificate */ revokedCert_t *revokedCert = alloc_thing(revokedCert_t, "revokedCert"); revokedCert->userCertificate = userCertificate; revokedCert->revocationDate = parse_time(object, level); revokedCert->n
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -