krb5_db_entry * entry,
krb5_tl_data * new_tl_data);
+/* Compute the salt for a key data entry given the corresponding principal. */
+krb5_error_code
+krb5_dbe_compute_salt(krb5_context context, const krb5_key_data *key,
+ krb5_const_principal princ, krb5_int16 *salttype_out,
+ krb5_data **salt_out);
+
krb5_error_code
krb5_dbe_cpw( krb5_context kcontext,
krb5_keyblock * master_key,
static krb5_error_code
_make_etype_info_entry(krb5_context context,
krb5_principal client_princ, krb5_key_data *client_key,
- krb5_enctype etype, krb5_etype_info_entry **entry,
+ krb5_enctype etype, krb5_etype_info_entry **entry_out,
int etype_info2)
{
- krb5_data salt;
- krb5_etype_info_entry * tmp_entry;
- krb5_error_code retval;
+ krb5_error_code retval;
+ krb5_int16 salttype;
+ krb5_data *salt = NULL;
+ krb5_etype_info_entry *entry = NULL;
- if ((tmp_entry = malloc(sizeof(krb5_etype_info_entry))) == NULL)
+ *entry_out = NULL;
+ entry = malloc(sizeof(*entry));
+ if (entry == NULL)
return ENOMEM;
- salt.data = 0;
-
- tmp_entry->magic = KV5M_ETYPE_INFO_ENTRY;
- tmp_entry->etype = etype;
- tmp_entry->length = KRB5_ETYPE_NO_SALT;
- tmp_entry->salt = 0;
- tmp_entry->s2kparams.data = NULL;
- tmp_entry->s2kparams.length = 0;
- retval = get_salt_from_key(context, client_princ, client_key, &salt);
+ entry->magic = KV5M_ETYPE_INFO_ENTRY;
+ entry->etype = etype;
+ entry->length = KRB5_ETYPE_NO_SALT;
+ entry->salt = NULL;
+ entry->s2kparams = empty_data();
+ retval = krb5_dbe_compute_salt(context, client_key, client_princ,
+ &salttype, &salt);
if (retval)
- goto fail;
- if (etype_info2 && client_key->key_data_ver > 1 &&
- client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_AFS3) {
+ goto cleanup;
+ if (etype_info2 && salttype == KRB5_KDB_SALTTYPE_AFS3) {
switch (etype) {
case ENCTYPE_DES_CBC_CRC:
case ENCTYPE_DES_CBC_MD4:
case ENCTYPE_DES_CBC_MD5:
- tmp_entry->s2kparams.data = malloc(1);
- if (tmp_entry->s2kparams.data == NULL) {
- retval = ENOMEM;
- goto fail;
- }
- tmp_entry->s2kparams.length = 1;
- tmp_entry->s2kparams.data[0] = 1;
+ retval = alloc_data(&entry->s2kparams, 1);
+ if (retval)
+ goto cleanup;
+ entry->s2kparams.data[0] = 1;
break;
default:
break;
}
}
- if (salt.length >= 0) {
- tmp_entry->length = salt.length;
- tmp_entry->salt = (unsigned char *) salt.data;
- salt.data = 0;
- }
- *entry = tmp_entry;
- return 0;
+ entry->length = salt->length;
+ entry->salt = (unsigned char *)salt->data;
+ salt->data = NULL;
+ *entry_out = entry;
+ entry = NULL;
-fail:
- if (tmp_entry) {
- if (tmp_entry->s2kparams.data)
- free(tmp_entry->s2kparams.data);
- free(tmp_entry);
- }
- if (salt.data)
- free(salt.data);
+cleanup:
+ if (entry != NULL)
+ krb5_free_data_contents(context, &entry->s2kparams);
+ free(entry);
+ krb5_free_data(context, salt);
return retval;
}
{
krb5_error_code retval;
krb5_pa_data * padata;
- krb5_data * scratch;
- krb5_data salt_data;
+ krb5_data * salt = NULL;
+ krb5_int16 salttype;
krb5_key_data * client_key = rock->client_key;
int i;
if (enctype_requires_etype_info_2(request->ktype[i]))
return 0;
}
- if (client_key->key_data_ver == 1 ||
- client_key->key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)
+ retval = krb5_dbe_compute_salt(context, client_key, request->client,
+ &salttype, &salt);
+ if (retval)
return 0;
- if ((padata = malloc(sizeof(krb5_pa_data))) == NULL)
- return ENOMEM;
+ padata = k5alloc(sizeof(*padata), &retval);
+ if (padata == NULL)
+ goto cleanup;
padata->magic = KV5M_PA_DATA;
- padata->pa_type = KRB5_PADATA_PW_SALT;
- switch (client_key->key_data_type[1]) {
- case KRB5_KDB_SALTTYPE_V4:
- /* send an empty (V4) salt */
- padata->contents = 0;
- padata->length = 0;
- break;
- case KRB5_KDB_SALTTYPE_NOREALM:
- if ((retval = krb5_principal2salt_norealm(kdc_context,
- request->client,
- &salt_data)))
+ if (salttype == KRB5_KDB_SALTTYPE_AFS3) {
+ padata->contents = k5alloc(salt->length + 1, &retval);
+ if (padata->contents == NULL)
goto cleanup;
- padata->contents = (krb5_octet *)salt_data.data;
- padata->length = salt_data.length;
- break;
- case KRB5_KDB_SALTTYPE_AFS3:
- /* send an AFS style realm-based salt */
- /* for now, just pass the realm back and let the client
- do the work. In the future, add a kdc configuration
- variable that specifies the old cell name. */
+ memcpy(padata->contents, salt->data, salt->length);
padata->pa_type = KRB5_PADATA_AFS3_SALT;
- /* it would be just like ONLYREALM, but we need to pass the 0 */
- scratch = krb5_princ_realm(kdc_context, request->client);
- if ((padata->contents = malloc(scratch->length+1)) == NULL) {
- retval = ENOMEM;
- goto cleanup;
- }
- memcpy(padata->contents, scratch->data, scratch->length);
- padata->length = scratch->length+1;
- padata->contents[scratch->length] = 0;
- break;
- case KRB5_KDB_SALTTYPE_ONLYREALM:
- scratch = krb5_princ_realm(kdc_context, request->client);
- if ((padata->contents = malloc(scratch->length)) == NULL) {
- retval = ENOMEM;
- goto cleanup;
- }
- memcpy(padata->contents, scratch->data, scratch->length);
- padata->length = scratch->length;
- break;
- case KRB5_KDB_SALTTYPE_SPECIAL:
- if ((padata->contents = malloc(client_key->key_data_length[1]))
- == NULL) {
- retval = ENOMEM;
- goto cleanup;
- }
- memcpy(padata->contents, client_key->key_data_contents[1],
- client_key->key_data_length[1]);
- padata->length = client_key->key_data_length[1];
- break;
- default:
- free(padata);
- return 0;
+ padata->contents[salt->length] = '\0';
+ padata->length = salt->length + 1;
+ } else {
+ padata->pa_type = KRB5_PADATA_PW_SALT;
+ padata->length = salt->length;
+ padata->contents = (krb5_octet *)salt->data;
+ salt->data = NULL;
}
*send_pa = padata;
- return 0;
+ padata = NULL;
cleanup:
free(padata);
+ krb5_free_data(context, salt);
return retval;
}
return 0;
}
-/*
- * This function returns salt information for a particular client_key
- */
-krb5_error_code
-get_salt_from_key(krb5_context context, krb5_principal client,
- krb5_key_data *client_key, krb5_data *salt)
-{
- krb5_error_code retval;
- krb5_data * realm;
-
- salt->data = 0;
- salt->length = SALT_TYPE_NO_LENGTH;
-
- if (client_key->key_data_ver == 1)
- return 0;
-
- switch (client_key->key_data_type[1]) {
- case KRB5_KDB_SALTTYPE_NORMAL:
- /*
- * The client could infer the salt from the principal, but
- * might use the wrong principal name if this is an alias. So
- * it's more reliable to send an explicit salt.
- */
- if ((retval = krb5_principal2salt(context, client, salt)))
- return retval;
- break;
- case KRB5_KDB_SALTTYPE_V4:
- /* send an empty (V4) salt */
- salt->data = 0;
- salt->length = 0;
- break;
- case KRB5_KDB_SALTTYPE_NOREALM:
- if ((retval = krb5_principal2salt_norealm(context, client, salt)))
- return retval;
- break;
- case KRB5_KDB_SALTTYPE_AFS3:
- /* send the same salt as with onlyrealm - but with no type info,
- we just hope they figure it out on the other end. */
- /* fall through to onlyrealm: */
- case KRB5_KDB_SALTTYPE_ONLYREALM:
- realm = krb5_princ_realm(context, client);
- salt->length = realm->length;
- if ((salt->data = malloc(realm->length)) == NULL)
- return ENOMEM;
- memcpy(salt->data, realm->data, realm->length);
- break;
- case KRB5_KDB_SALTTYPE_SPECIAL:
- salt->length = client_key->key_data_length[1];
- if ((salt->data = malloc(salt->length)) == NULL)
- return ENOMEM;
- memcpy(salt->data, client_key->key_data_contents[1], salt->length);
- break;
- }
- return 0;
-}
-
/*
* Limit strings to a "reasonable" length to prevent crowding out of
* other useful information in the log entry
int nktypes,
krb5_enctype *ktypes);
-krb5_error_code
-get_salt_from_key (krb5_context, krb5_principal,
- krb5_key_data *, krb5_data *);
-
void limit_string (char *name);
void
{
krb5_db_entry *kdb;
osa_princ_ent_rec adb;
- int ret, i;
+ krb5_error_code ret;
kadm5_server_handle_t handle = server_handle;
- krb5_int32 stype;
- krb5_data sdata;
+ krb5_int16 stype, i;
+ krb5_data *salt = NULL;
CHECK_HANDLE(server_handle);
/* Transform salts as necessary. */
for (i = 0; i < kdb->n_key_data; i++) {
- sdata = empty_data();
- if (kdb->key_data[i].key_data_ver > 1)
- stype = kdb->key_data[i].key_data_type[1];
- else
- stype = KRB5_KDB_SALTTYPE_NORMAL;
-
- /* For salt types which compute a salt from the principal name, compute
- * the salt based on the old principal name into sdata. */
- switch (stype) {
- case KRB5_KDB_SALTTYPE_NORMAL:
- ret = krb5_principal2salt(handle->context, kdb->princ, &sdata);
- if (ret)
- goto done;
- break;
- case KRB5_KDB_SALTTYPE_NOREALM:
- ret = krb5_principal2salt_norealm(handle->context, kdb->princ,
- &sdata);
- if (ret)
- goto done;
- break;
- case KRB5_KDB_SALTTYPE_ONLYREALM:
- ret = alloc_data(&sdata, kdb->princ->realm.length);
- if (ret)
- goto done;
- memcpy(sdata.data, kdb->princ->realm.data,
- kdb->princ->realm.length);
- break;
- case KRB5_KDB_SALTTYPE_SPECIAL:
- case KRB5_KDB_SALTTYPE_V4:
- case KRB5_KDB_SALTTYPE_AFS3:
- /* Don't compute a new salt. Assume the realm doesn't change for
- * V4 and AFS3. */
- break;
- default:
- /* We don't recognize this salt type. Be conservative. */
+ ret = krb5_dbe_compute_salt(handle->context, &kdb->key_data[i],
+ kdb->princ, &stype, &salt);
+ if (ret == KRB5_KDB_BAD_SALTTYPE)
ret = KADM5_NO_RENAME_SALT;
+ if (ret)
goto done;
- }
- /* If we computed a salt, store it as an explicit salt. */
- if (sdata.data != NULL) {
- kdb->key_data[i].key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
- free(kdb->key_data[i].key_data_contents[1]);
- kdb->key_data[i].key_data_contents[1] = (krb5_octet *)sdata.data;
- kdb->key_data[i].key_data_length[1] = sdata.length;
- kdb->key_data[i].key_data_ver = 2;
- }
+ kdb->key_data[i].key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
+ free(kdb->key_data[i].key_data_contents[1]);
+ kdb->key_data[i].key_data_contents[1] = (krb5_octet *)salt->data;
+ kdb->key_data[i].key_data_length[1] = salt->length;
+ kdb->key_data[i].key_data_ver = 2;
+ free(salt);
+ salt = NULL;
}
kadm5_free_principal(handle->context, kdb->princ);
ret = kdb_delete_entry(handle, source);
done:
+ krb5_free_data(handle->context, salt);
kdb_free_entry(handle, kdb, &adb);
return ret;
}
return (0);
}
+krb5_error_code
+krb5_dbe_compute_salt(krb5_context context, const krb5_key_data *key,
+ krb5_const_principal princ, krb5_int16 *salttype_out,
+ krb5_data **salt_out)
+{
+ krb5_error_code retval;
+ krb5_int16 stype;
+ krb5_data *salt, sdata;
+
+ stype = (key->key_data_ver < 2) ? KRB5_KDB_SALTTYPE_NORMAL :
+ key->key_data_type[1];
+ *salttype_out = stype;
+ *salt_out = NULL;
+
+ /* Place computed salt into sdata, or directly into salt_out and return. */
+ switch (stype) {
+ case KRB5_KDB_SALTTYPE_NORMAL:
+ retval = krb5_principal2salt(context, princ, &sdata);
+ if (retval)
+ return retval;
+ break;
+ case KRB5_KDB_SALTTYPE_V4:
+ sdata = empty_data();
+ break;
+ case KRB5_KDB_SALTTYPE_NOREALM:
+ retval = krb5_principal2salt_norealm(context, princ, &sdata);
+ if (retval)
+ return retval;
+ break;
+ case KRB5_KDB_SALTTYPE_AFS3:
+ case KRB5_KDB_SALTTYPE_ONLYREALM:
+ return krb5_copy_data(context, &princ->realm, salt_out);
+ case KRB5_KDB_SALTTYPE_SPECIAL:
+ sdata = make_data(key->key_data_contents[1], key->key_data_length[1]);
+ return krb5_copy_data(context, &sdata, salt_out);
+ default:
+ return KRB5_KDB_BAD_SALTTYPE;
+ }
+
+ /* Make a container for sdata. */
+ salt = malloc(sizeof(*salt));
+ if (salt == NULL) {
+ free(sdata.data);
+ return ENOMEM;
+ }
+ *salt = sdata;
+ *salt_out = salt;
+ return 0;
+}
+
/* change password functions */
krb5_error_code
krb5_dbe_cpw(krb5_context kcontext, krb5_keyblock *master_key,
krb5_dbe_get_mkvno
krb5_dbe_get_string
krb5_dbe_get_strings
+krb5_dbe_compute_salt
krb5_dbe_lookup_last_admin_unlock
krb5_dbe_lookup_last_pwd_change
krb5_dbe_lookup_actkvno