Пример #1
0
static int
any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs)
{
    int ret;
    size_t i;

    if (sd->certificates == NULL)
	return 0;

    for (i = 0; i < sd->certificates->len; i++) {
	heim_error_t error;
	hx509_cert c;

	c = hx509_cert_init_data(context,
				 sd->certificates->val[i].data,
				 sd->certificates->val[i].length,
				 &error);
	if (c == NULL) {
	    ret = heim_error_get_code(error);
	    heim_release(error);
	    return ret;
	}
	ret = hx509_certs_add(context, certs, c);
	hx509_cert_free(c);
	if (ret)
	    return ret;
    }

    return 0;
}
Пример #2
0
static int
any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs)
{
    int ret;
    size_t i;

    if (sd->certificates == NULL)
	return 0;

    for (i = 0; i < sd->certificates->len; i++) {
	hx509_cert c;

	ret = hx509_cert_init_data(context,
				   sd->certificates->val[i].data,
				   sd->certificates->val[i].length,
				   &c);
	if (ret)
	    return ret;
	ret = hx509_certs_add(context, certs, c);
	hx509_cert_free(c);
	if (ret)
	    return ret;
    }

    return 0;
}
Пример #3
0
static int
certBag_parser(hx509_context context,
	       struct hx509_collector *c,
	       const void *data, size_t length,
	       const PKCS12_Attributes *attrs)
{
    heim_octet_string os;
    hx509_cert cert;
    PKCS12_CertBag cb;
    int ret;

    ret = decode_PKCS12_CertBag(data, length, &cb, NULL);
    if (ret)
	return ret;

    if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType)) {
	free_PKCS12_CertBag(&cb);
	return 0;
    }

    ret = decode_PKCS12_OctetString(cb.certValue.data,
				    cb.certValue.length,
				    &os,
				    NULL);
    free_PKCS12_CertBag(&cb);
    if (ret)
	return ret;

    ret = hx509_cert_init_data(context, os.data, os.length, &cert);
    der_free_octet_string(&os);
    if (ret)
	return ret;

    ret = _hx509_collector_certs_add(context, c, cert);
    if (ret) {
	hx509_cert_free(cert);
	return ret;
    }

    {
	const PKCS12_Attribute *attr;
	const heim_oid *oids[] = {
	    &asn1_oid_id_pkcs_9_at_localKeyId, &asn1_oid_id_pkcs_9_at_friendlyName
	};
	size_t i;

	for  (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) {
	    const heim_oid *oid = oids[i];
	    attr = find_attribute(attrs, oid);
	    if (attr)
		_hx509_set_cert_attribute(context, cert, oid,
					  &attr->attrValues);
	}
    }

    hx509_cert_free(cert);

    return 0;
}
Пример #4
0
static int
collect_cert(hx509_context context,
             struct p11_module *p, struct p11_slot *slot,
             CK_SESSION_HANDLE session,
             CK_OBJECT_HANDLE object,
             void *ptr, CK_ATTRIBUTE *query, int num_query)
{
    struct hx509_collector *collector = ptr;
    hx509_cert cert;
    int ret;

    if ((CK_LONG)query[0].ulValueLen == -1 ||
            (CK_LONG)query[1].ulValueLen == -1)
    {
        return 0;
    }

    ret = hx509_cert_init_data(context, query[1].pValue,
                               query[1].ulValueLen, &cert);
    if (ret)
        return ret;

    if (p->ref == 0)
        _hx509_abort("pkcs11 ref == 0 on alloc");
    p->ref++;
    if (p->ref == UINT_MAX)
        _hx509_abort("pkcs11 ref to high");

    _hx509_cert_set_release(cert, p11_cert_release, p);

    {
        heim_octet_string data;

        data.data = query[0].pValue;
        data.length = query[0].ulValueLen;

        _hx509_set_cert_attribute(context,
                                  cert,
                                  oid_id_pkcs_9_at_localKeyId(),
                                  &data);
    }

    if ((CK_LONG)query[2].ulValueLen != -1) {
        char *str;

        asprintf(&str, "%.*s",
                 (int)query[2].ulValueLen, (char *)query[2].pValue);
        if (str) {
            hx509_cert_set_friendly_name(cert, str);
            free(str);
        }
    }

    ret = _hx509_collector_certs_add(context, collector, cert);
    hx509_cert_free(cert);

    return ret;
}
Пример #5
0
/*
 * Encrypt a blob with the private key of the certificate
 * passed as a parameter.
 */
