1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-08 04:58:40 +03:00

r21434: - get rid of "krb5Key"

- use "sambaPassword" only as virtual attribute for passing
  the cleartext password (in unix charset) into the ldb layer
- store des-cbc-crc, des-cbc-md5 keys in the Primary:Kerberos
  blob to match w2k and w2k3
- aes key support is disabled by default, as we don't know
  exacly how longhorn stores them. use password_hash:create_aes_key=yes
  to force creation of them.
- store the cleartext password in the Primary:CLEARTEXT blob
  if configured

TODO:
 - find out how longhorn stores aes keys
 - find out how the Primary:WDigest blob needs to be constructed
   (not supported by w2k)

metze
(This used to be commit e20b53f6feaaca2cc81ee7d296ca3ff757ee3953)
This commit is contained in:
Stefan Metzmacher 2007-02-18 22:01:02 +00:00 committed by Gerald (Jerry) Carter
parent 0515f728e6
commit 6e2d85e38b
4 changed files with 891 additions and 435 deletions

View File

@ -36,7 +36,7 @@ const char *user_attrs[] = {
"userPrincipalName",
"servicePrincipalName",
"msDS-KeyVersionNumber",
"krb5Key",
"supplementalCredentials",
/* passwords */
"dBCSPwd",

View File

@ -52,8 +52,7 @@
*/
static const char * const password_attrs[] = {
"sambaPassword",
"krb5Key",
"supplementalCredentials",
"unicodePwd",
"dBCSPwd",
"lmPwdHistory",

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,9 @@
#include "auth/auth_sam.h"
#include "db_wrap.h"
#include "dsdb/samdb/samdb.h"
#include "librpc/ndr/libndr.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "libcli/auth/libcli_auth.h"
enum hdb_ldb_ent_type
{ HDB_LDB_ENT_TYPE_CLIENT, HDB_LDB_ENT_TYPE_SERVER,
@ -67,9 +70,9 @@ static const char * const krb5_attrs[] = {
"whenChanged",
"msDS-KeyVersionNumber",
"krb5Key",
"unicodePwd",
"supplementalCredentials",
NULL
};
@ -205,10 +208,14 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context,
hdb_entry_ex *entry_ex)
{
krb5_error_code ret = 0;
struct ldb_message_element *krb5keys;
NTSTATUS status;
struct samr_Password *hash;
int i;
bool arcfour_needed = true;
const struct ldb_val *sc_val;
struct supplementalCredentialsBlob scb;
struct supplementalCredentialsPackage *scp = NULL;
struct package_PrimaryKerberosBlob _pkb;
struct package_PrimaryKerberosBlob *pkb = NULL;
uint32_t i;
uint32_t allocated_keys = 0;
entry_ex->entry.keys.val = NULL;
@ -216,19 +223,66 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context,
entry_ex->entry.kvno = ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0);
/* Get krb5Key from the db */
/* Get keys from the db */
krb5keys = ldb_msg_find_element(msg, "krb5Key");
hash = samdb_result_hash(mem_ctx, msg, "unicodePwd");
sc_val = ldb_msg_find_ldb_val(msg, "supplementalCredentials");
if (krb5keys) {
allocated_keys = krb5keys->num_values;
}
/* unicodePwd for enctype 0x17 (23) if present */
if (hash) {
allocated_keys++;
}
/* supplementalCredentials if present */
if (sc_val) {
status = ndr_pull_struct_blob_all(sc_val, mem_ctx, &scb,
(ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
if (!NT_STATUS_IS_OK(status)) {
dump_data(0, sc_val->data, sc_val->length);
ret = EINVAL;
goto out;
}
for (i=0; i < scb.sub.num_packages; i++) {
if (scb.sub.packages[i].unknown1 != 0x00000001) {
continue;
}
if (strcmp("Primary:Kerberos", scb.sub.packages[i].name) != 0) {
continue;
}
if (!scb.sub.packages[i].data || !scb.sub.packages[i].data[0]) {
continue;
}
scp = &scb.sub.packages[i];
break;
}
}
/* Primary:Kerberos element of supplementalCredentials */
if (scp) {
DATA_BLOB blob;
blob = strhex_to_data_blob(scp->data);
if (!blob.data) {
ret = ENOMEM;
goto out;
}
talloc_steal(mem_ctx, blob.data);
/* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
status = ndr_pull_struct_blob(&blob, mem_ctx, &_pkb,
(ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
if (!NT_STATUS_IS_OK(status)) {
ret = EINVAL;
goto out;
}
pkb = &_pkb;
allocated_keys += pkb->num_keys1;
}
if (allocated_keys == 0) {
/* oh, no password. Apparently (comment in
* hdb-ldap.c) this violates the ASN.1, but this
@ -244,49 +298,14 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context,
goto out;
}
/* Decode Kerberos keys into the hdb structure */
for (i=0; (krb5keys && i < krb5keys->num_values); i++) {
size_t decode_len;
Key key;
ret = decode_Key(krb5keys->values[i].data, krb5keys->values[i].length,
&key, &decode_len);
if (ret) {
/* Could be bougus data in the entry, or out of memory */
goto out;
}
if (userAccountControl & UF_USE_DES_KEY_ONLY) {
switch (key.key.keytype) {
case KEYTYPE_DES:
arcfour_needed = false;
entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key;
entry_ex->entry.keys.len++;
break;
default:
/* We must use DES keys only */
break;
}
} else {
switch (key.key.keytype) {
case KEYTYPE_ARCFOUR:
arcfour_needed = false;
break;
default:
break;
}
entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key;
entry_ex->entry.keys.len++;
}
}
if (arcfour_needed && hash) {
if (hash && !(userAccountControl & UF_USE_DES_KEY_ONLY)) {
Key key;
key.mkvno = 0;
key.salt = NULL; /* No salt for this enc type */
ret = krb5_keyblock_init(context,
KEYTYPE_ARCFOUR,
ENCTYPE_ARCFOUR_HMAC_MD5,
hash->hash, sizeof(hash->hash),
&key.key);
if (ret) {
@ -297,11 +316,75 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context,
entry_ex->entry.keys.len++;
}
if (pkb) {
for (i=0; i < pkb->num_keys1; i++) {
bool use = true;
Key key;
if (!pkb->keys1[i].value) continue;
if (userAccountControl & UF_USE_DES_KEY_ONLY) {
switch (pkb->keys1[i].keytype) {
case ENCTYPE_DES_CBC_CRC:
case ENCTYPE_DES_CBC_MD5:
break;
default:
use = false;
break;
}
}
if (!use) continue;
key.mkvno = 0;
if (pkb->salt.string) {
DATA_BLOB salt;
salt = data_blob_string_const(pkb->salt.string);
key.salt = calloc(1, sizeof(*key.salt));
if (key.salt == NULL) {
ret = ENOMEM;
goto out;
}
key.salt->type = hdb_pw_salt;
ret = krb5_data_copy(&key.salt->salt, salt.data, salt.length);
if (ret) {
free(key.salt);
key.salt = NULL;
goto out;
}
}
ret = krb5_keyblock_init(context,
pkb->keys1[i].keytype,
pkb->keys1[i].value->data,
pkb->keys1[i].value->length,
&key.key);
if (ret) {
if (key.salt) {
free_Salt(key.salt);
free(key.salt);
key.salt = NULL;
}
goto out;
}
entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key;
entry_ex->entry.keys.len++;
}
}
out:
if (ret != 0 && entry_ex->entry.keys.val) {
if (ret != 0) {
entry_ex->entry.keys.len = 0;
}
if (entry_ex->entry.keys.len == 0 && entry_ex->entry.keys.val) {
free(entry_ex->entry.keys.val);
entry_ex->entry.keys.val = NULL;
entry_ex->entry.keys.len = 0;
}
return ret;
}