ipa-pwd-extop: Move encoding in common too

Also to be used by ipa-kdb
This commit is contained in:
Simo Sorce 2011-06-20 11:55:13 -04:00
parent 4928229093
commit eed401306c
6 changed files with 174 additions and 202 deletions

View File

@ -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)"\" \

View File

@ -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;
}

View File

@ -53,12 +53,15 @@
#include <ssl.h>
#include <dirsrv/slapi-plugin.h>
#include <krb5.h>
#include <kdb.h>
#include <lber.h>
#include <time.h>
#include <iconv.h>
#include <openssl/des.h>
#include <openssl/md4.h>
#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,

View File

@ -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;
}

View File

@ -1,6 +1,8 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <lber.h>
#include <errno.h>
#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;
}

View File

@ -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_ */