static DATA_BLOB *encrypt_blob_pk(struct torture_context *tctx,
				  TALLOC_CTX *mem_ctx,
				  uint8_t *cert_data,
				  uint32_t cert_len,
				  DATA_BLOB *to_encrypt)
{
	hx509_context hctx;
	hx509_cert cert;
	heim_octet_string secretdata;
	heim_octet_string encrypted;
	heim_oid encryption_oid;
	DATA_BLOB *blob;
	int hret;

	hx509_context_init(&hctx);

	hret = hx509_cert_init_data(hctx, cert_data, cert_len, &cert);
	if (hret) {
		torture_comment(tctx, "error while loading the cert\n");
		hx509_context_free(&hctx);
		return NULL;
	}

	secretdata.data = to_encrypt->data;
	secretdata.length = to_encrypt->length;
	hret = hx509_cert_public_encrypt(hctx, &secretdata,
					  cert, &encryption_oid,
					  &encrypted);
	hx509_cert_free(cert);
	hx509_context_free(&hctx);
	if (hret) {
		torture_comment(tctx, "error while encrypting\n");
		return NULL;
	}

	blob = talloc_zero(mem_ctx, DATA_BLOB);
	if (blob == NULL) {
		der_free_oid(&encryption_oid);
		der_free_octet_string(&encrypted);
		return NULL;
	}

	*blob = data_blob_talloc(blob, encrypted.data, encrypted.length);
	der_free_octet_string(&encrypted);
	der_free_oid(&encryption_oid);
	if (blob->data == NULL) {
		return NULL;
	}

	return blob;
}
Пример #6
0
static int
test_compare(hx509_context context)
{
    int ret;
    hx509_cert c1, c2, c3;
    int l0, l1, l2, l3;

    /* check transative properties of name compare function */

    ret = hx509_cert_init_data(context, certdata1, sizeof(certdata1) - 1, &c1);
    if (ret) return 1;

    ret = hx509_cert_init_data(context, certdata2, sizeof(certdata2) - 1, &c2);
    if (ret) return 1;

    ret = hx509_cert_init_data(context, certdata3, sizeof(certdata3) - 1, &c3);
    if (ret) return 1;

    ret = compare_subject(c1, c1, &l0);
    if (ret) return 1;
    ret = compare_subject(c1, c2, &l1);
    if (ret) return 1;
    ret = compare_subject(c1, c3, &l2);
    if (ret) return 1;
    ret = compare_subject(c2, c3, &l3);
    if (ret) return 1;

    if (l0 != 0) return 1;
    if (l2 < l1) return 1;
    if (l3 < l2) return 1;
    if (l3 < l1) return 1;

    hx509_cert_free(c1);
    hx509_cert_free(c2);
    hx509_cert_free(c3);

    return 0;
}
Пример #7
0
/*
 * Certs used for this protocol have a GUID in the issuer_uniq_id field.
 * This function fetch it.
 */
