r275: added IDL and test code for samr_QueryDisplayInfo3(),
authorAndrew Tridgell <tridge@samba.org>
Mon, 19 Apr 2004 05:48:03 +0000 (05:48 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:51:19 +0000 (12:51 -0500)
samr_AddMultipleMembersToAlias(),
samr_RemoveMultipleMembersFromAlias(), samr_OemChangePasswordUser2(),
and samr_ChangePasswordUser2()

The password change functions don't actually work yet (but should
soon). At this stage I have just completed the IDL for them. Next step
is to get the hash verifiers right and the torture test should be able
to do password changes.
(This used to be commit 849d0d314a2add80f2b2be6b503fea05973f998e)

source4/libcli/util/smbencrypt.c
source4/librpc/idl/idl_types.h
source4/librpc/idl/samr.idl
source4/librpc/ndr/ndr_basic.c
source4/torture/rpc/autoidl.c
source4/torture/rpc/samr.c

index fc3449d7676b6ab96335f521f887117ab513aed2..13d56e1e788fec606380e38feff313c218c5bee4 100644 (file)
@@ -217,7 +217,9 @@ void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
 #endif
 }
 
-BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode)
+BOOL make_oem_passwd_hash(char data[516], const char *passwd, 
+                         const uchar old_pw_hash[16], 
+                         BOOL unicode)
 {
        int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
 
@@ -242,7 +244,9 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[
        DEBUG(100,("make_oem_passwd_hash\n"));
        dump_data(100, data, 516);
 #endif
-       SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
+       SamOEMhash((unsigned char *)data, 
+                  (const unsigned char *)old_pw_hash, 
+                  516);
 
        return True;
 }
index 434dfb8c649c58ba7c59739d753943e1f23d886e..7f1ba48bc8d6bbdaf1c5a0b4c0706f69fd9f02c1 100644 (file)
 */
 #define ascstr3       [flag(STR_ASCII|STR_SIZE2)]            string
 
+/*
+  an ascii string prefixed with [size] [offset] [length], all 32 bits
+  not null terminated
+*/
+#define ascstr_noterm        [flag(STR_NOTERM|STR_ASCII|STR_SIZE4|STR_LEN4)]  string
+
 
 #define NDR_NOALIGN       LIBNDR_FLAG_NOALIGN
 #define NDR_REMAINING     LIBNDR_FLAG_REMAINING
index 01bfc7ed7a47bbf9a7d1acbba25ee6941c33b039..3639c21cd3121ae01422bb0eb24dbc490b2e5c83 100644 (file)
        typedef struct {
                [value(strlen_m(r->name))] uint16 name_len;
                [value(strlen_m(r->name))] uint16 name_size;
-               ascstr *name;
+               ascstr_noterm *name;
        } samr_AsciiName;       
 
        typedef struct {
 
        /************************/
        /* Function    0x33     */
-       NTSTATUS samr_QUERY_DISPINFO3();
+
+       /*
+         another duplicate. There must be a reason ....
+       */
+       NTSTATUS samr_QueryDisplayInfo3(
+               [in,ref]    policy_handle *handle,
+               [in]        uint16 level,
+               [in]        uint32 start_idx,
+               [in]        uint32 max_entries,
+               [in]        uint32 buf_size,
+               [out]       uint32 total_size,
+               [out]       uint32 returned_size,
+               [out,switch_is(level)] samr_DispInfo info
+               );
 
        /************************/
        /* Function    0x34     */
-       NTSTATUS samr_ADD_MULTIPLE_MEMBERS_TO_ALIAS();
+       NTSTATUS samr_AddMultipleMembersToAlias(
+               [in,ref]    policy_handle *handle,
+               [in,ref]    lsa_SidArray *sids
+               );
 
        /************************/
        /* Function    0x35     */
-       NTSTATUS samr_REMOVE_MULTIPLE_MEMBERS_FROM_ALIAS();
+       NTSTATUS samr_RemoveMultipleMembersFromAlias(
+               [in,ref]    policy_handle *handle,
+               [in,ref]    lsa_SidArray *sids
+               );
 
        /************************/
        /* Function    0x36     */
-       NTSTATUS samr_OEM_CHANGE_PASSWORD_USER2();
+
+       typedef [flag(NDR_PAHEX)] struct {
+               uint8 data[516];
+       } samr_CryptPassword;
+
+       NTSTATUS samr_OemChangePasswordUser2(
+               [in]              samr_AsciiName *server,
+               [in,ref]          samr_AsciiName *account,
+               [in]              samr_CryptPassword *password,
+               [in]              samr_Hash *hash
+               );
 
        /************************/
        /* Function    0x37     */
-       NTSTATUS samr_UNICODE_CHANGE_PASSWORD_USER2();
+       NTSTATUS samr_ChangePasswordUser2(
+               [in]              samr_Name *server,
+               [in,ref]          samr_Name *account,
+               [in]              samr_CryptPassword *nt_password,
+               [in]              samr_Hash *nt_verifier,
+               [in]              bool8 lm_change,
+               [in]              samr_CryptPassword *lm_password,
+               [in]              samr_Hash *lm_verifier
+               );
 
        /************************/
        /* Function    0x38     */
index 570f7719a49c308875c8021a7bf62d83ffcaa739..33176ec9c001a6a65fc05932652d8253d3d04ab4 100644 (file)
@@ -419,6 +419,7 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
                break;
 
        case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+       case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
                NDR_CHECK(ndr_pull_uint32(ndr, &len1));
                NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
                NDR_CHECK(ndr_pull_uint32(ndr, &len2));
@@ -550,6 +551,21 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
                ndr->offset += c_len + 1;
                break;
 
+       case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+               NDR_CHECK(ndr_push_uint32(ndr, c_len));
+               NDR_CHECK(ndr_push_uint32(ndr, 0));
+               NDR_CHECK(ndr_push_uint32(ndr, c_len));
+               NDR_PUSH_NEED_BYTES(ndr, c_len);
+               ret = convert_string(CH_UNIX, CH_DOS, 
+                                    s, s_len,
+                                    ndr->data+ndr->offset, c_len);
+               if (ret == -1) {
+                       return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
+                                             "Bad character conversion");
+               }
+               ndr->offset += c_len;
+               break;
+
        case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4:
                NDR_CHECK(ndr_push_uint32(ndr, 0));
                NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
@@ -733,8 +749,8 @@ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name,
 {
        int i;
 
-       if (count <= 32 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
-               char s[65];
+       if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
+               char s[1202];
                for (i=0;i<count;i++) {
                        snprintf(&s[i*2], 3, "%02x", data[i]);
                }
index 5f89970d170e4156947b386ad5c17b730e8e8c49..31359b4baf4262a327a9e333521b174ba6e7332c 100644 (file)
@@ -74,9 +74,56 @@ static void reopen(struct dcerpc_pipe **p, const struct dcerpc_interface_table *
        }
 }
 
+static void print_depth(int depth)
+{
+       int i;
+       for (i=0;i<depth;i++) {
+               printf("    ");
+       }
+}
 
 static void test_ptr_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, 
-                         int opnum, int min_in)
+                         int opnum, DATA_BLOB *base_in, int min_ofs, int max_ofs, int depth);
+
+static void try_expand(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, 
+                      int opnum, DATA_BLOB *base_in, int insert_ofs, int depth)
+{
+       DATA_BLOB stub_in, stub_out;
+       int n;
+       NTSTATUS status;
+       struct dcerpc_pipe *p = NULL;
+
+       reopen(&p, iface);
+
+       /* work out how much to expand to get a non fault */
+       for (n=0;n<2000;n++) {
+               stub_in = data_blob(NULL, base_in->length + n);
+               data_blob_clear(&stub_in);
+               memcpy(stub_in.data, base_in->data, insert_ofs);
+               memcpy(stub_in.data+insert_ofs+n, base_in->data+insert_ofs, base_in->length-insert_ofs);
+
+               status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out);
+
+               if (!NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
+                       print_depth(depth);
+                       printf("expand by %d gives %s\n", n, nt_errstr(status));
+                       if (n >= 4) {
+                               test_ptr_scan(mem_ctx, iface, opnum, &stub_in, 
+                                             insert_ofs, insert_ofs+n, depth+1);
+                       }
+                       return;
+               }
+               if (p->last_fault_code == 5) {
+                       reopen(&p, iface);
+               }
+       }
+
+       dcerpc_pipe_close(p);   
+}
+
+
+static void test_ptr_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, 
+                         int opnum, DATA_BLOB *base_in, int min_ofs, int max_ofs, int depth)
 {
        DATA_BLOB stub_in, stub_out;
        int ofs;
@@ -85,24 +132,30 @@ static void test_ptr_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_tab
 
        reopen(&p, iface);
 
-       stub_in = data_blob(NULL, min_in);
-       data_blob_clear(&stub_in);
+       stub_in = data_blob(NULL, base_in->length);
+       memcpy(stub_in.data, base_in->data, base_in->length);
 
-       /* work out the minimum amount of input data */
-       for (ofs=0;ofs<min_in;ofs+=4) {
+       /* work out which elements are pointers */
+       for (ofs=min_ofs;ofs<=max_ofs-4;ofs+=4) {
                SIVAL(stub_in.data, ofs, 1);
                status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out);
-               SIVAL(stub_in.data, ofs, 0);
 
                if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
-                       printf("opnum %d ofs %d size %d fault 0x%08x\n", 
-                              opnum, ofs, min_in, p->last_fault_code);
+                       print_depth(depth);
+                       printf("possible ptr at ofs %d - fault 0x%08x\n", 
+                              ofs-min_ofs, p->last_fault_code);
                        if (p->last_fault_code == 5) {
                                reopen(&p, iface);
                        }
+                       if (depth == 0) {
+                               try_expand(mem_ctx, iface, opnum, &stub_in, ofs+4, depth+1);
+                       } else {
+                               try_expand(mem_ctx, iface, opnum, &stub_in, max_ofs, depth+1);
+                       }
+                       SIVAL(stub_in.data, ofs, 0);
                        continue;
                }
-               printf("opnum %d  ofs %d error %s\n", opnum, ofs, nt_errstr(status));
+               SIVAL(stub_in.data, ofs, 0);
        }
 
        dcerpc_pipe_close(p);   
