From eed401306c400ae938e2d328de22da6f729c8f3f Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 20 Jun 2011 11:55:13 -0400 Subject: ipa-pwd-extop: Move encoding in common too Also to be used by ipa-kdb --- .../ipa-slapi-plugins/ipa-pwd-extop/Makefile.am | 3 +- .../ipa-pwd-extop/ipa_pwd_extop.c | 90 ++++++------- daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h | 16 +-- .../ipa-pwd-extop/ipapwd_encoding.c | 143 +-------------------- util/ipa_krb5.c | 120 +++++++++++++++++ util/ipa_krb5.h | 4 + 6 files changed, 174 insertions(+), 202 deletions(-) diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am index 1daf942da..cc041aa4f 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am @@ -2,13 +2,14 @@ NULL = PLUGIN_COMMON_DIR=../common KRB5_UTIL_DIR= ../../../util -KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c +KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c INCLUDES = \ -I. \ -I$(srcdir) \ -I$(PLUGIN_COMMON_DIR) \ -I$(KRB5_UTIL_DIR) \ + -I$(COMMON_BER_DIR) \ -DPREFIX=\""$(prefix)"\" \ -DBINDIR=\""$(bindir)"\" \ -DLIBDIR=\""$(libdir)"\" \ diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c index 9ce497746..68d1703b5 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c @@ -86,13 +86,14 @@ Slapi_PluginDesc ipapwd_plugin_desc = { void *ipapwd_plugin_id; -static int filter_keys(struct ipapwd_krbcfg *krbcfg, struct ipapwd_keyset *kset) +static int filter_keys(struct ipapwd_krbcfg *krbcfg, + struct ipapwd_keyset *kset) { int i, j; for (i = 0; i < kset->num_keys; i++) { for (j = 0; j < krbcfg->num_supp_encsalts; j++) { - if (kset->keys[i].ekey->type == + if (kset->keys[i].key_data_type[0] == krbcfg->supp_encsalts[j].ks_enctype) { break; } @@ -100,15 +101,8 @@ static int filter_keys(struct ipapwd_krbcfg *krbcfg, struct ipapwd_keyset *kset) if (j == krbcfg->num_supp_encsalts) { /* not valid */ /* free key */ - if (kset->keys[i].ekey) { - free(kset->keys[i].ekey->value.bv_val); - free(kset->keys[i].ekey); - } - if (kset->keys[i].salt) { - free(kset->keys[i].salt->value.bv_val); - free(kset->keys[i].salt); - } - free(kset->keys[i].s2kparams.bv_val); + free(kset->keys[i].key_data_contents[0]); + free(kset->keys[i].key_data_contents[1]); /* move all remaining keys up by one */ kset->num_keys -= 1; @@ -672,6 +666,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) kset = malloc(sizeof(struct ipapwd_keyset)); if (!kset) { LOG_OOM(); + rc = LDAP_OPERATIONS_ERROR; goto free_and_return; } @@ -679,7 +674,6 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) /* major-vno = 1 and minor-vno = 1 */ kset->major_vno = 1; kset->minor_vno = 1; - kset->kvno = kvno; kset->mkvno = krbcfg->mkvno; kset->keys = NULL; @@ -687,6 +681,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) rtag = ber_peek_tag(ber, &tlen); while (rtag == LBER_SEQUENCE) { + krb5_key_data *newset; krb5_data plain; krb5_enc_data cipher; struct berval tval; @@ -696,28 +691,18 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) i = kset->num_keys; - if (kset->keys) { - struct ipapwd_krbkey *newset; - - newset = realloc(kset->keys, sizeof(struct ipapwd_krbkey) * (i + 1)); - if (!newset) { - LOG_OOM(); - goto free_and_return; - } - kset->keys = newset; - } else { - kset->keys = malloc(sizeof(struct ipapwd_krbkey)); - if (!kset->keys) { - LOG_OOM(); - goto free_and_return; - } + newset = realloc(kset->keys, sizeof(krb5_key_data) * (i + 1)); + if (!newset) { + LOG_OOM(); + goto free_and_return; } + kset->keys = newset; + kset->num_keys += 1; - kset->keys[i].salt = NULL; - kset->keys[i].ekey = NULL; - kset->keys[i].s2kparams.bv_len = 0; - kset->keys[i].s2kparams.bv_val = NULL; + memset(&kset->keys[i], 0, sizeof(krb5_key_data)); + kset->keys[i].key_data_ver = 1; + kset->keys[i].key_data_kvno = kvno; /* EncryptionKey */ rtag = ber_scanf(ber, "{t[{t[i]t[o]}]", &ttmp, &ttmp, &tint, &ttmp, &tval); @@ -728,13 +713,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) goto free_and_return; } - kset->keys[i].ekey = calloc(1, sizeof(struct ipapwd_krbkeydata)); - if (!kset->keys[i].ekey) { - LOG_OOM(); - goto free_and_return; - } - - kset->keys[i].ekey->type = tint; + kset->keys[i].key_data_type[0] = tint; plain.length = tval.bv_len; plain.data = tval.bv_val; @@ -755,8 +734,8 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) t = htole16(plain.length); memcpy(kdata, &t, 2); - kset->keys[i].ekey->value.bv_len = 2 + klen; - kset->keys[i].ekey->value.bv_val = (char *)kdata; + kset->keys[i].key_data_length[0] = 2 + klen; + kset->keys[i].key_data_contents[0] = (krb5_octet *)kdata; cipher.ciphertext.length = klen; cipher.ciphertext.data = (char *)kdata + 2; @@ -768,7 +747,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) goto free_and_return; } - free(tval.bv_val); + ber_memfree(tval.bv_val); rtag = ber_peek_tag(ber, &tlen); @@ -783,13 +762,8 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) goto free_and_return; } - kset->keys[i].salt = calloc(1, sizeof(struct ipapwd_krbkeydata)); - if (!kset->keys[i].salt) { - LOG_OOM(); - goto free_and_return; - } - - kset->keys[i].salt->type = tint; + kset->keys[i].key_data_ver = 2; /* we have a salt */ + kset->keys[i].key_data_type[1] = tint; rtag = ber_peek_tag(ber, &tlen); if (rtag == (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) { @@ -802,7 +776,16 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) goto free_and_return; } - kset->keys[i].salt->value = tval; + kset->keys[i].key_data_length[1] = tval.bv_len; + kset->keys[i].key_data_contents[1] = malloc(tval.bv_len); + if (!kset->keys[i].key_data_contents[1]) { + LOG_OOM(); + rc = LDAP_OPERATIONS_ERROR; + goto free_and_return; + } + memcpy(kset->keys[i].key_data_contents[1], + tval.bv_val, tval.bv_len); + ber_memfree(tval.bv_val); rtag = ber_peek_tag(ber, &tlen); } @@ -866,9 +849,10 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "krbPasswordExpiration", timestr); #endif - bval = encode_keys(kset); - if (!bval) { - LOG_FATAL("encoding asn1 KrbSalt failed\n"); + ret = ber_encode_krb5_key_data(kset->keys, kset->num_keys, + kset->mkvno, &bval); + if (ret != 0) { + LOG_FATAL("encoding krb5_key_data failed\n"); slapi_mods_free(&smods); goto free_and_return; } @@ -954,7 +938,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg) } for (i = 0; i < kset->num_keys; i++) { - ret = ber_printf(ber, "{i}", (ber_int_t)kset->keys[i].ekey->type); + ret = ber_printf(ber, "{i}", (ber_int_t)kset->keys[i].key_data_type[0]); if (ret == -1) { goto free_and_return; } diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h index 904995eca..7d81bda3d 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h @@ -53,12 +53,15 @@ #include #include #include +#include #include #include #include #include #include +#include "ipa_krb5.h" + #define IPAPWD_PLUGIN_NAME "ipa-pwd-extop" #define IPAPWD_FEATURE_DESC "IPA Password Manager" #define IPAPWD_PLUGIN_DESC "IPA Password Extended Operation plugin" @@ -132,25 +135,14 @@ void ipapwd_free_slapi_value_array(Slapi_Value ***svals); void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg); /* from ipapwd_encoding.c */ -struct ipapwd_krbkeydata { - int32_t type; - struct berval value; -}; -struct ipapwd_krbkey { - struct ipapwd_krbkeydata *salt; - struct ipapwd_krbkeydata *ekey; - struct berval s2kparams; -}; struct ipapwd_keyset { uint16_t major_vno; uint16_t minor_vno; - uint32_t kvno; uint32_t mkvno; - struct ipapwd_krbkey *keys; + krb5_key_data *keys; int num_keys; }; -struct berval *encode_keys(struct ipapwd_keyset *kset); void ipapwd_keyset_free(struct ipapwd_keyset **pkset); int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg, diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c index a1b0e99f5..ea01ab865 100644 --- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c +++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_encoding.c @@ -72,36 +72,6 @@ #define KTF_DISALLOW_SVR 0x00001000 #define KTF_PWCHANGE_SERVICE 0x00002000 -/* Novell key-format scheme: - - KrbKeySet ::= SEQUENCE { - attribute-major-vno [0] UInt16, - attribute-minor-vno [1] UInt16, - kvno [2] UInt32, - mkvno [3] UInt32 OPTIONAL, - keys [4] SEQUENCE OF KrbKey, - ... - } - - KrbKey ::= SEQUENCE { - salt [0] KrbSalt OPTIONAL, - key [1] EncryptionKey, - s2kparams [2] OCTET STRING OPTIONAL, - ... - } - - KrbSalt ::= SEQUENCE { - type [0] Int32, - salt [1] OCTET STRING OPTIONAL - } - - EncryptionKey ::= SEQUENCE { - keytype [0] Int32, - keyvalue [1] OCTET STRING - } - - */ - /* ascii hex output of bytes in "in" * out len is 32 (preallocated) * in len is 16 */ @@ -116,99 +86,6 @@ static void hexbuf(char *out, const uint8_t *in) } } -struct berval *encode_keys(struct ipapwd_keyset *kset) -{ - BerElement *be = NULL; - struct berval *bval = NULL; - int ret, i; - - be = ber_alloc_t(LBER_USE_DER); - - if (!be) { - LOG_OOM(); - return NULL; - } - - ret = ber_printf(be, "{t[i]t[i]t[i]t[i]t[{", - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), - kset->major_vno, - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), - kset->minor_vno, - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2), - kset->kvno, - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 3), - kset->mkvno, - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 4)); - if (ret == -1) { - LOG_FATAL("encoding asn1 vno info failed\n"); - goto done; - } - - for (i = 0; i < kset->num_keys; i++) { - - ret = ber_printf(be, "{"); - if (ret == -1) { - LOG_FATAL("encoding asn1 EncryptionKey failed\n"); - goto done; - } - - if (kset->keys[i].salt) { - ret = ber_printf(be, "t[{t[i]", - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), - kset->keys[i].salt->type); - if ((ret != -1) && kset->keys[i].salt->value.bv_len) { - ret = ber_printf(be, "t[o]", - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), - kset->keys[i].salt->value.bv_val, - kset->keys[i].salt->value.bv_len); - } - if (ret != -1) { - ret = ber_printf(be, "}]"); - } - if (ret == -1) { - goto done; - } - } - - ret = ber_printf(be, "t[{t[i]t[o]}]", - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), - kset->keys[i].ekey->type, - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), - kset->keys[i].ekey->value.bv_val, - kset->keys[i].ekey->value.bv_len); - if (ret == -1) { - LOG_FATAL("encoding asn1 EncryptionKey failed\n"); - goto done; - } - - /* FIXME: s2kparams not supported yet */ - - ret = ber_printf(be, "}"); - if (ret == -1) { - LOG_FATAL("encoding asn1 EncryptionKey failed\n"); - goto done; - } - } - - ret = ber_printf(be, "}]}"); - if (ret == -1) { - LOG_FATAL("encoding asn1 end of sequences failed\n"); - goto done; - } - - ret = ber_flatten(be, &bval); - if (ret == -1) { - LOG_FATAL("flattening asn1 failed\n"); - goto done; - } -done: - ber_free(be, 1); - - return bval; -} - void ipapwd_keyset_free(struct ipapwd_keyset **pkset) { struct ipapwd_keyset *kset = *pkset; @@ -217,15 +94,8 @@ void ipapwd_keyset_free(struct ipapwd_keyset **pkset) if (!kset) return; for (i = 0; i < kset->num_keys; i++) { - if (kset->keys[i].salt) { - free(kset->keys[i].salt->value.bv_val); - free(kset->keys[i].salt); - } - if (kset->keys[i].ekey) { - free(kset->keys[i].ekey->value.bv_val); - free(kset->keys[i].ekey); - } - free(kset->keys[i].s2kparams.bv_val); + free(kset->keys[i].key_data_contents[0]); + free(kset->keys[i].key_data_contents[1]); } free(kset->keys); free(kset); @@ -285,7 +155,7 @@ static Slapi_Value **encrypt_encode_key(struct ipapwd_krbcfg *krbcfg, kset->major_vno = 1; kset->minor_vno = 1; /* increment kvno (will be 1 if this is a new entry) */ - kset->kvno = kvno + 1; + kvno += 1; kset->mkvno = krbcfg->mkvno; krberr = ipa_krb5_generate_key_data(krbctx, princ, @@ -299,9 +169,10 @@ static Slapi_Value **encrypt_encode_key(struct ipapwd_krbcfg *krbcfg, goto enc_error; } - bval = encode_keys(kset); - if (!bval) { - LOG_FATAL("encoding asn1 KrbSalt failed\n"); + krberr = ber_encode_krb5_key_data(kset->keys, kset->num_keys, + kset->mkvno, &bval); + if (krberr != 0) { + LOG_FATAL("encoding krb5_key_data failed\n"); goto enc_error; } diff --git a/util/ipa_krb5.c b/util/ipa_krb5.c index b75da1e25..3cedbedb6 100644 --- a/util/ipa_krb5.c +++ b/util/ipa_krb5.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "ipa_krb5.h" @@ -259,3 +261,121 @@ void ipa_krb5_free_key_data(krb5_key_data *keys, int num_keys) free(keys); } +/* Novell key-format scheme: + + KrbKeySet ::= SEQUENCE { + attribute-major-vno [0] UInt16, + attribute-minor-vno [1] UInt16, + kvno [2] UInt32, + mkvno [3] UInt32 OPTIONAL, + keys [4] SEQUENCE OF KrbKey, + ... + } + + KrbKey ::= SEQUENCE { + salt [0] KrbSalt OPTIONAL, + key [1] EncryptionKey, + s2kparams [2] OCTET STRING OPTIONAL, + ... + } + + KrbSalt ::= SEQUENCE { + type [0] Int32, + salt [1] OCTET STRING OPTIONAL + } + + EncryptionKey ::= SEQUENCE { + keytype [0] Int32, + keyvalue [1] OCTET STRING + } + + */ + +int ber_encode_krb5_key_data(krb5_key_data *data, + int numk, int mkvno, + struct berval **encoded) +{ + BerElement *be = NULL; + ber_tag_t tag; + int ret, i; + + be = ber_alloc_t(LBER_USE_DER); + if (!be) { + return ENOMEM; + } + + tag = LBER_CONSTRUCTED | LBER_CLASS_CONTEXT; + + ret = ber_printf(be, "{t[i]t[i]t[i]t[i]t[{", + tag | 0, 1, tag | 1, 1, + tag | 2, (ber_int_t)data[0].key_data_kvno, + tag | 3, (ber_int_t)mkvno, tag | 4); + if (ret == -1) { + ret = EFAULT; + goto done; + } + + for (i = 0; i < numk; i++) { + + ret = ber_printf(be, "{"); + if (ret == -1) { + ret = EFAULT; + goto done; + } + + if (data[i].key_data_length[1] != 0) { + ret = ber_printf(be, "t[{t[i]", + tag | 0, + tag | 0, + (ber_int_t)data[i].key_data_type[1]); + if (ret != -1) { + ret = ber_printf(be, "t[o]", + tag | 1, + data[i].key_data_contents[1], + (ber_len_t)data[i].key_data_length[1]); + } + if (ret != -1) { + ret = ber_printf(be, "}]"); + } + if (ret == -1) { + ret = EFAULT; + goto done; + } + } + + ret = ber_printf(be, "t[{t[i]t[o]}]", + tag | 1, + tag | 0, + (ber_int_t)data[i].key_data_type[0], + tag | 1, + data[i].key_data_contents[0], + (ber_len_t)data[i].key_data_length[0]); + if (ret == -1) { + ret = EFAULT; + goto done; + } + + ret = ber_printf(be, "}"); + if (ret == -1) { + ret = EFAULT; + goto done; + } + } + + ret = ber_printf(be, "}]}"); + if (ret == -1) { + ret = EFAULT; + goto done; + } + + ret = ber_flatten(be, encoded); + if (ret == -1) { + ret = EFAULT; + goto done; + } + +done: + ber_free(be, 1); + return ret; +} + diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h index 0bc667a93..ee6078db3 100644 --- a/util/ipa_krb5.h +++ b/util/ipa_krb5.h @@ -22,4 +22,8 @@ krb5_error_code ipa_krb5_generate_key_data(krb5_context krbctx, void ipa_krb5_free_key_data(krb5_key_data *keys, int num_keys); +int ber_encode_krb5_key_data(krb5_key_data *data, + int numk, int mkvno, + struct berval **encoded); + #endif /* __IPA_KRB5_H_ */ -- cgit