static struct GUID *get_cert_guid(struct torture_context *tctx,
				  TALLOC_CTX *mem_ctx,
				  uint8_t *cert_data,
				  uint32_t cert_len)
{
	hx509_context hctx;
	hx509_cert cert;
	heim_bit_string subjectuniqid;
	DATA_BLOB data;
	int hret;
	uint32_t size;
	struct GUID *guid = talloc_zero(mem_ctx, struct GUID);
	NTSTATUS status;

	hx509_context_init(&hctx);

	hret = hx509_cert_init_data(hctx, cert_data, cert_len, &cert);
	if (hret) {
		torture_comment(tctx, "error while loading the cert\n");
		hx509_context_free(&hctx);
		return NULL;
	}
	hret = hx509_cert_get_issuer_unique_id(hctx, cert, &subjectuniqid);
	if (hret) {
		torture_comment(tctx, "error while getting the issuer_uniq_id\n");
		hx509_cert_free(cert);
		hx509_context_free(&hctx);
		return NULL;
	}

	/* The subjectuniqid is a bit string,
	 * which means that the real size has to be divided by 8
	 * to have the number of bytes
	 */
	hx509_cert_free(cert);
	hx509_context_free(&hctx);
	size = subjectuniqid.length / 8;
	data = data_blob_const(subjectuniqid.data, size);

	status = GUID_from_data_blob(&data, guid);
	der_free_bit_string(&subjectuniqid);
	if (!NT_STATUS_IS_OK(status)) {
		return NULL;
	}

	return guid;
}
Пример #8
0
static int
parse_certificate(hx509_context context, const char *fn,
		  struct hx509_collector *c,
		  const hx509_pem_header *headers,
		  const void *data, size_t len)
{
    hx509_cert cert;
    int ret;

    ret = hx509_cert_init_data(context, data, len, &cert);
    if (ret)
	return ret;

    ret = _hx509_collector_certs_add(context, c, cert);
    hx509_cert_free(cert);
    return ret;
}
Пример #9
0
static int
parse_certificate(hx509_context context, const char *fn,
		  struct hx509_collector *c,
		  const hx509_pem_header *headers,
		  const void *data, size_t len,
		  const AlgorithmIdentifier *ai)
{
    heim_error_t error = NULL;
    hx509_cert cert;
    int ret;

    cert = hx509_cert_init_data(context, data, len, &error);
    if (cert == NULL) {
	ret = heim_error_get_code(error);
	heim_release(error);
	return ret;
    }

    ret = _hx509_collector_certs_add(context, c, cert);
    hx509_cert_free(cert);
    return ret;
}
Пример #10
0
krb5_error_code
_kdc_pk_rd_padata(krb5_context context,
		  krb5_kdc_configuration *config,
		  const KDC_REQ *req,
		  const PA_DATA *pa,
		  hdb_entry_ex *client,
		  pk_client_params **ret_params)
{
    pk_client_params *cp;
    krb5_error_code ret;
    heim_oid eContentType = { 0, NULL }, contentInfoOid = { 0, NULL };
    krb5_data eContent = { 0, NULL };
    krb5_data signed_content = { 0, NULL };
    const char *type = "unknown type";
    hx509_certs trust_anchors;
    int have_data = 0;
    const HDB_Ext_PKINIT_cert *pc;

    *ret_params = NULL;

    if (!config->enable_pkinit) {
	kdc_log(context, config, 0, "PK-INIT request but PK-INIT not enabled");
	krb5_clear_error_message(context);
	return 0;
    }

    cp = calloc(1, sizeof(*cp));
    if (cp == NULL) {
	krb5_clear_error_message(context);
	ret = ENOMEM;
	goto out;
    }

    ret = hx509_certs_init(context->hx509ctx,
			   "MEMORY:trust-anchors",
			   0, NULL, &trust_anchors);
    if (ret) {
	krb5_set_error_message(context, ret, "failed to create trust anchors");
	goto out;
    }

    ret = hx509_certs_merge(context->hx509ctx, trust_anchors,
			    kdc_identity->anchors);
    if (ret) {
	hx509_certs_free(&trust_anchors);
	krb5_set_error_message(context, ret, "failed to create verify context");
	goto out;
    }

    /* Add any registered certificates for this client as trust anchors */
    ret = hdb_entry_get_pkinit_cert(&client->entry, &pc);
    if (ret == 0 && pc != NULL) {
	hx509_cert cert;
	unsigned int i;

	for (i = 0; i < pc->len; i++) {
	    cert = hx509_cert_init_data(context->hx509ctx,
					pc->val[i].cert.data,
					pc->val[i].cert.length,
					NULL);
	    if (cert == NULL)
		continue;
	    hx509_certs_add(context->hx509ctx, trust_anchors, cert);
	    hx509_cert_free(cert);
	}
    }

    ret = hx509_verify_init_ctx(context->hx509ctx, &cp->verify_ctx);
    if (ret) {
	hx509_certs_free(&trust_anchors);
	krb5_set_error_message(context, ret, "failed to create verify context");
	goto out;
    }

    hx509_verify_set_time(cp->verify_ctx, kdc_time);
    hx509_verify_attach_anchors(cp->verify_ctx, trust_anchors);
    hx509_certs_free(&trust_anchors);

    if (config->pkinit_allow_proxy_certs)
	hx509_verify_set_proxy_certificate(cp->verify_ctx, 1);

    if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) {
	PA_PK_AS_REQ_Win2k r;

	type = "PK-INIT-Win2k";

	if (_kdc_is_anon_request(&req->req_body)) {
	    ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED;
	    krb5_set_error_message(context, ret,
				   "Anon not supported in RSA mode");
	    goto out;
	}

	ret = decode_PA_PK_AS_REQ_Win2k(pa->padata_value.data,
					pa->padata_value.length,
					&r,
					NULL);
	if (ret) {
	    krb5_set_error_message(context, ret, "Can't decode "
				   "PK-AS-REQ-Win2k: %d", ret);
	    goto out;
	}

	ret = hx509_cms_unwrap_ContentInfo(&r.signed_auth_pack,
					   &contentInfoOid,
					   &signed_content,
					   &have_data);
	free_PA_PK_AS_REQ_Win2k(&r);
	if (ret) {
	    krb5_set_error_message(context, ret,
				   "Can't unwrap ContentInfo(win): %d", ret);
	    goto out;
	}

    } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) {
	PA_PK_AS_REQ r;

	type = "PK-INIT-IETF";

	ret = decode_PA_PK_AS_REQ(pa->padata_value.data,
				  pa->padata_value.length,
				  &r,
				  NULL);
	if (ret) {
	    krb5_set_error_message(context, ret,
				   "Can't decode PK-AS-REQ: %d", ret);
	    goto out;
	}

	/* XXX look at r.kdcPkId */
	if (r.trustedCertifiers) {
	    ExternalPrincipalIdentifiers *edi = r.trustedCertifiers;
	    unsigned int i, maxedi;

	    ret = hx509_certs_init(context->hx509ctx,
				   "MEMORY:client-anchors",
				   0, NULL,
				   &cp->client_anchors);
	    if (ret) {
		krb5_set_error_message(context, ret,
				       "Can't allocate client anchors: %d",
				       ret);
		goto out;

	    }
	    /*
	     * If the client sent more then 10 EDI, don't bother
	     * looking more then 10 of performance reasons.
	     */
	    maxedi = edi->len;
	    if (maxedi > 10)
		maxedi = 10;
	    for (i = 0; i < maxedi; i++) {
		IssuerAndSerialNumber iasn;
		hx509_query *q;
		hx509_cert cert;
		size_t size;

		if (edi->val[i].issuerAndSerialNumber == NULL)
		    continue;

		ret = hx509_query_alloc(context->hx509ctx, &q);
		if (ret) {
		    krb5_set_error_message(context, ret,
					  "Failed to allocate hx509_query");
		    goto out;
		}

		ret = decode_IssuerAndSerialNumber(edi->val[i].issuerAndSerialNumber->data,
						   edi->val[i].issuerAndSerialNumber->length,
						   &iasn,
						   &size);
		if (ret) {
		    hx509_query_free(context->hx509ctx, q);
		    continue;
		}
		ret = hx509_query_match_issuer_serial(q, &iasn.issuer, &iasn.serialNumber);
		free_IssuerAndSerialNumber(&iasn);
		if (ret) {
		    hx509_query_free(context->hx509ctx, q);
		    continue;
		}

		ret = hx509_certs_find(context->hx509ctx,
				       kdc_identity->certs,
				       q,
				       &cert);
		hx509_query_free(context->hx509ctx, q);
		if (ret)
		    continue;
		hx509_certs_add(context->hx509ctx,
				cp->client_anchors, cert);
		hx509_cert_free(cert);
	    }
	}

	ret = hx509_cms_unwrap_ContentInfo(&r.signedAuthPack,
					   &contentInfoOid,
					   &signed_content,
					   &have_data);
	free_PA_PK_AS_REQ(&r);
	if (ret) {
	    krb5_set_error_message(context, ret,
				   "Can't unwrap ContentInfo: %d", ret);
	    goto out;
	}

    } else {
	krb5_clear_error_message(context);
	ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
	goto out;
    }

    ret = der_heim_oid_cmp(&contentInfoOid, &asn1_oid_id_pkcs7_signedData);
    if (ret != 0) {
	ret = KRB5KRB_ERR_GENERIC;
	krb5_set_error_message(context, ret,
			       "PK-AS-REQ-Win2k invalid content type oid");
	goto out;
    }

    if (!have_data) {
	ret = KRB5KRB_ERR_GENERIC;
	krb5_set_error_message(context, ret,
			      "PK-AS-REQ-Win2k no signed auth pack");
	goto out;
    }

    {
	hx509_certs signer_certs;
	int flags = HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; /* BTMM */

	if (_kdc_is_anon_request(&req->req_body))
	    flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER;

	ret = hx509_cms_verify_signed(context->hx509ctx,
				      cp->verify_ctx,
				      flags,
				      signed_content.data,
				      signed_content.length,
				      NULL,
				      kdc_identity->certpool,
				      &eContentType,
				      &eContent,
				      &signer_certs);
	if (ret) {
	    char *s = hx509_get_error_string(context->hx509ctx, ret);
	    krb5_warnx(context, "PKINIT: failed to verify signature: %s: %d",
		       s, ret);
	    free(s);
	    goto out;
	}

	if (signer_certs) {
	    ret = hx509_get_one_cert(context->hx509ctx, signer_certs,
				     &cp->cert);
	    hx509_certs_free(&signer_certs);
	}
	if (ret)
	    goto out;
    }

    /* Signature is correct, now verify the signed message */
    if (der_heim_oid_cmp(&eContentType, &asn1_oid_id_pkcs7_data) != 0 &&
	der_heim_oid_cmp(&eContentType, &asn1_oid_id_pkauthdata) != 0)
    {
	ret = KRB5_BADMSGTYPE;
	krb5_set_error_message(context, ret, "got wrong oid for pkauthdata");
	goto out;
    }

    if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) {
	AuthPack_Win2k ap;

	ret = decode_AuthPack_Win2k(eContent.data,
				    eContent.length,
				    &ap,
				    NULL);
	if (ret) {
	    krb5_set_error_message(context, ret,
				   "Can't decode AuthPack: %d", ret);
	    goto out;
	}

	ret = pk_check_pkauthenticator_win2k(context,
					     &ap.pkAuthenticator,
					     req);
	if (ret) {
	    free_AuthPack_Win2k(&ap);
	    goto out;
	}

	cp->type = PKINIT_WIN2K;
	cp->nonce = ap.pkAuthenticator.nonce;

	if (ap.clientPublicValue) {
	    ret = KRB5KRB_ERR_GENERIC;
	    krb5_set_error_message(context, ret,
				   "DH not supported for windows");
	    goto out;
	}
	free_AuthPack_Win2k(&ap);

    } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) {
	AuthPack ap;

	ret = decode_AuthPack(eContent.data,
			      eContent.length,
			      &ap,
			      NULL);
	if (ret) {
	    krb5_set_error_message(context, ret,
				   "Can't decode AuthPack: %d", ret);
	    free_AuthPack(&ap);
	    goto out;
	}

	if (_kdc_is_anon_request(&req->req_body) &&
	    ap.clientPublicValue == NULL) {
	    free_AuthPack(&ap);
	    ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED;
	    krb5_set_error_message(context, ret,
				   "Anon not supported in RSA mode");
	    goto out;
	}

	ret = pk_check_pkauthenticator(context,
				       &ap.pkAuthenticator,
				       req);
	if (ret) {
	    free_AuthPack(&ap);
	    goto out;
	}

	cp->type = PKINIT_27;
	cp->nonce = ap.pkAuthenticator.nonce;

	if (ap.clientPublicValue) {
	    if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_dhpublicnumber) == 0) {
		cp->keyex = USE_DH;
		ret = get_dh_param(context, config,
				   ap.clientPublicValue, cp);
	    } else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) {
		cp->keyex = USE_ECDH;
                ret = _kdc_get_ecdh_param(context, config,
                                          ap.clientPublicValue,
                                          &cp->u.ecdh.public_key);
	    } else {
		ret = KRB5_BADMSGTYPE;
		krb5_set_error_message(context, ret, "PKINIT unknown DH mechanism");
	    }
	    if (ret) {
		free_AuthPack(&ap);
		goto out;
	    }
	} else
	    cp->keyex = USE_RSA;

	ret = hx509_peer_info_alloc(context->hx509ctx,
					&cp->peer);
	if (ret) {
	    free_AuthPack(&ap);
	    goto out;
	}

	if (ap.supportedCMSTypes) {
	    ret = hx509_peer_info_set_cms_algs(context->hx509ctx,
					       cp->peer,
					       ap.supportedCMSTypes->val,
					       ap.supportedCMSTypes->len);
	    if (ret) {
		free_AuthPack(&ap);
		goto out;
	    }
	} else {
	    /* assume old client */
	    hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer,
					hx509_crypto_des_rsdi_ede3_cbc());
	    hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer,
					hx509_signature_rsa_with_sha1());
	    hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer,
					hx509_signature_sha1());
	}
	free_AuthPack(&ap);
    } else
	krb5_abortx(context, "internal pkinit error");

    kdc_log(context, config, 0, "PK-INIT request of type %s", type);

