Move a comment where it belongs
[ira/wip.git] / source4 / rpc_server / samr / dcesrv_samr.c
index 0f16320a8cc7d334b54c20772bc67a124cda0827..03acf97cab700cc817bad19bc187a7b8a3172771 100644 (file)
 
 #define SET_PARAMETERS(msg, field, attr) do {                          \
        struct ldb_message_element *set_el;                             \
-       if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
-               return NT_STATUS_NO_MEMORY;                             \
+       if (r->in.info->field.length != 0) {                            \
+               if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
+                       return NT_STATUS_NO_MEMORY;                     \
+               }                                                       \
+               set_el = ldb_msg_find_element(msg, attr);               \
+               set_el->flags = LDB_FLAG_MOD_REPLACE;                   \
        }                                                               \
-       set_el = ldb_msg_find_element(msg, attr);                       \
-       set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
 } while (0)
 
 
@@ -271,13 +273,10 @@ static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TAL
        struct dcesrv_handle *h;
        struct dom_sid *sid;
        const char * const dom_attrs[] = { "objectSid", NULL};
-       const char * const ref_attrs[] = { "ncName", NULL};
        struct ldb_message **dom_msgs;
-       struct ldb_message **ref_msgs;
        int ret;
-       struct ldb_dn *partitions_basedn;
 
-       r->out.sid = NULL;
+       *r->out.sid = NULL;
 
        DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
 
@@ -287,27 +286,17 @@ static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TAL
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
-
        if (strcasecmp(r->in.domain_name->string, "BUILTIN") == 0) {
                ret = gendb_search(c_state->sam_ctx,
                                   mem_ctx, NULL, &dom_msgs, dom_attrs,
                                   "(objectClass=builtinDomain)");
-       } else {
-               ret = gendb_search(c_state->sam_ctx,
-                                  mem_ctx, partitions_basedn, &ref_msgs, ref_attrs,
-                                  "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))", 
-                                  ldb_binary_encode_string(mem_ctx, r->in.domain_name->string));
-               if (ret != 1) {
-                       return NT_STATUS_NO_SUCH_DOMAIN;
-               }
-               
-               ret = gendb_search_dn(c_state->sam_ctx, mem_ctx, 
-                                     samdb_result_dn(c_state->sam_ctx, mem_ctx,
-                                                     ref_msgs[0], "ncName", NULL), 
+       } else if (strcasecmp_m(r->in.domain_name->string, lp_sam_name(dce_call->conn->dce_ctx->lp_ctx)) == 0) {
+               ret = gendb_search_dn(c_state->sam_ctx,
+                                     mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), 
                                      &dom_msgs, dom_attrs);
+       } else {
+               return NT_STATUS_NO_SUCH_DOMAIN;
        }
-
        if (ret != 1) {
                return NT_STATUS_NO_SUCH_DOMAIN;
        }
@@ -319,7 +308,7 @@ static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TAL
                return NT_STATUS_NO_SUCH_DOMAIN;
        }
 
-       r->out.sid = sid;
+       *r->out.sid = sid;
 
        return NT_STATUS_OK;
 }
@@ -336,35 +325,21 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL
        struct samr_connect_state *c_state;
        struct dcesrv_handle *h;
        struct samr_SamArray *array;
-       int i, start_i, ret;
-       const char * const dom_attrs[] = { "cn", NULL};
-       const char * const ref_attrs[] = { "nETBIOSName", NULL};
-       struct ldb_result *dom_res;
-       struct ldb_result *ref_res;
-       struct ldb_dn *partitions_basedn;
+       int i, start_i;
 
        *r->out.resume_handle = 0;
-       r->out.sam = NULL;
-       r->out.num_entries = 0;
+       *r->out.sam = NULL;
+       *r->out.num_entries = 0;
 
        DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
 
        c_state = h->data;
 