@@ -126,9 +179,6 @@ static void test_scan_call(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_ta
                stub_in = data_blob(NULL, i);
                data_blob_clear(&stub_in);
 
-#if 1
-               fill_blob_handle(&stub_in, mem_ctx, &handle);
-#endif
 
                status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out);
 
@@ -137,7 +187,20 @@ static void test_scan_call(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_ta
                               opnum, stub_in.length, stub_out.length);
                        dump_data(0, stub_out.data, stub_out.length);
                        dcerpc_pipe_close(p);
-                       test_ptr_scan(mem_ctx, iface, opnum, stub_in.length);
+                       test_ptr_scan(mem_ctx, iface, opnum, &stub_in, 0, stub_in.length, 0);
+                       return;
+               }
+
+               fill_blob_handle(&stub_in, mem_ctx, &handle);
+
+               status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out);
+
+               if (NT_STATUS_IS_OK(status)) {
+                       printf("opnum %d   min_input %d - output %d (with handle)\n", 
+                              opnum, stub_in.length, stub_out.length);
+                       dump_data(0, stub_out.data, stub_out.length);
+                       dcerpc_pipe_close(p);
+                       test_ptr_scan(mem_ctx, iface, opnum, &stub_in, 0, stub_in.length, 0);
                        return;
                }
 