out:
    if (ret)
	krb5_warn(context, ret, "PKINIT");

    if (signed_content.data)
	free(signed_content.data);
    krb5_data_free(&eContent);
    der_free_oid(&eContentType);
    der_free_oid(&contentInfoOid);
    if (ret) {
        _kdc_pk_free_client_param(context, cp);
    } else
	*ret_params = cp;
    return ret;
}
Пример #11
0
krb5_error_code
_kdc_pk_check_client(krb5_context context,
		     krb5_kdc_configuration *config,
		     HDB *clientdb,
		     hdb_entry_ex *client,
		     pk_client_params *cp,
		     char **subject_name)
{
    const HDB_Ext_PKINIT_acl *acl;
    const HDB_Ext_PKINIT_cert *pc;
    krb5_error_code ret;
    hx509_name name;
    size_t i;

    if (cp->cert == NULL) {

	*subject_name = strdup("anonymous client client");
	if (*subject_name == NULL)
	    return ENOMEM;
	return 0;
    }

    ret = hx509_cert_get_base_subject(context->hx509ctx,
				      cp->cert,
				      &name);
    if (ret)
	return ret;

    ret = hx509_name_to_string(name, subject_name);
    hx509_name_free(&name);
    if (ret)
	return ret;

    kdc_log(context, config, 0,
	    "Trying to authorize PK-INIT subject DN %s",
	    *subject_name);

    ret = hdb_entry_get_pkinit_cert(&client->entry, &pc);
    if (ret == 0 && pc) {
	hx509_cert cert;
	size_t j;

	for (j = 0; j < pc->len; j++) {
	    cert = hx509_cert_init_data(context->hx509ctx,
					pc->val[j].cert.data,
					pc->val[j].cert.length,
					NULL);
	    if (cert == NULL)
		continue;
	    ret = hx509_cert_cmp(cert, cp->cert);
	    hx509_cert_free(cert);
	    if (ret == 0) {
		kdc_log(context, config, 5,
			"Found matching PK-INIT cert in hdb");
		return 0;
	    }
	}
    }


    if (config->pkinit_princ_in_cert) {
	ret = match_rfc_san(context, config,
			    context->hx509ctx,
			    cp->cert,
			    client->entry.principal);
	if (ret == 0) {
	    kdc_log(context, config, 5,
		    "Found matching PK-INIT SAN in certificate");
	    return 0;
	}
	ret = match_ms_upn_san(context, config,
			       context->hx509ctx,
			       cp->cert,
			       clientdb,
			       client);
	if (ret == 0) {
	    kdc_log(context, config, 5,
		    "Found matching MS UPN SAN in certificate");
	    return 0;
	}
    }

    ret = hdb_entry_get_pkinit_acl(&client->entry, &acl);
    if (ret == 0 && acl != NULL) {
	/*
	 * Cheat here and compare the generated name with the string
	 * and not the reverse.
	 */
	for (i = 0; i < acl->len; i++) {
	    if (strcmp(*subject_name, acl->val[0].subject) != 0)
		continue;

	    /* Don't support isser and anchor checking right now */
	    if (acl->val[0].issuer)
		continue;
	    if (acl->val[0].anchor)
		continue;

	    kdc_log(context, config, 5,
		    "Found matching PK-INIT database ACL");
	    return 0;
	}
    }

    for (i = 0; i < principal_mappings.len; i++) {
	krb5_boolean b;

	b = krb5_principal_compare(context,
				   client->entry.principal,
				   principal_mappings.val[i].principal);
	if (b == FALSE)
	    continue;
	if (strcmp(principal_mappings.val[i].subject, *subject_name) != 0)
	    continue;
	kdc_log(context, config, 5,
		"Found matching PK-INIT FILE ACL");
	return 0;
    }

    ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
    krb5_set_error_message(context, ret,
			  "PKINIT no matching principals for %s",
			  *subject_name);

    kdc_log(context, config, 5,
	    "PKINIT no matching principals for %s",
	    *subject_name);

    free(*subject_name);
    *subject_name = NULL;

    return ret;
}
Пример #12
0
static int
keychain_iter(hx509_context context,
	      hx509_certs certs, void *data, void *cursor, hx509_cert *cert)
{
    SecKeychainAttributeList *attrs = NULL;
    SecKeychainAttributeInfo attrInfo;
    uint32 attrFormat[1] = { 0 };
    SecKeychainItemRef itemRef;
    SecItemAttr item[1];
    struct iter *iter = cursor;
    OSStatus ret;
    UInt32 len;
    void *ptr = NULL;

    if (iter->certs)
	return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert);

    *cert = NULL;

    ret = SecKeychainSearchCopyNext(iter->searchRef, &itemRef);
    if (ret == errSecItemNotFound)
	return 0;
    else if (ret != 0)
	return EINVAL;
	
    /*
     * Pick out certificate and matching "keyid"
     */

    item[0] = kSecPublicKeyHashItemAttr;

    attrInfo.count = 1;
    attrInfo.tag = item;
    attrInfo.format = attrFormat;
  
    ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,
					       &attrs, &len, &ptr);
    if (ret)
	return EINVAL;

    ret = hx509_cert_init_data(context, ptr, len, cert);
    if (ret)
	goto out;

    /* 
     * Find related private key if there is one by looking at
     * kSecPublicKeyHashItemAttr == kSecKeyLabel
     */
    {
	SecKeychainSearchRef search;
	SecKeychainAttribute attrKeyid;
	SecKeychainAttributeList attrList;

	attrKeyid.tag = kSecKeyLabel;
	attrKeyid.length = attrs->attr[0].length;
	attrKeyid.data = attrs->attr[0].data;
	
	attrList.count = 1;
	attrList.attr = &attrKeyid;

	ret = SecKeychainSearchCreateFromAttributes(NULL,
						    CSSM_DL_DB_RECORD_PRIVATE_KEY,
						    &attrList,
						    &search);
	if (ret) {
	    ret = 0;
	    goto out;
	}

	ret = SecKeychainSearchCopyNext(search, &itemRef);
	CFRelease(search);
	if (ret == errSecItemNotFound) {
	    ret = 0;
	    goto out;
	} else if (ret) {
	    ret = EINVAL;
	    goto out;
	}
	set_private_key(context, itemRef, *cert);
    }

