summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2012-03-13 10:29:00 +0100
committerMartin Kosek <mkosek@redhat.com>2012-06-11 12:04:05 +0200
commitee936431c88a7b089c9c2780d63b393813d114e5 (patch)
tree72cfb0b7988b30d8995db33fcc21833af0aca624
parent20fce97dfadbd2c5ade2a3a165f06bf9f0aa68db (diff)
downloadfreeipa-ee936431c88a7b089c9c2780d63b393813d114e5.tar.gz
freeipa-ee936431c88a7b089c9c2780d63b393813d114e5.tar.xz
freeipa-ee936431c88a7b089c9c2780d63b393813d114e5.zip
Move some krb5 keys related functions from ipa-client to util
-rw-r--r--ipa-client/ipa-getkeytab.c381
-rw-r--r--util/ipa_krb5.c362
-rw-r--r--util/ipa_krb5.h36
3 files changed, 403 insertions, 376 deletions
diff --git a/ipa-client/ipa-getkeytab.c b/ipa-client/ipa-getkeytab.c
index 7d7b97176..ca6e63413 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);
}
diff --git a/util/ipa_krb5.c b/util/ipa_krb5.c
index 0e82b2380..0240c079e 100644
--- a/util/ipa_krb5.c
+++ b/util/ipa_krb5.c
@@ -26,6 +26,9 @@
#include <lber.h>
#include <errno.h>
+#include <libintl.h>
+#define _(STRING) gettext(STRING)
+
#include "ipa_krb5.h"
/* Salt types */
@@ -530,3 +533,362 @@ krb5_error_code filter_key_salt_tuples(krb5_context context,
return 0;
}
+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;
+}
+
+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,
+ char **err_msg)
+{
+ struct krb_key_salt *ksdata;
+ krb5_error_code krberr;
+ int n, i, j, nkeys;
+
+ *err_msg = NULL;
+
+ if (str == NULL) {
+ krb5_enctype *ktypes;
+
+ krberr = krb5_get_permitted_enctypes(krbctx, &ktypes);
+ if (krberr) {
+ *err_msg = _("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) {
+ *err_msg = _("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) {
+ *err_msg = _("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) {
+ *err_msg = _("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) {
+ *err_msg = _("Warning unrecognized encryption type.\n");
+ 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) {
+ *err_msg = _("Warning unrecognized salt type.\n");
+ 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);
+ *err_msg = _("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;
+}
+
+int create_keys(krb5_context krbctx,
+ krb5_principal princ,
+ char *password,
+ const char *enctypes_string,
+ struct keys_container *keys,
+ char **err_msg)
+{
+ struct krb_key_salt *ksdata;
+ krb5_error_code krberr;
+ krb5_data key_password;
+ krb5_data *realm = NULL;
+ int i, nkeys;
+ int ret;
+
+ *err_msg = NULL;
+
+ ret = prep_ksdata(krbctx, enctypes_string, keys, err_msg);
+ 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) {
+ *err_msg = _("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) {
+ *err_msg = _("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) {
+ *err_msg = _("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) {
+ *err_msg = _("Failed to create key!\n");
+ return 0;
+ }
+ break;
+
+ case KRB5_KDB_SALTTYPE_NORMAL:
+ krberr = krb5_principal2salt(krbctx, princ, &ksdata[i].salt);
+ if (krberr) {
+ *err_msg = _("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) {
+ *err_msg = _("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:
+ *err_msg = _("Bad or unsupported salt type.\n");
+/* FIXME:
+ 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) {
+ *err_msg = _("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;
+}
+
diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h
index f0513d109..97ffc47b5 100644
--- a/util/ipa_krb5.h
+++ b/util/ipa_krb5.h
@@ -4,6 +4,30 @@
#include <krb5/krb5.h>
#include <kdb.h>
+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;
+};
+
+/* 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"
+
void
ipa_krb5_free_ktypes(krb5_context context, krb5_enctype *val);
@@ -36,4 +60,16 @@ krb5_error_code filter_key_salt_tuples(krb5_context context,
krb5_key_salt_tuple *req, int n_req,
krb5_key_salt_tuple *supp, int n_supp,
krb5_key_salt_tuple **res, int *n_res);
+
+void free_keys_contents(krb5_context krbctx, struct keys_container *keys);
+
+struct berval *create_key_control(struct keys_container *keys,
+ const char *principalName);
+
+int create_keys(krb5_context krbctx,
+ krb5_principal princ,
+ char *password,
+ const char *enctypes_string,
+ struct keys_container *keys,
+ char **err_msg);
#endif /* __IPA_KRB5_H_ */