-       partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
-
-       ret = ldb_search(c_state->sam_ctx, mem_ctx, &dom_res, ldb_get_default_basedn(c_state->sam_ctx),
-                                LDB_SCOPE_SUBTREE, dom_attrs, "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))");
-       if (ret != LDB_SUCCESS) {
-               DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx)));
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-
-       *r->out.resume_handle = dom_res->count;
+       *r->out.resume_handle = 2;
 
        start_i = *r->in.resume_handle;
 
-       if (start_i >= dom_res->count) {
+       if (start_i >= 2) {
                /* search past end of list is not an error for this call */
                return NT_STATUS_OK;
        }
@@ -377,33 +352,23 @@ static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALL
        array->count = 0;
        array->entries = NULL;
 
-       array->entries = talloc_array(mem_ctx, struct samr_SamEntry, dom_res->count - start_i);
+       array->entries = talloc_array(mem_ctx, struct samr_SamEntry, 2 - start_i);
        if (array->entries == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       for (i=0;i<dom_res->count-start_i;i++) {
+       for (i=0;i<2-start_i;i++) {
                array->entries[i].idx = start_i + i;
-               /* try and find the domain */
-               ret = ldb_search(c_state->sam_ctx, mem_ctx, &ref_res, partitions_basedn,
-                                        LDB_SCOPE_SUBTREE, ref_attrs, "(&(objectClass=crossRef)(ncName=%s))", 
-                                        ldb_dn_get_linearized(dom_res->msgs[i]->dn));
-
-               if (ret != LDB_SUCCESS) {
-                       DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx)));
-                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
-               }
-
-               if (ref_res->count == 1) {
-                       array->entries[i].name.string = samdb_result_string(ref_res->msgs[0], "nETBIOSName", NULL);
+               if (i == 0) {
+                       array->entries[i].name.string = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
                } else {
-                       array->entries[i].name.string = samdb_result_string(dom_res->msgs[i], "cn", NULL);
+                       array->entries[i].name.string = "BUILTIN";
                }
        }
 
-       r->out.sam = array;
-       r->out.num_entries = i;
-       array->count = r->out.num_entries;
+       *r->out.sam = array;
+       *r->out.num_entries = i;
+       array->count = *r->out.num_entries;
 
        return NT_STATUS_OK;
 }