@@ -159,7 +222,7 @@ static void test_scan_call(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_ta
 
 static void test_auto_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface)
 {
-       test_scan_call(mem_ctx, iface, 0x26);
+       test_scan_call(mem_ctx, iface, 0x37);
 }
 
 BOOL torture_rpc_autoidl(int dummy)
index a098fbd9caaba9f416e96f44bc456c08d4a0fda7..2a48a6c58474dd0c6293e1dc448c4beeb3d0dc56 100644 (file)
@@ -421,6 +421,76 @@ static BOOL test_ChangePasswordUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 
+static BOOL test_OemChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                                       struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_OemChangePasswordUser2 r;
+       BOOL ret = True;
+       struct samr_Hash hash;
+       struct samr_CryptPassword pass;
+       struct samr_AsciiName server, account;
+
+       printf("Testing OemChangePasswordUser2\n");
+
+       ZERO_STRUCT(hash);
+       ZERO_STRUCT(pass);
+
+       server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       account.name = TEST_USERNAME;
+
+       r.in.server = &server;
+       r.in.account = &account;
+       r.in.password = &pass;
+       r.in.hash = &hash;
+
+       status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
+static BOOL test_ChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                                    struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_ChangePasswordUser2 r;
+       BOOL ret = True;
+       struct samr_Name server, account;
+       struct samr_CryptPassword nt_pass, lm_pass;
+       struct samr_Hash nt_verifier, lm_verifier;
+
+       printf("Testing ChangePasswordUser2\n");
+
+       server.name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       init_samr_Name(&account, TEST_USERNAME);
+
+       ZERO_STRUCT(nt_pass);
+       ZERO_STRUCT(lm_pass);
+       ZERO_STRUCT(nt_verifier);
+       ZERO_STRUCT(lm_verifier);
+       
+       r.in.server = &server;
+       r.in.account = &account;
+       r.in.nt_password = &nt_pass;
+       r.in.nt_verifier = &nt_verifier;
+       r.in.lm_change = 1;
+       r.in.lm_password = &lm_pass;
+       r.in.lm_verifier = &lm_verifier;
+
+       status = dcerpc_samr_ChangePasswordUser2(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
+
 static BOOL test_GetMembersInAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                  struct policy_handle *alias_handle)
 {
@@ -479,6 +549,62 @@ static BOOL test_AddMemberToAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
+static BOOL test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                                          struct policy_handle *alias_handle)
+{
+       struct samr_AddMultipleMembersToAlias a;
+       struct samr_RemoveMultipleMembersFromAlias r;
+       NTSTATUS status;
+       BOOL ret = True;
+       struct lsa_SidArray sids;
+
+       printf("testing AddMultipleMembersToAlias\n");
+       a.in.handle = alias_handle;
+       a.in.sids = &sids;
+
+       sids.num_sids = 3;
+       sids.sids = talloc_array_p(mem_ctx, struct lsa_SidPtr, 3);
+
+       sids.sids[0].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-1");
+       sids.sids[1].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-2");
+       sids.sids[2].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-3");
+
+       status = dcerpc_samr_AddMultipleMembersToAlias(p, mem_ctx, &a);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("AddMultipleMembersToAlias failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+
+       printf("testing RemoveMultipleMembersFromAlias\n");
+       r.in.handle = alias_handle;
+       r.in.sids = &sids;
+
+       status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       /* strange! removing twice doesn't give any error */
+       status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       /* but removing an alias that isn't there does */
+       sids.sids[2].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-4");
+
+       status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
+       if (!NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
+               printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
+               ret = False;
+       }
+
+       return ret;
+}
+
 static BOOL test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                            struct policy_handle *user_handle)
 {
@@ -556,6 +682,10 @@ static BOOL test_alias_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                ret = False;
        }
 
