summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2012-07-27 11:51:18 -0400
committerGreg Hudson <ghudson@mit.edu>2012-08-23 13:29:55 -0400
commita7dc565cafbaa6c18d5a76ea3cc823c7159a0d6b (patch)
tree821137ba5134f009c5423148f9cfd85863ab231d /src/lib
parentbe74d2e7fa486fd7e5cf59b7e845278164cfb76a (diff)
downloadkrb5-a7dc565cafbaa6c18d5a76ea3cc823c7159a0d6b.tar.gz
krb5-a7dc565cafbaa6c18d5a76ea3cc823c7159a0d6b.tar.xz
krb5-a7dc565cafbaa6c18d5a76ea3cc823c7159a0d6b.zip
Add ASN.1 support for OTP
Add encoders and decoders for the OTP-TOKENINFO, PA-OTP-CHALLENGE, PA-OTP-REQUEST, and PA-OTP-ENC-REQUEST types from RFC 6560. For more thorough testing, add support for generating test encodings using asn1c for sample objects (currently only for the OTP types).
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/krb5/asn.1/asn1_k_encode.c129
-rw-r--r--src/lib/krb5/asn.1/krbasn1.h1
-rw-r--r--src/lib/krb5/krb/kfree.c65
-rw-r--r--src/lib/krb5/libkrb5.exports12
4 files changed, 190 insertions, 17 deletions
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
index d8a2a872bd..68a907fce4 100644
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
@@ -29,11 +29,24 @@
DEFINT_IMMEDIATE(krb5_version, KVNO, KRB5KDC_ERR_BAD_PVNO);
+static int
+int32_not_minus1(const void *p)
+{
+ return (*(krb5_int32 *)p != -1);
+}
+
+static void
+init_int32_minus1(void *p)
+{
+ *(krb5_int32 *)p = -1;
+}
+
DEFBOOLTYPE(bool, krb5_boolean);
DEFINTTYPE(int32, krb5_int32);
DEFPTRTYPE(int32_ptr, int32);
DEFCOUNTEDSEQOFTYPE(cseqof_int32, krb5_int32, int32_ptr);
DEFOPTIONALZEROTYPE(opt_int32, int32);
+DEFOPTIONALTYPE(opt_int32_minus1, int32_not_minus1, init_int32_minus1, int32);
DEFUINTTYPE(uint, unsigned int);
DEFUINTTYPE(octet, krb5_octet);
@@ -73,6 +86,19 @@ DEFOPTIONALTYPE(opt_gstring_data, nonempty_data, NULL, gstring_data);
DEFPTRTYPE(gstring_data_ptr, gstring_data);
DEFCOUNTEDSEQOFTYPE(cseqof_gstring_data, krb5_int32, gstring_data_ptr);
+DEFCOUNTEDSTRINGTYPE(utf8string, char *, unsigned int,
+ k5_asn1_encode_bytestring, k5_asn1_decode_bytestring,
+ ASN1_UTF8STRING);
+DEFCOUNTEDTYPE(utf8_data, krb5_data, data, length, utf8string);
+DEFOPTIONALTYPE(opt_utf8_data, nonempty_data, NULL, utf8_data);
+DEFPTRTYPE(utf8_data_ptr, utf8_data);
+
+DEFCOUNTEDSTRINGTYPE(object_identifier, char *, unsigned int,
+ k5_asn1_encode_bytestring, k5_asn1_decode_bytestring,
+ ASN1_OBJECTIDENTIFIER);
+DEFCOUNTEDTYPE(oid_data, krb5_data, data, length, object_identifier);
+DEFPTRTYPE(oid_data_ptr, oid_data);
+
DEFOFFSETTYPE(realm_of_principal_data, krb5_principal_data, realm,
gstring_data);
DEFPTRTYPE(realm_of_principal, realm_of_principal_data);
@@ -1311,18 +1337,6 @@ krb5int_get_authdata_containee_types(krb5_context context,
return 0;
}
-/*
- * PKINIT
- */
-
-#ifndef DISABLE_PKINIT
-
-DEFCOUNTEDSTRINGTYPE(object_identifier, char *, unsigned int,
- k5_asn1_encode_bytestring, k5_asn1_decode_bytestring,
- ASN1_OBJECTIDENTIFIER);
-DEFCOUNTEDTYPE(oid_data, krb5_data, data, length, object_identifier);
-DEFPTRTYPE(oid_data_ptr, oid_data);
-
/* RFC 3280. No context tags. */
DEFOFFSETTYPE(algid_0, krb5_algorithm_identifier, algorithm, oid_data);
DEFOFFSETTYPE(algid_1, krb5_algorithm_identifier, parameters, opt_der_data);
@@ -1331,7 +1345,18 @@ static const struct atype_info *algorithm_identifier_fields[] = {
};
DEFSEQTYPE(algorithm_identifier, krb5_algorithm_identifier,
algorithm_identifier_fields);
-DEFPTRTYPE(algorithm_identifier_ptr, algorithm_identifier);
+DEFPTRTYPE(ptr_algorithm_identifier, algorithm_identifier);
+DEFOPTIONALZEROTYPE(opt_ptr_algorithm_identifier, ptr_algorithm_identifier);
+DEFNULLTERMSEQOFTYPE(seqof_algorithm_identifier, ptr_algorithm_identifier);
+DEFPTRTYPE(ptr_seqof_algorithm_identifier, seqof_algorithm_identifier);
+DEFOPTIONALEMPTYTYPE(opt_ptr_seqof_algorithm_identifier,
+ ptr_seqof_algorithm_identifier);
+
+/*
+ * PKINIT
+ */
+
+#ifndef DISABLE_PKINIT
DEFCTAGGEDTYPE(kdf_alg_id_0, 0, oid_data);
static const struct atype_info *kdf_alg_id_fields[] = {
@@ -1426,10 +1451,6 @@ DEFSEQTYPE(subject_pk_info, krb5_subject_pk_info, subject_pk_info_fields);
DEFPTRTYPE(subject_pk_info_ptr, subject_pk_info);
DEFOPTIONALZEROTYPE(opt_subject_pk_info_ptr, subject_pk_info_ptr);
-DEFNULLTERMSEQOFTYPE(seqof_algorithm_identifier, algorithm_identifier_ptr);
-DEFPTRTYPE(ptr_seqof_algorithm_identifier, seqof_algorithm_identifier);
-DEFOPTIONALZEROTYPE(opt_ptr_seqof_algorithm_identifier,
- ptr_seqof_algorithm_identifier);
DEFFIELD(auth_pack_0, krb5_auth_pack, pkAuthenticator, 0, pk_authenticator);
DEFFIELD(auth_pack_1, krb5_auth_pack, clientPublicValue, 1,
opt_subject_pk_info_ptr);
@@ -1616,3 +1637,77 @@ DEFPTRTYPE(typed_data_ptr, typed_data);
DEFNULLTERMSEQOFTYPE(seqof_typed_data, typed_data_ptr);
MAKE_CODEC(krb5_typed_data, seqof_typed_data);
+
+/* Definitions for OTP preauth (RFC 6560) */
+
+DEFFIELD_IMPLICIT(tokinfo_0, krb5_otp_tokeninfo, flags, 0, krb5_flags);
+DEFFIELD_IMPLICIT(tokinfo_1, krb5_otp_tokeninfo, vendor, 1, opt_utf8_data);
+DEFFIELD_IMPLICIT(tokinfo_2, krb5_otp_tokeninfo, challenge, 2,
+ opt_ostring_data);
+DEFFIELD_IMPLICIT(tokinfo_3, krb5_otp_tokeninfo, length, 3, opt_int32_minus1);
+DEFFIELD_IMPLICIT(tokinfo_4, krb5_otp_tokeninfo, format, 4, opt_int32_minus1);
+DEFFIELD_IMPLICIT(tokinfo_5, krb5_otp_tokeninfo, token_id, 5,
+ opt_ostring_data);
+DEFFIELD_IMPLICIT(tokinfo_6, krb5_otp_tokeninfo, alg_id, 6, opt_utf8_data);
+DEFFIELD_IMPLICIT(tokinfo_7, krb5_otp_tokeninfo, supported_hash_alg, 7,
+ opt_ptr_seqof_algorithm_identifier);
+DEFFIELD_IMPLICIT(tokinfo_8, krb5_otp_tokeninfo, iteration_count, 8,
+ opt_int32_minus1);
+static const struct atype_info *otp_tokeninfo_fields[] = {
+ &k5_atype_tokinfo_0, &k5_atype_tokinfo_1, &k5_atype_tokinfo_2,
+ &k5_atype_tokinfo_3, &k5_atype_tokinfo_4, &k5_atype_tokinfo_5,
+ &k5_atype_tokinfo_6, &k5_atype_tokinfo_7, &k5_atype_tokinfo_8
+};
+DEFSEQTYPE(otp_tokeninfo, krb5_otp_tokeninfo, otp_tokeninfo_fields);
+MAKE_CODEC(krb5_otp_tokeninfo, otp_tokeninfo);
+
+DEFPTRTYPE(otp_tokeninfo_ptr, otp_tokeninfo);
+DEFNONEMPTYNULLTERMSEQOFTYPE(seqof_otp_tokeninfo, otp_tokeninfo_ptr);
+DEFPTRTYPE(ptr_seqof_otp_tokeninfo, seqof_otp_tokeninfo);
+
+DEFFIELD_IMPLICIT(otp_ch_0, krb5_pa_otp_challenge, nonce, 0, ostring_data);
+DEFFIELD_IMPLICIT(otp_ch_1, krb5_pa_otp_challenge, service, 1, opt_utf8_data);
+DEFFIELD_IMPLICIT(otp_ch_2, krb5_pa_otp_challenge, tokeninfo, 2,
+ ptr_seqof_otp_tokeninfo);
+DEFFIELD_IMPLICIT(otp_ch_3, krb5_pa_otp_challenge, salt, 3, opt_gstring_data);
+DEFFIELD_IMPLICIT(otp_ch_4, krb5_pa_otp_challenge, s2kparams, 4,
+ opt_ostring_data);
+static const struct atype_info *pa_otp_challenge_fields[] = {
+ &k5_atype_otp_ch_0, &k5_atype_otp_ch_1, &k5_atype_otp_ch_2,
+ &k5_atype_otp_ch_3, &k5_atype_otp_ch_4
+};
+DEFSEQTYPE(pa_otp_challenge, krb5_pa_otp_challenge, pa_otp_challenge_fields);
+MAKE_CODEC(krb5_pa_otp_challenge, pa_otp_challenge);
+
+DEFFIELD_IMPLICIT(otp_req_0, krb5_pa_otp_req, flags, 0, krb5_flags);
+DEFFIELD_IMPLICIT(otp_req_1, krb5_pa_otp_req, nonce, 1, opt_ostring_data);
+DEFFIELD_IMPLICIT(otp_req_2, krb5_pa_otp_req, enc_data, 2, encrypted_data);
+DEFFIELD_IMPLICIT(otp_req_3, krb5_pa_otp_req, hash_alg, 3,
+ opt_ptr_algorithm_identifier);
+DEFFIELD_IMPLICIT(otp_req_4, krb5_pa_otp_req, iteration_count, 4,
+ opt_int32_minus1);
+DEFFIELD_IMPLICIT(otp_req_5, krb5_pa_otp_req, otp_value, 5, opt_ostring_data);
+DEFFIELD_IMPLICIT(otp_req_6, krb5_pa_otp_req, pin, 6, opt_utf8_data);
+DEFFIELD_IMPLICIT(otp_req_7, krb5_pa_otp_req, challenge, 7, opt_ostring_data);
+DEFFIELD_IMPLICIT(otp_req_8, krb5_pa_otp_req, time, 8, opt_kerberos_time);
+DEFFIELD_IMPLICIT(otp_req_9, krb5_pa_otp_req, counter, 9, opt_ostring_data);
+DEFFIELD_IMPLICIT(otp_req_10, krb5_pa_otp_req, format, 10, opt_int32_minus1);
+DEFFIELD_IMPLICIT(otp_req_11, krb5_pa_otp_req, token_id, 11, opt_ostring_data);
+DEFFIELD_IMPLICIT(otp_req_12, krb5_pa_otp_req, alg_id, 12, opt_utf8_data);
+DEFFIELD_IMPLICIT(otp_req_13, krb5_pa_otp_req, vendor, 13, opt_utf8_data);
+static const struct atype_info *pa_otp_req_fields[] = {
+ &k5_atype_otp_req_0, &k5_atype_otp_req_1, &k5_atype_otp_req_2,
+ &k5_atype_otp_req_3, &k5_atype_otp_req_4, &k5_atype_otp_req_5,
+ &k5_atype_otp_req_6, &k5_atype_otp_req_7, &k5_atype_otp_req_8,
+ &k5_atype_otp_req_9, &k5_atype_otp_req_10, &k5_atype_otp_req_11,
+ &k5_atype_otp_req_12, &k5_atype_otp_req_13
+};
+DEFSEQTYPE(pa_otp_req, krb5_pa_otp_req, pa_otp_req_fields);
+MAKE_CODEC(krb5_pa_otp_req, pa_otp_req);
+
+DEFCTAGGEDTYPE_IMPLICIT(pa_otp_enc_req_0, 0, ostring_data);
+static const struct atype_info *pa_otp_enc_req_fields[] = {
+ &k5_atype_pa_otp_enc_req_0
+};
+DEFSEQTYPE(pa_otp_enc_req, krb5_data, pa_otp_enc_req_fields);
+MAKE_CODEC(krb5_pa_otp_enc_req, pa_otp_enc_req);
diff --git a/src/lib/krb5/asn.1/krbasn1.h b/src/lib/krb5/asn.1/krbasn1.h
index 215dc5be8d..73de724a09 100644
--- a/src/lib/krb5/asn.1/krbasn1.h
+++ b/src/lib/krb5/asn.1/krbasn1.h
@@ -53,6 +53,7 @@ typedef int asn1_tagnum;
#define ASN1_NULL 5
#define ASN1_OBJECTIDENTIFIER 6
#define ASN1_ENUMERATED 10
+#define ASN1_UTF8STRING 12
#define ASN1_SEQUENCE 16
#define ASN1_SET 17
#define ASN1_PRINTABLESTRING 19
diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c
index 5c79900323..9629ae6631 100644
--- a/src/lib/krb5/krb/kfree.c
+++ b/src/lib/krb5/krb/kfree.c
@@ -765,3 +765,68 @@ krb5_free_iakerb_finished(krb5_context context, krb5_iakerb_finished *val)
krb5_free_checksum_contents(context, &val->checksum);
free(val);
}
+
+void
+k5_free_algorithm_identifier(krb5_context context,
+ krb5_algorithm_identifier *val)
+{
+ if (val == NULL)
+ return;
+ free(val->algorithm.data);
+ free(val->parameters.data);
+ free(val);
+}
+
+void
+k5_free_otp_tokeninfo(krb5_context context, krb5_otp_tokeninfo *val)
+{
+ krb5_algorithm_identifier **alg;
+
+ if (val == NULL)
+ return;
+ free(val->vendor.data);
+ free(val->challenge.data);
+ free(val->token_id.data);
+ free(val->alg_id.data);
+ for (alg = val->supported_hash_alg; alg != NULL && *alg != NULL; alg++)
+ k5_free_algorithm_identifier(context, *alg);
+ free(val->supported_hash_alg);
+ free(val);
+}
+
+void
+k5_free_pa_otp_challenge(krb5_context context, krb5_pa_otp_challenge *val)
+{
+ krb5_otp_tokeninfo **ti;
+
+ if (val == NULL)
+ return;
+ free(val->nonce.data);
+ free(val->service.data);
+ for (ti = val->tokeninfo; *ti != NULL; ti++)
+ k5_free_otp_tokeninfo(context, *ti);
+ free(val->tokeninfo);
+ free(val->salt.data);
+ free(val->s2kparams.data);
+ free(val);
+}
+
+void
+k5_free_pa_otp_req(krb5_context context, krb5_pa_otp_req *val)
+{
+ if (val == NULL)
+ return;
+ val->flags = 0;
+ free(val->nonce.data);
+ free(val->enc_data.ciphertext.data);
+ if (val->hash_alg != NULL)
+ k5_free_algorithm_identifier(context, val->hash_alg);
+ free(val->otp_value.data);
+ free(val->pin.data);
+ free(val->challenge.data);
+ free(val->counter.data);
+ free(val->token_id.data);
+ free(val->alg_id.data);
+ free(val->vendor.data);
+ free(val);
+}
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 1591b35667..270959876f 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -24,10 +24,14 @@ decode_krb5_fast_response
decode_krb5_iakerb_finished
decode_krb5_iakerb_header
decode_krb5_kdc_req_body
+decode_krb5_otp_tokeninfo
decode_krb5_pa_enc_ts
decode_krb5_pa_for_user
decode_krb5_pa_fx_fast_reply
decode_krb5_pa_fx_fast_request
+decode_krb5_pa_otp_challenge
+decode_krb5_pa_otp_req
+decode_krb5_pa_otp_enc_req
decode_krb5_pa_pac_req
decode_krb5_pa_s4u_x509_user
decode_krb5_padata_sequence
@@ -67,9 +71,13 @@ encode_krb5_fast_response
encode_krb5_iakerb_finished
encode_krb5_iakerb_header
encode_krb5_kdc_req_body
+encode_krb5_otp_tokeninfo
encode_krb5_pa_enc_ts
encode_krb5_pa_for_user
encode_krb5_pa_fx_fast_reply
+encode_krb5_pa_otp_challenge
+encode_krb5_pa_otp_req
+encode_krb5_pa_otp_enc_req
encode_krb5_pa_s4u_x509_user
encode_krb5_padata_sequence
encode_krb5_pkinit_supp_pub_info
@@ -103,6 +111,10 @@ k5_count_etypes
k5_etypes_contains
k5_expand_path_tokens
k5_expand_path_tokens_extra
+k5_free_algorithm_identifier
+k5_free_otp_tokeninfo
+k5_free_pa_otp_challenge
+k5_free_pa_otp_req
k5_free_serverlist
k5_kt_get_principal
k5_locate_kdc