@@ -416,15 +381,11 @@ static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLO
                                struct samr_OpenDomain *r)
 {
        struct dcesrv_handle *h_conn, *h_domain;
-       const char *domain_name;
        struct samr_connect_state *c_state;
        struct samr_domain_state *d_state;
        const char * const dom_attrs[] = { "cn", NULL};
-       const char * const ref_attrs[] = { "nETBIOSName", NULL};
        struct ldb_message **dom_msgs;
-       struct ldb_message **ref_msgs;
        int ret;
-       struct ldb_dn *partitions_basedn;
 
        ZERO_STRUCTP(r->out.domain_handle);
 
@@ -436,63 +397,44 @@ static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLO
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
+       d_state = talloc(c_state, struct samr_domain_state);
+       if (!d_state) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       d_state->domain_sid = talloc_steal(d_state, r->in.sid);
+
+       if (dom_sid_equal(d_state->domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) {
+               d_state->builtin = true;
+               d_state->domain_name = "BUILTIN";
+       } else {
+               d_state->builtin = false;
+               d_state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
+       }
 
        ret = gendb_search(c_state->sam_ctx,
-                          mem_ctx, NULL, &dom_msgs, dom_attrs,
-                          "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", 
+                          mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), &dom_msgs, dom_attrs,
+                          "(objectSid=%s)", 
                           ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
+       
        if (ret == 0) {
+               talloc_free(d_state);
                return NT_STATUS_NO_SUCH_DOMAIN;
        } else if (ret > 1) {
+               talloc_free(d_state);
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        } else if (ret == -1) {
+               talloc_free(d_state);
                DEBUG(1, ("Failed to open domain %s: %s\n", dom_sid_string(mem_ctx, r->in.sid), ldb_errstring(c_state->sam_ctx)));
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       } else {
-               ret = gendb_search(c_state->sam_ctx,
-                                  mem_ctx, partitions_basedn, &ref_msgs, ref_attrs,
-                                  "(&(&(nETBIOSName=*)(objectclass=crossRef))(ncName=%s))", 
-                                  ldb_dn_get_linearized(dom_msgs[0]->dn));
-               if (ret == 0) {
-                       domain_name = ldb_msg_find_attr_as_string(dom_msgs[0], "cn", NULL);
-                       if (domain_name == NULL) {
-                               return NT_STATUS_NO_SUCH_DOMAIN;
-                       }
-               } else if (ret == 1) {
-               
-                       domain_name = ldb_msg_find_attr_as_string(ref_msgs[0], "nETBIOSName", NULL);
-                       if (domain_name == NULL) {
-                               return NT_STATUS_NO_SUCH_DOMAIN;
-                       }
-               } else {
-                       return NT_STATUS_NO_SUCH_DOMAIN;
-               }
-       }
-
-       d_state = talloc(c_state, struct samr_domain_state);
-       if (!d_state) {
-               return NT_STATUS_NO_MEMORY;
        }
 
+       d_state->domain_dn = talloc_steal(d_state, dom_msgs[0]->dn);
        d_state->role = lp_server_role(dce_call->conn->dce_ctx->lp_ctx);
        d_state->connect_state = talloc_reference(d_state, c_state);
        d_state->sam_ctx = c_state->sam_ctx;
-       d_state->domain_sid = dom_sid_dup(d_state, r->in.sid);
-       d_state->domain_name = talloc_strdup(d_state, domain_name);
-       d_state->domain_dn = ldb_dn_copy(d_state, dom_msgs[0]->dn);
-       if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) {
-               talloc_free(d_state);
-               return NT_STATUS_NO_MEMORY;             
-       }
        d_state->access_mask = r->in.access_mask;
 
-       if (dom_sid_equal(d_state->domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) {
-               d_state->builtin = true;
-       } else {
-               d_state->builtin = false;
-       }
-
        d_state->lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
 
        h_domain = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_DOMAIN);
@@ -704,7 +646,7 @@ static NTSTATUS dcesrv_samr_info_DomInfo9(struct samr_domain_state *state,
                                    struct ldb_message **dom_msgs,
                                   struct samr_DomInfo9 *info)
 {
-       info->unknown = 1;
+       info->domain_server_state = DOMAIN_SERVER_ENABLED;
 
        return NT_STATUS_OK;
 }
@@ -763,8 +705,7 @@ static NTSTATUS dcesrv_samr_info_DomInfo13(struct samr_domain_state *state,
        info->domain_create_time = ldb_msg_find_attr_as_uint(dom_msgs[0], "creationTime",
                                                     0x0LL);
 
-       info->unknown1 = 0;
-       info->unknown2 = 0;
+       info->modified_count_at_last_promotion = 0;
 
        return NT_STATUS_OK;
 }
@@ -1150,10 +1091,11 @@ static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call,
        int ldb_cnt, count, i, first;
        struct samr_SamEntry *entries;
        const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
+       struct samr_SamArray *sam;
 
        *r->out.resume_handle = 0;
-       r->out.sam = NULL;
-       r->out.num_entries = 0;
+       *r->out.sam = NULL;
+       *r->out.num_entries = 0;
 
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
@@ -1204,20 +1146,22 @@ static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call,
 
        /* return the rest, limit by max_size. Note that we 
           use the w2k3 element size value of 54 */
-       r->out.num_entries = count - first;
-       r->out.num_entries = MIN(r->out.num_entries, 
+       *r->out.num_entries = count - first;
+       *r->out.num_entries = MIN(*r->out.num_entries,
                                 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
 
-       r->out.sam = talloc(mem_ctx, struct samr_SamArray);
-       if (!r->out.sam) {
+       sam = talloc(mem_ctx, struct samr_SamArray);
+       if (!sam) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       r->out.sam->entries = entries+first;
-       r->out.sam->count = r->out.num_entries;
+       sam->entries = entries+first;
+       sam->count = *r->out.num_entries;
+
+       *r->out.sam = sam;
 
-       if (r->out.num_entries < count - first) {
-               *r->out.resume_handle = entries[first+r->out.num_entries-1].idx;
+       if (*r->out.num_entries < count - first) {
+               *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx;
                return STATUS_MORE_ENTRIES;
        }
 
@@ -1269,6 +1213,9 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL
        if (d_state->builtin) {
                DEBUG(5, ("Cannot create a user in the BUILTIN domain"));
                return NT_STATUS_ACCESS_DENIED;
+       } else if (r->in.acct_flags == ACB_DOMTRUST) {
+               /* Domain trust accounts must be created by the LSA calls */
+               return NT_STATUS_ACCESS_DENIED;
        }
        account_name = r->in.account_name->string;
 
@@ -1276,6 +1223,11 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       /*
+        * Start a transaction, so we can query and do a subsequent atomic
+        * modify
+        */
+
        ret = ldb_transaction_start(d_state->sam_ctx);
        if (ret != 0) {
                DEBUG(0,("Failed to start a transaction for user creation: %s\n",
@@ -1314,6 +1266,7 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL
 
        } else if (r->in.acct_flags == ACB_WSTRUST) {
                if (cn_name[cn_name_len - 1] != '$') {
+                       ldb_transaction_cancel(d_state->sam_ctx);
                        return NT_STATUS_FOOBAR;
                }
                cn_name[cn_name_len - 1] = '\0';
@@ -1323,17 +1276,13 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL
 
        } else if (r->in.acct_flags == ACB_SVRTRUST) {
                if (cn_name[cn_name_len - 1] != '$') {
+                       ldb_transaction_cancel(d_state->sam_ctx);
                        return NT_STATUS_FOOBAR;                
                }
                cn_name[cn_name_len - 1] = '\0';
                container = "OU=Domain Controllers";
                obj_class = "computer";
                samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DCS);
-
-       } else if (r->in.acct_flags == ACB_DOMTRUST) {
-               container = "CN=Users";
-               obj_class = "user";
-
        } else {
                ldb_transaction_cancel(d_state->sam_ctx);
                return NT_STATUS_INVALID_PARAMETER;
@@ -1348,9 +1297,7 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL
 
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", account_name);
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", obj_class);
-       
-       /* Start a transaction, so we can query and do a subsequent atomic modify */
-       
+
        /* create the user */
        ret = ldb_add(d_state->sam_ctx, msg);
        switch (ret) {
@@ -1507,10 +1454,11 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call,
        int ret, num_filtered_entries, i, first;
        struct samr_SamEntry *entries;
        const char * const attrs[] = { "objectSid", "sAMAccountName", "userAccountControl", NULL };
+       struct samr_SamArray *sam;
 
        *r->out.resume_handle = 0;
-       r->out.sam = NULL;
-       r->out.num_entries = 0;
+       *r->out.sam = NULL;
+       *r->out.num_entries = 0;
 
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
@@ -1554,24 +1502,26 @@ static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call,
 
        /* return the rest, limit by max_size. Note that we 
           use the w2k3 element size value of 54 */
-       r->out.num_entries = num_filtered_entries - first;
-       r->out.num_entries = MIN(r->out.num_entries, 
+       *r->out.num_entries = num_filtered_entries - first;
+       *r->out.num_entries = MIN(*r->out.num_entries,
                                 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
 
-       r->out.sam = talloc(mem_ctx, struct samr_SamArray);
-       if (!r->out.sam) {
+       sam = talloc(mem_ctx, struct samr_SamArray);
+       if (!sam) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       r->out.sam->entries = entries+first;
-       r->out.sam->count = r->out.num_entries;
+       sam->entries = entries+first;
+       sam->count = *r->out.num_entries;
+
+       *r->out.sam = sam;
 
        if (first == num_filtered_entries) {
                return NT_STATUS_OK;
        }
 
-       if (r->out.num_entries < num_filtered_entries - first) {
-               *r->out.resume_handle = entries[first+r->out.num_entries-1].idx;
+       if (*r->out.num_entries < num_filtered_entries - first) {
+               *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx;
                return STATUS_MORE_ENTRIES;
        }
 
@@ -1700,10 +1650,11 @@ static NTSTATUS dcesrv_samr_EnumDomainAliases(struct dcesrv_call_state *dce_call
        int ldb_cnt, count, i, first;
        struct samr_SamEntry *entries;
        const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
+       struct samr_SamArray *sam;
 
        *r->out.resume_handle = 0;
-       r->out.sam = NULL;
-       r->out.num_entries = 0;
+       *r->out.sam = NULL;
+       *r->out.num_entries = 0;
 
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
@@ -1763,20 +1714,22 @@ static NTSTATUS dcesrv_samr_EnumDomainAliases(struct dcesrv_call_state *dce_call
                return NT_STATUS_OK;
        }
 
-       r->out.num_entries = count - first;
-       r->out.num_entries = MIN(r->out.num_entries, 1000);
+       *r->out.num_entries = count - first;
+       *r->out.num_entries = MIN(*r->out.num_entries, 1000);
 
-       r->out.sam = talloc(mem_ctx, struct samr_SamArray);
-       if (!r->out.sam) {
+       sam = talloc(mem_ctx, struct samr_SamArray);
+       if (!sam) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       r->out.sam->entries = entries+first;
-       r->out.sam->count = r->out.num_entries;
+       sam->entries = entries+first;
+       sam->count = *r->out.num_entries;
+
+       *r->out.sam = sam;
 
-       if (r->out.num_entries < count - first) {
+       if (*r->out.num_entries < count - first) {
                *r->out.resume_handle =
-                       entries[first+r->out.num_entries-1].idx;
+                       entries[first+*r->out.num_entries-1].idx;
                return STATUS_MORE_ENTRIES;
        }
 
@@ -1874,8 +1827,8 @@ static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALL
        const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
        int count;
 
-       ZERO_STRUCT(r->out.rids);
-       ZERO_STRUCT(r->out.types);
+       ZERO_STRUCTP(r->out.rids);
+       ZERO_STRUCTP(r->out.types);
 
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
@@ -1885,13 +1838,13 @@ static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALL
                return NT_STATUS_OK;
        }
 
-       r->out.rids.ids = talloc_array(mem_ctx, uint32_t, r->in.num_names);
-       r->out.types.ids = talloc_array(mem_ctx, uint32_t, r->in.num_names);
-       if (!r->out.rids.ids || !r->out.types.ids) {
+       r->out.rids->ids = talloc_array(mem_ctx, uint32_t, r->in.num_names);
+       r->out.types->ids = talloc_array(mem_ctx, uint32_t, r->in.num_names);
+       if (!r->out.rids->ids || !r->out.types->ids) {
                return NT_STATUS_NO_MEMORY;
        }
-       r->out.rids.count = r->in.num_names;
-       r->out.types.count = r->in.num_names;
+       r->out.rids->count = r->in.num_names;
+       r->out.types->count = r->in.num_names;
 
        num_mapped = 0;
 
@@ -1900,8 +1853,8 @@ static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALL
                struct dom_sid *sid;
                uint32_t atype, rtype;
 
-               r->out.rids.ids[i] = 0;
-               r->out.types.ids[i] = SID_NAME_UNKNOWN;
+               r->out.rids->ids[i] = 0;
+               r->out.types->ids[i] = SID_NAME_UNKNOWN;
 
                count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, 
                                     "sAMAccountName=%s", 
@@ -1930,8 +1883,8 @@ static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALL
                        continue;
                }
 
-               r->out.rids.ids[i] = sid->sub_auths[sid->num_auths-1];
-               r->out.types.ids[i] = rtype;
+               r->out.rids->ids[i] = sid->sub_auths[sid->num_auths-1];
+               r->out.types->ids[i] = rtype;
                num_mapped++;
        }
        
@@ -2120,7 +2073,7 @@ static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, T
        int ret;
        union samr_GroupInfo *info;
 
-       r->out.info = NULL;
+       *r->out.info = NULL;
 
        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
 
@@ -2176,7 +2129,7 @@ static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, T
                return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       r->out.info = info;
+       *r->out.info = info;
 
        return NT_STATUS_OK;
 }
@@ -2593,7 +2546,7 @@ static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, T
        int ret;
        union samr_AliasInfo *info;
 
-       r->out.info = NULL;
+       *r->out.info = NULL;
 
        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
 
@@ -2630,7 +2583,7 @@ static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, T
                return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       r->out.info = info;
+       *r->out.info = info;
 
        return NT_STATUS_OK;
 }
@@ -3010,7 +2963,7 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA
        const char * const *attrs = NULL;
        union samr_UserInfo *info;
 
-       r->out.info = NULL;
+       *r->out.info = NULL;
 
        DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
 
@@ -3346,7 +3299,7 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA
                return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       r->out.info = info;
+       *r->out.info = info;
 
        return NT_STATUS_OK;
 }
@@ -3503,14 +3456,14 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL
                        SET_UINT  (msg, info23.info.country_code, "countryCode");
                IFSET(SAMR_FIELD_CODE_PAGE)    
                        SET_UINT  (msg, info23.info.code_page,    "codePage");
-               IFSET(SAMR_FIELD_PASSWORD) {
+               IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) {
                        status = samr_set_password(dce_call,
                                                   a_state->sam_ctx,
                                                   a_state->account_dn,
                                                   a_state->domain_state->domain_dn,
                                                   mem_ctx, msg, 
                                                   &r->in.info->info23.password);
-               } else IFSET(SAMR_FIELD_PASSWORD2) {
+               } else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) {
                        status = samr_set_password(dce_call,
                                                   a_state->sam_ctx,
                                                   a_state->account_dn,
@@ -3559,14 +3512,14 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL
                        SET_UINT  (msg, info25.info.country_code, "countryCode");
                IFSET(SAMR_FIELD_CODE_PAGE)    
                        SET_UINT  (msg, info25.info.code_page,    "codePage");
-               IFSET(SAMR_FIELD_PASSWORD) {
+               IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) {
                        status = samr_set_password_ex(dce_call,
                                                      a_state->sam_ctx,
                                                      a_state->account_dn,
                                                      a_state->domain_state->domain_dn,
                                                      mem_ctx, msg, 
                                                      &r->in.info->info25.password);
-               } else IFSET(SAMR_FIELD_PASSWORD2) {
+               } else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) {
                        status = samr_set_password_ex(dce_call,
                                                      a_state->sam_ctx,
                                                      a_state->account_dn,
@@ -3829,65 +3782,65 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
                count += 1;
        }
 
-       r->out.total_size = count;
+       *r->out.total_size = count;
 
        if (r->in.start_idx >= count) {
-               r->out.returned_size = 0;
+               *r->out.returned_size = 0;
                switch(r->in.level) {
                case 1:
-                       r->out.info.info1.count = r->out.returned_size;
-                       r->out.info.info1.entries = NULL;
+                       r->out.info->info1.count = *r->out.returned_size;
+                       r->out.info->info1.entries = NULL;
                        break;
                case 2:
-                       r->out.info.info2.count = r->out.returned_size;
-                       r->out.info.info2.entries = NULL;
+                       r->out.info->info2.count = *r->out.returned_size;
+                       r->out.info->info2.entries = NULL;
                        break;
                case 3:
-                       r->out.info.info3.count = r->out.returned_size;
-                       r->out.info.info3.entries = NULL;
+                       r->out.info->info3.count = *r->out.returned_size;
+                       r->out.info->info3.entries = NULL;
                        break;
                case 4:
-                       r->out.info.info4.count = r->out.returned_size;
-                       r->out.info.info4.entries = NULL;
+                       r->out.info->info4.count = *r->out.returned_size;
+                       r->out.info->info4.entries = NULL;
                        break;
                case 5:
-                       r->out.info.info5.count = r->out.returned_size;
-                       r->out.info.info5.entries = NULL;
+                       r->out.info->info5.count = *r->out.returned_size;
+                       r->out.info->info5.entries = NULL;
                        break;
                }
        } else {
-               r->out.returned_size = MIN(count - r->in.start_idx,
+               *r->out.returned_size = MIN(count - r->in.start_idx,
                                           r->in.max_entries);
                switch(r->in.level) {
                case 1:
-                       r->out.info.info1.count = r->out.returned_size;
-                       r->out.info.info1.entries =
+                       r->out.info->info1.count = *r->out.returned_size;
+                       r->out.info->info1.entries =
                                &(entriesGeneral[r->in.start_idx]);
                        break;
                case 2:
-                       r->out.info.info2.count = r->out.returned_size;
-                       r->out.info.info2.entries =
+                       r->out.info->info2.count = *r->out.returned_size;
+                       r->out.info->info2.entries =
                                &(entriesFull[r->in.start_idx]);
                        break;
                case 3:
-                       r->out.info.info3.count = r->out.returned_size;
-                       r->out.info.info3.entries =
+                       r->out.info->info3.count = *r->out.returned_size;
+                       r->out.info->info3.entries =
                                &(entriesFullGroup[r->in.start_idx]);
                        break;
                case 4:
-                       r->out.info.info4.count = r->out.returned_size;
-                       r->out.info.info4.entries =
+                       r->out.info->info4.count = *r->out.returned_size;
+                       r->out.info->info4.entries =
                                &(entriesAscii[r->in.start_idx]);
                        break;
                case 5:
-                       r->out.info.info5.count = r->out.returned_size;
-                       r->out.info.info5.entries =
+                       r->out.info->info5.count = *r->out.returned_size;
+                       r->out.info->info5.entries =
                                &(entriesAscii[r->in.start_idx]);
                        break;
                }
        }
 
-       return (r->out.returned_size < (count - r->in.start_idx)) ?
+       return (*r->out.returned_size < (count - r->in.start_idx)) ?
                STATUS_MORE_ENTRIES : NT_STATUS_OK;
 }
 
@@ -4048,13 +4001,11 @@ static NTSTATUS dcesrv_samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, T
        struct samr_QueryUserInfo r1;
        NTSTATUS status;
 
-       ZERO_STRUCT(r1.out);
        r1.in.user_handle = r->in.user_handle;
        r1.in.level  = r->in.level;
+       r1.out.info  = r->out.info;
        
        status = dcesrv_samr_QueryUserInfo(dce_call, mem_ctx, &r1);
-       
-       r->out.info = r1.out.info;
 
        return status;
 }
@@ -4074,14 +4025,12 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call
        q.in.start_idx = r->in.start_idx;
        q.in.max_entries = r->in.max_entries;
        q.in.buf_size = r->in.buf_size;
-       ZERO_STRUCT(q.out);
+       q.out.total_size = r->out.total_size;
+       q.out.returned_size = r->out.returned_size;
+       q.out.info = r->out.info;
 
        result = dcesrv_samr_QueryDisplayInfo(dce_call, mem_ctx, &q);
 
-       r->out.total_size = q.out.total_size;
-       r->out.returned_size = q.out.returned_size;
-       r->out.info = q.out.info;
-
        return result;
 }
 
@@ -4110,14 +4059,12 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call
        q.in.start_idx = r->in.start_idx;
        q.in.max_entries = r->in.max_entries;
        q.in.buf_size = r->in.buf_size;
-       ZERO_STRUCT(q.out);
+       q.out.total_size = r->out.total_size;
+       q.out.returned_size = r->out.returned_size;
+       q.out.info = r->out.info;
 
        result = dcesrv_samr_QueryDisplayInfo(dce_call, mem_ctx, &q);
 
-       r->out.total_size = q.out.total_size;
-       r->out.returned_size = q.out.returned_size;
-       r->out.info = q.out.info;
-
        return result;
 }