summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2007-02-08 19:40:54 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:44:52 -0500
commit2d3eea45312f3cb0121ea403eb5a809a4e6c062e (patch)
tree84e85e59a6ce29d5d80addfb851d0abac0c27d50
parentf7959890d4e0e91f6e11cd1d2d0a209bca098800 (diff)
downloadsamba-2d3eea45312f3cb0121ea403eb5a809a4e6c062e.tar.gz
samba-2d3eea45312f3cb0121ea403eb5a809a4e6c062e.tar.bz2
samba-2d3eea45312f3cb0121ea403eb5a809a4e6c062e.zip
r21245: combination "c[3] s[1] e[1] d[0]..." was successful!!!!!!!!!!!!!!!!!!!!!!!!!!
we now support the session depended password attribute encryption used in DsGetNCChanges() the static encryption (something like sam_rid_crypt() is assumed for some attributes and the format of the attribute values isn't known yet, but some contain some unicode strings... metze (This used to be commit daee739ebba38e54fbdbd7e53d16fd30bc0dd54e)
-rw-r--r--source4/torture/rpc/dssync.c341
1 files changed, 75 insertions, 266 deletions
diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c
index 9f171c4a00..79172e366c 100644
--- a/source4/torture/rpc/dssync.c
+++ b/source4/torture/rpc/dssync.c
@@ -42,9 +42,6 @@ struct DsSyncBindInfo {
struct drsuapi_DsBindInfo28 our_bind_info28;
struct drsuapi_DsBindInfo28 peer_bind_info28;
struct policy_handle bind_handle;
- DATA_BLOB dce_key;
- DATA_BLOB gen_key;
- struct samr_Password nthash;
};
struct DsSyncLDAPInfo {
@@ -181,11 +178,10 @@ static BOOL _test_DsBind(struct DsSyncTest *ctx, struct cli_credentials *credent
NTSTATUS status;
BOOL ret = True;
struct event_context *event = NULL;
- const struct samr_Password *nthash;
status = dcerpc_pipe_connect_b(ctx,
&b->pipe, ctx->drsuapi_binding,
- &dcerpc_table_drsuapi,
+ &dcerpc_table_drsuapi,
credentials, event);
if (!NT_STATUS_IS_OK(status)) {
@@ -224,20 +220,6 @@ static BOOL _test_DsBind(struct DsSyncTest *ctx, struct cli_credentials *credent
}
}
- dcerpc_fetch_session_key(b->pipe, &b->dce_key);
- gensec_session_key(b->pipe->conn->security_state.generic_state, &b->gen_key);
- nthash = cli_credentials_get_nt_hash(credentials, NULL);
- if (nthash) b->nthash = *nthash;
-
- if (lp_parm_bool(-1,"dssync","print_pwd_blobs",False)) {
- DEBUG(0,("DCERPC session key:\n"));
- dump_data(0, b->dce_key.data, b->dce_key.length);
- DEBUG(0,("GENSEC session key:\n"));
- dump_data(0, b->gen_key.data, b->gen_key.length);
- DEBUG(0,("CREDENTIALS nthash:\n"));
- dump_data(0, b->nthash.hash, sizeof(b->nthash.hash));
- }
-
return ret;
}
@@ -318,263 +300,81 @@ static BOOL test_GetInfo(struct DsSyncTest *ctx)
return ret;
}
-static void choose_confounder_v01(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- uint32_t confounder_len,
- DATA_BLOB *confounder,
- DATA_BLOB *enc_buffer)
-{
- *confounder = data_blob_talloc(mem_ctx, buffer->data, confounder_len);
- *enc_buffer = data_blob_talloc(mem_ctx, buffer->data+confounder_len, buffer->length - confounder_len);
-}
-
-static void choose_confounder_v02(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- uint32_t confounder_len,
- DATA_BLOB *confounder,
- DATA_BLOB *enc_buffer)
-{
- *confounder = data_blob_talloc(mem_ctx, buffer->data + buffer->length - confounder_len, confounder_len);
- *enc_buffer = data_blob_talloc(mem_ctx, buffer->data, buffer->length - confounder_len);
-}
-
-static const struct {
- uint32_t len;
- void (*fn)(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- uint32_t confounder_len,
- DATA_BLOB *confounder,
- DATA_BLOB *enc_buffer);
-} choose_confounder_fns[] = {
- {
- .len = 4,
- .fn = choose_confounder_v01,
- },
- {
- .len = 8,
- .fn = choose_confounder_v01,
- },
- {
- .len = 12,
- .fn = choose_confounder_v01,
- },
- {
- .len = 16,
- .fn = choose_confounder_v01,
- },
- {
- .len = 4,
- .fn = choose_confounder_v02,
- },
- {
- .len = 8,
- .fn = choose_confounder_v02,
- },
- {
- .len = 12,
- .fn = choose_confounder_v02,
- },
- {
- .len = 16,
- .fn = choose_confounder_v02,
- },
-};
-
-static void choose_session_key_v01(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- DATA_BLOB *session_key)
-{
- *session_key = data_blob_talloc(mem_ctx, b->dce_key.data, b->dce_key.length);
-}
-
-static void choose_session_key_v02(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- DATA_BLOB *session_key)
-{
- *session_key = data_blob_talloc(mem_ctx, b->gen_key.data, b->gen_key.length);
-}
-
-static const struct {
- void (*fn)(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- DATA_BLOB *session_key);
-} choose_session_key_fns[] = {
- {
- .fn = choose_session_key_v01,
- },
- {
- .fn = choose_session_key_v02,
- },
-};
-
-static void create_enc_key_v01(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- const DATA_BLOB *confounder,
- const DATA_BLOB *session_key,
- DATA_BLOB *_enc_key)
-{
- struct MD5Context md5;
- DATA_BLOB enc_key;
-
- enc_key = data_blob_talloc(mem_ctx, NULL, 16);
- MD5Init(&md5);
- MD5Update(&md5, confounder->data, confounder->length);
- MD5Update(&md5, session_key->data, session_key->length);
- MD5Final(enc_key.data, &md5);
-
- *_enc_key = enc_key;
-}
-
-static void create_enc_key_v02(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- const DATA_BLOB *confounder,
- const DATA_BLOB *session_key,
- DATA_BLOB *_enc_key)
-{
- struct MD5Context md5;
- DATA_BLOB enc_key;
-
- enc_key = data_blob_talloc(mem_ctx, NULL, 16);
- MD5Init(&md5);
- MD5Update(&md5, session_key->data, session_key->length);
- MD5Update(&md5, confounder->data, confounder->length);
- MD5Final(enc_key.data, &md5);
-
- *_enc_key = enc_key;
-}
-
-static const struct {
- void (*fn)(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- const DATA_BLOB *confounder,
- const DATA_BLOB *session_key,
- DATA_BLOB *_enc_key);
-} create_enc_key_fns[] = {
- {
- .fn = create_enc_key_v01,
- },
- {
- .fn = create_enc_key_v02,
- },
-};
-
-static void do_decryption_v01(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- const DATA_BLOB *enc_key,
- const DATA_BLOB *enc_buffer,
- DATA_BLOB *_plain_buffer)
-{
- DATA_BLOB plain_buffer;
-
- plain_buffer = data_blob_talloc(mem_ctx, enc_buffer->data, enc_buffer->length);
-
- arcfour_crypt_blob(plain_buffer.data, plain_buffer.length, enc_key);
-
- *_plain_buffer = plain_buffer;
-}
-
-static const struct {
- void (*fn)(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
- struct drsuapi_DsReplicaObjectIdentifier *id,
- uint32_t rid,
- const DATA_BLOB *buffer,
- const DATA_BLOB *enc_key,
- const DATA_BLOB *enc_buffer,
- DATA_BLOB *plain_buffer);
-} do_decryption_fns[] = {
- {
- .fn = do_decryption_v01,
- },
-};
-
static DATA_BLOB decrypt_blob(TALLOC_CTX *mem_ctx,
- struct DsSyncBindInfo *b,
+ const DATA_BLOB *gensec_skey,
struct drsuapi_DsReplicaObjectIdentifier *id,
uint32_t rid,
const DATA_BLOB *buffer)
{
- uint32_t conf_i;
- uint32_t skey_i;
- uint32_t ekey_i;
- uint32_t crypt_i;
-
-
- for (conf_i = 0; conf_i < ARRAY_SIZE(choose_confounder_fns); conf_i++) {
- DATA_BLOB confounder;
- DATA_BLOB enc_buffer;
+ DATA_BLOB confounder;
+ DATA_BLOB enc_buffer;
- choose_confounder_fns[conf_i].fn(mem_ctx, b, id, rid, buffer,
- choose_confounder_fns[conf_i].len,
- &confounder, &enc_buffer);
-
- for (skey_i = 0; skey_i < ARRAY_SIZE(choose_session_key_fns); skey_i++) {
- DATA_BLOB session_key;
-
- choose_session_key_fns[skey_i].fn(mem_ctx, b, id, rid, buffer,
- &session_key);
-
- for (ekey_i = 0; ekey_i < ARRAY_SIZE(create_enc_key_fns); ekey_i++) {
- DATA_BLOB enc_key;
-
- create_enc_key_fns[ekey_i].fn(mem_ctx, b, id, rid, buffer,
- &confounder, &session_key,
- &enc_key);
+ struct MD5Context md5;
+ uint8_t _enc_key[16];
+ DATA_BLOB enc_key;
- for (crypt_i = 0; crypt_i < ARRAY_SIZE(do_decryption_fns); crypt_i++) {
- DATA_BLOB plain_buffer;
+ DATA_BLOB plain_buffer;
- do_decryption_fns[crypt_i].fn(mem_ctx, b, id, rid, buffer,
- &enc_key, &enc_buffer,
- &plain_buffer);
+ /*
+ * the combination "c[3] s[1] e[1] d[0]..."
+ * was successful!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
- DEBUGADD(0,("c[%u] s[%u] e[%u] d[%u] len[%u]:\n",
- conf_i, skey_i, ekey_i, crypt_i,
- plain_buffer.length));
- dump_data(0, confounder.data, confounder.length);
- dump_data(0, session_key.data, session_key.length);
- dump_data(0, enc_key.data, enc_key.length);
- dump_data(0, enc_buffer.data, enc_buffer.length);
- dump_data(0, plain_buffer.data, plain_buffer.length);
- }
- }
- }
+ /* the first 16 bytes at the beginning are the confounder */
+ if (buffer->length <= 16) {
+ return data_blob_const(NULL, 0);
}
+ confounder = data_blob_const(buffer->data, 16);
+ enc_buffer = data_blob_const(buffer->data + 16, buffer->length - 16);
+
+ /*
+ * build the encryption key md5 over the session key followed
+ * by the confounder
+ *
+ * here the gensec session key is used and
+ * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key!
+ */
+ enc_key = data_blob_const(_enc_key, sizeof(_enc_key));
+ MD5Init(&md5);
+ MD5Update(&md5, gensec_skey->data, gensec_skey->length);
+ MD5Update(&md5, confounder.data, confounder.length);
+ MD5Final(enc_key.data, &md5);
- return data_blob(NULL, 0);
+ /*
+ * copy the encrypted buffer part and
+ * decrypt it using the created encryption key using arcfour
+ */
+ plain_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length);
+ if (!plain_buffer.data) {
+ return data_blob_const(NULL, 0);
+ }
+ arcfour_crypt_blob(plain_buffer.data, plain_buffer.length, &enc_key);
+
+ /*
+ * some attributes seem to be in a usable form after this decryption
+ * (supplementalCredentials, priorValue, currentValue, trustAuthOutgoing,
+ * trustAuthIncoming, initialAuthOutgoing, initialAuthIncoming)
+ * At least supplementalCredentials contains plaintext
+ * like "Primary:Kerberos" (in unicode form)
+ *
+ * some attributes seem to have some additional encryption
+ * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory
+ *
+ * it's assumed it's something like this sam_rid_crypt()
+ * function, as the value is constant, so it doesn't depend
+ * on sessionkeys. But for the unicodePwd attribute which contains
+ * the nthash be have 20 bytes at this point, but the ntnash only
+ * is 16 bytes long, so using the current sam_rid_crypt() function
+ * doesn't work.
+ *
+ * sam_rid_crypt(rid, crypt_nt_hash.hash, plain_nt_hash.hash, 0);
+ */
+
+ return plain_buffer;
}
static void test_analyse_objects(struct DsSyncTest *ctx,
+ const DATA_BLOB *gensec_skey,
struct drsuapi_DsReplicaObjectListItemEx *cur)
{
if (!lp_parm_bool(-1,"dssync","print_pwd_blobs",False)) {
@@ -648,7 +448,7 @@ static void test_analyse_objects(struct DsSyncTest *ctx,
enc_data = attr->value_ctr.values[0].blob;
ZERO_STRUCT(plain_data);
- plain_data = decrypt_blob(ctx, &ctx->new_dc.drsuapi,
+ plain_data = decrypt_blob(ctx, gensec_skey,
cur->object.identifier, rid,
enc_data);
if (!dn_printed) {
@@ -657,9 +457,10 @@ static void test_analyse_objects(struct DsSyncTest *ctx,
}
DEBUGADD(0,("ATTR: %s enc.length=%lu plain.length=%lu\n",
name, (long)enc_data->length, (long)plain_data.length));
- dump_data(0, enc_data->data, enc_data->length);
if (plain_data.length) {
dump_data(0, plain_data.data, plain_data.length);
+ } else {
+ dump_data(0, enc_data->data, enc_data->length);
}
}
}
@@ -679,6 +480,7 @@ static BOOL test_FetchData(struct DsSyncTest *ctx)
int32_t out_level = 0;
struct GUID null_guid;
struct dom_sid null_sid;
+ DATA_BLOB gensec_skey;
struct {
int32_t level;
} array[] = {
@@ -701,6 +503,13 @@ static BOOL test_FetchData(struct DsSyncTest *ctx)
highest_usn = lp_parm_int(-1, "dssync", "highest_usn", 0);
+ status = gensec_session_key(ctx->new_dc.drsuapi.pipe->conn->security_state.generic_state,
+ &gensec_skey);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("failed to get gensec session key: %s\n", nt_errstr(status));
+ return False;
+ }
+
for (i=0; i < ARRAY_SIZE(array); i++) {
printf("testing DsGetNCChanges level %d\n",
array[i].level);
@@ -821,7 +630,7 @@ static BOOL test_FetchData(struct DsSyncTest *ctx)
(long long)ctr1->new_highwatermark.tmp_highest_usn,
(long long)ctr1->new_highwatermark.highest_usn));
- test_analyse_objects(ctx, ctr1->first_object);
+ test_analyse_objects(ctx, &gensec_skey, ctr1->first_object);
if (ctr1->new_highwatermark.tmp_highest_usn > ctr1->new_highwatermark.highest_usn) {
r.in.req.req5.highwatermark = ctr1->new_highwatermark;
@@ -844,7 +653,7 @@ static BOOL test_FetchData(struct DsSyncTest *ctx)
(long long)ctr6->new_highwatermark.tmp_highest_usn,
(long long)ctr6->new_highwatermark.highest_usn));
- test_analyse_objects(ctx, ctr6->first_object);
+ test_analyse_objects(ctx, &gensec_skey, ctr6->first_object);
if (ctr6->new_highwatermark.tmp_highest_usn > ctr6->new_highwatermark.highest_usn) {
r.in.req.req8.highwatermark = ctr6->new_highwatermark;