diff options
author | Stefan Metzmacher <metze@samba.org> | 2007-02-08 19:40:54 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:44:52 -0500 |
commit | 2d3eea45312f3cb0121ea403eb5a809a4e6c062e (patch) | |
tree | 84e85e59a6ce29d5d80addfb851d0abac0c27d50 /source4/torture | |
parent | f7959890d4e0e91f6e11cd1d2d0a209bca098800 (diff) | |
download | samba-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)
Diffstat (limited to 'source4/torture')
-rw-r--r-- | source4/torture/rpc/dssync.c | 341 |
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; |