svn rev #23493: branches/anonymous/src/plugins/preauth/pkinit/
hartmans@MIT.EDU
hartmans at MIT.EDU
Wed Dec 23 16:09:53 EST 2009
http://src.mit.edu/fisheye/changelog/krb5/?cs=23493
Commit By: hartmans
Log Message:
Implement support for unsigned pkinit messages.
* cms_signeddata_verify will take a ContentInfo as well as SignedData and returns an indication of whether a message is signed
* Accept unsigned authpacks in the anonymous case.
Changed Files:
U branches/anonymous/src/plugins/preauth/pkinit/pkinit_clnt.c
U branches/anonymous/src/plugins/preauth/pkinit/pkinit_crypto.h
U branches/anonymous/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
U branches/anonymous/src/plugins/preauth/pkinit/pkinit_srv.c
Modified: branches/anonymous/src/plugins/preauth/pkinit/pkinit_clnt.c
===================================================================
--- branches/anonymous/src/plugins/preauth/pkinit/pkinit_clnt.c 2009-12-23 21:09:50 UTC (rev 23492)
+++ branches/anonymous/src/plugins/preauth/pkinit/pkinit_clnt.c 2009-12-23 21:09:53 UTC (rev 23493)
@@ -61,7 +61,8 @@
pkinit_as_req_create(krb5_context context, pkinit_context plgctx,
pkinit_req_context reqctx, krb5_timestamp ctsec,
krb5_int32 cusec, krb5_ui_4 nonce,
- const krb5_checksum *cksum, krb5_principal server,
+ const krb5_checksum *cksum,
+ krb5_principal client, krb5_principal server,
krb5_data **as_req);
static krb5_error_code
@@ -139,7 +140,7 @@
nonce = request->nonce;
retval = pkinit_as_req_create(context, plgctx, reqctx, ctsec, cusec,
- nonce, &cksum, request->server, &out_data);
+ nonce, &cksum, request->client, request->server, &out_data);
if (retval || !out_data->length) {
pkiDebug("error %d on pkinit_as_req_create; aborting PKINIT\n",
(int) retval);
@@ -218,6 +219,7 @@
krb5_int32 cusec,
krb5_ui_4 nonce,
const krb5_checksum * cksum,
+ krb5_principal client,
krb5_principal server,
krb5_data ** as_req)
{
@@ -344,10 +346,17 @@
retval = ENOMEM;
goto cleanup;
}
- retval = cms_signeddata_create(context, plgctx->cryptoctx,
- reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_CLIENT, 1,
- (unsigned char *)coded_auth_pack->data, coded_auth_pack->length,
- &req->signedAuthPack.data, &req->signedAuthPack.length);
+ /*For the new protocol, we support anonymous*/
+ if (krb5_principal_compare_any_realm(context, client,
+ krb5_anonymous_principal()))
+ retval = cms_contentinfo_create(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_CLIENT,
+ (unsigned char *)coded_auth_pack->data, coded_auth_pack->length,
+ &req->signedAuthPack.data, &req->signedAuthPack.length);
+ else retval = cms_signeddata_create(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_CLIENT, 1,
+ (unsigned char *)coded_auth_pack->data, coded_auth_pack->length,
+ &req->signedAuthPack.data, &req->signedAuthPack.length);
#ifdef DEBUG_ASN1
print_buffer_bin((unsigned char *)req->signedAuthPack.data,
req->signedAuthPack.length,
@@ -677,7 +686,7 @@
reqctx->opts->require_crl_checking,
kdc_reply->u.dh_Info.dhSignedData.data,
kdc_reply->u.dh_Info.dhSignedData.length,
- &dh_data.data, &dh_data.length, NULL, NULL)) != 0) {
+ &dh_data.data, &dh_data.length, NULL, NULL, NULL)) != 0) {
pkiDebug("failed to verify pkcs7 signed data\n");
goto cleanup;
}
Modified: branches/anonymous/src/plugins/preauth/pkinit/pkinit_crypto.h
===================================================================
--- branches/anonymous/src/plugins/preauth/pkinit/pkinit_crypto.h 2009-12-23 21:09:50 UTC (rev 23492)
+++ branches/anonymous/src/plugins/preauth/pkinit/pkinit_crypto.h 2009-12-23 21:09:53 UTC (rev 23493)
@@ -181,8 +181,9 @@
receives required authorization data that
contains the verified certificate chain
(only used by the KDC) */
- unsigned int *authz_data_len); /* OUT
- receives length of authz_data */
+ unsigned int *authz_data_len, /* OUT
+ receives length of authz_data */
+ int *is_signed /*out: is message signed*/);
/*
* this function creates a CMS message where eContentType is EnvelopedData
Modified: branches/anonymous/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
===================================================================
--- branches/anonymous/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c 2009-12-23 21:09:50 UTC (rev 23492)
+++ branches/anonymous/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c 2009-12-23 21:09:53 UTC (rev 23493)
@@ -1120,8 +1120,9 @@
unsigned char **data,
unsigned int *data_len,
unsigned char **authz_data,
- unsigned int *authz_data_len)
-{
+ unsigned int *authz_data_len,
+ int *is_signed)
+ {
krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
PKCS7 *p7 = NULL;
BIO *out = NULL;
@@ -1146,7 +1147,8 @@
print_buffer_bin(signed_data, signed_data_len,
"/tmp/client_received_pkcs7_signeddata");
#endif
-
+ if (is_signed)
+ *is_signed = 1;
/* Do this early enough to create the shadow OID for pkcs7-data if needed */
oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
if (oid == NULL)
@@ -1162,12 +1164,32 @@
goto cleanup;
}
- /* verify that the received message is PKCS7 SignedData message */
- if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
- pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
- OBJ_obj2nid(p7->type));
- krb5_set_error_message(context, retval, "wrong oid\n");
- goto cleanup;
+/*Handle the case in pkinit anonymous where we get unsigned data.*/
+ if (is_signed && !OBJ_cmp( p7->type, oid)) {
+ unsigned char *d;
+ *is_signed = 0;
+ if (p7->d.other->type != V_ASN1_OCTET_STRING) {
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, "Invalid pkinit packet: octet string expected");
+ goto cleanup;
+ }
+ *data_len = ASN1_STRING_length(p7->d.other->value.octet_string);
+ d = malloc(*data_len);
+ if (d == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memcpy(d, ASN1_STRING_data(p7->d.other->value.octet_string),
+ *data_len);
+ *data = d;
+ goto out;
+ } else /* verify that the received message is PKCS7 SignedData message */
+ if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
+
+ pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
+ OBJ_obj2nid(p7->type));
+ krb5_set_error_message(context, retval, "wrong oid\n");
+ goto cleanup;
}
/* setup to verify X509 certificate used to sign PKCS7 message */
@@ -1370,7 +1392,6 @@
for (size = 0;;) {
int remain;
retval = ENOMEM;
-
if ((*data = realloc(*data, size + 1024 * 10)) == NULL)
goto cleanup;
remain = BIO_read(out, &((*data)[size]), 1024 * 10);
@@ -1703,7 +1724,7 @@
id_cryptoctx, msg_type,
require_crl_checking,
vfy_buf, vfy_buf_len,
- data, data_len, NULL, NULL);
+ data, data_len, NULL, NULL, NULL);
if (!retval)
pkiDebug("PKCS7 Verification Success\n");
Modified: branches/anonymous/src/plugins/preauth/pkinit/pkinit_srv.c
===================================================================
--- branches/anonymous/src/plugins/preauth/pkinit/pkinit_srv.c 2009-12-23 21:09:50 UTC (rev 23492)
+++ branches/anonymous/src/plugins/preauth/pkinit/pkinit_srv.c 2009-12-23 21:09:53 UTC (rev 23493)
@@ -314,6 +314,7 @@
krb5_authdata **my_authz_data = NULL, *pkinit_authz_data = NULL;
krb5_kdc_req *tmp_as_req = NULL;
krb5_data k5data;
+ int is_signed = 1;
krb5_keyblock *armor_key;
pkiDebug("pkinit_verify_padata: entered!\n");
@@ -367,7 +368,7 @@
plgctx->opts->require_crl_checking,
reqp->signedAuthPack.data, reqp->signedAuthPack.length,
&authp_data.data, &authp_data.length, &krb5_authz.data,
- &krb5_authz.length);
+ &krb5_authz.length, &is_signed);
break;
case KRB5_PADATA_PK_AS_REP_OLD:
case KRB5_PADATA_PK_AS_REQ_OLD:
@@ -389,7 +390,7 @@
plgctx->opts->require_crl_checking,
reqp9->signedAuthPack.data, reqp9->signedAuthPack.length,
&authp_data.data, &authp_data.length, &krb5_authz.data,
- &krb5_authz.length);
+ &krb5_authz.length, NULL);
break;
default:
pkiDebug("unrecognized pa_type = %d\n", data->pa_type);
@@ -400,28 +401,35 @@
pkiDebug("pkcs7_signeddata_verify failed\n");
goto cleanup;
}
+ if (is_signed) {
- retval = verify_client_san(context, plgctx, reqctx, request->client,
- &valid_san);
- if (retval)
- goto cleanup;
- if (!valid_san) {
- pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
- __FUNCTION__);
- retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
- goto cleanup;
- }
- retval = verify_client_eku(context, plgctx, reqctx, &valid_eku);
- if (retval)
- goto cleanup;
+ retval = verify_client_san(context, plgctx, reqctx, request->client,
+ &valid_san);
+ if (retval)
+ goto cleanup;
+ if (!valid_san) {
+ pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
+ __FUNCTION__);
+ retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+ goto cleanup;
+ }
+ retval = verify_client_eku(context, plgctx, reqctx, &valid_eku);
+ if (retval)
+ goto cleanup;
- if (!valid_eku) {
- pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
- __FUNCTION__);
- retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
- goto cleanup;
+ if (!valid_eku) {
+ pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
+ __FUNCTION__);
+ retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+ goto cleanup;
+ }
+ } else { /*!is_signed*/
+ if (!krb5_principal_compare( context, request->client, krb5_anonymous_principal())) {
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval, "Pkinit request not signed, but client not anonymous.");
+ goto cleanup;
+ }
}
-
#ifdef DEBUG_ASN1
print_buffer_bin(authp_data.data, authp_data.length, "/tmp/kdc_auth_pack");
#endif
@@ -446,6 +454,11 @@
pkiDebug("bad dh parameters\n");
goto cleanup;
}
+ } else if (!is_signed) {
+ /*Anonymous pkinit requires DH*/
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval, "Anonymous pkinit without DH public value not supported.");
+ goto cleanup;
}
/*
* The KDC may have modified the request after decoding it.
More information about the cvs-krb5
mailing list