ipa-pwd-extop: Move encryption of keys in common

This way we can reuse the same code from ipa-kdb later
This commit is contained in:
Simo Sorce
2011-06-20 10:46:11 -04:00
parent b4aab3d98d
commit 4928229093
3 changed files with 244 additions and 207 deletions

View File

@@ -72,18 +72,6 @@
#define KTF_DISALLOW_SVR 0x00001000
#define KTF_PWCHANGE_SERVICE 0x00002000
/* Salt types */
#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 KRB5P_SALT_SIZE 16
void krb5int_c_free_keyblock_contents(krb5_context context,
register krb5_keyblock *key);
/* Novell key-format scheme:
KrbKeySet ::= SEQUENCE {
@@ -250,7 +238,7 @@ static Slapi_Value **encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
{
krb5_context krbctx;
char *krbPrincipalName = NULL;
int kvno, i;
int kvno;
struct berval *bval = NULL;
Slapi_Value **svals = NULL;
krb5_principal princ = NULL;
@@ -300,198 +288,17 @@ static Slapi_Value **encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
kset->kvno = kvno + 1;
kset->mkvno = krbcfg->mkvno;
kset->num_keys = krbcfg->num_pref_encsalts;
kset->keys = calloc(kset->num_keys, sizeof(struct ipapwd_krbkey));
if (!kset->keys) {
LOG_OOM();
krberr = ipa_krb5_generate_key_data(krbctx, princ,
pwd, kvno, krbcfg->kmkey,
krbcfg->num_pref_encsalts,
krbcfg->pref_encsalts,
&kset->num_keys, &kset->keys);
if (krberr != 0) {
LOG_FATAL("generating kerberos keys failed [%s]\n",
krb5_get_error_message(krbctx, krberr));
goto enc_error;
}
for (i = 0; i < kset->num_keys; i++) {
krb5_keyblock key;
krb5_data salt;
krb5_octet *ptr;
krb5_data plain;
krb5_enc_data cipher;
krb5_int16 t;
size_t len;
const char *p;
salt.data = NULL;
switch (krbcfg->pref_encsalts[i].ks_salttype) {
case KRB5_KDB_SALTTYPE_ONLYREALM:
p = strchr(krbPrincipalName, '@');
if (!p) {
LOG_FATAL("Invalid principal name, no realm found!\n");
goto enc_error;
}
p++;
salt.data = strdup(p);
if (!salt.data) {
LOG_OOM();
goto enc_error;
}
salt.length = strlen(salt.data); /* final \0 omitted on purpose */
break;
case KRB5_KDB_SALTTYPE_NOREALM:
krberr = ipa_krb5_principal2salt_norealm(krbctx, princ, &salt);
if (krberr) {
LOG_FATAL("krb5_principal2salt failed [%s]\n",
krb5_get_error_message(krbctx, krberr));
goto enc_error;
}
break;
case KRB5_KDB_SALTTYPE_NORMAL:
krberr = krb5_principal2salt(krbctx, princ, &salt);
if (krberr) {
LOG_FATAL("krb5_principal2salt failed [%s]\n",
krb5_get_error_message(krbctx, krberr));
goto enc_error;
}
break;
case KRB5_KDB_SALTTYPE_SPECIAL:
/* make random salt */
salt.length = KRB5P_SALT_SIZE;
salt.data = malloc(KRB5P_SALT_SIZE);
if (!salt.data) {
LOG_OOM();
goto enc_error;
}
krberr = krb5_c_random_make_octets(krbctx, &salt);
if (krberr) {
LOG_FATAL("krb5_c_random_make_octets failed [%s]\n",
krb5_get_error_message(krbctx, krberr));
goto enc_error;
}
break;
case KRB5_KDB_SALTTYPE_V4:
salt.length = 0;
break;
case KRB5_KDB_SALTTYPE_AFS3:
p = strchr(krbPrincipalName, '@');
if (!p) {
LOG_FATAL("Invalid principal name, no realm found!\n");
goto enc_error;
}
p++;
salt.data = strdup(p);
if (!salt.data) {
LOG_OOM();
goto enc_error;
}
salt.length = SALT_TYPE_AFS_LENGTH; /* special value */
break;
default:
LOG_FATAL("Invalid salt type [%d]\n",
krbcfg->pref_encsalts[i].ks_salttype);
goto enc_error;
}
/* need to build the key now to manage the AFS salt.length
* special case */
krberr = krb5_c_string_to_key(krbctx,
krbcfg->pref_encsalts[i].ks_enctype,
&pwd, &salt, &key);
if (krberr) {
LOG_FATAL("krb5_c_string_to_key failed [%s]\n",
krb5_get_error_message(krbctx, krberr));
krb5_free_data_contents(krbctx, &salt);
goto enc_error;
}
if (salt.length == SALT_TYPE_AFS_LENGTH) {
salt.length = strlen(salt.data);
}
krberr = krb5_c_encrypt_length(krbctx,
krbcfg->kmkey->enctype,
key.length, &len);
if (krberr) {
LOG_FATAL("krb5_c_string_to_key failed [%s]\n",
krb5_get_error_message(krbctx, krberr));
krb5int_c_free_keyblock_contents(krbctx, &key);
krb5_free_data_contents(krbctx, &salt);
goto enc_error;
}
if ((ptr = (krb5_octet *) malloc(2 + len)) == NULL) {
LOG_OOM();
krb5int_c_free_keyblock_contents(krbctx, &key);
krb5_free_data_contents(krbctx, &salt);
goto enc_error;
}
t = htole16(key.length);
memcpy(ptr, &t, 2);
plain.length = key.length;
plain.data = (char *)key.contents;
cipher.ciphertext.length = len;
cipher.ciphertext.data = (char *)ptr+2;
krberr = krb5_c_encrypt(krbctx, krbcfg->kmkey, 0, 0, &plain, &cipher);
if (krberr) {
LOG_FATAL("krb5_c_encrypt failed [%s]\n",
krb5_get_error_message(krbctx, krberr));
krb5int_c_free_keyblock_contents(krbctx, &key);
krb5_free_data_contents(krbctx, &salt);
free(ptr);
goto enc_error;
}
/* KrbSalt */
kset->keys[i].salt = malloc(sizeof(struct ipapwd_krbkeydata));
if (!kset->keys[i].salt) {
LOG_OOM();
krb5int_c_free_keyblock_contents(krbctx, &key);
free(ptr);
goto enc_error;
}
kset->keys[i].salt->type = krbcfg->pref_encsalts[i].ks_salttype;
if (salt.length) {
kset->keys[i].salt->value.bv_len = salt.length;
kset->keys[i].salt->value.bv_val = salt.data;
}
/* EncryptionKey */
kset->keys[i].ekey = malloc(sizeof(struct ipapwd_krbkeydata));
if (!kset->keys[i].ekey) {
LOG_OOM();
krb5int_c_free_keyblock_contents(krbctx, &key);
free(ptr);
goto enc_error;
}
kset->keys[i].ekey->type = key.enctype;
kset->keys[i].ekey->value.bv_len = len+2;
kset->keys[i].ekey->value.bv_val = malloc(len+2);
if (!kset->keys[i].ekey->value.bv_val) {
LOG_OOM();
krb5int_c_free_keyblock_contents(krbctx, &key);
free(ptr);
goto enc_error;
}
memcpy(kset->keys[i].ekey->value.bv_val, ptr, len+2);
/* make sure we free the memory used now that we are done with it */
krb5int_c_free_keyblock_contents(krbctx, &key);
free(ptr);
}
bval = encode_keys(kset);
if (!bval) {
LOG_FATAL("encoding asn1 KrbSalt failed\n");