static int load_crl(const char *path, time_t *t, CRLCertificateList *crl) { size_t length, size; struct stat sb; void *data; int ret; memset(crl, 0, sizeof(*crl)); ret = rk_undumpdata(path, &data, &length); if (ret) return ret; ret = stat(path, &sb); if (ret) return errno; *t = sb.st_mtime; ret = decode_CRLCertificateList(data, length, crl, &size); rk_xfree(data); if (ret) return ret; /* check signature is aligned */ if (crl->signatureValue.length & 7) { free_CRLCertificateList(crl); return HX509_CRYPTO_SIG_INVALID_FORMAT; } return 0; }
void _hx509_unmap_file_os(heim_octet_string *os) { rk_xfree(os->data); }
static int file_init_common(hx509_context context, hx509_certs certs, void **data, int flags, const char *residue, hx509_lock lock, outformat format) { char *p, *pnext; struct ks_file *f = NULL; hx509_private_key *keys = NULL; int ret; struct pem_ctx pem_ctx; pem_ctx.flags = flags; pem_ctx.c = NULL; *data = NULL; if (lock == NULL) lock = _hx509_empty_lock; f = calloc(1, sizeof(*f)); if (f == NULL) { hx509_clear_error_string(context); return ENOMEM; } f->format = format; f->fn = strdup(residue); if (f->fn == NULL) { hx509_clear_error_string(context); ret = ENOMEM; goto out; } /* * XXX this is broken, the function should parse the file before * overwriting it */ if (flags & HX509_CERTS_CREATE) { ret = hx509_certs_init(context, "MEMORY:ks-file-create", 0, lock, &f->certs); if (ret) goto out; *data = f; return 0; } ret = _hx509_collector_alloc(context, lock, &pem_ctx.c); if (ret) goto out; for (p = f->fn; p != NULL; p = pnext) { FILE *f; pnext = strchr(p, ','); if (pnext) *pnext++ = '\0'; if ((f = fopen(p, "r")) == NULL) { ret = ENOENT; hx509_set_error_string(context, 0, ret, "Failed to open PEM file \"%s\": %s", p, strerror(errno)); goto out; } rk_cloexec_file(f); ret = hx509_pem_read(context, f, pem_func, &pem_ctx); fclose(f); if (ret != 0 && ret != HX509_PARSING_KEY_FAILED) goto out; else if (ret == HX509_PARSING_KEY_FAILED) { size_t length; void *ptr; int i; ret = rk_undumpdata(p, &ptr, &length); if (ret) { hx509_clear_error_string(context); goto out; } for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length); if (ret == 0) break; } rk_xfree(ptr); if (ret) goto out; } } ret = _hx509_collector_collect_certs(context, pem_ctx.c, &f->certs); if (ret) goto out; ret = _hx509_collector_collect_private_keys(context, pem_ctx.c, &keys); if (ret == 0) { int i; for (i = 0; keys[i]; i++) _hx509_certs_keys_add(context, f->certs, keys[i]); _hx509_certs_keys_free(context, keys); } out: if (ret == 0) *data = f; else { if (f->fn) free(f->fn); free(f); } if (pem_ctx.c) _hx509_collector_free(pem_ctx.c); return ret; }
static int p12_init(hx509_context context, hx509_certs certs, void **data, int flags, const char *residue, hx509_lock lock) { struct ks_pkcs12 *p12; size_t len; void *buf; PKCS12_PFX pfx; PKCS12_AuthenticatedSafe as; int ret; size_t i; struct hx509_collector *c; *data = NULL; if (lock == NULL) lock = _hx509_empty_lock; ret = _hx509_collector_alloc(context, lock, &c); if (ret) return ret; p12 = calloc(1, sizeof(*p12)); if (p12 == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "out of memory"); goto out; } p12->fn = strdup(residue); if (p12->fn == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "out of memory"); goto out; } if (flags & HX509_CERTS_CREATE) { ret = hx509_certs_init(context, "MEMORY:ks-file-create", 0, lock, &p12->certs); if (ret == 0) *data = p12; goto out; } ret = rk_undumpdata(residue, &buf, &len); if (ret) { hx509_clear_error_string(context); goto out; } ret = decode_PKCS12_PFX(buf, len, &pfx, NULL); rk_xfree(buf); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode the PFX in %s", residue); goto out; } if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) { free_PKCS12_PFX(&pfx); ret = EINVAL; hx509_set_error_string(context, 0, ret, "PKCS PFX isn't a pkcs7-data container"); goto out; } if (pfx.authSafe.content == NULL) { free_PKCS12_PFX(&pfx); ret = EINVAL; hx509_set_error_string(context, 0, ret, "PKCS PFX missing data"); goto out; } { heim_octet_string asdata; ret = decode_PKCS12_OctetString(pfx.authSafe.content->data, pfx.authSafe.content->length, &asdata, NULL); free_PKCS12_PFX(&pfx); if (ret) { hx509_clear_error_string(context); goto out; } ret = decode_PKCS12_AuthenticatedSafe(asdata.data, asdata.length, &as, NULL); der_free_octet_string(&asdata); if (ret) { hx509_clear_error_string(context); goto out; } } for (i = 0; i < as.len; i++) parse_pkcs12_type(context, c, &as.val[i].contentType, as.val[i].content->data, as.val[i].content->length, NULL); free_PKCS12_AuthenticatedSafe(&as); ret = _hx509_collector_collect_certs(context, c, &p12->certs); if (ret == 0) *data = p12; out: _hx509_collector_free(c); if (ret && p12) { if (p12->fn) free(p12->fn); if (p12->certs) hx509_certs_free(&p12->certs); free(p12); } return ret; }
int _hx509_request_parse(hx509_context context, const char *path, hx509_request *req) { CertificationRequest r; CertificationRequestInfo *rinfo; hx509_name subject; size_t len, size; void *p; int ret; if (strncmp(path, "PKCS10:", 7) != 0) { hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, "unsupport type in %s", path); return HX509_UNSUPPORTED_OPERATION; } path += 7; /* XXX PEM request */ ret = rk_undumpdata(path, &p, &len); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to map file %s", path); return ret; } ret = decode_CertificationRequest(p, len, &r, &size); rk_xfree(p); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to decode %s", path); return ret; } ret = _hx509_request_init(context, req); if (ret) { free_CertificationRequest(&r); return ret; } rinfo = &r.certificationRequestInfo; ret = _hx509_request_set_SubjectPublicKeyInfo(context, *req, &rinfo->subjectPKInfo); if (ret) { free_CertificationRequest(&r); _hx509_request_free(req); return ret; } ret = _hx509_name_from_Name(&rinfo->subject, &subject); if (ret) { free_CertificationRequest(&r); _hx509_request_free(req); return ret; } ret = _hx509_request_set_name(context, *req, subject); hx509_name_free(&subject); free_CertificationRequest(&r); if (ret) { _hx509_request_free(req); return ret; } return 0; }
static int load_ocsp(hx509_context context, struct revoke_ocsp *ocsp) { OCSPBasicOCSPResponse basic; hx509_certs certs = NULL; size_t length; struct stat sb; void *data; int ret; ret = rk_undumpdata(ocsp->path, &data, &length); if (ret) return ret; ret = stat(ocsp->path, &sb); if (ret) return errno; ret = parse_ocsp_basic(data, length, &basic); rk_xfree(data); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to parse OCSP response"); return ret; } if (basic.certs) { size_t i; ret = hx509_certs_init(context, "MEMORY:ocsp-certs", 0, NULL, &certs); if (ret) { free_OCSPBasicOCSPResponse(&basic); return ret; } for (i = 0; i < basic.certs->len; i++) { hx509_cert c; ret = hx509_cert_init(context, &basic.certs->val[i], &c); if (ret) continue; ret = hx509_certs_add(context, certs, c); hx509_cert_free(c); if (ret) continue; } } ocsp->last_modfied = sb.st_mtime; free_OCSPBasicOCSPResponse(&ocsp->ocsp); hx509_certs_free(&ocsp->certs); hx509_cert_free(ocsp->signer); ocsp->ocsp = basic; ocsp->certs = certs; ocsp->signer = NULL; return 0; }