diff options
author | Kevin Coffman <kwc@citi.umich.edu> | 2007-08-01 22:09:13 +0000 |
---|---|---|
committer | Kevin Coffman <kwc@citi.umich.edu> | 2007-08-01 22:09:13 +0000 |
commit | 0ef0646069c1d1376aa632a4791ea7e429f5ae9b (patch) | |
tree | 5b9f842dc45a9a14d5698a6f3ff321cea612d7c5 /src/lib | |
parent | 101446c6f40a13917fd0ba020bc276e82590058d (diff) | |
download | krb5-0ef0646069c1d1376aa632a4791ea7e429f5ae9b.zip krb5-0ef0646069c1d1376aa632a4791ea7e429f5ae9b.tar.gz krb5-0ef0646069c1d1376aa632a4791ea7e429f5ae9b.tar.bz2 |
Add PKINIT support
Pull up PKINIT support onto the trunk.
Changes from the version in branch users/coffman/pkinit are:
- Update the preauth plugin interface version to avoid
conflict with any existing plugins.
- Add a pkcs11.h locally to the pkinit code rather than
depending on opensc being installed.
ticket: new
Target_Version: 1.6.3
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19745 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_decode.c | 453 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_decode.h | 45 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_encode.c | 434 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_encode.h | 67 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/krb5_decode.c | 147 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/krb5_encode.c | 125 | ||||
-rw-r--r-- | src/lib/krb5/krb/preauth2.c | 57 | ||||
-rw-r--r-- | src/lib/krb5/os/accessor.c | 29 |
8 files changed, 1335 insertions, 22 deletions
diff --git a/src/lib/krb5/asn.1/asn1_k_decode.c b/src/lib/krb5/asn.1/asn1_k_decode.c index 6c20147..33b0f17 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.c +++ b/src/lib/krb5/asn.1/asn1_k_decode.c @@ -160,6 +160,28 @@ } else { len = 0; var = 0; } /* + * Deal with implicitly tagged fields + */ +#define get_implicit_octet_string(len, var, tagexpect) \ + if (tagnum != (tagexpect)) return ASN1_MISSING_FIELD; \ + if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \ + return ASN1_BAD_ID; \ + retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var)); \ + if (retval) return retval; \ + (len) = taglen; \ + next_tag() + +#define opt_implicit_octet_string(len, var, tagexpect) \ + if (tagnum == (tagexpect)) { \ + if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \ + return ASN1_BAD_ID; \ + retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var)); \ + if (retval) return retval; \ + (len) = taglen; \ + next_tag(); \ + } else { (len) = 0; (var) = NULL; } + +/* * begin_structure * * Declares some variables for decoding SEQUENCE types. This is meant @@ -176,6 +198,22 @@ if (retval) return retval; \ next_tag() +/* + * This is used for structures which have no tagging. + * It is the same as begin_structure() except next_tag() + * is not called. + */ +#define begin_structure_no_tag() \ + asn1buf subbuf; \ + int seqindef; \ + int indef; \ + unused_var(taglen); \ + unused_var(construction); \ + retval = asn1_get_sequence(buf, &length, &seqindef); \ + if (retval) return retval; \ + retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \ + if (retval) return retval + /* skip trailing garbage */ #define end_structure() \ retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum, \ @@ -183,6 +221,37 @@ if (retval) return retval /* + * begin_choice + * + * Declares some variables for decoding CHOICE types. This is meant + * to be called in an inner block that ends with a call to + * end_choice(). + */ +#define begin_choice() \ + asn1buf subbuf; \ + int seqindef; \ + int indef; \ + taginfo t; \ + retval = asn1_get_tag_2(buf, &t); \ + if (retval) return retval; \ + tagnum = t.tagnum; \ + taglen = t.length; \ + indef = t.indef; \ + length = t.length; \ + seqindef = t.indef; \ + asn1class = t.asn1class; \ + construction = t.construction; \ + retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \ + if (retval) return retval + +/* skip trailing garbage */ +#define end_choice() \ + length -= t.length; \ + retval = asn1buf_sync(buf, &subbuf, t.asn1class, t.tagnum, \ + length, t.indef, seqindef); \ + if (retval) return retval + +/* * sequence_of * * Declares some variables for decoding SEQUENCE OF types. This is @@ -1094,3 +1163,387 @@ asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_ } cleanup(); } + +/* PKINIT */ + +asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier *val) +{ + setup(); + { + begin_structure(); + opt_implicit_octet_string(val->subjectName.length, val->subjectName.data, 0); + opt_implicit_octet_string(val->issuerAndSerialNumber.length, val->issuerAndSerialNumber.data, 1); + opt_implicit_octet_string(val->subjectKeyIdentifier.length, val->subjectKeyIdentifier.data, 2); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_sequence_of_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier ***val) +{ + decode_array_body(krb5_external_principal_identifier,asn1_decode_external_principal_identifier); +} + +asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val) +{ + setup(); + { + begin_structure(); + get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0); + opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_external_principal_identifier, NULL); + opt_implicit_octet_string(val->kdcPkId.length, val->kdcPkId.data, 2); + end_structure(); + } + cleanup(); +} + +#if 0 /* XXX This needs to be tested!!! XXX */ +asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) +{ + setup(); + { + char *start, *end; + size_t alloclen; + + begin_explicit_choice(); + if (t.tagnum == choice_trusted_cas_principalName) { + val->choice = choice_trusted_cas_principalName; + } else if (t.tagnum == choice_trusted_cas_caName) { + val->choice = choice_trusted_cas_caName; + start = subbuf.next; + { + sequence_of_no_tagvars(&subbuf); + unused_var(size); + end_sequence_of_no_tagvars(&subbuf); + } + end = subbuf.next; + alloclen = end - start; + val->u.caName.data = malloc(alloclen); + if (val->u.caName.data == NULL) + return ENOMEM; + memcpy(val->u.caName.data, start, alloclen); + val->u.caName.length = alloclen; + next_tag(); + } else if (t.tagnum == choice_trusted_cas_issuerAndSerial) { + val->choice = choice_trusted_cas_issuerAndSerial; + start = subbuf.next; + { + sequence_of_no_tagvars(&subbuf); + unused_var(size); + end_sequence_of_no_tagvars(&subbuf); + } + end = subbuf.next; + alloclen = end - start; + val->u.issuerAndSerial.data = malloc(alloclen); + if (val->u.issuerAndSerial.data == NULL) + return ENOMEM; + memcpy(val->u.issuerAndSerial.data, start, alloclen); + val->u.issuerAndSerial.length = alloclen; + next_tag(); + } else return ASN1_BAD_ID; + end_explicit_choice(); + } + cleanup(); +} +#else +asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val) +{ + setup(); + { begin_choice(); + if (tagnum == choice_trusted_cas_principalName) { + val->choice = choice_trusted_cas_principalName; + asn1_decode_krb5_principal_name(&subbuf, &(val->u.principalName)); + } else if (tagnum == choice_trusted_cas_caName) { + val->choice = choice_trusted_cas_caName; + get_implicit_octet_string(val->u.caName.length, val->u.caName.data, choice_trusted_cas_caName); + } else if (tagnum == choice_trusted_cas_issuerAndSerial) { + val->choice = choice_trusted_cas_issuerAndSerial; + get_implicit_octet_string(val->u.issuerAndSerial.length, val->u.issuerAndSerial.data, + choice_trusted_cas_issuerAndSerial); + } else return ASN1_BAD_ID; + end_choice(); + } + cleanup(); +} +#endif + +asn1_error_code asn1_decode_sequence_of_trusted_ca(asn1buf *buf, krb5_trusted_ca ***val) +{ + decode_array_body(krb5_trusted_ca, asn1_decode_trusted_ca); +} + +asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val) +{ + setup(); + { begin_structure(); + get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0); + opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_trusted_ca, NULL); + opt_lenfield(val->kdcCert.length, val->kdcCert.data, 2, asn1_decode_octetstring); + opt_lenfield(val->encryptionCert.length, val->encryptionCert.data, 2, asn1_decode_octetstring); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val) +{ + setup(); + { begin_structure(); + get_implicit_octet_string(val->dhSignedData.length, val->dhSignedData.data, 0); + + opt_lenfield(val->serverDHNonce.length, val->serverDHNonce.data, 1, asn1_decode_octetstring); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator *val) +{ + setup(); + { begin_structure(); + get_field(val->cusec, 0, asn1_decode_int32); + get_field(val->ctime, 1, asn1_decode_kerberos_time); + get_field(val->nonce, 2, asn1_decode_int32); + opt_lenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_decode_octetstring); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authenticator_draft9 *val) +{ + setup(); + { begin_structure(); + alloc_field(val->kdcName,krb5_principal_data); + get_field(val->kdcName, 0, asn1_decode_principal_name); + get_field(val->kdcName, 1, asn1_decode_realm); + get_field(val->cusec, 2, asn1_decode_int32); + get_field(val->ctime, 3, asn1_decode_kerberos_time); + get_field(val->nonce, 4, asn1_decode_int32); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier *val) { + + setup(); + { begin_structure_no_tag(); + retval = asn1_decode_oid(&subbuf, &val->algorithm.length, + &val->algorithm.data); + if(retval) return retval; + val->parameters.length = 0; + val->parameters.data = NULL; + + if(length > subbuf.next - subbuf.base) { + unsigned int size = length - (subbuf.next - subbuf.base); + retval = asn1buf_remove_octetstring(&subbuf, size, + &val->parameters.data); + if(retval) return retval; + val->parameters.length = size; + } + + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info *val) +{ + asn1_octet unused; + setup(); + { begin_structure_no_tag(); + + retval = asn1_decode_algorithm_identifier(&subbuf, &val->algorithm); + if (retval) return retval; + + /* SubjectPublicKey encoded as a BIT STRING */ + next_tag(); + if (asn1class != UNIVERSAL || construction != PRIMITIVE || + tagnum != ASN1_BITSTRING) + return ASN1_BAD_ID; + + retval = asn1buf_remove_octet(&subbuf, &unused); + if(retval) return retval; + + /* Number of unused bits must be between 0 and 7. */ + /* What to do if unused is not zero? */ + if (unused > 7) return ASN1_BAD_FORMAT; + taglen--; + + val->subjectPublicKey.length = 0; + val->subjectPublicKey.data = NULL; + retval = asn1buf_remove_octetstring(&subbuf, taglen, + &val->subjectPublicKey.data); + if(retval) return retval; + val->subjectPublicKey.length = taglen; + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_sequence_of_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier ***val) +{ + decode_array_body(krb5_algorithm_identifier, asn1_decode_algorithm_identifier); +} + +asn1_error_code asn1_decode_kdc_dh_key_info (asn1buf *buf, krb5_kdc_dh_key_info *val) +{ + setup(); + { begin_structure(); + retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data); + if(retval) return retval; + val->subjectPublicKey.length = taglen; + next_tag(); + get_field(val->nonce, 1, asn1_decode_int32); + opt_field(val->dhKeyExpiration, 2, asn1_decode_kerberos_time, 0); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_reply_key_pack (asn1buf *buf, krb5_reply_key_pack *val) +{ + setup(); + { begin_structure(); + get_field(val->replyKey, 0, asn1_decode_encryption_key); + get_field(val->asChecksum, 1, asn1_decode_checksum); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_reply_key_pack_draft9 (asn1buf *buf, krb5_reply_key_pack_draft9 *val) +{ + setup(); + { begin_structure(); + get_field(val->replyKey, 0, asn1_decode_encryption_key); + get_field(val->nonce, 1, asn1_decode_int32); + end_structure(); + } + cleanup(); +} + + +asn1_error_code asn1_decode_krb5_principal_name (asn1buf *buf, krb5_principal *val) +{ + setup(); + { begin_structure(); + get_field(*val, 0, asn1_decode_realm); + get_field(*val, 1, asn1_decode_principal_name); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val) +{ + setup(); + { begin_structure(); + get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator); + if (tagnum == 1) { alloc_field(val->clientPublicValue, krb5_subject_pk_info); } + /* can't call opt_field because it does decoder(&subbuf, &(val)); */ + if (asn1buf_remains(&subbuf, seqindef)) { + if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) + && (tagnum || taglen || asn1class != UNIVERSAL)) + return ASN1_BAD_ID; + if (tagnum == 1) { + retval = asn1_decode_subject_pk_info(&subbuf, + val->clientPublicValue); + if (!taglen && indef) { get_eoc(); } + next_tag(); + } else val->clientPublicValue = NULL; + } + /* can't call opt_field because it does decoder(&subbuf, &(val)); */ + if (asn1buf_remains(&subbuf, seqindef)) { + if (tagnum == 2) { + asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes); + if (!taglen && indef) { get_eoc(); } + next_tag(); + } else val->supportedCMSTypes = NULL; + } + opt_lenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_decode_octetstring); + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 *val) +{ + setup(); + { begin_structure(); + get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator_draft9); + if (tagnum == 1) { + alloc_field(val->clientPublicValue, krb5_subject_pk_info); + /* can't call opt_field because it does decoder(&subbuf, &(val)); */ + if (asn1buf_remains(&subbuf, seqindef)) { + if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED) + && (tagnum || taglen || asn1class != UNIVERSAL)) + return ASN1_BAD_ID; + if (tagnum == 1) { + retval = asn1_decode_subject_pk_info(&subbuf, + val->clientPublicValue); + if (!taglen && indef) { get_eoc(); } + next_tag(); + } else val->clientPublicValue = NULL; + } + } + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val) +{ + setup(); + { begin_choice(); + if (tagnum == choice_pa_pk_as_rep_dhInfo) { + val->choice = choice_pa_pk_as_rep_dhInfo; + get_field_body(val->u.dh_Info, asn1_decode_dh_rep_info); + } else if (tagnum == choice_pa_pk_as_rep_encKeyPack) { + val->choice = choice_pa_pk_as_rep_encKeyPack; + get_implicit_octet_string(val->u.encKeyPack.length, val->u.encKeyPack.data, + choice_pa_pk_as_rep_encKeyPack); + } else { + val->choice = choice_pa_pk_as_rep_UNKNOWN; + } + end_choice(); + } + cleanup(); +} + +asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val) +{ + setup(); + { begin_structure(); + if (tagnum == choice_pa_pk_as_rep_draft9_dhSignedData) { + val->choice = choice_pa_pk_as_rep_draft9_dhSignedData; + get_lenfield(val->u.dhSignedData.length, val->u.dhSignedData.data, + choice_pa_pk_as_rep_draft9_dhSignedData, asn1_decode_octetstring); + } else if (tagnum == choice_pa_pk_as_rep_draft9_encKeyPack) { + val->choice = choice_pa_pk_as_rep_draft9_encKeyPack; + get_lenfield(val->u.encKeyPack.length, val->u.encKeyPack.data, + choice_pa_pk_as_rep_draft9_encKeyPack, asn1_decode_octetstring); + } else { + val->choice = choice_pa_pk_as_rep_UNKNOWN; + } + end_structure(); + } + cleanup(); +} + +asn1_error_code asn1_decode_sequence_of_typed_data(asn1buf *buf, krb5_typed_data ***val) +{ + decode_array_body(krb5_typed_data,asn1_decode_typed_data); +} + +asn1_error_code asn1_decode_typed_data(asn1buf *buf, krb5_typed_data *val) +{ + setup(); + { begin_structure(); + get_field(val->type,0,asn1_decode_int32); + get_lenfield(val->length,val->data,1,asn1_decode_octetstring); + end_structure(); + } + cleanup(); +} diff --git a/src/lib/krb5/asn.1/asn1_k_decode.h b/src/lib/krb5/asn.1/asn1_k_decode.h index 22e43fd..72c4e29 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.h +++ b/src/lib/krb5/asn.1/asn1_k_decode.h @@ -159,6 +159,44 @@ asn1_error_code asn1_decode_sam_response_2 (asn1buf *buf, krb5_sam_response_2 *val); asn1_error_code asn1_decode_predicted_sam_response (asn1buf *buf, krb5_predicted_sam_response *val); +asn1_error_code asn1_decode_external_principal_identifier + (asn1buf *buf, krb5_external_principal_identifier *val); +asn1_error_code asn1_decode_pa_pk_as_req + (asn1buf *buf, krb5_pa_pk_as_req *val); +asn1_error_code asn1_decode_trusted_ca + (asn1buf *buf, krb5_trusted_ca *val); +asn1_error_code asn1_decode_pa_pk_as_req_draft9 + (asn1buf *buf, krb5_pa_pk_as_req_draft9 *val); +asn1_error_code asn1_decode_dh_rep_info + (asn1buf *buf, krb5_dh_rep_info *val); +asn1_error_code asn1_decode_pk_authenticator + (asn1buf *buf, krb5_pk_authenticator *val); +asn1_error_code asn1_decode_pk_authenticator_draft9 + (asn1buf *buf, krb5_pk_authenticator_draft9 *val); +asn1_error_code asn1_decode_subject_pk_info + (asn1buf *buf, krb5_subject_pk_info *val); +asn1_error_code asn1_decode_algorithm_identifier + (asn1buf *buf, krb5_algorithm_identifier *val); +asn1_error_code asn1_decode_auth_pack + (asn1buf *buf, krb5_auth_pack *val); +asn1_error_code asn1_decode_auth_pack_draft9 + (asn1buf *buf, krb5_auth_pack_draft9 *val); +asn1_error_code asn1_decode_pa_pk_as_rep + (asn1buf *buf, krb5_pa_pk_as_rep *val); +asn1_error_code asn1_decode_pa_pk_as_rep_draft9 + (asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val); +asn1_error_code asn1_decode_kdc_dh_key_info + (asn1buf *buf, krb5_kdc_dh_key_info *val); +asn1_error_code asn1_decode_krb5_principal_name + (asn1buf *buf, krb5_principal *val); +asn1_error_code asn1_decode_reply_key_pack + (asn1buf *buf, krb5_reply_key_pack *val); +asn1_error_code asn1_decode_reply_key_pack_draft9 + (asn1buf *buf, krb5_reply_key_pack_draft9 *val); +asn1_error_code asn1_decode_sequence_of_typed_data + (asn1buf *buf, krb5_typed_data ***val); +asn1_error_code asn1_decode_typed_data + (asn1buf *buf, krb5_typed_data *val); /* arrays */ asn1_error_code asn1_decode_authorization_data @@ -187,6 +225,11 @@ asn1_error_code asn1_decode_etype_info (asn1buf *buf, krb5_etype_info_entry ***val); asn1_error_code asn1_decode_etype_info2 (asn1buf *buf, krb5_etype_info_entry ***val, krb5_boolean v1_3_behavior); - +asn1_error_code asn1_decode_sequence_of_external_principal_identifier + (asn1buf *buf, krb5_external_principal_identifier ***val); +asn1_error_code asn1_decode_sequence_of_trusted_ca + (asn1buf *buf, krb5_trusted_ca ***val); +asn1_error_code asn1_decode_sequence_of_algorithm_identifier + (asn1buf *buf, krb5_algorithm_identifier ***val); #endif diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index 00cfab0..4869ea7 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -103,6 +103,50 @@ return retval; }\ sum += length; } +/* asn1_addfield_implicit -- add an implicitly tagged field, or component, to the encoding */ +#define asn1_addfield_implicit(value,tag,encoder)\ +{ retval = encoder(buf,value,&length);\ + if(retval){\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum += length;\ + retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,length,&length); \ + if(retval){\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum += length; } + +/* asn1_insert_implicit_octetstring -- add an octet string with implicit tagging */ +#define asn1_insert_implicit_octetstring(len,value,tag)\ +{ retval = asn1buf_insert_octetstring(buf,len,value);\ + if(retval){\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum += len;\ + retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,len,&length); \ + if(retval){\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum += length; } + +/* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */ +#define asn1_insert_implicit_bitstring(len,value,tag)\ +{ retval = asn1buf_insert_octetstring(buf,len,value);\ + if(retval){\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum += len;\ + retval = asn1buf_insert_octet(buf, 0);\ + if(retval){\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum++;\ + retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,tag,len+1,&length); \ + if(retval){\ + asn1buf_destroy(&buf);\ + return retval; }\ + sum += length; } + /* form a sequence (by adding a sequence header to the current encoding) */ #define asn1_makeseq()\ retval = asn1_make_sequence(buf,sum,&length);\ @@ -959,3 +1003,393 @@ asn1_error_code asn1_encode_krb_saved_safe_body(asn1buf *buf, const krb5_data *b *retlen = body->length; return 0; } + +/* + * PKINIT + */ + +asn1_error_code asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen) +{ + asn1_setup(); + asn1_addlenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_encode_octetstring); + asn1_addfield(val->nonce, 2, asn1_encode_integer); + asn1_addfield(val->ctime, 1, asn1_encode_kerberos_time); + asn1_addfield(val->cusec, 0, asn1_encode_integer); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_pk_authenticator_draft9(asn1buf *buf, const krb5_pk_authenticator_draft9 *val, unsigned int *retlen) +{ + asn1_setup(); + + asn1_addfield(val->nonce, 4, asn1_encode_integer); + asn1_addfield(val->ctime, 3, asn1_encode_kerberos_time); + asn1_addfield(val->cusec, 2, asn1_encode_integer); + asn1_addfield(val->kdcName, 1, asn1_encode_realm); + asn1_addfield(val->kdcName, 0, asn1_encode_principal_name); + + asn1_makeseq(); + asn1_cleanup(); +} + + +asn1_error_code asn1_encode_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier *val, unsigned int *retlen) +{ + asn1_setup(); + + if (val->parameters.length != 0) { + retval = asn1buf_insert_octetstring(buf, val->parameters.length, + val->parameters.data); + if(retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += val->parameters.length; + } + + retval = asn1_encode_oid(buf, val->algorithm.length, + val->algorithm.data, + &length); + + if(retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += length; + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen) +{ + asn1_setup(); + + asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING); + + if (val->algorithm.parameters.length != 0) { + retval = asn1buf_insert_octetstring(buf, val->algorithm.parameters.length, + val->algorithm.parameters.data); + if(retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += val->algorithm.parameters.length; + } + + retval = asn1_encode_oid(buf, val->algorithm.algorithm.length, + val->algorithm.algorithm.data, + &length); + + if(retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += length; + + retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE, + val->algorithm.parameters.length + length, + &length); + + if(retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += length; + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_sequence_of_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier **val, unsigned int *retlen) +{ + asn1_setup(); + int i; + + if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; + + for(i=0; val[i] != NULL; i++); + for(i--; i>=0; i--){ + retval = asn1_encode_algorithm_identifier(buf,val[i],&length); + if(retval) return retval; + sum += length; + } + asn1_makeseq(); + + asn1_cleanup(); +} + +asn1_error_code asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val, unsigned int *retlen) +{ + asn1_setup(); + + if (val->clientDHNonce.length != 0) + asn1_addlenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_encode_octetstring); + if (val->supportedCMSTypes != NULL) + asn1_addfield((const krb5_algorithm_identifier **)val->supportedCMSTypes,2,asn1_encode_sequence_of_algorithm_identifier); + if (val->clientPublicValue != NULL) + asn1_addfield(val->clientPublicValue,1,asn1_encode_subject_pk_info); + asn1_addfield(&(val->pkAuthenticator),0,asn1_encode_pk_authenticator); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_auth_pack_draft9(asn1buf *buf, const krb5_auth_pack_draft9 *val, unsigned int *retlen) +{ + asn1_setup(); + + if (val->clientPublicValue != NULL) + asn1_addfield(val->clientPublicValue, 1, asn1_encode_subject_pk_info); + asn1_addfield(&(val->pkAuthenticator), 0, asn1_encode_pk_authenticator_draft9); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier *val, unsigned int *retlen) +{ + asn1_setup(); + + /* Verify there is something to encode */ + if (val->subjectKeyIdentifier.length == 0 && val->issuerAndSerialNumber.length == 0 && val->subjectName.length == 0) + return ASN1_MISSING_FIELD; + + if (val->subjectKeyIdentifier.length != 0) + asn1_insert_implicit_octetstring(val->subjectKeyIdentifier.length,val->subjectKeyIdentifier.data,2); + + if (val->issuerAndSerialNumber.length != 0) + asn1_insert_implicit_octetstring(val->issuerAndSerialNumber.length,val->issuerAndSerialNumber.data,1); + + if (val->subjectName.length != 0) + asn1_insert_implicit_octetstring(val->subjectName.length,val->subjectName.data,0); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_sequence_of_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen) +{ + asn1_setup(); + int i; + + if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; + + for(i=0; val[i] != NULL; i++); + for(i--; i>=0; i--){ + retval = asn1_encode_external_principal_identifier(buf,val[i],&length); + if(retval) return retval; + sum += length; + } + asn1_makeseq(); + + asn1_cleanup(); +} + +asn1_error_code asn1_encode_pa_pk_as_req(asn1buf *buf, const krb5_pa_pk_as_req *val, unsigned int *retlen) +{ + asn1_setup(); + + if (val->kdcPkId.length != 0) + asn1_insert_implicit_octetstring(val->kdcPkId.length,val->kdcPkId.data,2); + + if (val->trustedCertifiers != NULL) + asn1_addfield((const krb5_external_principal_identifier **)val->trustedCertifiers,1,asn1_encode_sequence_of_external_principal_identifier); + + asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_trusted_ca(asn1buf *buf, const krb5_trusted_ca *val, unsigned int *retlen) +{ + asn1_setup(); + + switch (val->choice) { + case choice_trusted_cas_issuerAndSerial: + asn1_insert_implicit_octetstring(val->u.issuerAndSerial.length,val->u.issuerAndSerial.data,2); + break; + case choice_trusted_cas_caName: + asn1_insert_implicit_octetstring(val->u.caName.length,val->u.caName.data,1); + break; + case choice_trusted_cas_principalName: + asn1_addfield_implicit(val->u.principalName,0,asn1_encode_principal_name); + break; + default: + return ASN1_MISSING_FIELD; + } + + asn1_cleanup(); +} + +asn1_error_code asn1_encode_sequence_of_trusted_ca(asn1buf *buf, const krb5_trusted_ca **val, unsigned int *retlen) +{ + asn1_setup(); + int i; + + if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; + + for(i=0; val[i] != NULL; i++); + for(i--; i>=0; i--){ + retval = asn1_encode_trusted_ca(buf,val[i],&length); + if(retval) return retval; + sum += length; + } + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_pa_pk_as_req_draft9(asn1buf *buf, const krb5_pa_pk_as_req_draft9 *val, unsigned int *retlen) +{ + asn1_setup(); + + if (val->encryptionCert.length != 0) + asn1_insert_implicit_octetstring(val->encryptionCert.length,val->encryptionCert.data,3); + + if (val->kdcCert.length != 0) + asn1_insert_implicit_octetstring(val->kdcCert.length,val->kdcCert.data,2); + + if (val->trustedCertifiers != NULL) + asn1_addfield((const krb5_trusted_ca **)val->trustedCertifiers,1,asn1_encode_sequence_of_trusted_ca); + + asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_dh_rep_info(asn1buf *buf, const krb5_dh_rep_info *val, unsigned int *retlen) +{ + asn1_setup(); + + if (val->serverDHNonce.length != 0) + asn1_insert_implicit_octetstring(val->serverDHNonce.length,val->serverDHNonce.data,1); + + asn1_insert_implicit_octetstring(val->dhSignedData.length,val->dhSignedData.data,0); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_info *val, unsigned int *retlen) +{ + asn1_setup(); + + if (val->dhKeyExpiration != 0) + asn1_addfield(val->dhKeyExpiration, 2, asn1_encode_kerberos_time); + asn1_addfield(val->nonce, 1, asn1_encode_integer); + + asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,3); + retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, + val->subjectPublicKey.length + 1 + length, + &length); + if(retval) { + asn1buf_destroy(&buf); + return retval; + } + sum += length; + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_reply_key_pack(asn1buf *buf, const krb5_reply_key_pack *val, unsigned int *retlen) +{ + asn1_setup(); + + asn1_addfield(&(val->asChecksum), 1, asn1_encode_checksum); + asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_reply_key_pack_draft9(asn1buf *buf, const krb5_reply_key_pack_draft9 *val, unsigned int *retlen) +{ + asn1_setup(); + + asn1_addfield(val->nonce, 1, asn1_encode_integer); + asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key); + + asn1_makeseq(); + asn1_cleanup(); +} + +asn1_error_code asn1_encode_pa_pk_as_rep(asn1buf *buf, const krb5_pa_pk_as_rep *val, unsigned int *retlen) +{ + asn1_setup(); + + switch (val->choice) + { + case choice_pa_pk_as_rep_dhInfo: + asn1_addfield(&(val->u.dh_Info), choice_pa_pk_as_rep_dhInfo, asn1_encode_dh_rep_info); + break; + case choice_pa_pk_as_rep_encKeyPack: + asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1); + break; + default: + return ASN1_MISSING_FIELD; + } + + asn1_cleanup(); +} + +asn1_error_code asn1_encode_pa_pk_as_rep_draft9(asn1buf *buf, const krb5_pa_pk_as_rep_draft9 *val, unsigned int *retlen) +{ + asn1_setup(); + + switch (val->choice) + { + case choice_pa_pk_as_rep_draft9_dhSignedData: + asn1_insert_implicit_octetstring(val->u.dhSignedData.length,val->u.dhSignedData.data,0); + break; + case choice_pa_pk_as_rep_encKeyPack: + asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1); + break; + default: + return ASN1_MISSING_FIELD; + } + + asn1_cleanup(); +} + +asn1_error_code asn1_encode_td_trusted_certifiers(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen) +{ + asn1_setup(); + retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length); + if (retval) { + asn1buf_destroy(&buf); + return retval; + } + asn1_cleanup(); +} + +asn1_error_code asn1_encode_sequence_of_typed_data(asn1buf *buf, const krb5_typed_data **val, unsigned int *retlen) +{ + asn1_setup(); + int i; + + if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD; + + for(i=0; val[i] != NULL; i++); + for(i--; i>=0; i--){ + retval = asn1_encode_typed_data(buf,val[i],&length); + if(retval) return retval; + sum += length; + } + asn1_makeseq(); + + asn1_cleanup(); +} + +asn1_error_code asn1_encode_typed_data(asn1buf *buf, const krb5_typed_data *val, unsigned int *retlen) +{ + asn1_setup(); + asn1_addlenfield(val->length, val->data, 1, asn1_encode_octetstring); + asn1_addfield(val->type, 0, asn1_encode_integer); + asn1_makeseq(); + asn1_cleanup(); +} diff --git a/src/lib/krb5/asn.1/asn1_k_encode.h b/src/lib/krb5/asn.1/asn1_k_encode.h index caa46c5..b5f24c4 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.h +++ b/src/lib/krb5/asn.1/asn1_k_encode.h @@ -269,4 +269,71 @@ asn1_error_code asn1_encode_predicted_sam_response asn1_error_code asn1_encode_krb_saved_safe_body (asn1buf *buf, const krb5_data *body, unsigned int *retlen); +/* PKINIT */ + +asn1_error_code asn1_encode_pk_authenticator + (asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen); + +asn1_error_code asn1_encode_pk_authenticator_draft9 + (asn1buf *buf, const krb5_pk_authenticator_draft9 *val, unsigned int *retlen); + +asn1_error_code asn1_encode_algorithm_identifier + (asn1buf *buf, const krb5_algorithm_identifier *val, unsigned int *retlen); + +asn1_error_code asn1_encode_subject_pk_info + (asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen); + +asn1_error_code asn1_encode_sequence_of_algorithm_identifier + (asn1buf *buf, const krb5_algorithm_identifier **val, unsigned int *retlen); + +asn1_error_code asn1_encode_auth_pack + (asn1buf *buf, const krb5_auth_pack *val, unsigned int *retlen); + +asn1_error_code asn1_encode_auth_pack_draft9 + (asn1buf *buf, const krb5_auth_pack_draft9 *val, unsigned int *retlen); + +asn1_error_code asn1_encode_external_principal_identifier + (asn1buf *buf, const krb5_external_principal_identifier *val, unsigned int *retlen); + +asn1_error_code asn1_encode_sequence_of_external_principal_identifier + (asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen); + +asn1_error_code asn1_encode_pa_pk_as_req + (asn1buf *buf, const krb5_pa_pk_as_req *val, unsigned int *retlen); + +asn1_error_code asn1_encode_trusted_ca + (asn1buf *buf, const krb5_trusted_ca *val, unsigned int *retlen); + +asn1_error_code asn1_encode_sequence_of_trusted_ca + (asn1buf *buf, const krb5_trusted_ca **val, unsigned int *retlen); + +asn1_error_code asn1_encode_pa_pk_as_req_draft9 + (asn1buf *buf, const krb5_pa_pk_as_req_draft9 *val, unsigned int *retlen); + +asn1_error_code asn1_encode_dh_rep_info + (asn1buf *buf, const krb5_dh_rep_info *val, unsigned int *retlen); + +asn1_error_code asn1_encode_kdc_dh_key_info + (asn1buf *buf, const krb5_kdc_dh_key_info *val, unsigned int *retlen); + +asn1_error_code asn1_encode_reply_key_pack + (asn1buf *buf, const krb5_reply_key_pack *val, unsigned int *retlen); + +asn1_error_code asn1_encode_reply_key_pack_draft9 + (asn1buf *buf, const krb5_reply_key_pack_draft9 *val, unsigned int *retlen); + +asn1_error_code asn1_encode_pa_pk_as_rep + (asn1buf *buf, const krb5_pa_pk_as_rep *val, unsigned int *retlen); + +asn1_error_code asn1_encode_pa_pk_as_rep_draft9 + (asn1buf *buf, const krb5_pa_pk_as_rep_draft9 *val, unsigned int *retlen); + +asn1_error_code asn1_encode_td_trusted_certifiers + (asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen); + +asn1_error_code asn1_encode_typed_data + (asn1buf *buf, const krb5_typed_data *val, unsigned int *retlen); + +asn1_error_code asn1_encode_sequence_of_typed_data + (asn1buf *buf, const krb5_typed_data **val, unsigned int *retlen); #endif diff --git a/src/lib/krb5/asn.1/krb5_decode.c b/src/lib/krb5/asn.1/krb5_decode.c index e5cd4f8..cbd6a12 100644 --- a/src/lib/krb5/asn.1/krb5_decode.c +++ b/src/lib/krb5/asn.1/krb5_decode.c @@ -934,3 +934,150 @@ krb5_error_code decode_krb5_predicted_sam_response(const krb5_data *code, krb5_p cleanup(free); } +krb5_error_code decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_pa_pk_as_req); + + retval = asn1_decode_pa_pk_as_req(&buf, *rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_pa_pk_as_req_draft9(const krb5_data *code, krb5_pa_pk_as_req_draft9 **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_pa_pk_as_req_draft9); + + retval = asn1_decode_pa_pk_as_req_draft9(&buf, *rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_pa_pk_as_rep(const krb5_data *code, krb5_pa_pk_as_rep **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_pa_pk_as_rep); + + retval = asn1_decode_pa_pk_as_rep(&buf, *rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_pa_pk_as_rep_draft9(const krb5_data *code, krb5_pa_pk_as_rep_draft9 **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_pa_pk_as_rep_draft9); + + retval = asn1_decode_pa_pk_as_rep_draft9(&buf, *rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_auth_pack(const krb5_data *code, krb5_auth_pack **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_auth_pack); + + retval = asn1_decode_auth_pack(&buf, *rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_auth_pack_draft9(const krb5_data *code, krb5_auth_pack_draft9 **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_auth_pack_draft9); + + retval = asn1_decode_auth_pack_draft9(&buf, *rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_kdc_dh_key_info(const krb5_data *code, krb5_kdc_dh_key_info **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_kdc_dh_key_info); + + retval = asn1_decode_kdc_dh_key_info(&buf, *rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_principal_name(const krb5_data *code, krb5_principal_data **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_principal_data); + + retval = asn1_decode_krb5_principal_name(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_reply_key_pack(const krb5_data *code, krb5_reply_key_pack **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_reply_key_pack); + + retval = asn1_decode_reply_key_pack(&buf, *rep); + if (retval) + goto error_out; + + cleanup_manual(); +error_out: + if (rep && *rep) { + if ((*rep)->replyKey.contents) + free((*rep)->replyKey.contents); + if ((*rep)->asChecksum.contents) + free((*rep)->asChecksum.contents); + free(*rep); + *rep = NULL; + } + return retval; +} + +krb5_error_code decode_krb5_reply_key_pack_draft9(const krb5_data *code, krb5_reply_key_pack_draft9 **rep) +{ + setup_buf_only(); + alloc_field(*rep, krb5_reply_key_pack_draft9); + + retval = asn1_decode_reply_key_pack_draft9(&buf, *rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_typed_data(const krb5_data *code, krb5_typed_data ***rep) +{ + setup_buf_only(); + retval = asn1_decode_sequence_of_typed_data(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_td_trusted_certifiers(const krb5_data *code, krb5_external_principal_identifier ***rep) +{ + setup_buf_only(); + retval = asn1_decode_sequence_of_external_principal_identifier(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code decode_krb5_td_dh_parameters(const krb5_data *code, krb5_algorithm_identifier ***rep) +{ + setup_buf_only(); + retval = asn1_decode_sequence_of_algorithm_identifier(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} diff --git a/src/lib/krb5/asn.1/krb5_encode.c b/src/lib/krb5/asn.1/krb5_encode.c index 639db43..682e9a2 100644 --- a/src/lib/krb5/asn.1/krb5_encode.c +++ b/src/lib/krb5/asn.1/krb5_encode.c @@ -697,6 +697,23 @@ krb5_error_code encode_krb5_authdata(const krb5_authdata **rep, krb5_data **code krb5_cleanup(); } +krb5_error_code encode_krb5_authdata_elt(const krb5_authdata *rep, krb5_data **code) +{ + asn1_error_code retval; + asn1buf *buf=NULL; + unsigned int length; + + if(rep == NULL) return ASN1_MISSING_FIELD; + + retval = asn1buf_create(&buf); + if(retval) return retval; + + retval = asn1_encode_krb5_authdata_elt(buf,rep, &length); + if(retval) return retval; + + krb5_cleanup(); +} + krb5_error_code encode_krb5_alt_method(const krb5_alt_method *rep, krb5_data **code) { krb5_setup(); @@ -887,3 +904,111 @@ krb5_error_code encode_krb5_setpw_req(const krb5_principal target, krb5_cleanup(); } + +krb5_error_code encode_krb5_pa_pk_as_req(const krb5_pa_pk_as_req *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_pa_pk_as_req(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_pa_pk_as_req_draft9(const krb5_pa_pk_as_req_draft9 *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_pa_pk_as_req_draft9(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_pa_pk_as_rep(const krb5_pa_pk_as_rep *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_pa_pk_as_rep(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_pa_pk_as_rep_draft9(const krb5_pa_pk_as_rep_draft9 *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_pa_pk_as_rep_draft9(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_auth_pack(const krb5_auth_pack *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_auth_pack(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_auth_pack_draft9(const krb5_auth_pack_draft9 *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_auth_pack_draft9(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_kdc_dh_key_info(const krb5_kdc_dh_key_info *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_kdc_dh_key_info(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_reply_key_pack(const krb5_reply_key_pack *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_reply_key_pack(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_reply_key_pack_draft9(const krb5_reply_key_pack_draft9 *rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_reply_key_pack_draft9(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_td_trusted_certifiers(const krb5_external_principal_identifier **rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_td_trusted_certifiers(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_typed_data(const krb5_typed_data **rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_sequence_of_typed_data(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} + +krb5_error_code encode_krb5_td_dh_parameters(const krb5_algorithm_identifier **rep, krb5_data **code) +{ + krb5_setup(); + retval = asn1_encode_sequence_of_algorithm_identifier(buf,rep,&length); + if(retval) return retval; + sum += length; + krb5_cleanup(); +} diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index 7be2bec..03bc2d3 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -71,7 +71,7 @@ krb5_init_preauth_context(krb5_context kcontext) { int n_modules, n_tables, i, j, k; void **tables; - struct krb5plugin_preauth_client_ftable_v0 *table; + struct krb5plugin_preauth_client_ftable_v1 *table; krb5_preauth_context *context = NULL; void *plugin_context; krb5_preauthtype pa_type; @@ -93,7 +93,7 @@ krb5_init_preauth_context(krb5_context kcontext) /* pull out the module function tables for all of the modules */ tables = NULL; if (krb5int_get_plugin_dir_data(&kcontext->preauth_plugins, - "preauthentication_client_0", + "preauthentication_client_1", &tables, &kcontext->err) != 0) { return; @@ -352,37 +352,45 @@ grow_ktypes(krb5_enctype **out_ktypes, int *out_nktypes, krb5_enctype ktype) } } -/* Add the given pa_data item to the list of items. Factored out here to make - * reading the do_preauth logic easier to read. */ +/* + * Add the given list of pa_data items to the existing list of items. + * Factored out here to make reading the do_preauth logic easier to read. + */ static int grow_pa_list(krb5_pa_data ***out_pa_list, int *out_pa_list_size, - krb5_pa_data *addition) + krb5_pa_data **addition, int num_addition) { krb5_pa_data **pa_list; - int i; + int i, j; - if (out_pa_list == NULL) { + if (out_pa_list == NULL || addition == NULL) { return EINVAL; } if (*out_pa_list == NULL) { - /* Allocate room for one entry and a NULL terminator. */ - pa_list = malloc(2 * sizeof(krb5_pa_data *)); + /* Allocate room for the new additions and a NULL terminator. */ + pa_list = malloc((num_addition + 1) * sizeof(krb5_pa_data *)); if (pa_list == NULL) return ENOMEM; - pa_list[0] = addition; - pa_list[1] = NULL; + for (i = 0; i < num_addition; i++) + pa_list[i] = addition[i]; + pa_list[i] = NULL; *out_pa_list = pa_list; - *out_pa_list_size = 1; + *out_pa_list_size = num_addition; } else { - /* Allocate room for one more entry and a NULL terminator. */ - pa_list = malloc((*out_pa_list_size + 2) * sizeof(krb5_pa_data *)); + /* + * Allocate room for the existing entries plus + * the new additions and a NULL terminator. + */ + pa_list = malloc((*out_pa_list_size + num_addition + 1) + * sizeof(krb5_pa_data *)); if (pa_list == NULL) return ENOMEM; for (i = 0; i < *out_pa_list_size; i++) pa_list[i] = (*out_pa_list)[i]; - pa_list[i++] = addition; - pa_list[i++] = NULL; + for (j = 0; j < num_addition;) + pa_list[i++] = addition[j++]; + pa_list[i] = NULL; free(*out_pa_list); *out_pa_list = pa_list; *out_pa_list_size = i; @@ -502,7 +510,7 @@ krb5_run_preauth_plugins(krb5_context kcontext, krb5_gic_opt_ext *opte) { int i; - krb5_pa_data *out_pa_data; + krb5_pa_data **out_pa_data; krb5_error_code ret; struct _krb5_preauth_context_module *module; @@ -554,7 +562,10 @@ krb5_run_preauth_plugins(krb5_context kcontext, *module_ret = ret; /* Save the new preauth data item. */ if (out_pa_data != NULL) { - ret = grow_pa_list(out_pa_list, out_pa_list_size, out_pa_data); + int i; + for (i = 0; out_pa_data[i] != NULL; i++); + ret = grow_pa_list(out_pa_list, out_pa_list_size, out_pa_data, i); + free(out_pa_data); if (ret != 0) return ret; } @@ -1363,7 +1374,7 @@ krb5_do_preauth_tryagain(krb5_context kcontext, krb5_gic_opt_ext *opte) { krb5_error_code ret; - krb5_pa_data *out_padata; + krb5_pa_data **out_padata; krb5_preauth_context *context; struct _krb5_preauth_context_module *module; int i, j; @@ -1404,7 +1415,11 @@ krb5_do_preauth_tryagain(krb5_context kcontext, as_key, &out_padata) == 0) { if (out_padata != NULL) { - grow_pa_list(return_padata, &out_pa_list_size, out_padata); + int i; + for (i = 0; out_padata[i] != NULL; i++); + grow_pa_list(return_padata, &out_pa_list_size, + out_padata, i); + free(out_padata); return 0; } } @@ -1584,7 +1599,7 @@ krb5_do_preauth(krb5_context context, } ret = grow_pa_list(&out_pa_list, &out_pa_list_size, - out_pa); + &out_pa, 1); if (ret != 0) { goto cleanup; } diff --git a/src/lib/krb5/os/accessor.c b/src/lib/krb5/os/accessor.c index 95f0f0f..66541e4 100644 --- a/src/lib/krb5/os/accessor.c +++ b/src/lib/krb5/os/accessor.c @@ -80,6 +80,35 @@ krb5int_accessor(krb5int_access *internals, krb5_int32 version) S (krb5_ser_unpack_int64, krb5_ser_unpack_int64), S (asn1_ldap_encode_sequence_of_keys, krb5int_ldap_encode_sequence_of_keys), S (asn1_ldap_decode_sequence_of_keys, krb5int_ldap_decode_sequence_of_keys), + S (encode_krb5_pa_pk_as_req, encode_krb5_pa_pk_as_req), + S (encode_krb5_pa_pk_as_req_draft9, encode_krb5_pa_pk_as_req_draft9), S (encode_krb5_pa_pk_as_rep, encode_krb5_pa_pk_as_rep), + S (encode_krb5_pa_pk_as_rep_draft9, encode_krb5_pa_pk_as_rep_draft9), + S (encode_krb5_auth_pack, encode_krb5_auth_pack), + S (encode_krb5_auth_pack_draft9, encode_krb5_auth_pack_draft9), + S (encode_krb5_kdc_dh_key_info, encode_krb5_kdc_dh_key_info), + S (encode_krb5_reply_key_pack, encode_krb5_reply_key_pack), + S (encode_krb5_reply_key_pack_draft9, encode_krb5_reply_key_pack_draft9), + S (encode_krb5_typed_data, encode_krb5_typed_data), + S (encode_krb5_td_trusted_certifiers, encode_krb5_td_trusted_certifiers), + S (encode_krb5_td_dh_parameters, encode_krb5_td_dh_parameters), + S (decode_krb5_pa_pk_as_req, decode_krb5_pa_pk_as_req), + S (decode_krb5_pa_pk_as_req_draft9, decode_krb5_pa_pk_as_req_draft9), + S (decode_krb5_pa_pk_as_rep, decode_krb5_pa_pk_as_rep), + S (decode_krb5_pa_pk_as_rep_draft9, decode_krb5_pa_pk_as_rep_draft9), + S (decode_krb5_auth_pack, decode_krb5_auth_pack), + S (decode_krb5_auth_pack_draft9, decode_krb5_auth_pack_draft9), + S (decode_krb5_kdc_dh_key_info, decode_krb5_kdc_dh_key_info), + S (decode_krb5_principal_name, decode_krb5_principal_name), + S (decode_krb5_reply_key_pack, decode_krb5_reply_key_pack), + S (decode_krb5_reply_key_pack_draft9, decode_krb5_reply_key_pack_draft9), + S (decode_krb5_typed_data, decode_krb5_typed_data), + S (decode_krb5_td_trusted_certifiers, decode_krb5_td_trusted_certifiers), + S (decode_krb5_td_dh_parameters, decode_krb5_td_dh_parameters), + S (decode_krb5_as_req, decode_krb5_as_req), + S (encode_krb5_kdc_req_body, encode_krb5_kdc_req_body), + S (krb5_free_kdc_req, krb5_free_kdc_req), + S (krb5int_set_prompt_types, krb5int_set_prompt_types), + S (encode_krb5_authdata_elt, encode_krb5_authdata_elt) #if DESIGNATED_INITIALIZERS }; #else |