/* * Loads PKCS#1 private key file */ pkcs1privkey_t* load_pkcs1_private_key(const char* filename, const char* passphrase) { chunk_t blob = empty_chunk; char path[512]; if (*filename == '/') /* absolute pathname */ strncpy(path, filename, sizeof(path)); else /* relative pathname */ snprintf(path, sizeof(path), "%s/%s", PRIVATE_KEY_PATH, filename); if (load_asn1_file(path, passphrase, "private key", &blob)) { pkcs1privkey_t *key = alloc_thing(pkcs1privkey_t, "pkcs1privkey"); *key = empty_pkcs1privkey; if (parse_pkcs1_private_key(blob, key)) return key; else { log(" error in PKCS#1 private key"); pfree(blob.ptr); pfree(key); } } return NULL; }
/* * Parse PKCS#7 wrapped X.509 certificates */ static bool parse_pkcs7_signedData(chunk_t blob, int level0, x509cert_t **cert) { asn1_ctx_t ctx; chunk_t object; u_int level; u_int objectID = 0; asn1_init(&ctx, blob, level0, FALSE, DBG_RAW); while (objectID < PKCS7_SIGNED_ROOF) { if (!extract_object(signedDataObjects, &objectID, &object, &level, &ctx)) return FALSE; if (objectID == PKCS7_SIGNED_CERT) { chunk_t cert_blob; x509cert_t *newcert = alloc_thing(x509cert_t, "pkcs7 wrapped x509cert"); clonetochunk(cert_blob, object.ptr, object.len, "pkcs7 cert blob"); *newcert = empty_x509cert; if (parse_x509cert(cert_blob, level + 1, newcert)) { newcert->next = *cert; *cert = newcert; } else { free_x509cert(newcert); } } objectID++; } return TRUE; }
/* * parses ietfAttrSyntax */ static ietfAttrList_t* parse_ietfAttrSyntax(chunk_t blob, int level0) { asn1_ctx_t ctx; chunk_t object; u_int level; u_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; }
/* * decodes a comma separated list of group attributes */ void decode_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 = (unsigned char *)groups; attr->value.len = end - groups; attr->count = 0; el->attr = add_ietfAttr(attr); el->next = *listp; *listp = el; } groups = next; } }
pb_stream *pbs_create(int size) { pb_stream *n; void *mem; n = alloc_thing(*n, "pbs_create"); mem=alloc_bytes(size, "pbs_memory"); init_pbs(n, mem, size, "tpm_pbs"); return n; }
/* * Decode the CR payload of Phase 1. */ void decode_cr(struct msg_digest *md, generalName_t **requested_ca) { struct payload_digest *p; for (p = md->chain[ISAKMP_NEXT_CR]; p != NULL; p = p->next) { struct isakmp_cr *const cr = &p->payload.cr; chunk_t ca_name; ca_name.len = pbs_left(&p->pbs); ca_name.ptr = (ca_name.len > 0)? p->pbs.cur : NULL; DBG_cond_dump_chunk(DBG_PARSING, "CR", ca_name); if (cr->isacr_type == CERT_X509_SIGNATURE) { if (ca_name.len > 0) { generalName_t *gn; if (!is_asn1(ca_name)) continue; gn = alloc_thing(generalName_t, "generalName"); clonetochunk(ca_name, ca_name.ptr,ca_name.len, "ca name"); gn->kind = GN_DIRECTORY_NAME; gn->name = ca_name; gn->next = *requested_ca; *requested_ca = gn; } DBG(DBG_PARSING | DBG_CONTROL, char buf[IDTOA_BUF]; dntoa_or_null(buf, IDTOA_BUF, ca_name, "%any"); DBG_log("requested CA: '%s'", buf); ) } else loglog(RC_LOG_SERIOUS, "ignoring %s certificate request payload", enum_show(&cert_type_names, cr->isacr_type)); }
/* * 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; } }
/* * Insert X.509 CRL into chained list */ bool insert_crl(chunk_t blob, chunk_t crl_uri) { x509crl_t *crl = alloc_thing(x509crl_t, "x509crl"); *crl = empty_x509crl; if (parse_x509crl(blob, 0, crl)) { x509cert_t *issuer_cert; x509crl_t *oldcrl; bool valid_sig; generalName_t *gn; /* add distribution point */ gn = alloc_thing(generalName_t, "generalName"); gn->kind = GN_URI; gn->name = crl_uri; gn->next = crl->distributionPoints; crl->distributionPoints = gn; lock_authcert_list("insert_crl"); /* get the issuer cacert */ issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber, crl->authKeyID, AUTH_CA); if (issuer_cert == NULL) { chunk_t *n = &crl->distributionPoints->name; loglog(RC_LOG_SERIOUS, "CRL rejected: crl issuer cacert not found for %.*s", (int)n->len, (char *)n->ptr); free_crl(crl); unlock_authcert_list("insert_crl"); return FALSE; } DBG(DBG_X509, DBG_log("crl issuer cacert found")); /* check the issuer's signature of the crl */ valid_sig = check_signature(crl->tbsCertList, crl->signature, crl->algorithm, issuer_cert); unlock_authcert_list("insert_crl"); if (!valid_sig) { free_crl(crl); return FALSE; } DBG(DBG_X509, DBG_log("valid crl signature")); lock_crl_list("insert_crl"); oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber, crl->authKeyID); if (oldcrl != NULL) { if (realbefore(oldcrl->thisUpdate, crl->thisUpdate)) { /* old CRL is older than new CRL: replace */ #if defined(LIBCURL) || defined(LDAP_VER) /* keep any known CRL distribution points */ add_distribution_points( oldcrl->distributionPoints, &crl->distributionPoints); #endif /* now delete the old CRL */ free_first_crl(); DBG(DBG_X509, DBG_log("thisUpdate is newer - existing crl deleted")); } else { /* old CRL is not older than new CRL: keep old one */ unlock_crl_list("insert_crls"); DBG(DBG_X509, DBG_log("thisUpdate is not newer - existing crl not replaced")); free_crl(crl); /* * is the fetched crl valid? * now + 2 * crl_check_interval < oldcrl->nextUpdate */ return realbefore(realtimesum(realnow(), deltatimescale(2, 1, crl_check_interval)), oldcrl->nextUpdate); } } /* insert new CRL */ crl->next = x509crls; x509crls = crl; unlock_crl_list("insert_crl"); /* * is the new crl valid? * now + 2 * crl_check_interval < crl->nextUpdate */ return realbefore(realtimesum(realnow(), deltatimescale(2, 1, crl_check_interval)), crl->nextUpdate); } else { loglog(RC_LOG_SERIOUS, " error in X.509 crl %s", (char *)crl_uri.ptr); free_crl(crl); return FALSE; } }
/* * Insert X.509 CRL into chained list */ bool insert_crl(chunk_t blob, chunk_t crl_uri) { x509crl_t *crl = alloc_thing(x509crl_t, "x509crl"); *crl = empty_x509crl; if (parse_x509crl(blob, 0, crl)) { x509cert_t *issuer_cert; x509crl_t *oldcrl; bool valid_sig; generalName_t *gn; /* add distribution point */ gn = alloc_thing(generalName_t, "generalName"); gn->kind = GN_URI; gn->name = crl_uri; gn->next = crl->distributionPoints; crl->distributionPoints = gn; lock_authcert_list("insert_crl"); /* get the issuer cacert */ issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber, crl->authKeyID, AUTH_CA); if (issuer_cert == NULL) { char distpoint[PATH_MAX]; distpoint[0] = '\0'; strncat(distpoint, (char *)crl->distributionPoints->name.ptr, (crl->distributionPoints->name.len < PATH_MAX ? crl->distributionPoints->name.len : PATH_MAX)); openswan_log("crl issuer cacert not found for (%s)", distpoint);; free_crl(crl); unlock_authcert_list("insert_crl"); return FALSE; } DBG(DBG_X509, DBG_log("crl issuer cacert found") ) /* check the issuer's signature of the crl */ valid_sig = check_signature(crl->tbsCertList, crl->signature , crl->algorithm, issuer_cert); unlock_authcert_list("insert_crl"); if (!valid_sig) { free_crl(crl); return FALSE; } DBG(DBG_X509, DBG_log("valid crl signature") ) lock_crl_list("insert_crl"); oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber , crl->authKeyID); if (oldcrl != NULL) { if (crl->thisUpdate > oldcrl->thisUpdate) { #ifdef HAVE_THREADS /* keep any known CRL distribution points */ add_distribution_points(oldcrl->distributionPoints , &crl->distributionPoints); #endif /* now delete the old CRL */ free_first_crl(); DBG(DBG_X509, DBG_log("thisUpdate is newer - existing crl deleted") ) } else {