handle pkinit-9, pkinit-19, and pkinit-25 enckey, still no DH
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@15116 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
		
							
								
								
									
										733
									
								
								kdc/pkinit.c
									
									
									
									
									
								
							
							
						
						
									
										733
									
								
								kdc/pkinit.c
									
									
									
									
									
								
							| @@ -66,7 +66,14 @@ struct krb5_pk_cert { | |||||||
|     X509 *cert; |     X509 *cert; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | enum pkinit_type { | ||||||
|  |     PKINIT_COMPAT_WIN2K = 1, | ||||||
|  |     PKINIT_COMPAT_19 = 2, | ||||||
|  |     PKINIT_COMPAT_25 = 3 | ||||||
|  | }; | ||||||
|  |  | ||||||
| struct pk_client_params { | struct pk_client_params { | ||||||
|  |     enum pkinit_type type; | ||||||
|     BIGNUM *dh_public_key; |     BIGNUM *dh_public_key; | ||||||
|     struct krb5_pk_cert *certificate; |     struct krb5_pk_cert *certificate; | ||||||
|     unsigned nonce; |     unsigned nonce; | ||||||
| @@ -112,6 +119,23 @@ static struct pk_principal_mapping principal_mappings; | |||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | static krb5_error_code | ||||||
|  | pk_check_pkauthenticator_win2k(krb5_context context, | ||||||
|  | 			       PKAuthenticator_Win2k *a, | ||||||
|  | 			       KDC_REQ *req) | ||||||
|  | { | ||||||
|  |     krb5_timestamp now; | ||||||
|  |  | ||||||
|  |     krb5_timeofday (context, &now); | ||||||
|  |  | ||||||
|  |     /* XXX cusec */ | ||||||
|  |     if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) { | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	return KRB5KRB_AP_ERR_SKEW; | ||||||
|  |     } | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static krb5_error_code | static krb5_error_code | ||||||
| pk_check_pkauthenticator_19(krb5_context context, | pk_check_pkauthenticator_19(krb5_context context, | ||||||
| 			    PKAuthenticator_19 *a, | 			    PKAuthenticator_19 *a, | ||||||
| @@ -131,6 +155,13 @@ pk_check_pkauthenticator_19(krb5_context context, | |||||||
| 	return KRB5KRB_AP_ERR_SKEW; | 	return KRB5KRB_AP_ERR_SKEW; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (a->paChecksum.cksumtype != CKSUMTYPE_RSA_MD5 && | ||||||
|  | 	a->paChecksum.cksumtype != CKSUMTYPE_SHA1) | ||||||
|  |     { | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	ret = KRB5KRB_ERR_GENERIC; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret); |     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret); | ||||||
|     if (ret) { |     if (ret) { | ||||||
| 	krb5_clear_error_string(context); | 	krb5_clear_error_string(context); | ||||||
| @@ -148,6 +179,59 @@ pk_check_pkauthenticator_19(krb5_context context, | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static krb5_error_code | ||||||
|  | pk_check_pkauthenticator(krb5_context context, | ||||||
|  | 			 PKAuthenticator *a, | ||||||
|  | 			 KDC_REQ *req) | ||||||
|  | { | ||||||
|  |     u_char *buf = NULL; | ||||||
|  |     size_t buf_size; | ||||||
|  |     krb5_error_code ret; | ||||||
|  |     size_t len; | ||||||
|  |     krb5_timestamp now; | ||||||
|  |     Checksum checksum; | ||||||
|  |  | ||||||
|  |     krb5_timeofday (context, &now); | ||||||
|  |  | ||||||
|  |     /* XXX cusec */ | ||||||
|  |     if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) { | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	return KRB5KRB_AP_ERR_SKEW; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret); | ||||||
|  |     if (ret) { | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	return ret; | ||||||
|  |     } | ||||||
|  |     if (buf_size != len) | ||||||
|  | 	krb5_abortx(context, "Internal error in ASN.1 encoder"); | ||||||
|  |  | ||||||
|  |     ret = krb5_create_checksum(context, | ||||||
|  | 			       NULL, | ||||||
|  | 			       0, | ||||||
|  | 			       CKSUMTYPE_SHA1, | ||||||
|  | 			       buf, | ||||||
|  | 			       len, | ||||||
|  | 			       &checksum); | ||||||
|  |     free(buf); | ||||||
|  |     if (ret) { | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	return ret; | ||||||
|  |     } | ||||||
|  | 	 | ||||||
|  |     if (a->paChecksum.length != checksum.checksum.length || | ||||||
|  | 	memcmp(a->paChecksum.data, checksum.checksum.data,  | ||||||
|  | 	       checksum.checksum.length) != 0) | ||||||
|  |     { | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	ret = KRB5KRB_ERR_GENERIC; | ||||||
|  |     } | ||||||
|  |     free_Checksum(&checksum); | ||||||
|  |  | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
| static krb5_error_code | static krb5_error_code | ||||||
| pk_encrypt_key(krb5_context context, | pk_encrypt_key(krb5_context context, | ||||||
|       	       krb5_keyblock *key, |       	       krb5_keyblock *key, | ||||||
| @@ -368,110 +452,20 @@ get_dh_param(krb5_context context, SubjectPublicKeyInfo *dh_key_info, | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| krb5_error_code | #if 0 | ||||||
| pk_rd_padata(krb5_context context, | /*  | ||||||
|              KDC_REQ *req, |  * XXX We only need this function if there are several certs for the | ||||||
|              PA_DATA *pa, |  * KDC to choose from, and right now, we can't handle that so punt for | ||||||
| 	     pk_client_params **ret_params) |  * now. | ||||||
|  |  * | ||||||
|  |  * If client has sent a list of CA's trusted by him, make sure our | ||||||
|  |  * CA is in the list. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | verify_trusted_ca(PA_PK_AS_REQ_19 *r) | ||||||
| { | { | ||||||
|     pk_client_params *client_params; |  | ||||||
|     krb5_error_code ret; |  | ||||||
|     PA_PK_AS_REQ_19 r; |  | ||||||
|     AuthPack_19 ap; |  | ||||||
|     heim_oid eContentType = { 0, NULL }; |  | ||||||
|     krb5_data eContent; |  | ||||||
|     int i; |  | ||||||
|  |  | ||||||
|     *ret_params = NULL; |  | ||||||
|      |  | ||||||
|     if (!enable_pkinit) { |  | ||||||
| 	krb5_clear_error_string(context); |  | ||||||
| 	return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     memset(&ap, 0, sizeof(ap)); |  | ||||||
|     memset(&r, 0, sizeof(r)); |  | ||||||
|     krb5_data_zero(&eContent); |  | ||||||
|  |  | ||||||
|     client_params = malloc(sizeof(*client_params)); |  | ||||||
|     if (client_params == NULL) { |  | ||||||
| 	krb5_clear_error_string(context); |  | ||||||
| 	ret = ENOMEM; |  | ||||||
| 	goto out; |  | ||||||
|     } |  | ||||||
|     memset(client_params, 0, sizeof(*client_params)); |  | ||||||
|  |  | ||||||
|     if (pa->padata_type !=  KRB5_PADATA_PK_AS_REQ) { |  | ||||||
| 	krb5_clear_error_string(context); |  | ||||||
| 	ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; |  | ||||||
| 	goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ret = decode_PA_PK_AS_REQ_19(pa->padata_value.data, |  | ||||||
| 				 pa->padata_value.length, |  | ||||||
| 				 &r, |  | ||||||
| 				 NULL); |  | ||||||
|     if (ret) { |  | ||||||
| 	krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret); |  | ||||||
| 	return ret; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (heim_oid_cmp(&r.signedAuthPack.contentType, oid_id_pkcs7_signedData())) { |  | ||||||
| 	krb5_set_error_string(context, "PK-AS-REQ invalid content type oid"); |  | ||||||
| 	ret = KRB5KRB_ERR_GENERIC; |  | ||||||
| 	goto out; |  | ||||||
|     } |  | ||||||
|    |  | ||||||
|     if (r.signedAuthPack.content == NULL) { |  | ||||||
| 	krb5_set_error_string(context, "PK-AS-REQ no signed auth pack"); |  | ||||||
| 	ret = KRB5KRB_ERR_GENERIC; |  | ||||||
| 	goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ret = _krb5_pk_verify_sign(context, |  | ||||||
| 			       r.signedAuthPack.content->data, |  | ||||||
| 			       r.signedAuthPack.content->length, |  | ||||||
| 			       kdc_identity, |  | ||||||
| 			       &eContentType, |  | ||||||
| 			       &eContent, |  | ||||||
| 			       &client_params->certificate); |  | ||||||
|     if (ret) |  | ||||||
| 	goto out; |  | ||||||
|  |  | ||||||
|     /* Signature is correct, now verify the signed message */ |  | ||||||
|     if (heim_oid_cmp(&eContentType, oid_id_pkauthdata())) { |  | ||||||
| 	krb5_set_error_string(context, "got wrong oid for pkauthdata"); |  | ||||||
| 	ret = KRB5_BADMSGTYPE; |  | ||||||
| 	goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ret = decode_AuthPack_19(eContent.data, |  | ||||||
| 			     eContent.length, |  | ||||||
| 			     &ap, |  | ||||||
| 			     NULL); |  | ||||||
|     if (ret) { |  | ||||||
| 	krb5_set_error_string(context, "can't decode AuthPack: %d", ret); |  | ||||||
| 	goto out; |  | ||||||
|     } |  | ||||||
|    |  | ||||||
|     ret = pk_check_pkauthenticator_19(context,  |  | ||||||
| 				      &ap.pkAuthenticator, |  | ||||||
| 				      req); |  | ||||||
|     if (ret) |  | ||||||
| 	goto out; |  | ||||||
|  |  | ||||||
|     client_params->nonce = ap.pkAuthenticator.nonce; |  | ||||||
|  |  | ||||||
|     if (ap.clientPublicValue) { |  | ||||||
| 	ret = get_dh_param(context, ap.clientPublicValue, client_params); |  | ||||||
| 	if (ret) |  | ||||||
| 	    goto out; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /*  |  | ||||||
|      * If client has sent a list of CA's trusted by him, make sure our |  | ||||||
|      * CA is in the list. |  | ||||||
|      */ |  | ||||||
|  |  | ||||||
|     if (r.trustedCertifiers != NULL) { |     if (r.trustedCertifiers != NULL) { | ||||||
| 	X509_NAME *kdc_issuer; | 	X509_NAME *kdc_issuer; | ||||||
| @@ -513,21 +507,326 @@ pk_rd_padata(krb5_context context, | |||||||
| 	if (ret) | 	if (ret) | ||||||
| 	    goto out; | 	    goto out; | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  | #endif /* 0 */ | ||||||
|  |  | ||||||
|  | krb5_error_code | ||||||
|  | pk_rd_padata(krb5_context context, | ||||||
|  |              KDC_REQ *req, | ||||||
|  |              PA_DATA *pa, | ||||||
|  | 	     pk_client_params **ret_params) | ||||||
|  | { | ||||||
|  |     pk_client_params *client_params; | ||||||
|  |     krb5_error_code ret; | ||||||
|  |     heim_oid eContentType = { 0, NULL }; | ||||||
|  |     krb5_data eContent = { 0, NULL }; | ||||||
|  |     krb5_data signed_content = { 0, NULL }; | ||||||
|  |     const char *type = "unknown type"; | ||||||
|  |     const heim_oid *pa_contentType; | ||||||
|  |  | ||||||
|  |     *ret_params = NULL; | ||||||
|  |      | ||||||
|  |     if (!enable_pkinit) { | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     client_params = malloc(sizeof(*client_params)); | ||||||
|  |     if (client_params == NULL) { | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	ret = ENOMEM; | ||||||
|  | 	goto out; | ||||||
|  |     } | ||||||
|  |     memset(client_params, 0, sizeof(*client_params)); | ||||||
|  |  | ||||||
|  |     if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) { | ||||||
|  | 	PA_PK_AS_REQ_Win2k r; | ||||||
|  | 	ContentInfo info; | ||||||
|  |  | ||||||
|  | 	type = "PK-INIT-Win2k"; | ||||||
|  | 	pa_contentType = oid_id_pkcs7_data(); | ||||||
|  |  | ||||||
|  | 	ret = decode_PA_PK_AS_REQ_Win2k(pa->padata_value.data, | ||||||
|  | 					pa->padata_value.length, | ||||||
|  | 					&r, | ||||||
|  | 					NULL); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context, "Can't decode " | ||||||
|  | 				  "PK-AS-REQ-Win2k: %d", ret); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	ret = decode_ContentInfo(r.signed_auth_pack.data, | ||||||
|  | 				 r.signed_auth_pack.length, &info, NULL); | ||||||
|  | 	free_PA_PK_AS_REQ_Win2k(&r); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (heim_oid_cmp(&info.contentType, oid_id_pkcs7_signedData())) { | ||||||
|  | 	    krb5_set_error_string(context, "PK-AS-REQ-Win2k invalid content " | ||||||
|  | 				  "type oid"); | ||||||
|  | 	    free_ContentInfo(&info); | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	if (info.content == NULL) { | ||||||
|  | 	    krb5_set_error_string(context, | ||||||
|  | 				  "PK-AS-REQ-Win2k no signed auth pack"); | ||||||
|  | 	    free_ContentInfo(&info); | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	signed_content.data = malloc(info.content->length); | ||||||
|  | 	if (signed_content.data == NULL) { | ||||||
|  | 	    ret = ENOMEM; | ||||||
|  | 	    free_ContentInfo(&info); | ||||||
|  | 	    krb5_set_error_string(context, "PK-AS-REQ-Win2k out of memory"); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	signed_content.length = info.content->length; | ||||||
|  | 	memcpy(signed_content.data, info.content->data, signed_content.length); | ||||||
|  |  | ||||||
|  | 	free_ContentInfo(&info); | ||||||
|  |  | ||||||
|  |     } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_19) { | ||||||
|  | 	PA_PK_AS_REQ_19 r; | ||||||
|  |  | ||||||
|  | 	type = "PK-INIT-19"; | ||||||
|  | 	pa_contentType = oid_id_pkauthdata(); | ||||||
|  |  | ||||||
|  | 	ret = decode_PA_PK_AS_REQ_19(pa->padata_value.data, | ||||||
|  | 				     pa->padata_value.length, | ||||||
|  | 				     &r, | ||||||
|  | 				     NULL); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context, "Can't decode " | ||||||
|  | 				  "PK-AS-REQ-19: %d", ret); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	if (heim_oid_cmp(&r.signedAuthPack.contentType,  | ||||||
|  | 			 oid_id_pkcs7_signedData())) | ||||||
|  | 	{ | ||||||
|  | 	    krb5_set_error_string(context, "PK-AS-REQ-19 invalid content " | ||||||
|  | 				  "type oid"); | ||||||
|  | 	    free_PA_PK_AS_REQ_19(&r); | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	if (r.signedAuthPack.content == NULL) { | ||||||
|  | 	    krb5_set_error_string(context, "PK-AS-REQ-19 no signed auth pack"); | ||||||
|  | 	    free_PA_PK_AS_REQ_19(&r); | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	signed_content.data = malloc(r.signedAuthPack.content->length); | ||||||
|  | 	if (signed_content.data == NULL) { | ||||||
|  | 	    ret = ENOMEM; | ||||||
|  | 	    free_PA_PK_AS_REQ_19(&r); | ||||||
|  | 	    krb5_set_error_string(context, "PK-AS-REQ-19 out of memory"); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	signed_content.length = r.signedAuthPack.content->length; | ||||||
|  | 	memcpy(signed_content.data, r.signedAuthPack.content->data, | ||||||
|  | 	       signed_content.length); | ||||||
|  |  | ||||||
|  | 	free_PA_PK_AS_REQ_19(&r); | ||||||
|  |     } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) { | ||||||
|  | 	PA_PK_AS_REQ r; | ||||||
|  | 	ContentInfo info; | ||||||
|  |  | ||||||
|  | 	type = "PK-INIT-25"; | ||||||
|  | 	pa_contentType = oid_id_pkauthdata(); | ||||||
|  |  | ||||||
|  | 	ret = decode_PA_PK_AS_REQ(pa->padata_value.data, | ||||||
|  | 				  pa->padata_value.length, | ||||||
|  | 				  &r, | ||||||
|  | 				  NULL); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	ret = decode_ContentInfo(r.signedAuthPack.data, | ||||||
|  | 				 r.signedAuthPack.length, &info, NULL); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (heim_oid_cmp(&info.contentType, oid_id_pkcs7_signedData())) { | ||||||
|  | 	    krb5_set_error_string(context, "PK-AS-REQ invalid content " | ||||||
|  | 				  "type oid"); | ||||||
|  | 	    free_ContentInfo(&info); | ||||||
|  | 	    free_PA_PK_AS_REQ(&r); | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	if (info.content == NULL) { | ||||||
|  | 	    krb5_set_error_string(context, "PK-AS-REQ no signed auth pack"); | ||||||
|  | 	    free_PA_PK_AS_REQ(&r); | ||||||
|  | 	    free_ContentInfo(&info); | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	signed_content.data = malloc(info.content->length); | ||||||
|  | 	if (signed_content.data == NULL) { | ||||||
|  | 	    ret = ENOMEM; | ||||||
|  | 	    free_ContentInfo(&info); | ||||||
|  | 	    free_PA_PK_AS_REQ(&r); | ||||||
|  | 	    krb5_set_error_string(context, "PK-AS-REQ out of memory"); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	signed_content.length = info.content->length; | ||||||
|  | 	memcpy(signed_content.data, info.content->data, signed_content.length); | ||||||
|  |  | ||||||
|  | 	free_ContentInfo(&info); | ||||||
|  | 	free_PA_PK_AS_REQ(&r); | ||||||
|  |  | ||||||
|  |     } else {  | ||||||
|  | 	krb5_clear_error_string(context); | ||||||
|  | 	ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; | ||||||
|  | 	goto out; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ret = _krb5_pk_verify_sign(context, | ||||||
|  | 			       signed_content.data, | ||||||
|  | 			       signed_content.length, | ||||||
|  | 			       kdc_identity, | ||||||
|  | 			       &eContentType, | ||||||
|  | 			       &eContent, | ||||||
|  | 			       &client_params->certificate); | ||||||
|  |     if (ret) | ||||||
|  | 	goto out; | ||||||
|  |  | ||||||
|  |     /* Signature is correct, now verify the signed message */ | ||||||
|  |     if (heim_oid_cmp(&eContentType, pa_contentType)) { | ||||||
|  | 	krb5_set_error_string(context, "got wrong oid for pkauthdata"); | ||||||
|  | 	ret = KRB5_BADMSGTYPE; | ||||||
|  | 	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_string(context, "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; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	client_params->type = PKINIT_COMPAT_WIN2K; | ||||||
|  | 	client_params->nonce = ap.pkAuthenticator.nonce; | ||||||
|  |  | ||||||
|  | 	if (ap.clientPublicValue) { | ||||||
|  | 	    krb5_set_error_string(context, "DH not supported for windows"); | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	free_AuthPack_Win2k(&ap); | ||||||
|  |  | ||||||
|  |     } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_19) { | ||||||
|  | 	AuthPack_19 ap; | ||||||
|  |  | ||||||
|  | 	ret = decode_AuthPack_19(eContent.data, | ||||||
|  | 				 eContent.length, | ||||||
|  | 				 &ap, | ||||||
|  | 				 NULL); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context, "can't decode AuthPack: %d", ret); | ||||||
|  | 	    free_AuthPack_19(&ap); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |    | ||||||
|  | 	ret = pk_check_pkauthenticator_19(context,  | ||||||
|  | 					  &ap.pkAuthenticator, | ||||||
|  | 					  req); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    free_AuthPack_19(&ap); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	client_params->type = PKINIT_COMPAT_19; | ||||||
|  | 	client_params->nonce = ap.pkAuthenticator.nonce; | ||||||
|  |  | ||||||
|  | 	if (ap.clientPublicValue) { | ||||||
|  | 	    ret = get_dh_param(context, ap.clientPublicValue, client_params); | ||||||
|  | 	    if (ret) { | ||||||
|  | 		free_AuthPack_19(&ap); | ||||||
|  | 		goto out; | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|  | 	free_AuthPack_19(&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_string(context, "can't decode AuthPack: %d", ret); | ||||||
|  | 	    free_AuthPack(&ap); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |    | ||||||
|  | 	ret = pk_check_pkauthenticator(context,  | ||||||
|  | 				       &ap.pkAuthenticator, | ||||||
|  | 				       req); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    free_AuthPack(&ap); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	client_params->type = PKINIT_COMPAT_25; | ||||||
|  | 	client_params->nonce = ap.pkAuthenticator.nonce; | ||||||
|  |  | ||||||
|  | 	if (ap.clientPublicValue) { | ||||||
|  | 	    krb5_set_error_string(context, "PK-INIT, no support for DH"); | ||||||
|  | 	    ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; | ||||||
|  | 	    free_AuthPack(&ap); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	free_AuthPack(&ap); | ||||||
|  |     } else | ||||||
|  | 	krb5_abortx(context, "internal pkinit error"); | ||||||
|  |  | ||||||
|     /*  |     /*  | ||||||
|      * Remaining fields (ie kdcCert and encryptionCert) in the request |      * Remaining fields (ie kdcCert and encryptionCert) in the request | ||||||
|      * are ignored for now. |      * are ignored for now. | ||||||
|      */ |      */ | ||||||
|  |  | ||||||
|  |     kdc_log(0, "PK-INIT request of type %s", type); | ||||||
|  |  | ||||||
|  out: |  out: | ||||||
|  |  | ||||||
|  |     if (signed_content.data) | ||||||
|  | 	free(signed_content.data); | ||||||
|     krb5_data_free(&eContent); |     krb5_data_free(&eContent); | ||||||
|     free_oid(&eContentType); |     free_oid(&eContentType); | ||||||
|     if (ret) |     if (ret) | ||||||
| 	pk_free_client_param(context, client_params); | 	pk_free_client_param(context, client_params); | ||||||
|     else |     else | ||||||
| 	*ret_params = client_params; | 	*ret_params = client_params; | ||||||
|     free_PA_PK_AS_REQ_19(&r); |  | ||||||
|     free_AuthPack_19(&ap); |  | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -551,9 +850,9 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) | |||||||
|  |  | ||||||
| static krb5_error_code | static krb5_error_code | ||||||
| pk_mk_pa_reply_enckey(krb5_context context, | pk_mk_pa_reply_enckey(krb5_context context, | ||||||
|       	              pk_client_params *client_params, | 		      pk_client_params *client_params, | ||||||
| 		      const KDC_REQ *req, | 		      const KDC_REQ *req, | ||||||
|                       krb5_keyblock *reply_key, | 		      krb5_keyblock *reply_key, | ||||||
| 		      ContentInfo *content_info) | 		      ContentInfo *content_info) | ||||||
| { | { | ||||||
|     KeyTransRecipientInfo *ri; |     KeyTransRecipientInfo *ri; | ||||||
| @@ -629,8 +928,8 @@ pk_mk_pa_reply_enckey(krb5_context context, | |||||||
|     enc_alg->parameters->data = params.data; |     enc_alg->parameters->data = params.data; | ||||||
|     enc_alg->parameters->length = params.length; |     enc_alg->parameters->length = params.length; | ||||||
|  |  | ||||||
|     { |     if (client_params->type == PKINIT_COMPAT_WIN2K || client_params->type == PKINIT_COMPAT_19 || client_params->type == PKINIT_COMPAT_25) { | ||||||
| 	ReplyKeyPack_19 kp; | 	ReplyKeyPack kp; | ||||||
| 	memset(&kp, 0, sizeof(kp)); | 	memset(&kp, 0, sizeof(kp)); | ||||||
|  |  | ||||||
| 	ret = copy_EncryptionKey(reply_key, &kp.replyKey); | 	ret = copy_EncryptionKey(reply_key, &kp.replyKey); | ||||||
| @@ -640,8 +939,10 @@ pk_mk_pa_reply_enckey(krb5_context context, | |||||||
| 	} | 	} | ||||||
| 	kp.nonce = client_params->nonce; | 	kp.nonce = client_params->nonce; | ||||||
| 	 | 	 | ||||||
| 	ASN1_MALLOC_ENCODE(ReplyKeyPack_19, buf.data, buf.length, &kp, &size,ret); | 	ASN1_MALLOC_ENCODE(ReplyKeyPack, buf.data, buf.length, &kp, &size,ret); | ||||||
| 	free_ReplyKeyPack_19(&kp); | 	free_ReplyKeyPack(&kp); | ||||||
|  |     } else { | ||||||
|  | 	krb5_abortx(context, "internal pkinit error"); | ||||||
|     } |     } | ||||||
|     if (ret) { |     if (ret) { | ||||||
| 	krb5_set_error_string(context, "ASN.1 encoding of ReplyKeyPack " | 	krb5_set_error_string(context, "ASN.1 encoding of ReplyKeyPack " | ||||||
| @@ -879,10 +1180,10 @@ pk_mk_pa_reply(krb5_context context, | |||||||
| 	       METHOD_DATA *md) | 	       METHOD_DATA *md) | ||||||
| { | { | ||||||
|     krb5_error_code ret; |     krb5_error_code ret; | ||||||
|     PA_PK_AS_REP_19 rep; |  | ||||||
|     void *buf; |     void *buf; | ||||||
|     size_t len, size; |     size_t len, size; | ||||||
|     krb5_enctype enctype; |     krb5_enctype enctype; | ||||||
|  |     int pa_type; | ||||||
|     int i; |     int i; | ||||||
|  |  | ||||||
|     if (!enable_pkinit) { |     if (!enable_pkinit) { | ||||||
| @@ -890,63 +1191,180 @@ pk_mk_pa_reply(krb5_context context, | |||||||
| 	return 0; | 	return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     memset(&rep, 0, sizeof(rep)); |     if (req->req_body.etype.len > 0) { | ||||||
|  | 	for (i = 0; i < req->req_body.etype.len; i++) | ||||||
|  | 	    if (krb5_enctype_valid(context, req->req_body.etype.val[i]) == 0) | ||||||
|  | 		break; | ||||||
|  | 	if (req->req_body.etype.len <= i) { | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	    krb5_set_error_string(context, | ||||||
|  | 				  "No valid enctype available from client"); | ||||||
|  | 	    goto out; | ||||||
|  | 	}	 | ||||||
|  | 	enctype = req->req_body.etype.val[i]; | ||||||
|  |     } else | ||||||
|  | 	enctype = ETYPE_DES3_CBC_SHA1; | ||||||
|  |  | ||||||
|     if (req->req_body.etype.len < 1) { |     if (client_params->type == PKINIT_COMPAT_25) { | ||||||
|     } | 	PA_PK_AS_REP rep; | ||||||
|  |  | ||||||
|     /* XXX select best/allowed enctype */ | 	pa_type = KRB5_PADATA_PK_AS_REP; | ||||||
|     for (i = 0; i < req->req_body.etype.len; i++) |  | ||||||
| 	if (krb5_enctype_valid(context, req->req_body.etype.val[i]) == 0) |  | ||||||
| 	    break; |  | ||||||
|     if (req->req_body.etype.len <= i) { |  | ||||||
| 	ret = KRB5KRB_ERR_GENERIC; |  | ||||||
| 	krb5_set_error_string(context, |  | ||||||
| 			      "No valid enctype available from client"); |  | ||||||
| 	goto out; |  | ||||||
|     }	 |  | ||||||
|     enctype = req->req_body.etype.val[i]; |  | ||||||
|  |  | ||||||
|     if (client_params->dh == NULL) { | 	memset(&rep, 0, sizeof(rep)); | ||||||
| 	rep.element = choice_PA_PK_AS_REP_19_encKeyPack; |  | ||||||
|  |  | ||||||
| 	krb5_generate_random_keyblock(context, enctype,  | 	if (client_params->dh == NULL) { | ||||||
| 				      &client_params->reply_key); | 	    rep.element = choice_PA_PK_AS_REP_encKeyPack; | ||||||
|  | 	    ContentInfo info; | ||||||
|  |  | ||||||
| 	ret = pk_mk_pa_reply_enckey(context, | 	    krb5_generate_random_keyblock(context, enctype,  | ||||||
|  | 					  &client_params->reply_key); | ||||||
|  | 	    ret = pk_mk_pa_reply_enckey(context, | ||||||
|  | 					client_params, | ||||||
|  | 					req, | ||||||
|  | 					&client_params->reply_key, | ||||||
|  | 					&info); | ||||||
|  | 	    if (ret) { | ||||||
|  | 		free_PA_PK_AS_REP(&rep); | ||||||
|  | 		goto out; | ||||||
|  | 	    } | ||||||
|  | 	    ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data,  | ||||||
|  | 			       rep.u.encKeyPack.length, &info, &size,  | ||||||
|  | 			       ret); | ||||||
|  | 	    free_ContentInfo(&info); | ||||||
|  | 	    if (ret) { | ||||||
|  | 		krb5_set_error_string(context, "encoding of Key ContentInfo " | ||||||
|  | 				      "failed %d", ret); | ||||||
|  | 		free_PA_PK_AS_REP(&rep); | ||||||
|  | 		goto out; | ||||||
|  | 	    } | ||||||
|  | 	    if (rep.u.encKeyPack.length != size) | ||||||
|  | 		krb5_abortx(context, "Internal ASN.1 encoder error"); | ||||||
|  |  | ||||||
|  | 	} else { | ||||||
|  | 	    krb5_set_error_string(context, "DH -25 not implemented"); | ||||||
|  | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
|  | 	} | ||||||
|  | 	if (ret) { | ||||||
|  | 	    free_PA_PK_AS_REP(&rep); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ASN1_MALLOC_ENCODE(PA_PK_AS_REP, buf, len, &rep, &size, ret); | ||||||
|  | 	free_PA_PK_AS_REP(&rep); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context, "encode PA-PK-AS-REP failed %d", | ||||||
|  | 				  ret); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	if (len != size) | ||||||
|  | 	    krb5_abortx(context, "Internal ASN.1 encoder error"); | ||||||
|  |  | ||||||
|  |     } else if (client_params->type == PKINIT_COMPAT_19) { | ||||||
|  | 	PA_PK_AS_REP_19 rep; | ||||||
|  |  | ||||||
|  | 	pa_type = KRB5_PADATA_PK_AS_REP_19; | ||||||
|  |  | ||||||
|  | 	memset(&rep, 0, sizeof(rep)); | ||||||
|  |  | ||||||
|  | 	if (client_params->dh == NULL) { | ||||||
|  | 	    rep.element = choice_PA_PK_AS_REP_19_encKeyPack; | ||||||
|  | 	    krb5_generate_random_keyblock(context, enctype,  | ||||||
|  | 					  &client_params->reply_key); | ||||||
|  | 	    ret = pk_mk_pa_reply_enckey(context, | ||||||
|  | 					client_params, | ||||||
|  | 					req, | ||||||
|  | 					&client_params->reply_key, | ||||||
|  | 					&rep.u.encKeyPack); | ||||||
|  | 	} else { | ||||||
|  | 	    rep.element = choice_PA_PK_AS_REP_19_dhSignedData; | ||||||
|  |  | ||||||
|  | 	    ret = check_dh_params(client_params->dh); | ||||||
|  | 	    if (ret) | ||||||
|  | 		return ret; | ||||||
|  |  | ||||||
|  | 	    ret = generate_dh_keyblock(context, client_params, enctype, | ||||||
|  | 				       &client_params->reply_key); | ||||||
|  | 	    if (ret) | ||||||
|  | 		return ret; | ||||||
|  |  | ||||||
|  | 	    ret = pk_mk_pa_reply_dh(context, client_params->dh, | ||||||
| 				    client_params,  | 				    client_params,  | ||||||
| 				    req, |  | ||||||
| 				    &client_params->reply_key, | 				    &client_params->reply_key, | ||||||
| 				    &rep.u.encKeyPack); | 				    &rep.u.dhSignedData); | ||||||
|     } else { | 	} | ||||||
| 	rep.element = choice_PA_PK_AS_REP_19_dhSignedData; | 	if (ret) { | ||||||
|  | 	    free_PA_PK_AS_REP_19(&rep); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	ret = check_dh_params(client_params->dh); | 	ASN1_MALLOC_ENCODE(PA_PK_AS_REP_19, buf, len, &rep, &size, ret); | ||||||
| 	if (ret) | 	free_PA_PK_AS_REP_19(&rep); | ||||||
| 	    return ret; | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context,  | ||||||
|  | 				  "encode PA-PK-AS-REP-19 failed %d", ret); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	if (len != size) | ||||||
|  | 	    krb5_abortx(context, "Internal ASN.1 encoder error"); | ||||||
|  |     } else if (client_params->type == PKINIT_COMPAT_WIN2K) { | ||||||
|  | 	PA_PK_AS_REP_Win2k rep; | ||||||
|  |  | ||||||
| 	ret = generate_dh_keyblock(context, client_params, enctype, | 	pa_type = KRB5_PADATA_PK_AS_REP_19; | ||||||
| 				   &client_params->reply_key); |  | ||||||
| 	if (ret) |  | ||||||
| 	    return ret; |  | ||||||
|  |  | ||||||
| 	ret = pk_mk_pa_reply_dh(context, client_params->dh, | 	memset(&rep, 0, sizeof(rep)); | ||||||
| 				client_params,  |  | ||||||
| 				&client_params->reply_key, |  | ||||||
| 				&rep.u.dhSignedData); |  | ||||||
|     } |  | ||||||
|     if (ret) |  | ||||||
| 	goto out; |  | ||||||
|  |  | ||||||
|     ASN1_MALLOC_ENCODE(PA_PK_AS_REP_19, buf, len, &rep, &size, ret); | 	if (client_params->dh) { | ||||||
|     if (ret) { | 	    krb5_set_error_string(context, "DH -25 not implemented"); | ||||||
| 	krb5_set_error_string(context, "encode PA-PK-AS-REP failed %d", ret); | 	    ret = KRB5KRB_ERR_GENERIC; | ||||||
| 	goto out; | 	} else { | ||||||
|     } | 	    rep.element = choice_PA_PK_AS_REP_encKeyPack; | ||||||
|     if (len != size) | 	    ContentInfo info; | ||||||
| 	krb5_abortx(context, "Internal ASN.1 encoder error"); |  | ||||||
|  |  | ||||||
|     ret = krb5_padata_add(context, md, KRB5_PADATA_PK_AS_REP, buf, len); | 	    krb5_generate_random_keyblock(context, enctype,  | ||||||
|  | 					  &client_params->reply_key); | ||||||
|  | 	    ret = pk_mk_pa_reply_enckey(context, | ||||||
|  | 					client_params, | ||||||
|  | 					req, | ||||||
|  | 					&client_params->reply_key, | ||||||
|  | 					&info); | ||||||
|  | 	    if (ret) { | ||||||
|  | 		free_PA_PK_AS_REP_Win2k(&rep); | ||||||
|  | 		goto out; | ||||||
|  | 	    } | ||||||
|  | 	    ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data,  | ||||||
|  | 			       rep.u.encKeyPack.length, &info, &size,  | ||||||
|  | 			       ret); | ||||||
|  | 	    free_ContentInfo(&info); | ||||||
|  | 	    if (ret) { | ||||||
|  | 		krb5_set_error_string(context, "encoding of Key ContentInfo " | ||||||
|  | 				      "failed %d", ret); | ||||||
|  | 		free_PA_PK_AS_REP_Win2k(&rep); | ||||||
|  | 		goto out; | ||||||
|  | 	    } | ||||||
|  | 	    if (rep.u.encKeyPack.length != size) | ||||||
|  | 		krb5_abortx(context, "Internal ASN.1 encoder error"); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  | 	if (ret) { | ||||||
|  | 	    free_PA_PK_AS_REP_Win2k(&rep); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ASN1_MALLOC_ENCODE(PA_PK_AS_REP_Win2k, buf, len, &rep, &size, ret); | ||||||
|  | 	free_PA_PK_AS_REP_Win2k(&rep); | ||||||
|  | 	if (ret) { | ||||||
|  | 	    krb5_set_error_string(context,  | ||||||
|  | 				  "encode PA-PK-AS-REP-Win2k failed %d", ret); | ||||||
|  | 	    goto out; | ||||||
|  | 	} | ||||||
|  | 	if (len != size) | ||||||
|  | 	    krb5_abortx(context, "Internal ASN.1 encoder error"); | ||||||
|  |  | ||||||
|  |     } else | ||||||
|  | 	krb5_abortx(context, "PK-INIT internal error"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     ret = krb5_padata_add(context, md, pa_type, buf, len); | ||||||
|     if (ret) { |     if (ret) { | ||||||
| 	krb5_set_error_string(context, "failed adding " | 	krb5_set_error_string(context, "failed adding " | ||||||
| 			      "PA-PK-AS-REP-19 %d", ret); | 			      "PA-PK-AS-REP-19 %d", ret); | ||||||
| @@ -955,7 +1373,6 @@ pk_mk_pa_reply(krb5_context context, | |||||||
|  out: |  out: | ||||||
|     if (ret == 0) |     if (ret == 0) | ||||||
| 	*reply_key = &client_params->reply_key; | 	*reply_key = &client_params->reply_key; | ||||||
|     free_PA_PK_AS_REP_19(&rep); |  | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -814,6 +814,18 @@ pk_mk_padata(krb5_context context, | |||||||
|     } else if (compat == COMPAT_25) { |     } else if (compat == COMPAT_25) { | ||||||
|  |  | ||||||
| 	pa_type = KRB5_PADATA_PK_AS_REQ; | 	pa_type = KRB5_PADATA_PK_AS_REQ; | ||||||
|  |  | ||||||
|  | 	ASN1_MALLOC_ENCODE(ContentInfo, | ||||||
|  | 			   req.signedAuthPack.data, | ||||||
|  | 			   req.signedAuthPack.length, | ||||||
|  | 			   &content_info, | ||||||
|  | 			   &size, | ||||||
|  | 			   ret); | ||||||
|  | 	if (ret) | ||||||
|  | 	    goto out; | ||||||
|  | 	if (req.signedAuthPack.length != size) | ||||||
|  | 	    krb5_abortx(context, "Internal ASN1 encoder error"); | ||||||
|  |  | ||||||
| 	ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length, | 	ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length, | ||||||
| 			   &req, &size, ret); | 			   &req, &size, ret); | ||||||
|  |  | ||||||
| @@ -851,7 +863,7 @@ _krb5_pk_mk_padata(krb5_context context, | |||||||
|     int win2k_compat; |     int win2k_compat; | ||||||
|  |  | ||||||
|     win2k_compat = krb5_config_get_bool_default(context, NULL, |     win2k_compat = krb5_config_get_bool_default(context, NULL, | ||||||
| 						TRUE, | 						FALSE, | ||||||
| 						"realms", | 						"realms", | ||||||
| 						req_body->realm, | 						req_body->realm, | ||||||
| 						"win2k_pkinit", | 						"win2k_pkinit", | ||||||
| @@ -867,11 +879,10 @@ _krb5_pk_mk_padata(krb5_context context, | |||||||
| 	ret = pk_mk_padata(context, COMPAT_19, ctx, req_body, nonce, md); | 	ret = pk_mk_padata(context, COMPAT_19, ctx, req_body, nonce, md); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 	    goto out; | 	    goto out; | ||||||
| #if 0 |  | ||||||
| 	ret = pk_mk_padata(context, COMPAT_25, ctx, req_body, nonce, md); | 	ret = pk_mk_padata(context, COMPAT_25, ctx, req_body, nonce, md); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 	    goto out; | 	    goto out; | ||||||
| #endif |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     provisioning_server = |     provisioning_server = | ||||||
| @@ -1724,79 +1735,126 @@ _krb5_pk_rd_pa_reply(krb5_context context, | |||||||
| { | { | ||||||
|     krb5_pk_init_ctx ctx = c; |     krb5_pk_init_ctx ctx = c; | ||||||
|     krb5_error_code ret; |     krb5_error_code ret; | ||||||
|     PA_PK_AS_REP_19 rep; |  | ||||||
|     PA_PK_AS_REP_Win2k w2krep; |  | ||||||
|     ContentInfo ci; |     ContentInfo ci; | ||||||
|     size_t size; |     size_t size; | ||||||
|  |  | ||||||
|     memset(&rep, 0, sizeof(rep)); |     /* Check for PK-INIT -25 */ | ||||||
|  |     { | ||||||
|  | 	PA_PK_AS_REP rep; | ||||||
|  |  | ||||||
|     ret = decode_PA_PK_AS_REP_19(pa->padata_value.data, | 	memset(&rep, 0, sizeof(rep)); | ||||||
| 				 pa->padata_value.length, |  | ||||||
| 				 &rep, | 	ret = decode_PA_PK_AS_REP(pa->padata_value.data, | ||||||
| 				 &size); | 				  pa->padata_value.length, | ||||||
|     if (ret == 0) { | 				  &rep, | ||||||
| 	switch(rep.element) { | 				  &size); | ||||||
| 	case choice_PA_PK_AS_REP_19_dhSignedData: | 	if (ret == 0) { | ||||||
| 	    ret = pk_rd_pa_reply_dh(context, &rep.u.dhSignedData, ctx, | 	     | ||||||
| 				    etype, nonce, pa, key); | 	    switch (rep.element) { | ||||||
| 	    break; | 	    case choice_PA_PK_AS_REP_encKeyPack: | ||||||
| 	case choice_PA_PK_AS_REP_19_encKeyPack: | 		ret = decode_ContentInfo(rep.u.encKeyPack.data, | ||||||
| 	    ret = pk_rd_pa_reply_enckey(context, 0, | 					 rep.u.encKeyPack.length, | ||||||
| 					&rep.u.encKeyPack, ctx, | 					 &ci, | ||||||
| 					etype, nonce, pa, key); | 					 &size); | ||||||
| 	    break; | 		if (ret) { | ||||||
| 	default: | 		    krb5_set_error_string(context, | ||||||
| 	    krb5_set_error_string(context, "PKINIT: reply invalid " | 					  "PKINIT: -25 decoding failed " | ||||||
| 				  "content type"); | 					  "ContentInfo: %d", ret); | ||||||
| 	    ret = EINVAL; | 		    return ret; | ||||||
| 	    break; | 		} | ||||||
|  | 		ret = pk_rd_pa_reply_enckey(context, 0, &ci, ctx, | ||||||
|  | 					    etype, nonce, pa, key); | ||||||
|  | 		free_ContentInfo(&ci); | ||||||
|  | 		break; | ||||||
|  | 	    default: | ||||||
|  | 		krb5_set_error_string(context, "PKINIT: -25 reply " | ||||||
|  | 				      "invalid content type"); | ||||||
|  | 		ret = EINVAL; | ||||||
|  | 		break; | ||||||
|  | 	    } | ||||||
| 	}     | 	}     | ||||||
| 	free_PA_PK_AS_REP_19(&rep); | 	free_PA_PK_AS_REP(&rep); | ||||||
|  |  | ||||||
| 	if (ret == 0) | 	if (ret == 0) | ||||||
| 	    return 0; | 	    return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Check for Windows encoding of the AS-REP pa data */  |     /* Check for PK-INIT -19 */ | ||||||
|  |     { | ||||||
|  | 	PA_PK_AS_REP_19 rep19; | ||||||
|  |  | ||||||
|     memset(&w2krep, 0, sizeof(w2krep)); | 	memset(&rep19, 0, sizeof(rep19)); | ||||||
|  |  | ||||||
|     ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data, | 	ret = decode_PA_PK_AS_REP_19(pa->padata_value.data, | ||||||
| 				    pa->padata_value.length, | 				     pa->padata_value.length, | ||||||
| 				    &w2krep, | 				     &rep19, | ||||||
| 				    &size); | 				     &size); | ||||||
|     if (ret) { | 	if (ret == 0) { | ||||||
| 	krb5_set_error_string(context, "PKINIT: Failed decoding windows" | 	    switch(rep19.element) { | ||||||
| 			      "pkinit reply %d", ret); | 	    case choice_PA_PK_AS_REP_19_dhSignedData: | ||||||
| 	return ret; | 		ret = pk_rd_pa_reply_dh(context, &rep19.u.dhSignedData, ctx, | ||||||
|  | 					etype, nonce, pa, key); | ||||||
|  | 		break; | ||||||
|  | 	    case choice_PA_PK_AS_REP_19_encKeyPack: | ||||||
|  | 		ret = pk_rd_pa_reply_enckey(context, 0, | ||||||
|  | 					    &rep19.u.encKeyPack, ctx, | ||||||
|  | 					    etype, nonce, pa, key); | ||||||
|  | 		break; | ||||||
|  | 	    default: | ||||||
|  | 		krb5_set_error_string(context, "PKINIT: -19 reply invalid " | ||||||
|  | 				      "content type"); | ||||||
|  | 		ret = EINVAL; | ||||||
|  | 		break; | ||||||
|  | 	    } | ||||||
|  | 	    free_PA_PK_AS_REP_19(&rep19); | ||||||
|  |  | ||||||
|  | 	    if (ret == 0) | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     switch (w2krep.element) { |     /* Check for Windows encoding of the AS-REP pa data */  | ||||||
|     case choice_PA_PK_AS_REP_Win2k_encKeyPack: |     { | ||||||
| 	ret = decode_ContentInfo(w2krep.u.encKeyPack.data, | 	PA_PK_AS_REP_Win2k w2krep; | ||||||
| 				 w2krep.u.encKeyPack.length, |  | ||||||
| 				 &ci, | 	memset(&w2krep, 0, sizeof(w2krep)); | ||||||
| 				 &size); | 	 | ||||||
|  | 	ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data, | ||||||
|  | 					pa->padata_value.length, | ||||||
|  | 					&w2krep, | ||||||
|  | 					&size); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 	    krb5_set_error_string(context, | 	    krb5_set_error_string(context, "PKINIT: Failed decoding windows" | ||||||
| 				  "PKINIT: decoding failed ContentInfo: %d", | 				  "pkinit reply %d", ret); | ||||||
| 				  ret); |  | ||||||
| 	    return ret; | 	    return ret; | ||||||
| 	} | 	} | ||||||
| 	ret = pk_rd_pa_reply_enckey(context, 1, &ci, ctx, |  | ||||||
| 				    etype, nonce, pa, key); |  | ||||||
| 	free_ContentInfo(&ci); |  | ||||||
| 	 | 	 | ||||||
| 	break; | 	switch (w2krep.element) { | ||||||
|     default: | 	case choice_PA_PK_AS_REP_Win2k_encKeyPack: | ||||||
| 	krb5_set_error_string(context, "PKINIT: reply invalid content type"); | 	    ret = decode_ContentInfo(w2krep.u.encKeyPack.data, | ||||||
| 	ret = EINVAL; | 				     w2krep.u.encKeyPack.length, | ||||||
| 	break; | 				     &ci, | ||||||
|  | 				     &size); | ||||||
|  | 	    if (ret) { | ||||||
|  | 		krb5_set_error_string(context, | ||||||
|  | 				      "PKINIT: decoding failed " | ||||||
|  | 				      "ContentInfo: %d", | ||||||
|  | 				      ret); | ||||||
|  | 		return ret; | ||||||
|  | 	    } | ||||||
|  | 	    ret = pk_rd_pa_reply_enckey(context, 1, &ci, ctx, | ||||||
|  | 					etype, nonce, pa, key); | ||||||
|  | 	    free_ContentInfo(&ci); | ||||||
|  | 	    break; | ||||||
|  | 	default: | ||||||
|  | 	    krb5_set_error_string(context, "PKINIT: win2k reply invalid " | ||||||
|  | 				  "content type"); | ||||||
|  | 	    ret = EINVAL; | ||||||
|  | 	    break; | ||||||
|  | 	} | ||||||
|  |      | ||||||
|  | 	free_PA_PK_AS_REP_Win2k(&w2krep); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     free_PA_PK_AS_REP_Win2k(&w2krep); |  | ||||||
|  |  | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Love Hörnquist Åstrand
					Love Hörnquist Åstrand