+       if (!test_AddMultipleMembersToAlias(p, mem_ctx, alias_handle)) {
+               ret = False;
+       }
+
        return ret;
 }
 
@@ -800,6 +930,14 @@ static BOOL test_CreateUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                ret = False;
        }
 
+       if (!test_OemChangePasswordUser2(p, mem_ctx, domain_handle)) {
+               ret = False;
+       }
+
+       if (!test_ChangePasswordUser2(p, mem_ctx, domain_handle)) {
+               ret = False;
+       }
+
        if (!test_user_ops(p, mem_ctx, user_handle)) {
                ret = False;
        }
@@ -1461,6 +1599,35 @@ static BOOL test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;     
 }
 
+static BOOL test_QueryDisplayInfo3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
+                                 struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct samr_QueryDisplayInfo3 r;
+       BOOL ret = True;
+       uint16 levels[] = {1, 2, 3, 4, 5};
+       int i;
+
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               printf("Testing QueryDisplayInfo3 level %u\n", levels[i]);
+
+               r.in.handle = handle;
+               r.in.level = levels[i];
+               r.in.start_idx = 0;
+               r.in.max_entries = 1000;
+               r.in.buf_size = (uint32)-1;
+
+               status = dcerpc_samr_QueryDisplayInfo3(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("QueryDisplayInfo3 level %u failed - %s\n", 
+                              levels[i], nt_errstr(status));
+                       ret = False;
+               }
+       }
+       
+       return ret;     
+}
+
 static BOOL test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
                                 struct policy_handle *handle)
 {
@@ -1920,6 +2087,10 @@ static BOOL test_OpenDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                ret = False;
        }
 
+       if (!test_QueryDisplayInfo3(p, mem_ctx, &domain_handle)) {
+               ret = False;
+       }
+
        if (!test_GetDisplayEnumerationIndex(p, mem_ctx, &domain_handle)) {
                ret = False;
        }