out:
    SecKeychainItemFreeAttributesAndData(attrs, ptr);

    return ret;
}
Пример #13
0
static int 
keychain_iter_start(hx509_context context,
		    hx509_certs certs, void *data, void **cursor)
{
    struct ks_keychain *ctx = data;
    struct iter *iter;

    iter = calloc(1, sizeof(*iter));
    if (iter == NULL) {
	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
	return ENOMEM;
    }

    if (ctx->anchors) {
        CFArrayRef anchors;
	int ret;
	int i;

	ret = hx509_certs_init(context, "MEMORY:ks-file-create", 
			       0, NULL, &iter->certs);
	if (ret) {
	    free(iter);
	    return ret;
	}

	ret = SecTrustCopyAnchorCertificates(&anchors);
	if (ret != 0) {
	    hx509_certs_free(&iter->certs);
	    free(iter);
	    hx509_set_error_string(context, 0, ENOMEM, 
				   "Can't get trust anchors from Keychain");
	    return ENOMEM;
	}
	for (i = 0; i < CFArrayGetCount(anchors); i++) {
	    SecCertificateRef cr; 
	    hx509_cert cert;
	    CSSM_DATA cssm;

	    cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i);

	    SecCertificateGetData(cr, &cssm);

	    ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert);
	    if (ret)
		continue;

	    ret = hx509_certs_add(context, iter->certs, cert);
	    hx509_cert_free(cert);
	}
	CFRelease(anchors);
    }

    if (iter->certs) {
	int ret;
	ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor);
	if (ret) {
	    hx509_certs_free(&iter->certs);
	    free(iter);
	    return ret;
	}
    } else {
	OSStatus ret;

	ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,
						    kSecCertificateItemClass,
						    NULL,
						    &iter->searchRef);
	if (ret) {
	    free(iter);
	    hx509_set_error_string(context, 0, ret, 
				   "Failed to start search for attributes");
	    return ENOMEM;
	}
    }

    *cursor = iter;
    return 0;
}
static int
keychain_iter_start(hx509_context context,
		    hx509_certs certs, void *data, void **cursor)
{
#ifndef __APPLE_TARGET_EMBEDDED__
    struct ks_keychain *ctx = data;
#endif
    struct iter *iter;

    iter = calloc(1, sizeof(*iter));
    if (iter == NULL) {
	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
	return ENOMEM;
    }

#ifndef __APPLE_TARGET_EMBEDDED__
    if (ctx->anchors) {
        CFArrayRef anchors;
	int ret;
	int i;

	ret = hx509_certs_init(context, "MEMORY:ks-file-create",
			       0, NULL, &iter->certs);
	if (ret) {
	    free(iter);
	    return ret;
	}

	ret = SecTrustCopyAnchorCertificates(&anchors);
	if (ret != 0) {
	    hx509_certs_free(&iter->certs);
	    free(iter);
	    hx509_set_error_string(context, 0, ENOMEM,
				   "Can't get trust anchors from Keychain");
	    return ENOMEM;
	}
	for (i = 0; i < CFArrayGetCount(anchors); i++) {
	    SecCertificateRef cr;
	    hx509_cert cert;
	    CFDataRef dataref;

	    cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i);

	    dataref = SecCertificateCopyData(cr);
	    if (dataref == NULL)
		continue;

	    ret = hx509_cert_init_data(context, CFDataGetBytePtr(dataref), CFDataGetLength(dataref), &cert);
	    CFRelease(dataref);
	    if (ret)
		continue;

	    ret = hx509_certs_add(context, iter->certs, cert);
	    hx509_cert_free(cert);
	}
	CFRelease(anchors);
	if (ret != 0) {
	    hx509_certs_free(&iter->certs);
	    free(iter);
	    hx509_set_error_string(context, 0, ret,
				   "Failed to add cert");
	    return ret;
	}
    }

    if (iter->certs) {
	int ret;
	ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor);
	if (ret) {
	    hx509_certs_free(&iter->certs);
	    free(iter);
	    return ret;
	}
    } else
#endif
    {
	OSStatus ret;
	const void *keys[] = {
	    kSecClass,
	    kSecReturnRef,
	    kSecMatchLimit
	};
	const void *values[] = {
	    kSecClassCertificate,
	    kCFBooleanTrue,
	    kSecMatchLimitAll
	};

	CFDictionaryRef secQuery;

	secQuery = CFDictionaryCreate(NULL, keys, values,
				      sizeof(keys) / sizeof(*keys),
				      &kCFTypeDictionaryKeyCallBacks,
				      &kCFTypeDictionaryValueCallBacks);
	
	ret = SecItemCopyMatching(secQuery, (CFTypeRef *)&iter->search);
	CFRelease(secQuery);
	if (ret) {
	    free(iter);
	    return ENOMEM;
	}
    }

    *cursor = iter;
    return 0;
}