From ee936431c88a7b089c9c2780d63b393813d114e5 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Tue, 13 Mar 2012 10:29:00 +0100 Subject: Move some krb5 keys related functions from ipa-client to util --- ipa-client/ipa-getkeytab.c | 381 +-------------------------------------------- 1 file changed, 5 insertions(+), 376 deletions(-) (limited to 'ipa-client') diff --git a/ipa-client/ipa-getkeytab.c b/ipa-client/ipa-getkeytab.c index 7d7b9717..ca6e6341 100644 --- a/ipa-client/ipa-getkeytab.c +++ b/ipa-client/ipa-getkeytab.c @@ -41,30 +41,6 @@ #include "ipa_krb5.h" #include "ipa-client-common.h" -/* Salt types */ -#define NO_SALT -1 -#define KRB5_KDB_SALTTYPE_NORMAL 0 -#define KRB5_KDB_SALTTYPE_V4 1 -#define KRB5_KDB_SALTTYPE_NOREALM 2 -#define KRB5_KDB_SALTTYPE_ONLYREALM 3 -#define KRB5_KDB_SALTTYPE_SPECIAL 4 -#define KRB5_KDB_SALTTYPE_AFS3 5 - -#define KEYTAB_SET_OID "2.16.840.1.113730.3.8.10.1" -#define KEYTAB_RET_OID "2.16.840.1.113730.3.8.10.2" - -struct krb_key_salt { - krb5_enctype enctype; - krb5_int32 salttype; - krb5_keyblock key; - krb5_data salt; -}; - -struct keys_container { - krb5_int32 nkeys; - struct krb_key_salt *ksdata; -}; - static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *sit) { sasl_interact_t *in = NULL; @@ -122,357 +98,6 @@ static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *s return ret; } -static void free_keys_contents(krb5_context krbctx, struct keys_container *keys) -{ - struct krb_key_salt *ksdata; - int i; - - ksdata = keys->ksdata; - for (i = 0; i < keys->nkeys; i++) { - krb5_free_keyblock_contents(krbctx, &ksdata[i].key); - krb5_free_data_contents(krbctx, &ksdata[i].salt); - } - free(ksdata); - - keys->ksdata = NULL; - keys->nkeys = 0; -} - -/* Determines Encryption and Salt types, - * allocates key_salt data storage, - * filters out equivalent encodings, - * returns 0 if no enctypes available, >0 if enctypes are available */ -static int prep_ksdata(krb5_context krbctx, const char *str, - struct keys_container *keys) -{ - struct krb_key_salt *ksdata; - krb5_error_code krberr; - int n, i, j, nkeys; - - if (str == NULL) { - krb5_enctype *ktypes; - - krberr = krb5_get_permitted_enctypes(krbctx, &ktypes); - if (krberr) { - fprintf(stderr, _("No system preferred enctypes ?!\n")); - return 0; - } - - for (n = 0; ktypes[n]; n++) /* count */ ; - - ksdata = calloc(n + 1, sizeof(struct krb_key_salt)); - if (NULL == ksdata) { - fprintf(stderr, _("Out of memory!?\n")); - return 0; - } - - for (i = 0; i < n; i++) { - ksdata[i].enctype = ktypes[i]; - ksdata[i].salttype = KRB5_KDB_SALTTYPE_NORMAL; - } - - ipa_krb5_free_ktypes(krbctx, ktypes); - - nkeys = i; - - } else { - char *tmp, *t, *p, *q; - - t = tmp = strdup(str); - if (!tmp) { - fprintf(stderr, _("Out of memory\n")); - return 0; - } - - /* count */ - n = 0; - while ((p = strchr(t, ','))) { - t = p+1; - n++; - } - n++; /* count the last one that is 0 terminated instead */ - - /* at the end we will have at most n entries + 1 terminating */ - ksdata = calloc(n + 1, sizeof(struct krb_key_salt)); - if (!ksdata) { - fprintf(stderr, _("Out of memory\n")); - return 0; - } - - for (i = 0, j = 0, t = tmp; i < n; i++) { - - p = strchr(t, ','); - if (p) *p = '\0'; - - q = strchr(t, ':'); - if (q) *q++ = '\0'; - - krberr = krb5_string_to_enctype(t, &ksdata[j].enctype); - if (krberr != 0) { - fprintf(stderr, - _("Warning unrecognized encryption type: [%s]\n"), t); - if (p) t = p + 1; - continue; - } - if (p) t = p + 1; - - if (!q) { - ksdata[j].salttype = KRB5_KDB_SALTTYPE_NORMAL; - j++; - continue; - } - - krberr = krb5_string_to_salttype(q, &ksdata[j].salttype); - if (krberr != 0) { - fprintf(stderr, - _("Warning unrecognized salt type: [%s]\n"), q); - continue; - } - - j++; - } - - nkeys = j; - - free(tmp); - } - - /* Check we don't already have a key with a similar encoding, - * it would just produce redundant data and this is what the - * MIT code do anyway */ - - for (i = 0, n = 0; i < nkeys; i++ ) { - krb5_boolean similar = 0; - - for (j = 0; j < i; j++) { - krberr = krb5_c_enctype_compare(krbctx, - ksdata[j].enctype, - ksdata[i].enctype, - &similar); - if (krberr) { - free_keys_contents(krbctx, keys); - free(ksdata); - fprintf(stderr, _("Enctype comparison failed!\n")); - return 0; - } - if (similar && - (ksdata[j].salttype == ksdata[i].salttype)) { - break; - } - } - if (j < i) { - /* redundant encoding, remove it, and shift others */ - int x; - for (x = i; x < nkeys-1; x++) { - ksdata[x].enctype = ksdata[x+1].enctype; - ksdata[x].salttype = ksdata[x+1].salttype; - } - continue; - } - /* count only confirmed enc/salt tuples */ - n++; - } - - keys->nkeys = n; - keys->ksdata = ksdata; - - return n; -} - -static int create_keys(krb5_context krbctx, - krb5_principal princ, - char *password, - const char *enctypes_string, - struct keys_container *keys) -{ - struct krb_key_salt *ksdata; - krb5_error_code krberr; - krb5_data key_password; - krb5_data *realm = NULL; - int i, nkeys; - int ret; - - ret = prep_ksdata(krbctx, enctypes_string, keys); - if (ret == 0) return 0; - - ksdata = keys->ksdata; - nkeys = keys->nkeys; - - if (password) { - key_password.data = password; - key_password.length = strlen(password); - - realm = krb5_princ_realm(krbctx, princ); - } - - for (i = 0; i < nkeys; i++) { - krb5_data *salt; - - if (!password) { - /* cool, random keys */ - krberr = krb5_c_make_random_key(krbctx, - ksdata[i].enctype, - &ksdata[i].key); - if (krberr) { - fprintf(stderr, _("Failed to create random key!\n")); - return 0; - } - /* set the salt to NO_SALT as the key was random */ - ksdata[i].salttype = NO_SALT; - continue; - } - - /* Make keys using password and required salt */ - switch (ksdata[i].salttype) { - case KRB5_KDB_SALTTYPE_ONLYREALM: - krberr = krb5_copy_data(krbctx, realm, &salt); - if (krberr) { - fprintf(stderr, _("Failed to create key!\n")); - return 0; - } - - ksdata[i].salt.length = salt->length; - ksdata[i].salt.data = malloc(salt->length); - if (!ksdata[i].salt.data) { - fprintf(stderr, _("Out of memory!\n")); - return 0; - } - memcpy(ksdata[i].salt.data, salt->data, salt->length); - krb5_free_data(krbctx, salt); - break; - - case KRB5_KDB_SALTTYPE_NOREALM: - krberr = ipa_krb5_principal2salt_norealm(krbctx, princ, &ksdata[i].salt); - if (krberr) { - fprintf(stderr, _("Failed to create key!\n")); - return 0; - } - break; - - case KRB5_KDB_SALTTYPE_NORMAL: - krberr = krb5_principal2salt(krbctx, princ, &ksdata[i].salt); - if (krberr) { - fprintf(stderr, _("Failed to create key!\n")); - return 0; - } - break; - - /* no KRB5_KDB_SALTTYPE_V4, we do not support krb v4 */ - - case KRB5_KDB_SALTTYPE_AFS3: - /* Comment from MIT sources: - * * Why do we do this? Well, the afs_mit_string_to_key - * * needs to use strlen, and the realm is not NULL - * * terminated.... - */ - ksdata[i].salt.data = (char *)malloc(realm->length + 1); - if (NULL == ksdata[i].salt.data) { - fprintf(stderr, _("Out of memory!\n")); - return 0; - } - memcpy((char *)ksdata[i].salt.data, - (char *)realm->data, realm->length); - ksdata[i].salt.data[realm->length] = '\0'; - /* AFS uses a special length (UGLY) */ - ksdata[i].salt.length = SALT_TYPE_AFS_LENGTH; - break; - - default: - fprintf(stderr, _("Bad or unsupported salt type (%d)!\n"), - ksdata[i].salttype); - return 0; - } - - krberr = krb5_c_string_to_key(krbctx, - ksdata[i].enctype, - &key_password, - &ksdata[i].salt, - &ksdata[i].key); - if (krberr) { - fprintf(stderr, _("Failed to create key!\n")); - return 0; - } - - /* set back salt length to real value if AFS3 */ - if (ksdata[i].salttype == KRB5_KDB_SALTTYPE_AFS3) { - ksdata[i].salt.length = realm->length; - } - } - - return nkeys; -} - -static struct berval *create_key_control(struct keys_container *keys, - const char *principalName) -{ - struct krb_key_salt *ksdata; - struct berval *bval; - BerElement *be; - int ret, i; - - be = ber_alloc_t(LBER_USE_DER); - if (!be) { - return NULL; - } - - ret = ber_printf(be, "{s{", principalName); - if (ret == -1) { - ber_free(be, 1); - return NULL; - } - - ksdata = keys->ksdata; - for (i = 0; i < keys->nkeys; i++) { - - /* we set only the EncryptionKey and salt, no s2kparams */ - - ret = ber_printf(be, "{t[{t[i]t[o]}]", - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), - (ber_int_t)ksdata[i].enctype, - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), - (char *)ksdata[i].key.contents, (ber_len_t)ksdata[i].key.length); - - if (ret == -1) { - ber_free(be, 1); - return NULL; - } - - if (ksdata[i].salttype == NO_SALT) { - ret = ber_printf(be, "}"); - continue; - } - - /* we have to pass a salt structure */ - 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), - (ber_int_t)ksdata[i].salttype, - (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), - (char *)ksdata[i].salt.data, (ber_len_t)ksdata[i].salt.length); - - if (ret == -1) { - ber_free(be, 1); - return NULL; - } - } - - ret = ber_printf(be, "}}"); - if (ret == -1) { - ber_free(be, 1); - return NULL; - } - - ret = ber_flatten(be, &bval); - if (ret == -1) { - ber_free(be, 1); - return NULL; - } - - ber_free(be, 1); - return bval; -} - int filter_keys(krb5_context krbctx, struct keys_container *keys, ber_int_t *enctypes) { @@ -854,6 +479,7 @@ int main(int argc, const char *argv[]) krb5_keytab kt; int kvno; int i, ret; + char *err_msg; ret = init_gettext(); if (ret) { @@ -955,8 +581,11 @@ int main(int argc, const char *argv[]) } /* create key material */ - ret = create_keys(krbctx, sprinc, password, enctypes_string, &keys); + ret = create_keys(krbctx, sprinc, password, enctypes_string, &keys, &err_msg); if (!ret) { + if (err_msg != NULL) { + fprintf(stderr, "%s", err_msg); + } fprintf(stderr, _("Failed to create key material\n")); exit(8); } -- cgit