svn commit: samba r21245 - in
branches/SAMBA_4_0/source/torture/rpc: .
metze at samba.org
metze at samba.org
Thu Feb 8 19:40:55 GMT 2007
Author: metze
Date: 2007-02-08 19:40:54 +0000 (Thu, 08 Feb 2007)
New Revision: 21245
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=21245
Log:
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
Modified:
branches/SAMBA_4_0/source/torture/rpc/dssync.c
Changeset:
Modified: branches/SAMBA_4_0/source/torture/rpc/dssync.c
===================================================================
--- branches/SAMBA_4_0/source/torture/rpc/dssync.c 2007-02-08 18:24:48 UTC (rev 21244)
+++ branches/SAMBA_4_0/source/torture/rpc/dssync.c 2007-02-08 19:40:54 UTC (rev 21245)
@@ -42,9 +42,6 @@
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 @@
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 @@
}
}
- 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 @@
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)
+static DATA_BLOB decrypt_blob(TALLOC_CTX *mem_ctx,
+ const DATA_BLOB *gensec_skey,
+ struct drsuapi_DsReplicaObjectIdentifier *id,
+ uint32_t rid,
+ const DATA_BLOB *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);
-}
+ DATA_BLOB confounder;
+ DATA_BLOB enc_buffer;
-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;
+ uint8_t _enc_key[16];
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);
+ DATA_BLOB plain_buffer;
- *_enc_key = enc_key;
-}
+ /*
+ * the combination "c[3] s[1] e[1] d[0]..."
+ * was successful!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
-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;
+ /* 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);
- enc_key = data_blob_talloc(mem_ctx, NULL, 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, session_key->data, session_key->length);
- MD5Update(&md5, confounder->data, confounder->length);
+ MD5Update(&md5, gensec_skey->data, gensec_skey->length);
+ MD5Update(&md5, confounder.data, confounder.length);
MD5Final(enc_key.data, &md5);
- *_enc_key = enc_key;
-}
+ /*
+ * 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);
-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,
- },
-};
+ /*
+ * 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);
+ */
-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;
+ return 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,
- 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;
-
- 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);
-
- for (crypt_i = 0; crypt_i < ARRAY_SIZE(do_decryption_fns); crypt_i++) {
- DATA_BLOB plain_buffer;
-
- do_decryption_fns[crypt_i].fn(mem_ctx, b, id, rid, buffer,
- &enc_key, &enc_buffer,
- &plain_buffer);
-
- 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);
- }
- }
- }
- }
-
- return data_blob(NULL, 0);
-}
-
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 @@
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 @@
}
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 @@
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 @@
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 @@
(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 @@
(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;
More information about the samba-cvs
mailing list