~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/rpc_server/samr/dcesrv_samr.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   endpoint server for the samr pipe
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2004
 
7
   Copyright (C) Volker Lendecke 2004
 
8
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
 
9
   
 
10
   This program is free software; you can redistribute it and/or modify
 
11
   it under the terms of the GNU General Public License as published by
 
12
   the Free Software Foundation; either version 3 of the License, or
 
13
   (at your option) any later version.
 
14
   
 
15
   This program is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
   GNU General Public License for more details.
 
19
   
 
20
   You should have received a copy of the GNU General Public License
 
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
22
*/
 
23
 
 
24
#include "includes.h"
 
25
#include "librpc/gen_ndr/ndr_samr.h"
 
26
#include "rpc_server/dcerpc_server.h"
 
27
#include "rpc_server/common/common.h"
 
28
#include "rpc_server/samr/dcesrv_samr.h"
 
29
#include "system/time.h"
 
30
#include "lib/ldb/include/ldb.h"
 
31
#include "lib/ldb/include/ldb_errors.h"
 
32
#include "dsdb/common/flags.h"
 
33
#include "dsdb/samdb/samdb.h"
 
34
#include "libcli/ldap/ldap_ndr.h"
 
35
#include "libcli/security/security.h"
 
36
#include "rpc_server/samr/proto.h"
 
37
#include "../lib/util/util_ldb.h"
 
38
#include "param/param.h"
 
39
 
 
40
/* these query macros make samr_Query[User|Group|Alias]Info a bit easier to read */
 
41
 
 
42
#define QUERY_STRING(msg, field, attr) \
 
43
        info->field.string = samdb_result_string(msg, attr, "");
 
44
#define QUERY_UINT(msg, field, attr) \
 
45
        info->field = samdb_result_uint(msg, attr, 0);
 
46
#define QUERY_RID(msg, field, attr) \
 
47
        info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
 
48
#define QUERY_UINT64(msg, field, attr) \
 
49
        info->field = samdb_result_uint64(msg, attr, 0);
 
50
#define QUERY_APASSC(msg, field, attr) \
 
51
        info->field = samdb_result_allow_password_change(sam_ctx, mem_ctx, \
 
52
                                                         a_state->domain_state->domain_dn, msg, attr);
 
53
#define QUERY_FPASSC(msg, field, attr) \
 
54
        info->field = samdb_result_force_password_change(sam_ctx, mem_ctx, \
 
55
                                                         a_state->domain_state->domain_dn, msg);
 
56
#define QUERY_LHOURS(msg, field, attr) \
 
57
        info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
 
58
#define QUERY_AFLAGS(msg, field, attr) \
 
59
        info->field = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, a_state->domain_state->domain_dn);
 
60
#define QUERY_PARAMETERS(msg, field, attr) \
 
61
        info->field = samdb_result_parameters(mem_ctx, msg, attr);
 
62
 
 
63
 
 
64
/* these are used to make the Set[User|Group]Info code easier to follow */
 
65
 
 
66
#define SET_STRING(msg, field, attr) do {                               \
 
67
        struct ldb_message_element *set_el;                             \
 
68
        if (r->in.info->field.string == NULL) return NT_STATUS_INVALID_PARAMETER; \
 
69
        if (r->in.info->field.string[0] == '\0') {                      \
 
70
                if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, NULL)) { \
 
71
                        return NT_STATUS_NO_MEMORY;                     \
 
72
                }                                                       \
 
73
        }                                                               \
 
74
        if (ldb_msg_add_string(msg, attr, r->in.info->field.string) != 0) { \
 
75
                return NT_STATUS_NO_MEMORY;                             \
 
76
        }                                                               \
 
77
        set_el = ldb_msg_find_element(msg, attr);                       \
 
78
        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
 
79
} while (0)
 
80
 
 
81
#define SET_UINT(msg, field, attr) do {                                 \
 
82
        struct ldb_message_element *set_el;                             \
 
83
        if (samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
 
84
                return NT_STATUS_NO_MEMORY;                             \
 
85
        }                                                               \
 
86
        set_el = ldb_msg_find_element(msg, attr);                       \
 
87
        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
 
88
} while (0)                                                             
 
89
                                                                        
 
90
#define SET_INT64(msg, field, attr) do {                                \
 
91
        struct ldb_message_element *set_el;                             \
 
92
        if (samdb_msg_add_int64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
 
93
                return NT_STATUS_NO_MEMORY;                             \
 
94
        }                                                               \
 
95
        set_el = ldb_msg_find_element(msg, attr);                       \
 
96
        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
 
97
} while (0)                                                             
 
98
                                                                        
 
99
#define SET_UINT64(msg, field, attr) do {                               \
 
100
        struct ldb_message_element *set_el;                             \
 
101
        if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
 
102
                return NT_STATUS_NO_MEMORY;                             \
 
103
        }                                                               \
 
104
        set_el = ldb_msg_find_element(msg, attr);                       \
 
105
        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
 
106
} while (0)                                                             
 
107
 
 
108
#define CHECK_FOR_MULTIPLES(value, flag, poss_flags)    \
 
109
        do { \
 
110
                if ((value & flag) && ((value & flag) != (value & (poss_flags)))) { \
 
111
                        return NT_STATUS_INVALID_PARAMETER;             \
 
112
                }                                                       \
 
113
        } while (0)                                                     \
 
114
        
 
115
/* Set account flags, discarding flags that cannot be set with SAMR */                                                          
 
116
#define SET_AFLAGS(msg, field, attr) do {                               \
 
117
        struct ldb_message_element *set_el;                             \
 
118
        if ((r->in.info->field & (ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST)) == 0) { \
 
119
                return NT_STATUS_INVALID_PARAMETER; \
 
120
        }                                                               \
 
121
        CHECK_FOR_MULTIPLES(r->in.info->field, ACB_NORMAL, ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); \
 
122
        CHECK_FOR_MULTIPLES(r->in.info->field, ACB_DOMTRUST, ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); \
 
123
        CHECK_FOR_MULTIPLES(r->in.info->field, ACB_WSTRUST, ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); \
 
124
        CHECK_FOR_MULTIPLES(r->in.info->field, ACB_SVRTRUST, ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST); \
 
125
        if (samdb_msg_add_acct_flags(sam_ctx, mem_ctx, msg, attr, (r->in.info->field & ~(ACB_AUTOLOCK|ACB_PW_EXPIRED))) != 0) { \
 
126
                return NT_STATUS_NO_MEMORY;                             \
 
127
        }                                                               \
 
128
        set_el = ldb_msg_find_element(msg, attr);                       \
 
129
        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
 
130
} while (0)                                                             
 
131
                                                                        
 
132
#define SET_LHOURS(msg, field, attr) do {                               \
 
133
        struct ldb_message_element *set_el;                             \
 
134
        if (samdb_msg_add_logon_hours(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
 
135
                return NT_STATUS_NO_MEMORY;                             \
 
136
        }                                                               \
 
137
        set_el = ldb_msg_find_element(msg, attr);                       \
 
138
        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
 
139
} while (0)
 
140
 
 
141
#define SET_PARAMETERS(msg, field, attr) do {                           \
 
142
        struct ldb_message_element *set_el;                             \
 
143
        if (r->in.info->field.length != 0) {                            \
 
144
                if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
 
145
                        return NT_STATUS_NO_MEMORY;                     \
 
146
                }                                                       \
 
147
                set_el = ldb_msg_find_element(msg, attr);               \
 
148
                set_el->flags = LDB_FLAG_MOD_REPLACE;                   \
 
149
        }                                                               \
 
150
} while (0)
 
151
 
 
152
 
 
153
 
 
154
/* 
 
155
  samr_Connect 
 
156
 
 
157
  create a connection to the SAM database
 
158
*/
 
159
static NTSTATUS dcesrv_samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
160
                             struct samr_Connect *r)
 
161
{
 
162
        struct samr_connect_state *c_state;
 
163
        struct dcesrv_handle *handle;
 
164
 
 
165
        ZERO_STRUCTP(r->out.connect_handle);
 
166
 
 
167
        c_state = talloc(dce_call->conn, struct samr_connect_state);
 
168
        if (!c_state) {
 
169
                return NT_STATUS_NO_MEMORY;
 
170
        }
 
171
 
 
172
        /* make sure the sam database is accessible */
 
173
        c_state->sam_ctx = samdb_connect(c_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 
 
174
        if (c_state->sam_ctx == NULL) {
 
175
                talloc_free(c_state);
 
176
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
 
177
        }
 
178
 
 
179
 
 
180
        handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_CONNECT);
 
181
        if (!handle) {
 
182
                talloc_free(c_state);
 
183
                return NT_STATUS_NO_MEMORY;
 
184
        }
 
185
 
 
186
        handle->data = talloc_steal(handle, c_state);
 
187
 
 
188
        c_state->access_mask = r->in.access_mask;
 
189
        *r->out.connect_handle = handle->wire_handle;
 
190
 
 
191
        return NT_STATUS_OK;
 
192
}
 
193
 
 
194
 
 
195
/* 
 
196
  samr_Close 
 
197
*/
 
198
static NTSTATUS dcesrv_samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
199
                           struct samr_Close *r)
 
200
{
 
201
        struct dcesrv_handle *h;
 
202
 
 
203
        *r->out.handle = *r->in.handle;
 
204
 
 
205
        DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
 
206
 
 
207
        talloc_free(h);
 
208
 
 
209
        ZERO_STRUCTP(r->out.handle);
 
210
 
 
211
        return NT_STATUS_OK;
 
212
}
 
213
 
 
214
 
 
215
/* 
 
216
  samr_SetSecurity 
 
217
*/
 
218
static NTSTATUS dcesrv_samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
219
                                 struct samr_SetSecurity *r)
 
220
{
 
221
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
222
}
 
223
 
 
224
 
 
225
/* 
 
226
  samr_QuerySecurity 
 
227
*/
 
228
static NTSTATUS dcesrv_samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
229
                                   struct samr_QuerySecurity *r)
 
230
{
 
231
        struct dcesrv_handle *h;
 
232
        struct sec_desc_buf *sd;
 
233
 
 
234
        *r->out.sdbuf = NULL;
 
235
 
 
236
        DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
 
237
 
 
238
        sd = talloc(mem_ctx, struct sec_desc_buf);
 
239
        if (sd == NULL) {
 
240
                return NT_STATUS_NO_MEMORY;
 
241
        }
 
242
 
 
243
        sd->sd = samdb_default_security_descriptor(mem_ctx);
 
244
 
 
245
        *r->out.sdbuf = sd;
 
246
 
 
247
        return NT_STATUS_OK;
 
248
}
 
249
 
 
250
 
 
251
/* 
 
252
  samr_Shutdown 
 
253
 
 
254
  we refuse this operation completely. If a admin wants to shutdown samr
 
255
  in Samba then they should use the samba admin tools to disable the samr pipe
 
256
*/
 
257
static NTSTATUS dcesrv_samr_Shutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
258
                              struct samr_Shutdown *r)
 
259
{
 
260
        return NT_STATUS_ACCESS_DENIED;
 
261
}
 
262
 
 
263
 
 
264
/* 
 
265
  samr_LookupDomain 
 
266
 
 
267
  this maps from a domain name to a SID
 
268
*/
 
269
static NTSTATUS dcesrv_samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
270
                                  struct samr_LookupDomain *r)
 
271
{
 
272
        struct samr_connect_state *c_state;
 
273
        struct dcesrv_handle *h;
 
274
        struct dom_sid *sid;
 
275
        const char * const dom_attrs[] = { "objectSid", NULL};
 
276
        const char * const ref_attrs[] = { "ncName", NULL};
 
277
        struct ldb_message **dom_msgs;
 
278
        struct ldb_message **ref_msgs;
 
279
        int ret;
 
280
        struct ldb_dn *partitions_basedn;
 
281
 
 
282
        *r->out.sid = NULL;
 
283
 
 
284
        DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
 
285
 
 
286
        c_state = h->data;
 
287
 
 
288
        if (r->in.domain_name->string == NULL) {
 
289
                return NT_STATUS_INVALID_PARAMETER;
 
290
        }
 
291
 
 
292
        partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
 
293
 
 
294
        if (strcasecmp(r->in.domain_name->string, "BUILTIN") == 0) {
 
295
                ret = gendb_search(c_state->sam_ctx,
 
296
                                   mem_ctx, NULL, &dom_msgs, dom_attrs,
 
297
                                   "(objectClass=builtinDomain)");
 
298
        } else {
 
299
                ret = gendb_search(c_state->sam_ctx,
 
300
                                   mem_ctx, partitions_basedn, &ref_msgs, ref_attrs,
 
301
                                   "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))", 
 
302
                                   ldb_binary_encode_string(mem_ctx, r->in.domain_name->string));
 
303
                if (ret != 1) {
 
304
                        return NT_STATUS_NO_SUCH_DOMAIN;
 
305
                }
 
306
                
 
307
                ret = gendb_search_dn(c_state->sam_ctx, mem_ctx, 
 
308
                                      samdb_result_dn(c_state->sam_ctx, mem_ctx,
 
309
                                                      ref_msgs[0], "ncName", NULL), 
 
310
                                      &dom_msgs, dom_attrs);
 
311
        }
 
312
 
 
313
        if (ret != 1) {
 
314
                return NT_STATUS_NO_SUCH_DOMAIN;
 
315
        }
 
316
        
 
317
        sid = samdb_result_dom_sid(mem_ctx, dom_msgs[0],
 
318
                                   "objectSid");
 
319
                
 
320
        if (sid == NULL) {
 
321
                return NT_STATUS_NO_SUCH_DOMAIN;
 
322
        }
 
323
 
 
324
        *r->out.sid = sid;
 
325
 
 
326
        return NT_STATUS_OK;
 
327
}
 
328
 
 
329
 
 
330
/* 
 
331
  samr_EnumDomains 
 
332
 
 
333
  list the domains in the SAM
 
334
*/
 
335
static NTSTATUS dcesrv_samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
336
                                 struct samr_EnumDomains *r)
 
337
{
 
338
        struct samr_connect_state *c_state;
 
339
        struct dcesrv_handle *h;
 
340
        struct samr_SamArray *array;
 
341
        int i, start_i, ret;
 
342
        const char * const dom_attrs[] = { "cn", NULL};
 
343
        const char * const ref_attrs[] = { "nETBIOSName", NULL};
 
344
        struct ldb_result *dom_res;
 
345
        struct ldb_result *ref_res;
 
346
        struct ldb_dn *partitions_basedn;
 
347
 
 
348
        *r->out.resume_handle = 0;
 
349
        *r->out.sam = NULL;
 
350
        *r->out.num_entries = 0;
 
351
 
 
352
        DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
 
353
 
 
354
        c_state = h->data;
 
355
 
 
356
        partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
 
357
 
 
358
        ret = ldb_search(c_state->sam_ctx, mem_ctx, &dom_res, ldb_get_default_basedn(c_state->sam_ctx),
 
359
                                 LDB_SCOPE_SUBTREE, dom_attrs, "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))");
 
360
        if (ret != LDB_SUCCESS) {
 
361
                DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx)));
 
362
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
363
        }
 
364
 
 
365
        *r->out.resume_handle = dom_res->count;
 
366
 
 
367
        start_i = *r->in.resume_handle;
 
368
 
 
369
        if (start_i >= dom_res->count) {
 
370
                /* search past end of list is not an error for this call */
 
371
                return NT_STATUS_OK;
 
372
        }
 
373
 
 
374
        array = talloc(mem_ctx, struct samr_SamArray);
 
375
        if (array == NULL) {
 
376
                return NT_STATUS_NO_MEMORY;
 
377
        }
 
378
                
 
379
        array->count = 0;
 
380
        array->entries = NULL;
 
381
 
 
382
        array->entries = talloc_array(mem_ctx, struct samr_SamEntry, dom_res->count - start_i);
 
383
        if (array->entries == NULL) {
 
384
                return NT_STATUS_NO_MEMORY;
 
385
        }
 
386
 
 
387
        for (i=0;i<dom_res->count-start_i;i++) {
 
388
                array->entries[i].idx = start_i + i;
 
389
                /* try and find the domain */
 
390
                ret = ldb_search(c_state->sam_ctx, mem_ctx, &ref_res, partitions_basedn,
 
391
                                         LDB_SCOPE_SUBTREE, ref_attrs, "(&(objectClass=crossRef)(ncName=%s))", 
 
392
                                         ldb_dn_get_linearized(dom_res->msgs[i]->dn));
 
393
 
 
394
                if (ret != LDB_SUCCESS) {
 
395
                        DEBUG(0,("samdb: unable to find domains: %s\n", ldb_errstring(c_state->sam_ctx)));
 
396
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
397
                }
 
398
 
 
399
                if (ref_res->count == 1) {
 
400
                        array->entries[i].name.string = samdb_result_string(ref_res->msgs[0], "nETBIOSName", NULL);
 
401
                } else {
 
402
                        array->entries[i].name.string = samdb_result_string(dom_res->msgs[i], "cn", NULL);
 
403
                }
 
404
        }
 
405
 
 
406
        *r->out.sam = array;
 
407
        *r->out.num_entries = i;
 
408
        array->count = *r->out.num_entries;
 
409
 
 
410
        return NT_STATUS_OK;
 
411
}
 
412
 
 
413
 
 
414
/* 
 
415
  samr_OpenDomain 
 
416
*/
 
417
static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
418
                                struct samr_OpenDomain *r)
 
419
{
 
420
        struct dcesrv_handle *h_conn, *h_domain;
 
421
        const char *domain_name;
 
422
        struct samr_connect_state *c_state;
 
423
        struct samr_domain_state *d_state;
 
424
        const char * const dom_attrs[] = { "cn", NULL};
 
425
        const char * const ref_attrs[] = { "nETBIOSName", NULL};
 
426
        struct ldb_message **dom_msgs;
 
427
        struct ldb_message **ref_msgs;
 
428
        int ret;
 
429
        struct ldb_dn *partitions_basedn;
 
430
 
 
431
        ZERO_STRUCTP(r->out.domain_handle);
 
432
 
 
433
        DCESRV_PULL_HANDLE(h_conn, r->in.connect_handle, SAMR_HANDLE_CONNECT);
 
434
 
 
435
        c_state = h_conn->data;
 
436
 
 
437
        if (r->in.sid == NULL) {
 
438
                return NT_STATUS_INVALID_PARAMETER;
 
439
        }
 
440
 
 
441
        partitions_basedn = samdb_partitions_dn(c_state->sam_ctx, mem_ctx);
 
442
 
 
443
        ret = gendb_search(c_state->sam_ctx,
 
444
                           mem_ctx, NULL, &dom_msgs, dom_attrs,
 
445
                           "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", 
 
446
                           ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
 
447
        if (ret == 0) {
 
448
                return NT_STATUS_NO_SUCH_DOMAIN;
 
449
        } else if (ret > 1) {
 
450
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
451
        } else if (ret == -1) {
 
452
                DEBUG(1, ("Failed to open domain %s: %s\n", dom_sid_string(mem_ctx, r->in.sid), ldb_errstring(c_state->sam_ctx)));
 
453
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
454
        } else {
 
455
                ret = gendb_search(c_state->sam_ctx,
 
456
                                   mem_ctx, partitions_basedn, &ref_msgs, ref_attrs,
 
457
                                   "(&(&(nETBIOSName=*)(objectclass=crossRef))(ncName=%s))", 
 
458
                                   ldb_dn_get_linearized(dom_msgs[0]->dn));
 
459
                if (ret == 0) {
 
460
                        domain_name = ldb_msg_find_attr_as_string(dom_msgs[0], "cn", NULL);
 
461
                        if (domain_name == NULL) {
 
462
                                return NT_STATUS_NO_SUCH_DOMAIN;
 
463
                        }
 
464
                } else if (ret == 1) {
 
465
                
 
466
                        domain_name = ldb_msg_find_attr_as_string(ref_msgs[0], "nETBIOSName", NULL);
 
467
                        if (domain_name == NULL) {
 
468
                                return NT_STATUS_NO_SUCH_DOMAIN;
 
469
                        }
 
470
                } else {
 
471
                        return NT_STATUS_NO_SUCH_DOMAIN;
 
472
                }
 
473
        }
 
474
 
 
475
        d_state = talloc(c_state, struct samr_domain_state);
 
476
        if (!d_state) {
 
477
                return NT_STATUS_NO_MEMORY;
 
478
        }
 
479
 
 
480
        d_state->role = lp_server_role(dce_call->conn->dce_ctx->lp_ctx);
 
481
        d_state->connect_state = talloc_reference(d_state, c_state);
 
482
        d_state->sam_ctx = c_state->sam_ctx;
 
483
        d_state->domain_sid = dom_sid_dup(d_state, r->in.sid);
 
484
        d_state->domain_name = talloc_strdup(d_state, domain_name);
 
485
        d_state->domain_dn = ldb_dn_copy(d_state, dom_msgs[0]->dn);
 
486
        if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) {
 
487
                talloc_free(d_state);
 
488
                return NT_STATUS_NO_MEMORY;             
 
489
        }
 
490
        d_state->access_mask = r->in.access_mask;
 
491
 
 
492
        if (dom_sid_equal(d_state->domain_sid, dom_sid_parse_talloc(mem_ctx, SID_BUILTIN))) {
 
493
                d_state->builtin = true;
 
494
        } else {
 
495
                d_state->builtin = false;
 
496
        }
 
497
 
 
498
        d_state->lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
 
499
 
 
500
        h_domain = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_DOMAIN);
 
501
        if (!h_domain) {
 
502
                talloc_free(d_state);
 
503
                return NT_STATUS_NO_MEMORY;
 
504
        }
 
505
        
 
506
        h_domain->data = talloc_steal(h_domain, d_state);
 
507
 
 
508
        *r->out.domain_handle = h_domain->wire_handle;
 
509
 
 
510
        return NT_STATUS_OK;
 
511
}
 
512
 
 
513
/*
 
514
  return DomInfo1
 
515
*/
 
516
static NTSTATUS dcesrv_samr_info_DomInfo1(struct samr_domain_state *state,
 
517
                                   TALLOC_CTX *mem_ctx,
 
518
                                    struct ldb_message **dom_msgs,
 
519
                                   struct samr_DomInfo1 *info)
 
520
{
 
521
        info->min_password_length =
 
522
                samdb_result_uint(dom_msgs[0], "minPwdLength", 0);
 
523
        info->password_history_length =
 
524
                samdb_result_uint(dom_msgs[0], "pwdHistoryLength", 0);
 
525
        info->password_properties = 
 
526
                samdb_result_uint(dom_msgs[0], "pwdProperties", 0);
 
527
        info->max_password_age = 
 
528
                samdb_result_int64(dom_msgs[0], "maxPwdAge", 0);
 
529
        info->min_password_age = 
 
530
                samdb_result_int64(dom_msgs[0], "minPwdAge", 0);
 
531
 
 
532
        return NT_STATUS_OK;
 
533
}
 
534
 
 
535
/*
 
536
  return DomInfo2
 
537
*/
 
538
static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state *state, 
 
539
                                                       TALLOC_CTX *mem_ctx,
 
540
                                                       struct ldb_message **dom_msgs,
 
541
                                                       struct samr_DomGeneralInformation *info)
 
542
{
 
543
        /* This pulls the NetBIOS name from the 
 
544
           cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
 
545
           string */
 
546
        info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, dom_msgs[0], "fSMORoleOwner");
 
547
 
 
548
        if (!info->primary.string) {
 
549
                info->primary.string = lp_netbios_name(state->lp_ctx);
 
550
        }
 
551
 
 
552
        info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 
 
553
                                                            0x8000000000000000LL);
 
554
 
 
555
        info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL);
 
556
        info->domain_name.string  = state->domain_name;
 
557
 
 
558
        info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 
 
559
                                                 0);
 
560
        switch (state->role) {
 
561
        case ROLE_DOMAIN_CONTROLLER:
 
562
                /* This pulls the NetBIOS name from the 
 
563
                   cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
 
564
                   string */
 
565
                if (samdb_is_pdc(state->sam_ctx)) {
 
566
                        info->role = SAMR_ROLE_DOMAIN_PDC;
 
567
                } else {
 
568
                        info->role = SAMR_ROLE_DOMAIN_BDC;
 
569
                }
 
570
                break;
 
571
        case ROLE_DOMAIN_MEMBER:
 
572
                info->role = SAMR_ROLE_DOMAIN_MEMBER;
 
573
                break;
 
574
        case ROLE_STANDALONE:
 
575
                info->role = SAMR_ROLE_STANDALONE;
 
576
                break;
 
577
        }
 
578
 
 
579
        /* No users in BUILTIN, and the LOCAL group types are only in builtin, and the global group type is never in BUILTIN */
 
580
        info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn, 
 
581
                                             "(objectClass=user)");
 
582
        info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
 
583
                                              "(&(objectClass=group)(sAMAccountType=%u))",
 
584
                                              ATYPE_GLOBAL_GROUP);
 
585
        info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
 
586
                                               "(&(objectClass=group)(sAMAccountType=%u))",
 
587
                                               ATYPE_LOCAL_GROUP);
 
588
 
 
589
        return NT_STATUS_OK;
 
590
}
 
591
 
 
592
/*
 
593
  return DomInfo3
 
594
*/
 
595
static NTSTATUS dcesrv_samr_info_DomInfo3(struct samr_domain_state *state,
 
596
                                   TALLOC_CTX *mem_ctx,
 
597
                                    struct ldb_message **dom_msgs,
 
598
                                   struct samr_DomInfo3 *info)
 
599
{
 
600
        info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 
 
601
                                                      0x8000000000000000LL);
 
602
 
 
603
        return NT_STATUS_OK;
 
604
}
 
605
 
 
606
/*
 
607
  return DomInfo4
 
608
*/
 
609
static NTSTATUS dcesrv_samr_info_DomOEMInformation(struct samr_domain_state *state,
 
610
                                   TALLOC_CTX *mem_ctx,
 
611
                                    struct ldb_message **dom_msgs,
 
612
                                   struct samr_DomOEMInformation *info)
 
613
{
 
614
        info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL);
 
615
 
 
616
        return NT_STATUS_OK;
 
617
}
 
618
 
 
619
/*
 
620
  return DomInfo5
 
621
*/
 
622
static NTSTATUS dcesrv_samr_info_DomInfo5(struct samr_domain_state *state,
 
623
                                   TALLOC_CTX *mem_ctx,
 
624
                                    struct ldb_message **dom_msgs,
 
625
                                   struct samr_DomInfo5 *info)
 
626
{
 
627
        info->domain_name.string  = state->domain_name;
 
628
 
 
629
        return NT_STATUS_OK;
 
630
}
 
631
 
 
632
/*
 
633
  return DomInfo6
 
634
*/
 
635
static NTSTATUS dcesrv_samr_info_DomInfo6(struct samr_domain_state *state,
 
636
                                   TALLOC_CTX *mem_ctx,
 
637
                                   struct ldb_message **dom_msgs,
 
638
                                   struct samr_DomInfo6 *info)
 
639
{
 
640
        /* This pulls the NetBIOS name from the 
 
641
           cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
 
642
           string */
 
643
        info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, 
 
644
                                                      dom_msgs[0], "fSMORoleOwner");
 
645
 
 
646
        if (!info->primary.string) {
 
647
                info->primary.string = lp_netbios_name(state->lp_ctx);
 
648
        }
 
649
 
 
650
        return NT_STATUS_OK;
 
651
}
 
652
 
 
653
/*
 
654
  return DomInfo7
 
655
*/
 
656
static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state,
 
657
                                   TALLOC_CTX *mem_ctx,
 
658
                                    struct ldb_message **dom_msgs,
 
659
                                   struct samr_DomInfo7 *info)
 
660
{
 
661
 
 
662
        switch (state->role) {
 
663
        case ROLE_DOMAIN_CONTROLLER:
 
664
                /* This pulls the NetBIOS name from the 
 
665
                   cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
 
666
                   string */
 
667
                if (samdb_is_pdc(state->sam_ctx)) {
 
668
                        info->role = SAMR_ROLE_DOMAIN_PDC;
 
669
                } else {
 
670
                        info->role = SAMR_ROLE_DOMAIN_BDC;
 
671
                }
 
672
                break;
 
673
        case ROLE_DOMAIN_MEMBER:
 
674
                info->role = SAMR_ROLE_DOMAIN_MEMBER;
 
675
                break;
 
676
        case ROLE_STANDALONE:
 
677
                info->role = SAMR_ROLE_STANDALONE;
 
678
                break;
 
679
        }
 
680
 
 
681
        return NT_STATUS_OK;
 
682
}
 
683
 
 
684
/*
 
685
  return DomInfo8
 
686
*/
 
687
static NTSTATUS dcesrv_samr_info_DomInfo8(struct samr_domain_state *state,
 
688
                                   TALLOC_CTX *mem_ctx,
 
689
                                    struct ldb_message **dom_msgs,
 
690
                                   struct samr_DomInfo8 *info)
 
691
{
 
692
        info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 
 
693
                                               time(NULL));
 
694
 
 
695
        info->domain_create_time = ldb_msg_find_attr_as_uint(dom_msgs[0], "creationTime",
 
696
                                                     0x0LL);
 
697
 
 
698
        return NT_STATUS_OK;
 
699
}
 
700
 
 
701
/*
 
702
  return DomInfo9
 
703
*/
 
704
static NTSTATUS dcesrv_samr_info_DomInfo9(struct samr_domain_state *state,
 
705
                                   TALLOC_CTX *mem_ctx,
 
706
                                    struct ldb_message **dom_msgs,
 
707
                                   struct samr_DomInfo9 *info)
 
708
{
 
709
        info->domain_server_state = DOMAIN_SERVER_ENABLED;
 
710
 
 
711
        return NT_STATUS_OK;
 
712
}
 
713
 
 
714
/*
 
715
  return DomInfo11
 
716
*/
 
717
static NTSTATUS dcesrv_samr_info_DomGeneralInformation2(struct samr_domain_state *state,
 
718
                                    TALLOC_CTX *mem_ctx,
 
719
                                    struct ldb_message **dom_msgs,
 
720
                                    struct samr_DomGeneralInformation2 *info)
 
721
{
 
722
        NTSTATUS status;
 
723
        status = dcesrv_samr_info_DomGeneralInformation(state, mem_ctx, dom_msgs, &info->general);
 
724
        if (!NT_STATUS_IS_OK(status)) {
 
725
                return status;
 
726
        }
 
727
        
 
728
        info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration", 
 
729
                                                    -18000000000LL);
 
730
        info->lockout_window = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockOutObservationWindow",
 
731
                                                    -18000000000LL);
 
732
        info->lockout_threshold = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutThreshold", 0);
 
733
 
 
734
        return NT_STATUS_OK;
 
735
}
 
736
 
 
737
/*
 
738
  return DomInfo12
 
739
*/
 
740
static NTSTATUS dcesrv_samr_info_DomInfo12(struct samr_domain_state *state,
 
741
                                   TALLOC_CTX *mem_ctx,
 
742
                                    struct ldb_message **dom_msgs,
 
743
                                   struct samr_DomInfo12 *info)
 
744
{
 
745
        info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration", 
 
746
                                                    -18000000000LL);
 
747
        info->lockout_window = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockOutObservationWindow",
 
748
                                                    -18000000000LL);
 
749
        info->lockout_threshold = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutThreshold", 0);
 
750
 
 
751
        return NT_STATUS_OK;
 
752
}
 
753
 
 
754
/*
 
755
  return DomInfo13
 
756
*/
 
757
static NTSTATUS dcesrv_samr_info_DomInfo13(struct samr_domain_state *state,
 
758
                                    TALLOC_CTX *mem_ctx,
 
759
                                    struct ldb_message **dom_msgs,
 
760
                                    struct samr_DomInfo13 *info)
 
761
{
 
762
        info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 
 
763
                                               time(NULL));
 
764
 
 
765
        info->domain_create_time = ldb_msg_find_attr_as_uint(dom_msgs[0], "creationTime",
 
766
                                                     0x0LL);
 
767
 
 
768
        info->modified_count_at_last_promotion = 0;
 
769
 
 
770
        return NT_STATUS_OK;
 
771
}
 
772
 
 
773
/* 
 
774
  samr_QueryDomainInfo 
 
775
*/
 
776
static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
777
                                     struct samr_QueryDomainInfo *r)
 
778
{
 
779
        struct dcesrv_handle *h;
 
780
        struct samr_domain_state *d_state;
 
781
        union samr_DomainInfo *info;
 
782
 
 
783
        struct ldb_message **dom_msgs;
 
784
        const char * const *attrs = NULL;
 
785
        
 
786
        *r->out.info = NULL;
 
787
 
 
788
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
789
 
 
790
        d_state = h->data;
 
791
 
 
792
        info = talloc(mem_ctx, union samr_DomainInfo);
 
793
        if (!info) {
 
794
                return NT_STATUS_NO_MEMORY;
 
795
        }
 
796
 
 
797
        switch (r->in.level) {
 
798
        case 1: 
 
799
        {
 
800
                static const char * const attrs2[] = { "minPwdLength", "pwdHistoryLength",
 
801
                                                       "pwdProperties", "maxPwdAge",
 
802
                                                       "minPwdAge", NULL };
 
803
                attrs = attrs2;
 
804
                break;
 
805
        }
 
806
        case 2:
 
807
        {
 
808
                static const char * const attrs2[] = {"forceLogoff",
 
809
                                                      "oEMInformation", 
 
810
                                                      "modifiedCount", 
 
811
                                                      "fSMORoleOwner",
 
812
                                                      NULL};
 
813
                attrs = attrs2;
 
814
                break;
 
815
        }
 
816
        case 3:
 
817
        {
 
818
                static const char * const attrs2[] = {"forceLogoff", 
 
819
                                                      NULL};
 
820
                attrs = attrs2;
 
821
                break;
 
822
        }
 
823
        case 4:
 
824
        {
 
825
                static const char * const attrs2[] = {"oEMInformation", 
 
826
                                                      NULL};
 
827
                attrs = attrs2;
 
828
                break;
 
829
        }
 
830
        case 5:
 
831
        {
 
832
                attrs = NULL;
 
833
                break;
 
834
        }
 
835
        case 6:
 
836
        {
 
837
                static const char * const attrs2[] = {"fSMORoleOwner", 
 
838
                                                      NULL};
 
839
                attrs = attrs2;
 
840
                break;
 
841
        }
 
842
        case 7:
 
843
        {
 
844
                attrs = NULL;
 
845
                break;
 
846
        }
 
847
        case 8:
 
848
        {
 
849
                static const char * const attrs2[] = { "modifiedCount", 
 
850
                                                       "creationTime", 
 
851
                                                       NULL };
 
852
                attrs = attrs2;
 
853
                break;
 
854
        }
 
855
        case 9:
 
856
                attrs = NULL;
 
857
                break;          
 
858
        case 11:
 
859
        {
 
860
                static const char * const attrs2[] = { "oEMInformation", "forceLogoff", 
 
861
                                                       "modifiedCount", 
 
862
                                                       "lockoutDuration", 
 
863
                                                       "lockOutObservationWindow", 
 
864
                                                       "lockoutThreshold", 
 
865
                                                       NULL};
 
866
                attrs = attrs2;
 
867
                break;
 
868
        }
 
869
        case 12:
 
870
        {
 
871
                static const char * const attrs2[] = { "lockoutDuration", 
 
872
                                                       "lockOutObservationWindow", 
 
873
                                                       "lockoutThreshold", 
 
874
                                                       NULL};
 
875
                attrs = attrs2;
 
876
                break;
 
877
        }
 
878
        case 13:
 
879
        {
 
880
                static const char * const attrs2[] = { "modifiedCount", 
 
881
                                                       "creationTime", 
 
882
                                                       NULL };
 
883
                attrs = attrs2;
 
884
                break;
 
885
        }
 
886
        }
 
887
 
 
888
        /* some levels don't need a search */
 
889
        if (attrs) {
 
890
                int ret;
 
891
                ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
 
892
                                      d_state->domain_dn, &dom_msgs, attrs);
 
893
                if (ret != 1) {
 
894
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
895
                }
 
896
        }
 
897
 
 
898
        *r->out.info = info;
 
899
 
 
900
        ZERO_STRUCTP(info);
 
901
 
 
902
        switch (r->in.level) {
 
903
        case 1:
 
904
                return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs, 
 
905
                                                 &info->info1);
 
906
        case 2:
 
907
                return dcesrv_samr_info_DomGeneralInformation(d_state, mem_ctx, dom_msgs, 
 
908
                                                              &info->general);
 
909
        case 3:
 
910
                return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs, 
 
911
                                                 &info->info3);
 
912
        case 4:
 
913
                return dcesrv_samr_info_DomOEMInformation(d_state, mem_ctx, dom_msgs, 
 
914
                                                          &info->oem);
 
915
        case 5:
 
916
                return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs, 
 
917
                                                 &info->info5);
 
918
        case 6:
 
919
                return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs, 
 
920
                                                 &info->info6);
 
921
        case 7:
 
922
                return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs, 
 
923
                                                 &info->info7);
 
924
        case 8:
 
925
                return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs, 
 
926
                                                 &info->info8);
 
927
        case 9:
 
928
                return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs, 
 
929
                                                 &info->info9);
 
930
        case 11:
 
931
                return dcesrv_samr_info_DomGeneralInformation2(d_state, mem_ctx, dom_msgs, 
 
932
                                                               &info->general2);
 
933
        case 12:
 
934
                return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs, 
 
935
                                                  &info->info12);
 
936
        case 13:
 
937
                return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs, 
 
938
                                                  &info->info13);
 
939
        }
 
940
 
 
941
        return NT_STATUS_INVALID_INFO_CLASS;
 
942
}
 
943
 
 
944
 
 
945
/* 
 
946
  samr_SetDomainInfo 
 
947
*/
 
948
static NTSTATUS dcesrv_samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
949
                       struct samr_SetDomainInfo *r)
 
950
{
 
951
        struct dcesrv_handle *h;
 
952
        struct samr_domain_state *d_state;
 
953
        struct ldb_message *msg;
 
954
        int ret;
 
955
        struct ldb_context *sam_ctx;
 
956
 
 
957
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
958
 
 
959
        d_state = h->data;
 
960
        sam_ctx = d_state->sam_ctx;
 
961
 
 
962
        msg = ldb_msg_new(mem_ctx);
 
963
        if (msg == NULL) {
 
964
                return NT_STATUS_NO_MEMORY;
 
965
        }
 
966
 
 
967
        msg->dn = talloc_reference(mem_ctx, d_state->domain_dn);
 
968
        if (!msg->dn) {
 
969
                return NT_STATUS_NO_MEMORY;
 
970
        }
 
971
 
 
972
        switch (r->in.level) {
 
973
        case 1:
 
974
                SET_UINT  (msg, info1.min_password_length,     "minPwdLength");
 
975
                SET_UINT  (msg, info1.password_history_length, "pwdHistoryLength");
 
976
                SET_UINT  (msg, info1.password_properties,     "pwdProperties");
 
977
                SET_INT64  (msg, info1.max_password_age,       "maxPwdAge");
 
978
                SET_INT64  (msg, info1.min_password_age,       "minPwdAge");
 
979
                break;
 
980
        case 3:
 
981
                SET_UINT64  (msg, info3.force_logoff_time,     "forceLogoff");
 
982
                break;
 
983
        case 4:
 
984
                SET_STRING(msg, oem.oem_information,           "oEMInformation");
 
985
                break;
 
986
 
 
987
        case 6:
 
988
        case 7:
 
989
        case 9:
 
990
                /* No op, we don't know where to set these */
 
991
                return NT_STATUS_OK;
 
992
 
 
993
        case 12:
 
994
                
 
995
                SET_INT64  (msg, info12.lockout_duration,      "lockoutDuration");
 
996
                SET_INT64  (msg, info12.lockout_window,        "lockOutObservationWindow");
 
997
                SET_INT64  (msg, info12.lockout_threshold,     "lockoutThreshold");
 
998
                break;
 
999
 
 
1000
        default:
 
1001
                /* many info classes are not valid for SetDomainInfo */
 
1002
                return NT_STATUS_INVALID_INFO_CLASS;
 
1003
        }
 
1004
 
 
1005
        /* modify the samdb record */
 
1006
        ret = ldb_modify(sam_ctx, msg);
 
1007
        if (ret != 0) {
 
1008
                DEBUG(1,("Failed to modify record %s: %s\n",
 
1009
                         ldb_dn_get_linearized(d_state->domain_dn),
 
1010
                         ldb_errstring(sam_ctx)));
 
1011
 
 
1012
                /* we really need samdb.c to return NTSTATUS */
 
1013
                return NT_STATUS_UNSUCCESSFUL;
 
1014
        }
 
1015
 
 
1016
        return NT_STATUS_OK;
 
1017
}
 
1018
 
 
1019
/* 
 
1020
  samr_CreateDomainGroup 
 
1021
*/
 
1022
static NTSTATUS dcesrv_samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1023
                                       struct samr_CreateDomainGroup *r)
 
1024
{
 
1025
        struct samr_domain_state *d_state;
 
1026
        struct samr_account_state *a_state;
 
1027
        struct dcesrv_handle *h;
 
1028
        const char *name;
 
1029
        struct ldb_message *msg;
 
1030
        struct dom_sid *sid;
 
1031
        const char *groupname;
 
1032
        struct dcesrv_handle *g_handle;
 
1033
        int ret;
 
1034
 
 
1035
        ZERO_STRUCTP(r->out.group_handle);
 
1036
        *r->out.rid = 0;
 
1037
 
 
1038
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1039
 
 
1040
        d_state = h->data;
 
1041
 
 
1042
        if (d_state->builtin) {
 
1043
                DEBUG(5, ("Cannot create a domain group in the BUILTIN domain"));
 
1044
                return NT_STATUS_ACCESS_DENIED;
 
1045
        }
 
1046
 
 
1047
        groupname = r->in.name->string;
 
1048
 
 
1049
        if (groupname == NULL) {
 
1050
                return NT_STATUS_INVALID_PARAMETER;
 
1051
        }
 
1052
 
 
1053
        /* check if the group already exists */
 
1054
        name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 
 
1055
                                   "sAMAccountName",
 
1056
                                   "(&(sAMAccountName=%s)(objectclass=group))",
 
1057
                                   ldb_binary_encode_string(mem_ctx, groupname));
 
1058
        if (name != NULL) {
 
1059
                return NT_STATUS_GROUP_EXISTS;
 
1060
        }
 
1061
 
 
1062
        msg = ldb_msg_new(mem_ctx);
 
1063
        if (msg == NULL) {
 
1064
                return NT_STATUS_NO_MEMORY;
 
1065
        }
 
1066
 
 
1067
        /* add core elements to the ldb_message for the user */
 
1068
        msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
 
1069
        ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname);
 
1070
        if (!msg->dn) {
 
1071
                return NT_STATUS_NO_MEMORY;
 
1072
        }
 
1073
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", groupname);
 
1074
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
 
1075
                             
 
1076
        /* create the group */
 
1077
        ret = ldb_add(d_state->sam_ctx, msg);
 
1078
        switch (ret) {
 
1079
        case  LDB_SUCCESS:
 
1080
                break;
 
1081
        case  LDB_ERR_ENTRY_ALREADY_EXISTS:
 
1082
                DEBUG(0,("Failed to create group record %s: %s\n",
 
1083
                         ldb_dn_get_linearized(msg->dn),
 
1084
                         ldb_errstring(d_state->sam_ctx)));
 
1085
                return NT_STATUS_GROUP_EXISTS;
 
1086
        case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
 
1087
                DEBUG(0,("Failed to create group record %s: %s\n",
 
1088
                         ldb_dn_get_linearized(msg->dn),
 
1089
                         ldb_errstring(d_state->sam_ctx)));
 
1090
                return NT_STATUS_ACCESS_DENIED;
 
1091
        default:
 
1092
                DEBUG(0,("Failed to create group record %s: %s\n",
 
1093
                         ldb_dn_get_linearized(msg->dn),
 
1094
                         ldb_errstring(d_state->sam_ctx)));
 
1095
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1096
        }
 
1097
 
 
1098
        a_state = talloc(d_state, struct samr_account_state);
 
1099
        if (!a_state) {
 
1100
                return NT_STATUS_NO_MEMORY;
 
1101
        }
 
1102
        a_state->sam_ctx = d_state->sam_ctx;
 
1103
        a_state->access_mask = r->in.access_mask;
 
1104
        a_state->domain_state = talloc_reference(a_state, d_state);
 
1105
        a_state->account_dn = talloc_steal(a_state, msg->dn);
 
1106
 
 
1107
        /* retrieve the sid for the group just created */
 
1108
        sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,
 
1109
                                   msg->dn, "objectSid", NULL);
 
1110
        if (sid == NULL) {
 
1111
                return NT_STATUS_UNSUCCESSFUL;
 
1112
        }
 
1113
 
 
1114
        a_state->account_name = talloc_strdup(a_state, groupname);
 
1115
        if (!a_state->account_name) {
 
1116
                return NT_STATUS_NO_MEMORY;
 
1117
        }
 
1118
 
 
1119
        /* create the policy handle */
 
1120
        g_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_GROUP);
 
1121
        if (!g_handle) {
 
1122
                return NT_STATUS_NO_MEMORY;
 
1123
        }
 
1124
 
 
1125
        g_handle->data = talloc_steal(g_handle, a_state);
 
1126
 
 
1127
        *r->out.group_handle = g_handle->wire_handle;
 
1128
        *r->out.rid = sid->sub_auths[sid->num_auths-1];
 
1129
 
 
1130
        return NT_STATUS_OK;
 
1131
}
 
1132
 
 
1133
 
 
1134
/*
 
1135
  comparison function for sorting SamEntry array
 
1136
*/
 
1137
static int compare_SamEntry(struct samr_SamEntry *e1, struct samr_SamEntry *e2)
 
1138
{
 
1139
        return e1->idx - e2->idx;
 
1140
}
 
1141
 
 
1142
/* 
 
1143
  samr_EnumDomainGroups 
 
1144
*/
 
1145
static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1146
                                      struct samr_EnumDomainGroups *r)
 
1147
{
 
1148
        struct dcesrv_handle *h;
 
1149
        struct samr_domain_state *d_state;
 
1150
        struct ldb_message **res;
 
1151
        int ldb_cnt, count, i, first;
 
1152
        struct samr_SamEntry *entries;
 
1153
        const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
 
1154
        struct samr_SamArray *sam;
 
1155
 
 
1156
        *r->out.resume_handle = 0;
 
1157
        *r->out.sam = NULL;
 
1158
        *r->out.num_entries = 0;
 
1159
 
 
1160
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1161
 
 
1162
        d_state = h->data;
 
1163
 
 
1164
        /* search for all domain groups in this domain. This could possibly be
 
1165
           cached and resumed based on resume_key */
 
1166
        ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
 
1167
                                      d_state->domain_dn, &res, attrs,
 
1168
                                      d_state->domain_sid,
 
1169
                                      "(&(grouptype=%d)(objectclass=group))",
 
1170
                                      GTYPE_SECURITY_GLOBAL_GROUP);
 
1171
        if (ldb_cnt == -1) {
 
1172
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1173
        }
 
1174
 
 
1175
        /* convert to SamEntry format */
 
1176
        entries = talloc_array(mem_ctx, struct samr_SamEntry, ldb_cnt);
 
1177
        if (!entries) {
 
1178
                return NT_STATUS_NO_MEMORY;
 
1179
        }
 
1180
 
 
1181
        count = 0;
 
1182
 
 
1183
        for (i=0;i<ldb_cnt;i++) {
 
1184
                struct dom_sid *group_sid;
 
1185
 
 
1186
                group_sid = samdb_result_dom_sid(mem_ctx, res[i],
 
1187
                                                 "objectSid");
 
1188
                if (group_sid == NULL)
 
1189
                        continue;
 
1190
 
 
1191
                entries[count].idx =
 
1192
                        group_sid->sub_auths[group_sid->num_auths-1];
 
1193
                entries[count].name.string =
 
1194
                        samdb_result_string(res[i], "sAMAccountName", "");
 
1195
                count += 1;
 
1196
        }
 
1197
 
 
1198
        /* sort the results by rid */
 
1199
        qsort(entries, count, sizeof(struct samr_SamEntry), 
 
1200
              (comparison_fn_t)compare_SamEntry);
 
1201
 
 
1202
        /* find the first entry to return */
 
1203
        for (first=0;
 
1204
             first<count && entries[first].idx <= *r->in.resume_handle;
 
1205
             first++) ;
 
1206
 
 
1207
        /* return the rest, limit by max_size. Note that we 
 
1208
           use the w2k3 element size value of 54 */
 
1209
        *r->out.num_entries = count - first;
 
1210
        *r->out.num_entries = MIN(*r->out.num_entries,
 
1211
                                 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
 
1212
 
 
1213
        sam = talloc(mem_ctx, struct samr_SamArray);
 
1214
        if (!sam) {
 
1215
                return NT_STATUS_NO_MEMORY;
 
1216
        }
 
1217
 
 
1218
        sam->entries = entries+first;
 
1219
        sam->count = *r->out.num_entries;
 
1220
 
 
1221
        *r->out.sam = sam;
 
1222
 
 
1223
        if (*r->out.num_entries < count - first) {
 
1224
                *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx;
 
1225
                return STATUS_MORE_ENTRIES;
 
1226
        }
 
1227
 
 
1228
        return NT_STATUS_OK;
 
1229
}
 
1230
 
 
1231
 
 
1232
/* 
 
1233
  samr_CreateUser2 
 
1234
 
 
1235
  This call uses transactions to ensure we don't get a new conflicting
 
1236
  user while we are processing this, and to ensure the user either
 
1237
  completly exists, or does not.
 
1238
*/
 
1239
static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1240
                                 struct samr_CreateUser2 *r)
 
1241
{
 
1242
        struct samr_domain_state *d_state;
 
1243
        struct samr_account_state *a_state;
 
1244
        struct dcesrv_handle *h;
 
1245
        const char *name;
 
1246
        struct ldb_message *msg;
 
1247
        struct dom_sid *sid;
 
1248
        const char *account_name;
 
1249
        struct dcesrv_handle *u_handle;
 
1250
        int ret;
 
1251
        const char *container, *obj_class=NULL;
 
1252
        char *cn_name;
 
1253
        int cn_name_len;
 
1254
 
 
1255
        const char *attrs[] = {
 
1256
                "objectSid", 
 
1257
                "userAccountControl",
 
1258
                NULL
 
1259
        };
 
1260
 
 
1261
        uint32_t user_account_control;
 
1262
 
 
1263
        struct ldb_message **msgs;
 
1264
 
 
1265
        ZERO_STRUCTP(r->out.user_handle);
 
1266
        *r->out.access_granted = 0;
 
1267
        *r->out.rid = 0;
 
1268
 
 
1269
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1270
 
 
1271
        d_state = h->data;
 
1272
 
 
1273
        if (d_state->builtin) {
 
1274
                DEBUG(5, ("Cannot create a user in the BUILTIN domain"));
 
1275
                return NT_STATUS_ACCESS_DENIED;
 
1276
        }
 
1277
        account_name = r->in.account_name->string;
 
1278
 
 
1279
        if (account_name == NULL) {
 
1280
                return NT_STATUS_INVALID_PARAMETER;
 
1281
        }
 
1282
 
 
1283
        ret = ldb_transaction_start(d_state->sam_ctx);
 
1284
        if (ret != 0) {
 
1285
                DEBUG(0,("Failed to start a transaction for user creation: %s\n",
 
1286
                         ldb_errstring(d_state->sam_ctx)));
 
1287
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1288
        }
 
1289
 
 
1290
        /* check if the user already exists */
 
1291
        name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 
 
1292
                                   "sAMAccountName", 
 
1293
                                   "(&(sAMAccountName=%s)(objectclass=user))", 
 
1294
                                   ldb_binary_encode_string(mem_ctx, account_name));
 
1295
        if (name != NULL) {
 
1296
                ldb_transaction_cancel(d_state->sam_ctx);
 
1297
                return NT_STATUS_USER_EXISTS;
 
1298
        }
 
1299
 
 
1300
        msg = ldb_msg_new(mem_ctx);
 
1301
        if (msg == NULL) {
 
1302
                ldb_transaction_cancel(d_state->sam_ctx);
 
1303
                return NT_STATUS_NO_MEMORY;
 
1304
        }
 
1305
 
 
1306
        cn_name   = talloc_strdup(mem_ctx, account_name);
 
1307
        if (!cn_name) {
 
1308
                ldb_transaction_cancel(d_state->sam_ctx);
 
1309
                return NT_STATUS_NO_MEMORY;
 
1310
        }
 
1311
 
 
1312
        cn_name_len = strlen(cn_name);
 
1313
 
 
1314
        /* This must be one of these values *only* */
 
1315
        if (r->in.acct_flags == ACB_NORMAL) {
 
1316
                container = "CN=Users";
 
1317
                obj_class = "user";
 
1318
 
 
1319
        } else if (r->in.acct_flags == ACB_WSTRUST) {
 
1320
                if (cn_name[cn_name_len - 1] != '$') {
 
1321
                        return NT_STATUS_FOOBAR;
 
1322
                }
 
1323
                cn_name[cn_name_len - 1] = '\0';
 
1324
                container = "CN=Computers";
 
1325
                obj_class = "computer";
 
1326
                samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DOMAIN_MEMBERS);
 
1327
 
 
1328
        } else if (r->in.acct_flags == ACB_SVRTRUST) {
 
1329
                if (cn_name[cn_name_len - 1] != '$') {
 
1330
                        return NT_STATUS_FOOBAR;                
 
1331
                }
 
1332
                cn_name[cn_name_len - 1] = '\0';
 
1333
                container = "OU=Domain Controllers";
 
1334
                obj_class = "computer";
 
1335
                samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DCS);
 
1336
 
 
1337
        } else if (r->in.acct_flags == ACB_DOMTRUST) {
 
1338
                container = "CN=Users";
 
1339
                obj_class = "user";
 
1340
 
 
1341
        } else {
 
1342
                ldb_transaction_cancel(d_state->sam_ctx);
 
1343
                return NT_STATUS_INVALID_PARAMETER;
 
1344
        }
 
1345
 
 
1346
        /* add core elements to the ldb_message for the user */
 
1347
        msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
 
1348
        if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) {
 
1349
                ldb_transaction_cancel(d_state->sam_ctx);
 
1350
                return NT_STATUS_FOOBAR;
 
1351
        }
 
1352
 
 
1353
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", account_name);
 
1354
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", obj_class);
 
1355
        
 
1356
        /* Start a transaction, so we can query and do a subsequent atomic modify */
 
1357
        
 
1358
        /* create the user */
 
1359
        ret = ldb_add(d_state->sam_ctx, msg);
 
1360
        switch (ret) {
 
1361
        case LDB_SUCCESS:
 
1362
                break;
 
1363
        case LDB_ERR_ENTRY_ALREADY_EXISTS:
 
1364
                ldb_transaction_cancel(d_state->sam_ctx);
 
1365
                DEBUG(0,("Failed to create user record %s: %s\n",
 
1366
                         ldb_dn_get_linearized(msg->dn),
 
1367
                         ldb_errstring(d_state->sam_ctx)));
 
1368
                return NT_STATUS_USER_EXISTS;
 
1369
        case LDB_ERR_UNWILLING_TO_PERFORM:
 
1370
        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
 
1371
                ldb_transaction_cancel(d_state->sam_ctx);
 
1372
                DEBUG(0,("Failed to create user record %s: %s\n",
 
1373
                         ldb_dn_get_linearized(msg->dn),
 
1374
                         ldb_errstring(d_state->sam_ctx)));
 
1375
                return NT_STATUS_ACCESS_DENIED;
 
1376
        default:
 
1377
                ldb_transaction_cancel(d_state->sam_ctx);
 
1378
                DEBUG(0,("Failed to create user record %s: %s\n",
 
1379
                         ldb_dn_get_linearized(msg->dn),
 
1380
                         ldb_errstring(d_state->sam_ctx)));
 
1381
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1382
        }
 
1383
 
 
1384
        a_state = talloc(d_state, struct samr_account_state);
 
1385
        if (!a_state) {
 
1386
                ldb_transaction_cancel(d_state->sam_ctx);
 
1387
                return NT_STATUS_NO_MEMORY;
 
1388
        }
 
1389
        a_state->sam_ctx = d_state->sam_ctx;
 
1390
        a_state->access_mask = r->in.access_mask;
 
1391
        a_state->domain_state = talloc_reference(a_state, d_state);
 
1392
        a_state->account_dn = talloc_steal(a_state, msg->dn);
 
1393
 
 
1394
        /* retrieve the sid and account control bits for the user just created */
 
1395
        ret = gendb_search_dn(d_state->sam_ctx, a_state,
 
1396
                              msg->dn, &msgs, attrs);
 
1397
 
 
1398
        if (ret != 1) {
 
1399
                ldb_transaction_cancel(d_state->sam_ctx);
 
1400
                DEBUG(0,("Apparently we failed to create an account record, as %s now doesn't exist\n",
 
1401
                         ldb_dn_get_linearized(msg->dn)));
 
1402
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1403
        }
 
1404
        sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid");
 
1405
        if (sid == NULL) {
 
1406
                ldb_transaction_cancel(d_state->sam_ctx);
 
1407
                DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n",
 
1408
                         ldb_dn_get_linearized(msg->dn)));
 
1409
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1410
        }
 
1411
 
 
1412
        /* Change the account control to be the correct account type.
 
1413
         * The default is for a workstation account */
 
1414
        user_account_control = samdb_result_uint(msgs[0], "userAccountControl", 0);
 
1415
        user_account_control = (user_account_control & 
 
1416
                                ~(UF_NORMAL_ACCOUNT |
 
1417
                                  UF_INTERDOMAIN_TRUST_ACCOUNT | 
 
1418
                                  UF_WORKSTATION_TRUST_ACCOUNT | 
 
1419
                                  UF_SERVER_TRUST_ACCOUNT));
 
1420
        user_account_control |= samdb_acb2uf(r->in.acct_flags);
 
1421
 
 
1422
        talloc_free(msg);
 
1423
        msg = ldb_msg_new(mem_ctx);
 
1424
        if (msg == NULL) {
 
1425
                ldb_transaction_cancel(d_state->sam_ctx);
 
1426
                return NT_STATUS_NO_MEMORY;
 
1427
        }
 
1428
 
 
1429
        msg->dn = ldb_dn_copy(msg, a_state->account_dn);
 
1430
 
 
1431
        if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, msg, 
 
1432
                               "userAccountControl", 
 
1433
                               user_account_control) != 0) { 
 
1434
                ldb_transaction_cancel(d_state->sam_ctx);
 
1435
                return NT_STATUS_NO_MEMORY; 
 
1436
        }
 
1437
 
 
1438
        /* modify the samdb record */
 
1439
        ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
 
1440
        if (ret != 0) {
 
1441
                DEBUG(0,("Failed to modify account record %s to set userAccountControl: %s\n",
 
1442
                         ldb_dn_get_linearized(msg->dn),
 
1443
                         ldb_errstring(d_state->sam_ctx)));
 
1444
                ldb_transaction_cancel(d_state->sam_ctx);
 
1445
 
 
1446
                /* we really need samdb.c to return NTSTATUS */
 
1447
                return NT_STATUS_UNSUCCESSFUL;
 
1448
        }
 
1449
 
 
1450
        ret = ldb_transaction_commit(d_state->sam_ctx);
 
1451
        if (ret != 0) {
 
1452
                DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
 
1453
                         ldb_dn_get_linearized(msg->dn),
 
1454
                         ldb_errstring(d_state->sam_ctx)));
 
1455
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1456
        }
 
1457
 
 
1458
        a_state->account_name = talloc_steal(a_state, account_name);
 
1459
        if (!a_state->account_name) {
 
1460
                return NT_STATUS_NO_MEMORY;
 
1461
        }
 
1462
 
 
1463
        /* create the policy handle */
 
1464
        u_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_USER);
 
1465
        if (!u_handle) {
 
1466
                return NT_STATUS_NO_MEMORY;
 
1467
        }
 
1468
 
 
1469
        u_handle->data = talloc_steal(u_handle, a_state);
 
1470
 
 
1471
        *r->out.user_handle = u_handle->wire_handle;
 
1472
        *r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
 
1473
 
 
1474
        *r->out.rid = sid->sub_auths[sid->num_auths-1];
 
1475
 
 
1476
        return NT_STATUS_OK;
 
1477
}
 
1478
 
 
1479
 
 
1480
/* 
 
1481
  samr_CreateUser 
 
1482
*/
 
1483
static NTSTATUS dcesrv_samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1484
                                struct samr_CreateUser *r)
 
1485
{
 
1486
        struct samr_CreateUser2 r2;
 
1487
        uint32_t access_granted = 0;
 
1488
 
 
1489
 
 
1490
        /* a simple wrapper around samr_CreateUser2 works nicely */
 
1491
        r2.in.domain_handle = r->in.domain_handle;
 
1492
        r2.in.account_name = r->in.account_name;
 
1493
        r2.in.acct_flags = ACB_NORMAL;
 
1494
        r2.in.access_mask = r->in.access_mask;
 
1495
        r2.out.user_handle = r->out.user_handle;
 
1496
        r2.out.access_granted = &access_granted;
 
1497
        r2.out.rid = r->out.rid;
 
1498
 
 
1499
        return dcesrv_samr_CreateUser2(dce_call, mem_ctx, &r2);
 
1500
}
 
1501
 
 
1502
/* 
 
1503
  samr_EnumDomainUsers 
 
1504
*/
 
1505
static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1506
                                     struct samr_EnumDomainUsers *r)
 
1507
{
 
1508
        struct dcesrv_handle *h;
 
1509
        struct samr_domain_state *d_state;
 
1510
        struct ldb_result *res;
 
1511
        int ret, num_filtered_entries, i, first;
 
1512
        struct samr_SamEntry *entries;
 
1513
        const char * const attrs[] = { "objectSid", "sAMAccountName", "userAccountControl", NULL };
 
1514
        struct samr_SamArray *sam;
 
1515
 
 
1516
        *r->out.resume_handle = 0;
 
1517
        *r->out.sam = NULL;
 
1518
        *r->out.num_entries = 0;
 
1519
 
 
1520
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1521
 
 
1522
        d_state = h->data;
 
1523
        
 
1524
        /* don't have to worry about users in the builtin domain, as there are none */
 
1525
        ret = ldb_search(d_state->sam_ctx, mem_ctx, &res, d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=user");
 
1526
 
 
1527
        if (ret != LDB_SUCCESS) {
 
1528
                DEBUG(3, ("Failed to search for Domain Users in %s: %s\n", 
 
1529
                          ldb_dn_get_linearized(d_state->domain_dn), ldb_errstring(d_state->sam_ctx)));
 
1530
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1531
        }
 
1532
 
 
1533
        /* convert to SamEntry format */
 
1534
        entries = talloc_array(mem_ctx, struct samr_SamEntry, res->count);
 
1535
        if (!entries) {
 
1536
                return NT_STATUS_NO_MEMORY;
 
1537
        }
 
1538
        num_filtered_entries = 0;
 
1539
        for (i=0;i<res->count;i++) {
 
1540
                /* Check if a mask has been requested */
 
1541
                if (r->in.acct_flags
 
1542
                    && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, res->msgs[i], 
 
1543
                                                 d_state->domain_dn) & r->in.acct_flags) == 0)) {
 
1544
                        continue;
 
1545
                }
 
1546
                entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res->msgs[i], "objectSid", 0);
 
1547
                entries[num_filtered_entries].name.string = samdb_result_string(res->msgs[i], "sAMAccountName", "");
 
1548
                num_filtered_entries++;
 
1549
        }
 
1550
 
 
1551
        /* sort the results by rid */
 
1552
        qsort(entries, num_filtered_entries, sizeof(struct samr_SamEntry), 
 
1553
              (comparison_fn_t)compare_SamEntry);
 
1554
 
 
1555
        /* find the first entry to return */
 
1556
        for (first=0;
 
1557
             first<num_filtered_entries && entries[first].idx <= *r->in.resume_handle;
 
1558
             first++) ;
 
1559
 
 
1560
        /* return the rest, limit by max_size. Note that we 
 
1561
           use the w2k3 element size value of 54 */
 
1562
        *r->out.num_entries = num_filtered_entries - first;
 
1563
        *r->out.num_entries = MIN(*r->out.num_entries,
 
1564
                                 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
 
1565
 
 
1566
        sam = talloc(mem_ctx, struct samr_SamArray);
 
1567
        if (!sam) {
 
1568
                return NT_STATUS_NO_MEMORY;
 
1569
        }
 
1570
 
 
1571
        sam->entries = entries+first;
 
1572
        sam->count = *r->out.num_entries;
 
1573
 
 
1574
        *r->out.sam = sam;
 
1575
 
 
1576
        if (first == num_filtered_entries) {
 
1577
                return NT_STATUS_OK;
 
1578
        }
 
1579
 
 
1580
        if (*r->out.num_entries < num_filtered_entries - first) {
 
1581
                *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx;
 
1582
                return STATUS_MORE_ENTRIES;
 
1583
        }
 
1584
 
 
1585
        return NT_STATUS_OK;
 
1586
}
 
1587
 
 
1588
 
 
1589
/* 
 
1590
  samr_CreateDomAlias 
 
1591
*/
 
1592
static NTSTATUS dcesrv_samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1593
                       struct samr_CreateDomAlias *r)
 
1594
{
 
1595
        struct samr_domain_state *d_state;
 
1596
        struct samr_account_state *a_state;
 
1597
        struct dcesrv_handle *h;
 
1598
        const char *alias_name, *name;
 
1599
        struct ldb_message *msg;
 
1600
        struct dom_sid *sid;
 
1601
        struct dcesrv_handle *a_handle;
 
1602
        int ret;
 
1603
 
 
1604
        ZERO_STRUCTP(r->out.alias_handle);
 
1605
        *r->out.rid = 0;
 
1606
 
 
1607
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1608
 
 
1609
        d_state = h->data;
 
1610
 
 
1611
        if (d_state->builtin) {
 
1612
                DEBUG(5, ("Cannot create a domain alias in the BUILTIN domain"));
 
1613
                return NT_STATUS_ACCESS_DENIED;
 
1614
        }
 
1615
 
 
1616
        alias_name = r->in.alias_name->string;
 
1617
 
 
1618
        if (alias_name == NULL) {
 
1619
                return NT_STATUS_INVALID_PARAMETER;
 
1620
        }
 
1621
 
 
1622
        /* Check if alias already exists */
 
1623
        name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
 
1624
                                   "sAMAccountName",
 
1625
                                   "(sAMAccountName=%s)(objectclass=group))",
 
1626
                                   ldb_binary_encode_string(mem_ctx, alias_name));
 
1627
 
 
1628
        if (name != NULL) {
 
1629
                return NT_STATUS_ALIAS_EXISTS;
 
1630
        }
 
1631
 
 
1632
        msg = ldb_msg_new(mem_ctx);
 
1633
        if (msg == NULL) {
 
1634
                return NT_STATUS_NO_MEMORY;
 
1635
        }
 
1636
 
 
1637
        /* add core elements to the ldb_message for the alias */
 
1638
        msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
 
1639
        ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", alias_name);
 
1640
        if (!msg->dn) {
 
1641
                return NT_STATUS_NO_MEMORY;
 
1642
        }
 
1643
 
 
1644
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", alias_name);
 
1645
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
 
1646
        samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "groupType", GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
 
1647
 
 
1648
        /* create the alias */
 
1649
        ret = ldb_add(d_state->sam_ctx, msg);
 
1650
        switch (ret) {
 
1651
        case LDB_SUCCESS:
 
1652
                break;
 
1653
        case LDB_ERR_ENTRY_ALREADY_EXISTS:
 
1654
                return NT_STATUS_ALIAS_EXISTS;
 
1655
        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
 
1656
                return NT_STATUS_ACCESS_DENIED;
 
1657
        default:
 
1658
                DEBUG(0,("Failed to create alias record %s: %s\n",
 
1659
                         ldb_dn_get_linearized(msg->dn),
 
1660
                         ldb_errstring(d_state->sam_ctx)));
 
1661
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1662
        }
 
1663
 
 
1664
        a_state = talloc(d_state, struct samr_account_state);
 
1665
        if (!a_state) {
 
1666
                return NT_STATUS_NO_MEMORY;
 
1667
        }
 
1668
 
 
1669
        a_state->sam_ctx = d_state->sam_ctx;
 
1670
        a_state->access_mask = r->in.access_mask;
 
1671
        a_state->domain_state = talloc_reference(a_state, d_state);
 
1672
        a_state->account_dn = talloc_steal(a_state, msg->dn);
 
1673
 
 
1674
        /* retrieve the sid for the alias just created */
 
1675
        sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,
 
1676
                                   msg->dn, "objectSid", NULL);
 
1677
 
 
1678
        a_state->account_name = talloc_strdup(a_state, alias_name);
 
1679
        if (!a_state->account_name) {
 
1680
                return NT_STATUS_NO_MEMORY;
 
1681
        }
 
1682
 
 
1683
        /* create the policy handle */
 
1684
        a_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_ALIAS);
 
1685
        if (a_handle == NULL)
 
1686
                return NT_STATUS_NO_MEMORY;
 
1687
 
 
1688
        a_handle->data = talloc_steal(a_handle, a_state);
 
1689
 
 
1690
        *r->out.alias_handle = a_handle->wire_handle;
 
1691
 
 
1692
        *r->out.rid = sid->sub_auths[sid->num_auths-1];
 
1693
 
 
1694
        return NT_STATUS_OK;
 
1695
}
 
1696
 
 
1697
 
 
1698
/* 
 
1699
  samr_EnumDomainAliases 
 
1700
*/
 
1701
static NTSTATUS dcesrv_samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1702
                       struct samr_EnumDomainAliases *r)
 
1703
{
 
1704
        struct dcesrv_handle *h;
 
1705
        struct samr_domain_state *d_state;
 
1706
        struct ldb_message **res;
 
1707
        int ldb_cnt, count, i, first;
 
1708
        struct samr_SamEntry *entries;
 
1709
        const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
 
1710
        struct samr_SamArray *sam;
 
1711
 
 
1712
        *r->out.resume_handle = 0;
 
1713
        *r->out.sam = NULL;
 
1714
        *r->out.num_entries = 0;
 
1715
 
 
1716
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1717
 
 
1718
        d_state = h->data;
 
1719
 
 
1720
        /* search for all domain groups in this domain. This could possibly be
 
1721
           cached and resumed based on resume_key */
 
1722
        ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
 
1723
                                      d_state->domain_dn,
 
1724
                                      &res, attrs, 
 
1725
                                      d_state->domain_sid,
 
1726
                                      "(&(|(grouptype=%d)(grouptype=%d)))"
 
1727
                                      "(objectclass=group))",
 
1728
                                      GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
 
1729
                                      GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
 
1730
        if (ldb_cnt == -1) {
 
1731
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1732
        }
 
1733
        if (ldb_cnt == 0) {
 
1734
                return NT_STATUS_OK;
 
1735
        }
 
1736
 
 
1737
        /* convert to SamEntry format */
 
1738
        entries = talloc_array(mem_ctx, struct samr_SamEntry, ldb_cnt);
 
1739
        if (!entries) {
 
1740
                return NT_STATUS_NO_MEMORY;
 
1741
        }
 
1742
 
 
1743
        count = 0;
 
1744
 
 
1745
        for (i=0;i<ldb_cnt;i++) {
 
1746
                struct dom_sid *alias_sid;
 
1747
 
 
1748
                alias_sid = samdb_result_dom_sid(mem_ctx, res[i],
 
1749
                                                 "objectSid");
 
1750
 
 
1751
                if (alias_sid == NULL)
 
1752
                        continue;
 
1753
 
 
1754
                entries[count].idx =
 
1755
                        alias_sid->sub_auths[alias_sid->num_auths-1];
 
1756
                entries[count].name.string =
 
1757
                        samdb_result_string(res[i], "sAMAccountName", "");
 
1758
                count += 1;
 
1759
        }
 
1760
 
 
1761
        /* sort the results by rid */
 
1762
        qsort(entries, count, sizeof(struct samr_SamEntry), 
 
1763
              (comparison_fn_t)compare_SamEntry);
 
1764
 
 
1765
        /* find the first entry to return */
 
1766
        for (first=0;
 
1767
             first<count && entries[first].idx <= *r->in.resume_handle;
 
1768
             first++) ;
 
1769
 
 
1770
        if (first == count) {
 
1771
                return NT_STATUS_OK;
 
1772
        }
 
1773
 
 
1774
        *r->out.num_entries = count - first;
 
1775
        *r->out.num_entries = MIN(*r->out.num_entries, 1000);
 
1776
 
 
1777
        sam = talloc(mem_ctx, struct samr_SamArray);
 
1778
        if (!sam) {
 
1779
                return NT_STATUS_NO_MEMORY;
 
1780
        }
 
1781
 
 
1782
        sam->entries = entries+first;
 
1783
        sam->count = *r->out.num_entries;
 
1784
 
 
1785
        *r->out.sam = sam;
 
1786
 
 
1787
        if (*r->out.num_entries < count - first) {
 
1788
                *r->out.resume_handle =
 
1789
                        entries[first+*r->out.num_entries-1].idx;
 
1790
                return STATUS_MORE_ENTRIES;
 
1791
        }
 
1792
 
 
1793
        return NT_STATUS_OK;
 
1794
}
 
1795
 
 
1796
 
 
1797
/* 
 
1798
  samr_GetAliasMembership 
 
1799
*/
 
1800
static NTSTATUS dcesrv_samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1801
                       struct samr_GetAliasMembership *r)
 
1802
{
 
1803
        struct dcesrv_handle *h;
 
1804
        struct samr_domain_state *d_state;
 
1805
        struct ldb_message **res;
 
1806
        int i, count = 0;
 
1807
 
 
1808
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1809
 
 
1810
        d_state = h->data;
 
1811
 
 
1812
        if (r->in.sids->num_sids > 0) {
 
1813
                const char *filter;
 
1814
                const char * const attrs[2] = { "objectSid", NULL };
 
1815
 
 
1816
                filter = talloc_asprintf(mem_ctx,
 
1817
                                         "(&(|(grouptype=%d)(grouptype=%d))"
 
1818
                                         "(objectclass=group)(|",
 
1819
                                         GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
 
1820
                                         GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
 
1821
                if (filter == NULL)
 
1822
                        return NT_STATUS_NO_MEMORY;
 
1823
 
 
1824
                for (i=0; i<r->in.sids->num_sids; i++) {
 
1825
                        const char *memberdn;
 
1826
 
 
1827
                        memberdn = 
 
1828
                                samdb_search_string(d_state->sam_ctx,
 
1829
                                                    mem_ctx, NULL, "distinguishedName",
 
1830
                                                    "(objectSid=%s)",
 
1831
                                                    ldap_encode_ndr_dom_sid(mem_ctx, 
 
1832
                                                                            r->in.sids->sids[i].sid));
 
1833
 
 
1834
                        if (memberdn == NULL)
 
1835
                                continue;
 
1836
 
 
1837
                        filter = talloc_asprintf(mem_ctx, "%s(member=%s)",
 
1838
                                                 filter, memberdn);
 
1839
                        if (filter == NULL)
 
1840
                                return NT_STATUS_NO_MEMORY;
 
1841
                }
 
1842
 
 
1843
                count = samdb_search_domain(d_state->sam_ctx, mem_ctx,
 
1844
                                            d_state->domain_dn, &res, attrs,
 
1845
                                            d_state->domain_sid, "%s))", filter);
 
1846
                if (count < 0)
 
1847
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
1848
        }
 
1849
 
 
1850
        r->out.rids->count = 0;
 
1851
        r->out.rids->ids = talloc_array(mem_ctx, uint32_t, count);
 
1852
        if (r->out.rids->ids == NULL)
 
1853
                return NT_STATUS_NO_MEMORY;
 
1854
 
 
1855
        for (i=0; i<count; i++) {
 
1856
                struct dom_sid *alias_sid;
 
1857
 
 
1858
                alias_sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
 
1859
 
 
1860
                if (alias_sid == NULL) {
 
1861
                        DEBUG(0, ("Could not find objectSid\n"));
 
1862
                        continue;
 
1863
                }
 
1864
 
 
1865
                r->out.rids->ids[r->out.rids->count] =
 
1866
                        alias_sid->sub_auths[alias_sid->num_auths-1];
 
1867
                r->out.rids->count += 1;
 
1868
        }
 
1869
 
 
1870
        return NT_STATUS_OK;
 
1871
}
 
1872
 
 
1873
 
 
1874
/* 
 
1875
  samr_LookupNames 
 
1876
*/
 
1877
static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1878
                                 struct samr_LookupNames *r)
 
1879
{
 
1880
        struct dcesrv_handle *h;
 
1881
        struct samr_domain_state *d_state;
 
1882
        int i, num_mapped;
 
1883
        NTSTATUS status = NT_STATUS_OK;
 
1884
        const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
 
1885
        int count;
 
1886
 
 
1887
        ZERO_STRUCTP(r->out.rids);
 
1888
        ZERO_STRUCTP(r->out.types);
 
1889
 
 
1890
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1891
 
 
1892
        d_state = h->data;
 
1893
 
 
1894
        if (r->in.num_names == 0) {
 
1895
                return NT_STATUS_OK;
 
1896
        }
 
1897
 
 
1898
        r->out.rids->ids = talloc_array(mem_ctx, uint32_t, r->in.num_names);
 
1899
        r->out.types->ids = talloc_array(mem_ctx, uint32_t, r->in.num_names);
 
1900
        if (!r->out.rids->ids || !r->out.types->ids) {
 
1901
                return NT_STATUS_NO_MEMORY;
 
1902
        }
 
1903
        r->out.rids->count = r->in.num_names;
 
1904
        r->out.types->count = r->in.num_names;
 
1905
 
 
1906
        num_mapped = 0;
 
1907
 
 
1908
        for (i=0;i<r->in.num_names;i++) {
 
1909
                struct ldb_message **res;
 
1910
                struct dom_sid *sid;
 
1911
                uint32_t atype, rtype;
 
1912
 
 
1913
                r->out.rids->ids[i] = 0;
 
1914
                r->out.types->ids[i] = SID_NAME_UNKNOWN;
 
1915
 
 
1916
                count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, 
 
1917
                                     "sAMAccountName=%s", 
 
1918
                                     ldb_binary_encode_string(mem_ctx, r->in.names[i].string));
 
1919
                if (count != 1) {
 
1920
                        status = STATUS_SOME_UNMAPPED;
 
1921
                        continue;
 
1922
                }
 
1923
 
 
1924
                sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
 
1925
                if (sid == NULL) {
 
1926
                        status = STATUS_SOME_UNMAPPED;
 
1927
                        continue;
 
1928
                }
 
1929
                
 
1930
                atype = samdb_result_uint(res[0], "sAMAccountType", 0);
 
1931
                if (atype == 0) {
 
1932
                        status = STATUS_SOME_UNMAPPED;
 
1933
                        continue;
 
1934
                }
 
1935
 
 
1936
                rtype = samdb_atype_map(atype);
 
1937
                
 
1938
                if (rtype == SID_NAME_UNKNOWN) {
 
1939
                        status = STATUS_SOME_UNMAPPED;
 
1940
                        continue;
 
1941
                }
 
1942
 
 
1943
                r->out.rids->ids[i] = sid->sub_auths[sid->num_auths-1];
 
1944
                r->out.types->ids[i] = rtype;
 
1945
                num_mapped++;
 
1946
        }
 
1947
        
 
1948
        if (num_mapped == 0) {
 
1949
                return NT_STATUS_NONE_MAPPED;
 
1950
        }
 
1951
        return status;
 
1952
}
 
1953
 
 
1954
 
 
1955
/* 
 
1956
  samr_LookupRids 
 
1957
*/
 
1958
static NTSTATUS dcesrv_samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
1959
                       struct samr_LookupRids *r)
 
1960
{
 
1961
        struct dcesrv_handle *h;
 
1962
        struct samr_domain_state *d_state;
 
1963
        int i, total;
 
1964
        NTSTATUS status = NT_STATUS_OK;
 
1965
        struct lsa_String *names;
 
1966
        uint32_t *ids;
 
1967
 
 
1968
        ZERO_STRUCTP(r->out.names);
 
1969
        ZERO_STRUCTP(r->out.types);
 
1970
 
 
1971
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
1972
 
 
1973
        d_state = h->data;
 
1974
 
 
1975
        if (r->in.num_rids == 0)
 
1976
                return NT_STATUS_OK;
 
1977
 
 
1978
        names = talloc_array(mem_ctx, struct lsa_String, r->in.num_rids);
 
1979
        ids = talloc_array(mem_ctx, uint32_t, r->in.num_rids);
 
1980
 
 
1981
        if ((names == NULL) || (ids == NULL))
 
1982
                return NT_STATUS_NO_MEMORY;
 
1983
 
 
1984
        total = 0;
 
1985
 
 
1986
        for (i=0; i<r->in.num_rids; i++) {
 
1987
                struct ldb_message **res;
 
1988
                int count;
 
1989
                const char * const attrs[] = {  "sAMAccountType",
 
1990
                                                "sAMAccountName", NULL };
 
1991
                uint32_t atype;
 
1992
                struct dom_sid *sid;
 
1993
 
 
1994
                ids[i] = SID_NAME_UNKNOWN;
 
1995
 
 
1996
                sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rids[i]);
 
1997
                if (sid == NULL) {
 
1998
                        names[i].string = NULL;
 
1999
                        status = STATUS_SOME_UNMAPPED;
 
2000
                        continue;
 
2001
                }
 
2002
                
 
2003
                count = gendb_search(d_state->sam_ctx, mem_ctx,
 
2004
                                     d_state->domain_dn, &res, attrs,
 
2005
                                     "(objectSid=%s)", 
 
2006
                                     ldap_encode_ndr_dom_sid(mem_ctx, sid));
 
2007
                if (count != 1) {
 
2008
                        names[i].string = NULL;
 
2009
                        status = STATUS_SOME_UNMAPPED;
 
2010
                        continue;
 
2011
                }
 
2012
 
 
2013
                names[i].string = samdb_result_string(res[0], "sAMAccountName",
 
2014
                                                      NULL);
 
2015
 
 
2016
                atype = samdb_result_uint(res[0], "sAMAccountType", 0);
 
2017
                if (atype == 0) {
 
2018
                        status = STATUS_SOME_UNMAPPED;
 
2019
                        continue;
 
2020
                }
 
2021
 
 
2022
                ids[i] = samdb_atype_map(atype);
 
2023
                
 
2024
                if (ids[i] == SID_NAME_UNKNOWN) {
 
2025
                        status = STATUS_SOME_UNMAPPED;
 
2026
                        continue;
 
2027
                }
 
2028
        }
 
2029
 
 
2030
        r->out.names->names = names;
 
2031
        r->out.names->count = r->in.num_rids;
 
2032
 
 
2033
        r->out.types->ids = ids;
 
2034
        r->out.types->count = r->in.num_rids;
 
2035
 
 
2036
        return status;
 
2037
}
 
2038
 
 
2039
 
 
2040
/* 
 
2041
  samr_OpenGroup 
 
2042
*/
 
2043
static NTSTATUS dcesrv_samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2044
                       struct samr_OpenGroup *r)
 
2045
{
 
2046
        struct samr_domain_state *d_state;
 
2047
        struct samr_account_state *a_state;
 
2048
        struct dcesrv_handle *h;
 
2049
        const char *groupname;
 
2050
        struct dom_sid *sid;
 
2051
        struct ldb_message **msgs;
 
2052
        struct dcesrv_handle *g_handle;
 
2053
        const char * const attrs[2] = { "sAMAccountName", NULL };
 
2054
        int ret;
 
2055
 
 
2056
        ZERO_STRUCTP(r->out.group_handle);
 
2057
 
 
2058
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
2059
 
 
2060
        d_state = h->data;
 
2061
 
 
2062
        /* form the group SID */
 
2063
        sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
 
2064
        if (!sid) {
 
2065
                return NT_STATUS_NO_MEMORY;
 
2066
        }
 
2067
 
 
2068
        /* search for the group record */
 
2069
        ret = gendb_search(d_state->sam_ctx,
 
2070
                           mem_ctx, d_state->domain_dn, &msgs, attrs,
 
2071
                           "(&(objectSid=%s)(objectclass=group)"
 
2072
                           "(grouptype=%d))",
 
2073
                           ldap_encode_ndr_dom_sid(mem_ctx, sid),
 
2074
                           GTYPE_SECURITY_GLOBAL_GROUP);
 
2075
        if (ret == 0) {
 
2076
                return NT_STATUS_NO_SUCH_GROUP;
 
2077
        }
 
2078
        if (ret != 1) {
 
2079
                DEBUG(0,("Found %d records matching sid %s\n", 
 
2080
                         ret, dom_sid_string(mem_ctx, sid)));
 
2081
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2082
        }
 
2083
 
 
2084
        groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
 
2085
        if (groupname == NULL) {
 
2086
                DEBUG(0,("sAMAccountName field missing for sid %s\n", 
 
2087
                         dom_sid_string(mem_ctx, sid)));
 
2088
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2089
        }
 
2090
 
 
2091
        a_state = talloc(d_state, struct samr_account_state);
 
2092
        if (!a_state) {
 
2093
                return NT_STATUS_NO_MEMORY;
 
2094
        }
 
2095
        a_state->sam_ctx = d_state->sam_ctx;
 
2096
        a_state->access_mask = r->in.access_mask;
 
2097
        a_state->domain_state = talloc_reference(a_state, d_state);
 
2098
        a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
 
2099
        a_state->account_sid = talloc_steal(a_state, sid);
 
2100
        a_state->account_name = talloc_strdup(a_state, groupname);
 
2101
        if (!a_state->account_name) {
 
2102
                return NT_STATUS_NO_MEMORY;
 
2103
        }
 
2104
 
 
2105
        /* create the policy handle */
 
2106
        g_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_GROUP);
 
2107
        if (!g_handle) {
 
2108
                return NT_STATUS_NO_MEMORY;
 
2109
        }
 
2110
 
 
2111
        g_handle->data = talloc_steal(g_handle, a_state);
 
2112
 
 
2113
        *r->out.group_handle = g_handle->wire_handle;
 
2114
 
 
2115
        return NT_STATUS_OK;
 
2116
}
 
2117
 
 
2118
/* 
 
2119
  samr_QueryGroupInfo 
 
2120
*/
 
2121
static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2122
                       struct samr_QueryGroupInfo *r)
 
2123
{
 
2124
        struct dcesrv_handle *h;
 
2125
        struct samr_account_state *a_state;
 
2126
        struct ldb_message *msg;
 
2127
        struct ldb_result *res;
 
2128
        const char * const attrs[4] = { "sAMAccountName", "description",
 
2129
                                        "numMembers", NULL };
 
2130
        int ret;
 
2131
        union samr_GroupInfo *info;
 
2132
 
 
2133
        *r->out.info = NULL;
 
2134
 
 
2135
        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
 
2136
 
 
2137
        a_state = h->data;
 
2138
        
 
2139
        ret = ldb_search(a_state->sam_ctx, mem_ctx, &res, a_state->account_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=*");
 
2140
        
 
2141
        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 
2142
                return NT_STATUS_NO_SUCH_GROUP;
 
2143
        } else if (ret != LDB_SUCCESS) {
 
2144
                DEBUG(2, ("Error reading group info: %s\n", ldb_errstring(a_state->sam_ctx)));
 
2145
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2146
        }
 
2147
 
 
2148
        if (res->count != 1) {
 
2149
                DEBUG(2, ("Error finding group info, got %d entries\n", res->count));
 
2150
                
 
2151
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2152
        }
 
2153
        msg = res->msgs[0];
 
2154
 
 
2155
        /* allocate the info structure */
 
2156
        info = talloc_zero(mem_ctx, union samr_GroupInfo);
 
2157
        if (info == NULL) {
 
2158
                return NT_STATUS_NO_MEMORY;
 
2159
        }
 
2160
 
 
2161
        /* Fill in the level */
 
2162
        switch (r->in.level) {
 
2163
        case GROUPINFOALL:
 
2164
                QUERY_STRING(msg, all.name,        "sAMAccountName");
 
2165
                info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */
 
2166
                QUERY_UINT  (msg, all.num_members,      "numMembers")
 
2167
                QUERY_STRING(msg, all.description, "description");
 
2168
                break;
 
2169
        case GROUPINFONAME:
 
2170
                QUERY_STRING(msg, name,            "sAMAccountName");
 
2171
                break;
 
2172
        case GROUPINFOATTRIBUTES:
 
2173
                info->attributes.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */
 
2174
                break;
 
2175
        case GROUPINFODESCRIPTION:
 
2176
                QUERY_STRING(msg, description, "description");
 
2177
                break;
 
2178
        case GROUPINFOALL2:
 
2179
                QUERY_STRING(msg, all2.name,        "sAMAccountName");
 
2180
                info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */
 
2181
                QUERY_UINT  (msg, all2.num_members,      "numMembers")
 
2182
                QUERY_STRING(msg, all2.description, "description");
 
2183
                break;
 
2184
        default:
 
2185
                talloc_free(info);
 
2186
                return NT_STATUS_INVALID_INFO_CLASS;
 
2187
        }
 
2188
 
 
2189
        *r->out.info = info;
 
2190
 
 
2191
        return NT_STATUS_OK;
 
2192
}
 
2193
 
 
2194
 
 
2195
/* 
 
2196
  samr_SetGroupInfo 
 
2197
*/
 
2198
static NTSTATUS dcesrv_samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2199
                                  struct samr_SetGroupInfo *r)
 
2200
{
 
2201
        struct dcesrv_handle *h;
 
2202
        struct samr_account_state *g_state;
 
2203
        struct ldb_message *msg;
 
2204
        struct ldb_context *sam_ctx;
 
2205
        int ret;
 
2206
 
 
2207
        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
 
2208
 
 
2209
        g_state = h->data;
 
2210
        sam_ctx = g_state->sam_ctx;
 
2211
 
 
2212
        msg = ldb_msg_new(mem_ctx);
 
2213
        if (msg == NULL) {
 
2214
                return NT_STATUS_NO_MEMORY;
 
2215
        }       
 
2216
 
 
2217
        msg->dn = ldb_dn_copy(mem_ctx, g_state->account_dn);
 
2218
        if (!msg->dn) {
 
2219
                return NT_STATUS_NO_MEMORY;
 
2220
        }
 
2221
 
 
2222
        switch (r->in.level) {
 
2223
        case GROUPINFODESCRIPTION:
 
2224
                SET_STRING(msg, description,         "description");
 
2225
                break;
 
2226
        case GROUPINFONAME:
 
2227
                /* On W2k3 this does not change the name, it changes the
 
2228
                 * sAMAccountName attribute */
 
2229
                SET_STRING(msg, name,                "sAMAccountName");
 
2230
                break;
 
2231
        case GROUPINFOATTRIBUTES:
 
2232
                /* This does not do anything obviously visible in W2k3 LDAP */
 
2233
                return NT_STATUS_OK;
 
2234
        default:
 
2235
                return NT_STATUS_INVALID_INFO_CLASS;
 
2236
        }
 
2237
 
 
2238
        /* modify the samdb record */
 
2239
        ret = ldb_modify(g_state->sam_ctx, msg);
 
2240
        if (ret != 0) {
 
2241
                /* we really need samdb.c to return NTSTATUS */
 
2242
                return NT_STATUS_UNSUCCESSFUL;
 
2243
        }
 
2244
 
 
2245
        return NT_STATUS_OK;
 
2246
}
 
2247
 
 
2248
 
 
2249
/* 
 
2250
  samr_AddGroupMember 
 
2251
*/
 
2252
static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2253
                       struct samr_AddGroupMember *r)
 
2254
{
 
2255
        struct dcesrv_handle *h;
 
2256
        struct samr_account_state *a_state;
 
2257
        struct samr_domain_state *d_state;
 
2258
        struct ldb_message *mod;
 
2259
        struct dom_sid *membersid;
 
2260
        const char *memberdn;
 
2261
        struct ldb_result *res;
 
2262
        const char * const attrs[] = { NULL };
 
2263
        int ret;
 
2264
 
 
2265
        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
 
2266
 
 
2267
        a_state = h->data;
 
2268
        d_state = a_state->domain_state;
 
2269
 
 
2270
        membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
 
2271
        if (membersid == NULL)
 
2272
                return NT_STATUS_NO_MEMORY;
 
2273
 
 
2274
        /* In native mode, AD can also nest domain groups. Not sure yet
 
2275
         * whether this is also available via RPC. */
 
2276
        ret = ldb_search(d_state->sam_ctx, mem_ctx, &res,
 
2277
                                 d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
 
2278
                                 "(&(objectSid=%s)(objectclass=user))",
 
2279
                                 ldap_encode_ndr_dom_sid(mem_ctx, membersid));
 
2280
 
 
2281
        if (ret != 0) {
 
2282
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2283
        }
 
2284
 
 
2285
        if (res->count == 0) {
 
2286
                return NT_STATUS_NO_SUCH_USER;
 
2287
        }
 
2288
                
 
2289
        if (res->count > 1) {
 
2290
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2291
        }
 
2292
 
 
2293
        memberdn = ldb_dn_alloc_linearized(mem_ctx, res->msgs[0]->dn);
 
2294
 
 
2295
        if (memberdn == NULL)
 
2296
                return NT_STATUS_NO_MEMORY;
 
2297
 
 
2298
        mod = ldb_msg_new(mem_ctx);
 
2299
        if (mod == NULL) {
 
2300
                return NT_STATUS_NO_MEMORY;
 
2301
        }
 
2302
 
 
2303
        mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
 
2304
 
 
2305
        if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
 
2306
                                 memberdn) != 0)
 
2307
                return NT_STATUS_UNSUCCESSFUL;
 
2308
 
 
2309
        ret = ldb_modify(a_state->sam_ctx, mod);
 
2310
        switch (ret) {
 
2311
        case LDB_SUCCESS:
 
2312
                return NT_STATUS_OK;
 
2313
        case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
 
2314
                return NT_STATUS_MEMBER_IN_GROUP;
 
2315
        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
 
2316
                return NT_STATUS_ACCESS_DENIED;
 
2317
        default:
 
2318
                return NT_STATUS_UNSUCCESSFUL;
 
2319
        }
 
2320
 
 
2321
}
 
2322
 
 
2323
 
 
2324
/* 
 
2325
  samr_DeleteDomainGroup 
 
2326
*/
 
2327
static NTSTATUS dcesrv_samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2328
                       struct samr_DeleteDomainGroup *r)
 
2329
{
 
2330
        struct dcesrv_handle *h;
 
2331
        struct samr_account_state *a_state;
 
2332
        int ret;
 
2333
 
 
2334
        *r->out.group_handle = *r->in.group_handle;
 
2335
 
 
2336
        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
 
2337
 
 
2338
        a_state = h->data;
 
2339
 
 
2340
        ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
 
2341
        if (ret != 0) {
 
2342
                return NT_STATUS_UNSUCCESSFUL;
 
2343
        }
 
2344
 
 
2345
        ZERO_STRUCTP(r->out.group_handle);
 
2346
 
 
2347
        return NT_STATUS_OK;
 
2348
}
 
2349
 
 
2350
 
 
2351
/* 
 
2352
  samr_DeleteGroupMember 
 
2353
*/
 
2354
static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2355
                       struct samr_DeleteGroupMember *r)
 
2356
{
 
2357
        struct dcesrv_handle *h;
 
2358
        struct samr_account_state *a_state;
 
2359
        struct samr_domain_state *d_state;
 
2360
        struct ldb_message *mod;
 
2361
        struct dom_sid *membersid;
 
2362
        const char *memberdn;
 
2363
        struct ldb_result *res;
 
2364
        const char * const attrs[] = { NULL };
 
2365
        int ret;
 
2366
 
 
2367
        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
 
2368
 
 
2369
        a_state = h->data;
 
2370
        d_state = a_state->domain_state;
 
2371
 
 
2372
        membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
 
2373
        if (membersid == NULL)
 
2374
                return NT_STATUS_NO_MEMORY;
 
2375
 
 
2376
        /* In native mode, AD can also nest domain groups. Not sure yet
 
2377
         * whether this is also available via RPC. */
 
2378
        ret = ldb_search(d_state->sam_ctx, mem_ctx, &res,
 
2379
                                 d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
 
2380
                                 "(&(objectSid=%s)(objectclass=user))",
 
2381
                                 ldap_encode_ndr_dom_sid(mem_ctx, membersid));
 
2382
 
 
2383
        if (ret != 0) {
 
2384
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2385
        }
 
2386
 
 
2387
        if (res->count == 0) {
 
2388
                return NT_STATUS_NO_SUCH_USER;
 
2389
        }
 
2390
                
 
2391
        if (res->count > 1) {
 
2392
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2393
        }
 
2394
 
 
2395
        memberdn = ldb_dn_alloc_linearized(mem_ctx, res->msgs[0]->dn);
 
2396
 
 
2397
        if (memberdn == NULL)
 
2398
                return NT_STATUS_NO_MEMORY;
 
2399
 
 
2400
        mod = ldb_msg_new(mem_ctx);
 
2401
        if (mod == NULL) {
 
2402
                return NT_STATUS_NO_MEMORY;
 
2403
        }
 
2404
 
 
2405
        mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
 
2406
 
 
2407
        if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
 
2408
                                 memberdn) != 0) {
 
2409
                return NT_STATUS_NO_MEMORY;
 
2410
        }
 
2411
 
 
2412
        ret = ldb_modify(a_state->sam_ctx, mod);
 
2413
        switch (ret) {
 
2414
        case LDB_SUCCESS:
 
2415
                return NT_STATUS_OK;
 
2416
        case LDB_ERR_NO_SUCH_ATTRIBUTE:
 
2417
                return NT_STATUS_MEMBER_NOT_IN_GROUP;
 
2418
        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
 
2419
                return NT_STATUS_ACCESS_DENIED;
 
2420
        default:
 
2421
                return NT_STATUS_UNSUCCESSFUL;
 
2422
        }
 
2423
 
 
2424
}
 
2425
 
 
2426
 
 
2427
/* 
 
2428
  samr_QueryGroupMember 
 
2429
*/
 
2430
static NTSTATUS dcesrv_samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2431
                                      struct samr_QueryGroupMember *r)
 
2432
{
 
2433
        struct dcesrv_handle *h;
 
2434
        struct samr_account_state *a_state;
 
2435
        struct ldb_message **res;
 
2436
        struct ldb_message_element *el;
 
2437
        struct samr_RidTypeArray *array;
 
2438
        const char * const attrs[2] = { "member", NULL };
 
2439
        int ret;
 
2440
 
 
2441
        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
 
2442
 
 
2443
        a_state = h->data;
 
2444
 
 
2445
        /* pull the member attribute */
 
2446
        ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
 
2447
                              a_state->account_dn, &res, attrs);
 
2448
 
 
2449
        if (ret != 1) {
 
2450
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2451
        }
 
2452
 
 
2453
        array = talloc(mem_ctx, struct samr_RidTypeArray);
 
2454
 
 
2455
        if (array == NULL)
 
2456
                return NT_STATUS_NO_MEMORY;
 
2457
 
 
2458
        ZERO_STRUCTP(array);
 
2459
 
 
2460
        el = ldb_msg_find_element(res[0], "member");
 
2461
 
 
2462
        if (el != NULL) {
 
2463
                int i;
 
2464
 
 
2465
                array->count = el->num_values;
 
2466
 
 
2467
                array->rids = talloc_array(mem_ctx, uint32_t,
 
2468
                                             el->num_values);
 
2469
                if (array->rids == NULL)
 
2470
                        return NT_STATUS_NO_MEMORY;
 
2471
 
 
2472
                array->types = talloc_array(mem_ctx, uint32_t,
 
2473
                                            el->num_values);
 
2474
                if (array->types == NULL)
 
2475
                        return NT_STATUS_NO_MEMORY;
 
2476
 
 
2477
                for (i=0; i<el->num_values; i++) {
 
2478
                        struct ldb_message **res2;
 
2479
                        const char * const attrs2[2] = { "objectSid", NULL };
 
2480
                        ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
 
2481
                                           ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]),
 
2482
                                           &res2, attrs2);
 
2483
                        if (ret != 1)
 
2484
                                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2485
 
 
2486
                        array->rids[i] =
 
2487
                                samdb_result_rid_from_sid(mem_ctx, res2[0],
 
2488
                                                          "objectSid", 0);
 
2489
 
 
2490
                        if (array->rids[i] == 0)
 
2491
                                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2492
 
 
2493
                        array->types[i] = 7; /* RID type of some kind, not sure what the value means. */
 
2494
                }
 
2495
        }
 
2496
 
 
2497
        *r->out.rids = array;
 
2498
 
 
2499
        return NT_STATUS_OK;
 
2500
}
 
2501
 
 
2502
 
 
2503
/* 
 
2504
  samr_SetMemberAttributesOfGroup 
 
2505
*/
 
2506
static NTSTATUS dcesrv_samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2507
                       struct samr_SetMemberAttributesOfGroup *r)
 
2508
{
 
2509
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
2510
}
 
2511
 
 
2512
 
 
2513
/* 
 
2514
  samr_OpenAlias 
 
2515
*/
 
2516
static NTSTATUS dcesrv_samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2517
                       struct samr_OpenAlias *r)
 
2518
{
 
2519
        struct samr_domain_state *d_state;
 
2520
        struct samr_account_state *a_state;
 
2521
        struct dcesrv_handle *h;
 
2522
        const char *alias_name;
 
2523
        struct dom_sid *sid;
 
2524
        struct ldb_message **msgs;
 
2525
        struct dcesrv_handle *g_handle;
 
2526
        const char * const attrs[2] = { "sAMAccountName", NULL };
 
2527
        int ret;
 
2528
 
 
2529
        ZERO_STRUCTP(r->out.alias_handle);
 
2530
 
 
2531
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
2532
 
 
2533
        d_state = h->data;
 
2534
 
 
2535
        /* form the alias SID */
 
2536
        sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
 
2537
        if (sid == NULL)
 
2538
                return NT_STATUS_NO_MEMORY;
 
2539
 
 
2540
        /* search for the group record */
 
2541
        ret = gendb_search(d_state->sam_ctx,
 
2542
                           mem_ctx, d_state->domain_dn, &msgs, attrs,
 
2543
                           "(&(objectSid=%s)(objectclass=group)"
 
2544
                           "(|(grouptype=%d)(grouptype=%d)))",
 
2545
                           ldap_encode_ndr_dom_sid(mem_ctx, sid),
 
2546
                           GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
 
2547
                           GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
 
2548
        if (ret == 0) {
 
2549
                return NT_STATUS_NO_SUCH_ALIAS;
 
2550
        }
 
2551
        if (ret != 1) {
 
2552
                DEBUG(0,("Found %d records matching sid %s\n", 
 
2553
                         ret, dom_sid_string(mem_ctx, sid)));
 
2554
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2555
        }
 
2556
 
 
2557
        alias_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
 
2558
        if (alias_name == NULL) {
 
2559
                DEBUG(0,("sAMAccountName field missing for sid %s\n", 
 
2560
                         dom_sid_string(mem_ctx, sid)));
 
2561
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2562
        }
 
2563
 
 
2564
        a_state = talloc(d_state, struct samr_account_state);
 
2565
        if (!a_state) {
 
2566
                return NT_STATUS_NO_MEMORY;
 
2567
        }
 
2568
        a_state->sam_ctx = d_state->sam_ctx;
 
2569
        a_state->access_mask = r->in.access_mask;
 
2570
        a_state->domain_state = talloc_reference(a_state, d_state);
 
2571
        a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
 
2572
        a_state->account_sid = talloc_steal(a_state, sid);
 
2573
        a_state->account_name = talloc_strdup(a_state, alias_name);
 
2574
        if (!a_state->account_name) {
 
2575
                return NT_STATUS_NO_MEMORY;
 
2576
        }
 
2577
 
 
2578
        /* create the policy handle */
 
2579
        g_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_ALIAS);
 
2580
        if (!g_handle) {
 
2581
                return NT_STATUS_NO_MEMORY;
 
2582
        }
 
2583
 
 
2584
        g_handle->data = talloc_steal(g_handle, a_state);
 
2585
 
 
2586
        *r->out.alias_handle = g_handle->wire_handle;
 
2587
 
 
2588
        return NT_STATUS_OK;
 
2589
}
 
2590
 
 
2591
 
 
2592
/* 
 
2593
  samr_QueryAliasInfo 
 
2594
*/
 
2595
static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2596
                       struct samr_QueryAliasInfo *r)
 
2597
{
 
2598
        struct dcesrv_handle *h;
 
2599
        struct samr_account_state *a_state;
 
2600
        struct ldb_message *msg, **res;
 
2601
        const char * const attrs[4] = { "sAMAccountName", "description",
 
2602
                                        "numMembers", NULL };
 
2603
        int ret;
 
2604
        union samr_AliasInfo *info;
 
2605
 
 
2606
        *r->out.info = NULL;
 
2607
 
 
2608
        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
 
2609
 
 
2610
        a_state = h->data;
 
2611
 
 
2612
        /* pull all the alias attributes */
 
2613
        ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
 
2614
                              a_state->account_dn ,&res, attrs);
 
2615
        if (ret != 1) {
 
2616
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2617
        }
 
2618
        msg = res[0];
 
2619
 
 
2620
        /* allocate the info structure */
 
2621
        info = talloc_zero(mem_ctx, union samr_AliasInfo);
 
2622
        if (info == NULL) {
 
2623
                return NT_STATUS_NO_MEMORY;
 
2624
        }
 
2625
 
 
2626
        switch(r->in.level) {
 
2627
        case ALIASINFOALL:
 
2628
                QUERY_STRING(msg, all.name, "sAMAccountName");
 
2629
                QUERY_UINT  (msg, all.num_members, "numMembers");
 
2630
                QUERY_STRING(msg, all.description, "description");
 
2631
                break;
 
2632
        case ALIASINFONAME:
 
2633
                QUERY_STRING(msg, name, "sAMAccountName");
 
2634
                break;
 
2635
        case ALIASINFODESCRIPTION:
 
2636
                QUERY_STRING(msg, description, "description");
 
2637
                break;
 
2638
        default:
 
2639
                talloc_free(info);
 
2640
                return NT_STATUS_INVALID_INFO_CLASS;
 
2641
        }
 
2642
 
 
2643
        *r->out.info = info;
 
2644
 
 
2645
        return NT_STATUS_OK;
 
2646
}
 
2647
 
 
2648
 
 
2649
/* 
 
2650
  samr_SetAliasInfo 
 
2651
*/
 
2652
static NTSTATUS dcesrv_samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2653
                       struct samr_SetAliasInfo *r)
 
2654
{
 
2655
        struct dcesrv_handle *h;
 
2656
        struct samr_account_state *a_state;
 
2657
        struct ldb_message *msg;
 
2658
        struct ldb_context *sam_ctx;
 
2659
        int ret;
 
2660
 
 
2661
        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
 
2662
 
 
2663
        a_state = h->data;
 
2664
        sam_ctx = a_state->sam_ctx;
 
2665
 
 
2666
        msg = ldb_msg_new(mem_ctx);
 
2667
        if (msg == NULL) {
 
2668
                return NT_STATUS_NO_MEMORY;
 
2669
        }
 
2670
 
 
2671
        msg->dn = ldb_dn_copy(mem_ctx, a_state->account_dn);
 
2672
        if (!msg->dn) {
 
2673
                return NT_STATUS_NO_MEMORY;
 
2674
        }
 
2675
 
 
2676
        switch (r->in.level) {
 
2677
        case ALIASINFODESCRIPTION:
 
2678
                SET_STRING(msg, description,         "description");
 
2679
                break;
 
2680
        case ALIASINFONAME:
 
2681
                /* On W2k3 this does not change the name, it changes the
 
2682
                 * sAMAccountName attribute */
 
2683
                SET_STRING(msg, name,                "sAMAccountName");
 
2684
                break;
 
2685
        default:
 
2686
                return NT_STATUS_INVALID_INFO_CLASS;
 
2687
        }
 
2688
 
 
2689
        /* modify the samdb record */
 
2690
        ret = ldb_modify(a_state->sam_ctx, msg);
 
2691
        if (ret != 0) {
 
2692
                /* we really need samdb.c to return NTSTATUS */
 
2693
                return NT_STATUS_UNSUCCESSFUL;
 
2694
        }
 
2695
 
 
2696
        return NT_STATUS_OK;
 
2697
}
 
2698
 
 
2699
 
 
2700
/* 
 
2701
  samr_DeleteDomAlias 
 
2702
*/
 
2703
static NTSTATUS dcesrv_samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2704
                       struct samr_DeleteDomAlias *r)
 
2705
{
 
2706
        struct dcesrv_handle *h;
 
2707
        struct samr_account_state *a_state;
 
2708
        int ret;
 
2709
 
 
2710
        *r->out.alias_handle = *r->in.alias_handle;
 
2711
 
 
2712
        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
 
2713
 
 
2714
        a_state = h->data;
 
2715
 
 
2716
        ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
 
2717
        if (ret != 0) {
 
2718
                return NT_STATUS_UNSUCCESSFUL;
 
2719
        }
 
2720
 
 
2721
        ZERO_STRUCTP(r->out.alias_handle);
 
2722
 
 
2723
        return NT_STATUS_OK;
 
2724
}
 
2725
 
 
2726
 
 
2727
/* 
 
2728
  samr_AddAliasMember 
 
2729
*/
 
2730
static NTSTATUS dcesrv_samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2731
                       struct samr_AddAliasMember *r)
 
2732
{
 
2733
        struct dcesrv_handle *h;
 
2734
        struct samr_account_state *a_state;
 
2735
        struct samr_domain_state *d_state;
 
2736
        struct ldb_message *mod;
 
2737
        struct ldb_message **msgs;
 
2738
        const char * const attrs[] = { NULL };
 
2739
        struct ldb_dn *memberdn = NULL;
 
2740
        int ret;
 
2741
        NTSTATUS status;
 
2742
 
 
2743
        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
 
2744
 
 
2745
        a_state = h->data;
 
2746
        d_state = a_state->domain_state;
 
2747
 
 
2748
        ret = gendb_search(d_state->sam_ctx, mem_ctx, NULL,
 
2749
                           &msgs, attrs, "(objectsid=%s)", 
 
2750
                           ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
 
2751
 
 
2752
        if (ret == 1) {
 
2753
                memberdn = msgs[0]->dn;
 
2754
        } else  if (ret > 1) {
 
2755
                DEBUG(0,("Found %d records matching sid %s\n", 
 
2756
                         ret, dom_sid_string(mem_ctx, r->in.sid)));
 
2757
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2758
        } else if (ret == 0) {
 
2759
                status = samdb_create_foreign_security_principal(d_state->sam_ctx, mem_ctx, 
 
2760
                                                                 r->in.sid, &memberdn);
 
2761
                if (!NT_STATUS_IS_OK(status)) {
 
2762
                        return status;
 
2763
                }
 
2764
        } else {
 
2765
                DEBUG(0, ("samdb_search returned %d: %s\n", ret, ldb_errstring(d_state->sam_ctx)));
 
2766
        }
 
2767
 
 
2768
        if (memberdn == NULL) {
 
2769
                DEBUG(0, ("Could not find memberdn\n"));
 
2770
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2771
        }
 
2772
 
 
2773
        mod = ldb_msg_new(mem_ctx);
 
2774
        if (mod == NULL) {
 
2775
                return NT_STATUS_NO_MEMORY;
 
2776
        }
 
2777
 
 
2778
        mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
 
2779
 
 
2780
        if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
 
2781
                                 ldb_dn_alloc_linearized(mem_ctx, memberdn)) != 0)
 
2782
                return NT_STATUS_UNSUCCESSFUL;
 
2783
 
 
2784
        if (ldb_modify(a_state->sam_ctx, mod) != 0)
 
2785
                return NT_STATUS_UNSUCCESSFUL;
 
2786
 
 
2787
        return NT_STATUS_OK;
 
2788
}
 
2789
 
 
2790
 
 
2791
/* 
 
2792
  samr_DeleteAliasMember 
 
2793
*/
 
2794
static NTSTATUS dcesrv_samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2795
                       struct samr_DeleteAliasMember *r)
 
2796
{
 
2797
        struct dcesrv_handle *h;
 
2798
        struct samr_account_state *a_state;
 
2799
        struct samr_domain_state *d_state;
 
2800
        struct ldb_message *mod;
 
2801
        const char *memberdn;
 
2802
 
 
2803
        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
 
2804
 
 
2805
        a_state = h->data;
 
2806
        d_state = a_state->domain_state;
 
2807
 
 
2808
        memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
 
2809
                                       "distinguishedName", "(objectSid=%s)", 
 
2810
                                       ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
 
2811
 
 
2812
        if (memberdn == NULL)
 
2813
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
2814
 
 
2815
        mod = ldb_msg_new(mem_ctx);
 
2816
        if (mod == NULL) {
 
2817
                return NT_STATUS_NO_MEMORY;
 
2818
        }
 
2819
 
 
2820
        mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
 
2821
 
 
2822
        if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
 
2823
                                 memberdn) != 0)
 
2824
                return NT_STATUS_UNSUCCESSFUL;
 
2825
 
 
2826
        if (ldb_modify(a_state->sam_ctx, mod) != 0)
 
2827
                return NT_STATUS_UNSUCCESSFUL;
 
2828
 
 
2829
        return NT_STATUS_OK;
 
2830
}
 
2831
 
 
2832
 
 
2833
/* 
 
2834
  samr_GetMembersInAlias 
 
2835
*/
 
2836
static NTSTATUS dcesrv_samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2837
                       struct samr_GetMembersInAlias *r)
 
2838
{
 
2839
        struct dcesrv_handle *h;
 
2840
        struct samr_account_state *a_state;
 
2841
        struct samr_domain_state *d_state;
 
2842
        struct ldb_message **msgs;
 
2843
        struct lsa_SidPtr *sids;
 
2844
        struct ldb_message_element *el;
 
2845
        const char * const attrs[2] = { "member", NULL};
 
2846
        int ret;
 
2847
 
 
2848
        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
 
2849
 
 
2850
        a_state = h->data;
 
2851
        d_state = a_state->domain_state;
 
2852
 
 
2853
        ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
 
2854
                              a_state->account_dn, &msgs, attrs);
 
2855
 
 
2856
        if (ret == -1) {
 
2857
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2858
        } else if (ret == 0) {
 
2859
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
2860
        } else if (ret != 1) {
 
2861
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2862
        }
 
2863
 
 
2864
        r->out.sids->num_sids = 0;
 
2865
        r->out.sids->sids = NULL;
 
2866
 
 
2867
        el = ldb_msg_find_element(msgs[0], "member");
 
2868
 
 
2869
        if (el != NULL) {
 
2870
                int i;
 
2871
 
 
2872
                sids = talloc_array(mem_ctx, struct lsa_SidPtr,
 
2873
                                      el->num_values);
 
2874
 
 
2875
                if (sids == NULL)
 
2876
                        return NT_STATUS_NO_MEMORY;
 
2877
 
 
2878
                for (i=0; i<el->num_values; i++) {
 
2879
                        struct ldb_message **msgs2;
 
2880
                        const char * const attrs2[2] = { "objectSid", NULL };
 
2881
                        ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
 
2882
                                              ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]),
 
2883
                                              &msgs2, attrs2);
 
2884
                        if (ret != 1)
 
2885
                                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2886
 
 
2887
                        sids[i].sid = samdb_result_dom_sid(mem_ctx, msgs2[0],
 
2888
                                                           "objectSid");
 
2889
 
 
2890
                        if (sids[i].sid == NULL)
 
2891
                                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2892
                }
 
2893
                r->out.sids->num_sids = el->num_values;
 
2894
                r->out.sids->sids = sids;
 
2895
        }
 
2896
 
 
2897
        return NT_STATUS_OK;
 
2898
}
 
2899
 
 
2900
/* 
 
2901
  samr_OpenUser 
 
2902
*/
 
2903
static NTSTATUS dcesrv_samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2904
                              struct samr_OpenUser *r)
 
2905
{
 
2906
        struct samr_domain_state *d_state;
 
2907
        struct samr_account_state *a_state;
 
2908
        struct dcesrv_handle *h;
 
2909
        const char *account_name;
 
2910
        struct dom_sid *sid;
 
2911
        struct ldb_message **msgs;
 
2912
        struct dcesrv_handle *u_handle;
 
2913
        const char * const attrs[2] = { "sAMAccountName", NULL };
 
2914
        int ret;
 
2915
 
 
2916
        ZERO_STRUCTP(r->out.user_handle);
 
2917
 
 
2918
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
2919
 
 
2920
        d_state = h->data;
 
2921
 
 
2922
        /* form the users SID */
 
2923
        sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
 
2924
        if (!sid) {
 
2925
                return NT_STATUS_NO_MEMORY;
 
2926
        }
 
2927
 
 
2928
        /* search for the user record */
 
2929
        ret = gendb_search(d_state->sam_ctx,
 
2930
                           mem_ctx, d_state->domain_dn, &msgs, attrs,
 
2931
                           "(&(objectSid=%s)(objectclass=user))", 
 
2932
                           ldap_encode_ndr_dom_sid(mem_ctx, sid));
 
2933
        if (ret == 0) {
 
2934
                return NT_STATUS_NO_SUCH_USER;
 
2935
        }
 
2936
        if (ret != 1) {
 
2937
                DEBUG(0,("Found %d records matching sid %s\n", ret, 
 
2938
                         dom_sid_string(mem_ctx, sid)));
 
2939
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2940
        }
 
2941
 
 
2942
        account_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
 
2943
        if (account_name == NULL) {
 
2944
                DEBUG(0,("sAMAccountName field missing for sid %s\n", 
 
2945
                         dom_sid_string(mem_ctx, sid)));
 
2946
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
2947
        }
 
2948
 
 
2949
        a_state = talloc(mem_ctx, struct samr_account_state);
 
2950
        if (!a_state) {
 
2951
                return NT_STATUS_NO_MEMORY;
 
2952
        }
 
2953
        a_state->sam_ctx = d_state->sam_ctx;
 
2954
        a_state->access_mask = r->in.access_mask;
 
2955
        a_state->domain_state = talloc_reference(a_state, d_state);
 
2956
        a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
 
2957
        a_state->account_sid = talloc_steal(a_state, sid);
 
2958
        a_state->account_name = talloc_strdup(a_state, account_name);
 
2959
        if (!a_state->account_name) {
 
2960
                return NT_STATUS_NO_MEMORY;
 
2961
        }
 
2962
 
 
2963
        /* create the policy handle */
 
2964
        u_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_USER);
 
2965
        if (!u_handle) {
 
2966
                return NT_STATUS_NO_MEMORY;
 
2967
        }
 
2968
 
 
2969
        u_handle->data = talloc_steal(u_handle, a_state);
 
2970
 
 
2971
        *r->out.user_handle = u_handle->wire_handle;
 
2972
 
 
2973
        return NT_STATUS_OK;
 
2974
 
 
2975
}
 
2976
 
 
2977
 
 
2978
/* 
 
2979
  samr_DeleteUser 
 
2980
*/
 
2981
static NTSTATUS dcesrv_samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
2982
                                struct samr_DeleteUser *r)
 
2983
{
 
2984
        struct dcesrv_handle *h;
 
2985
        struct samr_account_state *a_state;
 
2986
        int ret;
 
2987
 
 
2988
        *r->out.user_handle = *r->in.user_handle;
 
2989
 
 
2990
        DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
 
2991
 
 
2992
        a_state = h->data;
 
2993
 
 
2994
        ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
 
2995
        if (ret != 0) {
 
2996
                DEBUG(1, ("Failed to delete user: %s: %s\n", 
 
2997
                          ldb_dn_get_linearized(a_state->account_dn), 
 
2998
                          ldb_errstring(a_state->sam_ctx)));
 
2999
                return NT_STATUS_UNSUCCESSFUL;
 
3000
        }
 
3001
 
 
3002
        ZERO_STRUCTP(r->out.user_handle);
 
3003
 
 
3004
        return NT_STATUS_OK;
 
3005
}
 
3006
 
 
3007
 
 
3008
/* 
 
3009
  samr_QueryUserInfo 
 
3010
*/
 
3011
static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3012
                                   struct samr_QueryUserInfo *r)
 
3013
{
 
3014
        struct dcesrv_handle *h;
 
3015
        struct samr_account_state *a_state;
 
3016
        struct ldb_message *msg, **res;
 
3017
        int ret;
 
3018
        struct ldb_context *sam_ctx;
 
3019
 
 
3020
        const char * const *attrs = NULL;
 
3021
        union samr_UserInfo *info;
 
3022
 
 
3023
        *r->out.info = NULL;
 
3024
 
 
3025
        DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
 
3026
 
 
3027
        a_state = h->data;
 
3028
        sam_ctx = a_state->sam_ctx;
 
3029
 
 
3030
        /* fill in the reply */
 
3031
        switch (r->in.level) {
 
3032
        case 1:
 
3033
        {
 
3034
                static const char * const attrs2[] = {"sAMAccountName", "displayName",
 
3035
                                                      "primaryroupID", "description",
 
3036
                                                      "comment", NULL};
 
3037
                attrs = attrs2;
 
3038
                break;
 
3039
        }
 
3040
        case 2:
 
3041
        {
 
3042
                static const char * const attrs2[] = {"comment", "countryCode", "codePage", NULL};
 
3043
                attrs = attrs2;
 
3044
                break;
 
3045
        }
 
3046
        case 3:
 
3047
        {
 
3048
                static const char * const attrs2[] = {"sAMAccountName",
 
3049
                                                      "displayName",
 
3050
                                                      "objectSid",
 
3051
                                                      "primaryGroupID",
 
3052
                                                      "homeDirectory",
 
3053
                                                      "homeDrive",
 
3054
                                                      "scriptPath",
 
3055
                                                      "profilePath",
 
3056
                                                      "userWorkstations",
 
3057
                                                      "lastLogon",
 
3058
                                                      "lastLogoff",
 
3059
                                                      "pwdLastSet",
 
3060
                                                      "logonHours",
 
3061
                                                      "badPwdCount",
 
3062
                                                      "logonCount",
 
3063
                                                      "userAccountControl", NULL};
 
3064
                attrs = attrs2;
 
3065
                break;
 
3066
        }
 
3067
        case 4:
 
3068
        {
 
3069
                static const char * const attrs2[] = {"logonHours", NULL};
 
3070
                attrs = attrs2;
 
3071
                break;
 
3072
        }
 
3073
        case 5:
 
3074
        {
 
3075
                static const char * const attrs2[] = {"sAMAccountName", 
 
3076
                                                      "displayName",
 
3077
                                                      "objectSid",
 
3078
                                                      "primaryGroupID",
 
3079
                                                      "homeDirectory",
 
3080
                                                      "homeDrive",
 
3081
                                                      "scriptPath", 
 
3082
                                                      "profilePath",
 
3083
                                                      "description",
 
3084
                                                      "userWorkstations",
 
3085
                                                      "lastLogon",
 
3086
                                                      "lastLogoff",
 
3087
                                                      "logonHours",
 
3088
                                                      "badPwdCount",
 
3089
                                                      "logonCount",
 
3090
                                                      "pwdLastSet",
 
3091
                                                      "accountExpires",
 
3092
                                                      "userAccountControl",
 
3093
                                                      NULL};
 
3094
                attrs = attrs2;
 
3095
                break;
 
3096
        }
 
3097
        case 6:
 
3098
        {
 
3099
                static const char * const attrs2[] = {"sAMAccountName", "displayName", NULL};
 
3100
                attrs = attrs2;
 
3101
                break;
 
3102
        }
 
3103
        case 7:
 
3104
        {
 
3105
                static const char * const attrs2[] = {"sAMAccountName", NULL};
 
3106
                attrs = attrs2;
 
3107
                break;
 
3108
        }
 
3109
        case 8:
 
3110
        {
 
3111
                static const char * const attrs2[] = {"displayName", NULL};
 
3112
                attrs = attrs2;
 
3113
                break;
 
3114
        }
 
3115
        case 9:
 
3116
        {
 
3117
                static const char * const attrs2[] = {"primaryGroupID", NULL};
 
3118
                attrs = attrs2;
 
3119
                break;
 
3120
        }
 
3121
        case 10:
 
3122
        {
 
3123
                static const char * const attrs2[] = {"homeDirectory", "homeDrive", NULL};
 
3124
                attrs = attrs2;
 
3125
                break;
 
3126
        }
 
3127
        case 11:
 
3128
        {
 
3129
                static const char * const attrs2[] = {"scriptPath", NULL};
 
3130
                attrs = attrs2;
 
3131
                break;
 
3132
        }
 
3133
        case 12:
 
3134
        {
 
3135
                static const char * const attrs2[] = {"profilePath", NULL};
 
3136
                attrs = attrs2;
 
3137
                break;
 
3138
        }
 
3139
        case 13:
 
3140
        {
 
3141
                static const char * const attrs2[] = {"description", NULL};
 
3142
                attrs = attrs2;
 
3143
                break;
 
3144
        }
 
3145
        case 14:
 
3146
        {
 
3147
                static const char * const attrs2[] = {"userWorkstations", NULL};
 
3148
                attrs = attrs2;
 
3149
                break;
 
3150
        }
 
3151
        case 16:
 
3152
        {
 
3153
                static const char * const attrs2[] = {"userAccountControl", "pwdLastSet", NULL};
 
3154
                attrs = attrs2;
 
3155
                break;
 
3156
        }
 
3157
        case 17:
 
3158
        {
 
3159
                static const char * const attrs2[] = {"accountExpires", NULL};
 
3160
                attrs = attrs2;
 
3161
                break;
 
3162
        }
 
3163
        case 20:
 
3164
        {
 
3165
                static const char * const attrs2[] = {"userParameters", NULL};
 
3166
                attrs = attrs2;
 
3167
                break;
 
3168
        }
 
3169
        case 21:
 
3170
        {
 
3171
                static const char * const attrs2[] = {"lastLogon",
 
3172
                                                      "lastLogoff",
 
3173
                                                      "pwdLastSet",
 
3174
                                                      "accountExpires",
 
3175
                                                      "sAMAccountName",
 
3176
                                                      "displayName",
 
3177
                                                      "homeDirectory",
 
3178
                                                      "homeDrive",
 
3179
                                                      "scriptPath",
 
3180
                                                      "profilePath",
 
3181
                                                      "description",
 
3182
                                                      "userWorkstations",
 
3183
                                                      "comment",
 
3184
                                                      "userParameters",
 
3185
                                                      "objectSid",
 
3186
                                                      "primaryGroupID",
 
3187
                                                      "userAccountControl",
 
3188
                                                      "logonHours",
 
3189
                                                      "badPwdCount",
 
3190
                                                      "logonCount",
 
3191
                                                      "countryCode",
 
3192
                                                      "codePage",
 
3193
                                                      NULL};
 
3194
                attrs = attrs2;
 
3195
                break;
 
3196
        }
 
3197
        }
 
3198
 
 
3199
        /* pull all the user attributes */
 
3200
        ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
 
3201
                              a_state->account_dn ,&res, attrs);
 
3202
        if (ret != 1) {
 
3203
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
3204
        }
 
3205
        msg = res[0];
 
3206
 
 
3207
        /* allocate the info structure */
 
3208
        info = talloc_zero(mem_ctx, union samr_UserInfo);
 
3209
        if (info == NULL) {
 
3210
                return NT_STATUS_NO_MEMORY;
 
3211
        }
 
3212
 
 
3213
        /* fill in the reply */
 
3214
        switch (r->in.level) {
 
3215
        case 1:
 
3216
                QUERY_STRING(msg, info1.account_name,          "sAMAccountName");
 
3217
                QUERY_STRING(msg, info1.full_name,             "displayName");
 
3218
                QUERY_UINT  (msg, info1.primary_gid,           "primaryGroupID");
 
3219
                QUERY_STRING(msg, info1.description,           "description");
 
3220
                QUERY_STRING(msg, info1.comment,               "comment");
 
3221
                break;
 
3222
 
 
3223
        case 2:
 
3224
                QUERY_STRING(msg, info2.comment,               "comment");
 
3225
                QUERY_UINT  (msg, info2.country_code,          "countryCode");
 
3226
                QUERY_UINT  (msg, info2.code_page,             "codePage");
 
3227
                break;
 
3228
 
 
3229
        case 3:
 
3230
                QUERY_STRING(msg, info3.account_name,          "sAMAccountName");
 
3231
                QUERY_STRING(msg, info3.full_name,             "displayName");
 
3232
                QUERY_RID   (msg, info3.rid,                   "objectSid");
 
3233
                QUERY_UINT  (msg, info3.primary_gid,           "primaryGroupID");
 
3234
                QUERY_STRING(msg, info3.home_directory,        "homeDirectory");
 
3235
                QUERY_STRING(msg, info3.home_drive,            "homeDrive");
 
3236
                QUERY_STRING(msg, info3.logon_script,          "scriptPath");
 
3237
                QUERY_STRING(msg, info3.profile_path,          "profilePath");
 
3238
                QUERY_STRING(msg, info3.workstations,          "userWorkstations");
 
3239
                QUERY_UINT64(msg, info3.last_logon,            "lastLogon");
 
3240
                QUERY_UINT64(msg, info3.last_logoff,           "lastLogoff");
 
3241
                QUERY_UINT64(msg, info3.last_password_change,  "pwdLastSet");
 
3242
                QUERY_APASSC(msg, info3.allow_password_change, "pwdLastSet");
 
3243
                QUERY_FPASSC(msg, info3.force_password_change, "pwdLastSet");
 
3244
                QUERY_LHOURS(msg, info3.logon_hours,           "logonHours");
 
3245
                QUERY_UINT  (msg, info3.bad_password_count,    "badPwdCount");
 
3246
                QUERY_UINT  (msg, info3.logon_count,           "logonCount");
 
3247
                QUERY_AFLAGS(msg, info3.acct_flags,            "userAccountControl");
 
3248
                break;
 
3249
 
 
3250
        case 4:
 
3251
                QUERY_LHOURS(msg, info4.logon_hours,           "logonHours");
 
3252
                break;
 
3253
 
 
3254
        case 5:
 
3255
                QUERY_STRING(msg, info5.account_name,          "sAMAccountName");
 
3256
                QUERY_STRING(msg, info5.full_name,             "displayName");
 
3257
                QUERY_RID   (msg, info5.rid,                   "objectSid");
 
3258
                QUERY_UINT  (msg, info5.primary_gid,           "primaryGroupID");
 
3259
                QUERY_STRING(msg, info5.home_directory,        "homeDirectory");
 
3260
                QUERY_STRING(msg, info5.home_drive,            "homeDrive");
 
3261
                QUERY_STRING(msg, info5.logon_script,          "scriptPath");
 
3262
                QUERY_STRING(msg, info5.profile_path,          "profilePath");
 
3263
                QUERY_STRING(msg, info5.description,           "description");
 
3264
                QUERY_STRING(msg, info5.workstations,          "userWorkstations");
 
3265
                QUERY_UINT64(msg, info5.last_logon,            "lastLogon");
 
3266
                QUERY_UINT64(msg, info5.last_logoff,           "lastLogoff");
 
3267
                QUERY_LHOURS(msg, info5.logon_hours,           "logonHours");
 
3268
                QUERY_UINT  (msg, info5.bad_password_count,    "badPwdCount");
 
3269
                QUERY_UINT  (msg, info5.logon_count,           "logonCount");
 
3270
                QUERY_UINT64(msg, info5.last_password_change,  "pwdLastSet");
 
3271
                QUERY_UINT64(msg, info5.acct_expiry,           "accountExpires");
 
3272
                QUERY_AFLAGS(msg, info5.acct_flags,            "userAccountControl");
 
3273
                break;
 
3274
 
 
3275
        case 6:
 
3276
                QUERY_STRING(msg, info6.account_name,   "sAMAccountName");
 
3277
                QUERY_STRING(msg, info6.full_name,      "displayName");
 
3278
                break;
 
3279
 
 
3280
        case 7:
 
3281
                QUERY_STRING(msg, info7.account_name,   "sAMAccountName");
 
3282
                break;
 
3283
 
 
3284
        case 8:
 
3285
                QUERY_STRING(msg, info8.full_name,      "displayName");
 
3286
                break;
 
3287
 
 
3288
        case 9:
 
3289
                QUERY_UINT  (msg, info9.primary_gid,    "primaryGroupID");
 
3290
                break;
 
3291
 
 
3292
        case 10:
 
3293
                QUERY_STRING(msg, info10.home_directory,"homeDirectory");
 
3294
                QUERY_STRING(msg, info10.home_drive,    "homeDrive");
 
3295
                break;
 
3296
 
 
3297
        case 11:
 
3298
                QUERY_STRING(msg, info11.logon_script,  "scriptPath");
 
3299
                break;
 
3300
 
 
3301
        case 12:
 
3302
                QUERY_STRING(msg, info12.profile_path,  "profilePath");
 
3303
                break;
 
3304
 
 
3305
        case 13:
 
3306
                QUERY_STRING(msg, info13.description,   "description");
 
3307
                break;
 
3308
 
 
3309
        case 14:
 
3310
                QUERY_STRING(msg, info14.workstations,  "userWorkstations");
 
3311
                break;
 
3312
 
 
3313
        case 16:
 
3314
                QUERY_AFLAGS(msg, info16.acct_flags,    "userAccountControl");
 
3315
                break;
 
3316
 
 
3317
        case 17:
 
3318
                QUERY_UINT64(msg, info17.acct_expiry,   "accountExpires");
 
3319
                break;
 
3320
 
 
3321
        case 20:
 
3322
                QUERY_PARAMETERS(msg, info20.parameters,    "userParameters");
 
3323
                break;
 
3324
 
 
3325
        case 21:
 
3326
                QUERY_UINT64(msg, info21.last_logon,           "lastLogon");
 
3327
                QUERY_UINT64(msg, info21.last_logoff,          "lastLogoff");
 
3328
                QUERY_UINT64(msg, info21.last_password_change, "pwdLastSet");
 
3329
                QUERY_UINT64(msg, info21.acct_expiry,          "accountExpires");
 
3330
                QUERY_APASSC(msg, info21.allow_password_change,"pwdLastSet");
 
3331
                QUERY_FPASSC(msg, info21.force_password_change,"pwdLastSet");
 
3332
                QUERY_STRING(msg, info21.account_name,         "sAMAccountName");
 
3333
                QUERY_STRING(msg, info21.full_name,            "displayName");
 
3334
                QUERY_STRING(msg, info21.home_directory,       "homeDirectory");
 
3335
                QUERY_STRING(msg, info21.home_drive,           "homeDrive");
 
3336
                QUERY_STRING(msg, info21.logon_script,         "scriptPath");
 
3337
                QUERY_STRING(msg, info21.profile_path,         "profilePath");
 
3338
                QUERY_STRING(msg, info21.description,          "description");
 
3339
                QUERY_STRING(msg, info21.workstations,         "userWorkstations");
 
3340
                QUERY_STRING(msg, info21.comment,              "comment");
 
3341
                QUERY_PARAMETERS(msg, info21.parameters,       "userParameters");
 
3342
                QUERY_RID   (msg, info21.rid,                  "objectSid");
 
3343
                QUERY_UINT  (msg, info21.primary_gid,          "primaryGroupID");
 
3344
                QUERY_AFLAGS(msg, info21.acct_flags,           "userAccountControl");
 
3345
                info->info21.fields_present = 0x00FFFFFF;
 
3346
                QUERY_LHOURS(msg, info21.logon_hours,          "logonHours");
 
3347
                QUERY_UINT  (msg, info21.bad_password_count,   "badPwdCount");
 
3348
                QUERY_UINT  (msg, info21.logon_count,          "logonCount");
 
3349
                QUERY_UINT  (msg, info21.country_code,         "countryCode");
 
3350
                QUERY_UINT  (msg, info21.code_page,            "codePage");
 
3351
                break;
 
3352
                
 
3353
 
 
3354
        default:
 
3355
                talloc_free(info);
 
3356
                return NT_STATUS_INVALID_INFO_CLASS;
 
3357
        }
 
3358
 
 
3359
        *r->out.info = info;
 
3360
 
 
3361
        return NT_STATUS_OK;
 
3362
}
 
3363
 
 
3364
 
 
3365
/* 
 
3366
  samr_SetUserInfo 
 
3367
*/
 
3368
static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3369
                                 struct samr_SetUserInfo *r)
 
3370
{
 
3371
        struct dcesrv_handle *h;
 
3372
        struct samr_account_state *a_state;
 
3373
        struct ldb_message *msg;
 
3374
        int ret;
 
3375
        NTSTATUS status = NT_STATUS_OK;
 
3376
        struct ldb_context *sam_ctx;
 
3377
 
 
3378
        DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
 
3379
 
 
3380
        a_state = h->data;
 
3381
        sam_ctx = a_state->sam_ctx;
 
3382
 
 
3383
        msg = ldb_msg_new(mem_ctx);
 
3384
        if (msg == NULL) {
 
3385
                return NT_STATUS_NO_MEMORY;
 
3386
        }
 
3387
 
 
3388
        msg->dn = talloc_reference(mem_ctx, a_state->account_dn);
 
3389
        if (!msg->dn) {
 
3390
                return NT_STATUS_NO_MEMORY;
 
3391
        }
 
3392
 
 
3393
        switch (r->in.level) {
 
3394
        case 2:
 
3395
                SET_STRING(msg, info2.comment,          "comment");
 
3396
                SET_UINT  (msg, info2.country_code,     "countryCode");
 
3397
                SET_UINT  (msg, info2.code_page,        "codePage");
 
3398
                break;
 
3399
 
 
3400
        case 4:
 
3401
                SET_LHOURS(msg, info4.logon_hours,      "logonHours");
 
3402
                break;
 
3403
 
 
3404
        case 6:
 
3405
                SET_STRING(msg, info6.full_name,        "displayName");
 
3406
                break;
 
3407
 
 
3408
        case 7:
 
3409
                SET_STRING(msg, info7.account_name,     "samAccountName");
 
3410
                break;
 
3411
 
 
3412
        case 8:
 
3413
                SET_STRING(msg, info8.full_name,        "displayName");
 
3414
                break;
 
3415
 
 
3416
        case 9:
 
3417
                SET_UINT(msg, info9.primary_gid,        "primaryGroupID");
 
3418
                break;
 
3419
 
 
3420
        case 10:
 
3421
                SET_STRING(msg, info10.home_directory,  "homeDirectory");
 
3422
                SET_STRING(msg, info10.home_drive,      "homeDrive");
 
3423
                break;
 
3424
 
 
3425
        case 11:
 
3426
                SET_STRING(msg, info11.logon_script,    "scriptPath");
 
3427
                break;
 
3428
 
 
3429
        case 12:
 
3430
                SET_STRING(msg, info12.profile_path,    "profilePath");
 
3431
                break;
 
3432
 
 
3433
        case 13:
 
3434
                SET_STRING(msg, info13.description,     "description");
 
3435
                break;
 
3436
 
 
3437
        case 14:
 
3438
                SET_STRING(msg, info14.workstations,    "userWorkstations");
 
3439
                break;
 
3440
 
 
3441
        case 16:
 
3442
                SET_AFLAGS(msg, info16.acct_flags,      "userAccountControl");
 
3443
                break;
 
3444
 
 
3445
        case 17:
 
3446
                SET_UINT64(msg, info17.acct_expiry,     "accountExpires");
 
3447
                break;
 
3448
 
 
3449
        case 20:
 
3450
                SET_PARAMETERS(msg, info20.parameters,      "userParameters");
 
3451
                break;
 
3452
 
 
3453
        case 21:
 
3454
#define IFSET(bit) if (bit & r->in.info->info21.fields_present) 
 
3455
                IFSET(SAMR_FIELD_ACCT_EXPIRY)
 
3456
                        SET_UINT64(msg, info21.acct_expiry,    "accountExpires");       
 
3457
                IFSET(SAMR_FIELD_ACCOUNT_NAME)         
 
3458
                        SET_STRING(msg, info21.account_name,   "samAccountName");
 
3459
                IFSET(SAMR_FIELD_FULL_NAME) 
 
3460
                        SET_STRING(msg, info21.full_name,      "displayName");
 
3461
                IFSET(SAMR_FIELD_DESCRIPTION)
 
3462
                        SET_STRING(msg, info21.description,    "description");
 
3463
                IFSET(SAMR_FIELD_COMMENT)
 
3464
                        SET_STRING(msg, info21.comment,        "comment");
 
3465
                IFSET(SAMR_FIELD_LOGON_SCRIPT)
 
3466
                        SET_STRING(msg, info21.logon_script,   "scriptPath");
 
3467
                IFSET(SAMR_FIELD_PROFILE_PATH)
 
3468
                        SET_STRING(msg, info21.profile_path,   "profilePath");
 
3469
                IFSET(SAMR_FIELD_HOME_DIRECTORY)
 
3470
                        SET_STRING(msg, info21.home_directory, "homeDirectory");
 
3471
                IFSET(SAMR_FIELD_HOME_DRIVE)
 
3472
                        SET_STRING(msg, info21.home_drive,     "homeDrive");
 
3473
                IFSET(SAMR_FIELD_WORKSTATIONS)
 
3474
                        SET_STRING(msg, info21.workstations,   "userWorkstations");
 
3475
                IFSET(SAMR_FIELD_LOGON_HOURS)
 
3476
                        SET_LHOURS(msg, info21.logon_hours,    "logonHours");
 
3477
                IFSET(SAMR_FIELD_ACCT_FLAGS)
 
3478
                        SET_AFLAGS(msg, info21.acct_flags,     "userAccountControl");
 
3479
                IFSET(SAMR_FIELD_PARAMETERS)   
 
3480
                        SET_PARAMETERS(msg, info21.parameters, "userParameters");
 
3481
                IFSET(SAMR_FIELD_COUNTRY_CODE)
 
3482
                        SET_UINT  (msg, info21.country_code,   "countryCode");
 
3483
                IFSET(SAMR_FIELD_CODE_PAGE)
 
3484
                        SET_UINT  (msg, info21.code_page,      "codePage");     
 
3485
#undef IFSET
 
3486
                break;
 
3487
 
 
3488
        case 23:
 
3489
#define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
 
3490
                IFSET(SAMR_FIELD_ACCT_EXPIRY)
 
3491
                        SET_UINT64(msg, info23.info.acct_expiry,  "accountExpires");    
 
3492
                IFSET(SAMR_FIELD_ACCOUNT_NAME)         
 
3493
                        SET_STRING(msg, info23.info.account_name, "samAccountName");
 
3494
                IFSET(SAMR_FIELD_FULL_NAME)         
 
3495
                        SET_STRING(msg, info23.info.full_name,    "displayName");
 
3496
                IFSET(SAMR_FIELD_DESCRIPTION)  
 
3497
                        SET_STRING(msg, info23.info.description,  "description");
 
3498
                IFSET(SAMR_FIELD_COMMENT)      
 
3499
                        SET_STRING(msg, info23.info.comment,      "comment");
 
3500
                IFSET(SAMR_FIELD_LOGON_SCRIPT) 
 
3501
                        SET_STRING(msg, info23.info.logon_script, "scriptPath");
 
3502
                IFSET(SAMR_FIELD_PROFILE_PATH)      
 
3503
                        SET_STRING(msg, info23.info.profile_path, "profilePath");
 
3504
                IFSET(SAMR_FIELD_WORKSTATIONS)  
 
3505
                        SET_STRING(msg, info23.info.workstations, "userWorkstations");
 
3506
                IFSET(SAMR_FIELD_LOGON_HOURS)  
 
3507
                        SET_LHOURS(msg, info23.info.logon_hours,  "logonHours");
 
3508
                IFSET(SAMR_FIELD_ACCT_FLAGS)     
 
3509
                        SET_AFLAGS(msg, info23.info.acct_flags,   "userAccountControl");
 
3510
                IFSET(SAMR_FIELD_PARAMETERS)     
 
3511
                        SET_PARAMETERS(msg, info23.info.parameters, "userParameters");
 
3512
                IFSET(SAMR_FIELD_COUNTRY_CODE) 
 
3513
                        SET_UINT  (msg, info23.info.country_code, "countryCode");
 
3514
                IFSET(SAMR_FIELD_CODE_PAGE)    
 
3515
                        SET_UINT  (msg, info23.info.code_page,    "codePage");
 
3516
                IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) {
 
3517
                        status = samr_set_password(dce_call,
 
3518
                                                   a_state->sam_ctx,
 
3519
                                                   a_state->account_dn,
 
3520
                                                   a_state->domain_state->domain_dn,
 
3521
                                                   mem_ctx, msg, 
 
3522
                                                   &r->in.info->info23.password);
 
3523
                } else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) {
 
3524
                        status = samr_set_password(dce_call,
 
3525
                                                   a_state->sam_ctx,
 
3526
                                                   a_state->account_dn,
 
3527
                                                   a_state->domain_state->domain_dn,
 
3528
                                                   mem_ctx, msg, 
 
3529
                                                   &r->in.info->info23.password);
 
3530
                }
 
3531
#undef IFSET
 
3532
                break;
 
3533
 
 
3534
                /* the set password levels are handled separately */
 
3535
        case 24:
 
3536
                status = samr_set_password(dce_call,
 
3537
                                           a_state->sam_ctx,
 
3538
                                           a_state->account_dn,
 
3539
                                           a_state->domain_state->domain_dn,
 
3540
                                           mem_ctx, msg, 
 
3541
                                           &r->in.info->info24.password);
 
3542
                break;
 
3543
 
 
3544
        case 25:
 
3545
#define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
 
3546
                IFSET(SAMR_FIELD_ACCT_EXPIRY)
 
3547
                        SET_UINT64(msg, info25.info.acct_expiry,  "accountExpires");    
 
3548
                IFSET(SAMR_FIELD_ACCOUNT_NAME)         
 
3549
                        SET_STRING(msg, info25.info.account_name, "samAccountName");
 
3550
                IFSET(SAMR_FIELD_FULL_NAME)         
 
3551
                        SET_STRING(msg, info25.info.full_name,    "displayName");
 
3552
                IFSET(SAMR_FIELD_DESCRIPTION)  
 
3553
                        SET_STRING(msg, info25.info.description,  "description");
 
3554
                IFSET(SAMR_FIELD_COMMENT)      
 
3555
                        SET_STRING(msg, info25.info.comment,      "comment");
 
3556
                IFSET(SAMR_FIELD_LOGON_SCRIPT) 
 
3557
                        SET_STRING(msg, info25.info.logon_script, "scriptPath");
 
3558
                IFSET(SAMR_FIELD_PROFILE_PATH)      
 
3559
                        SET_STRING(msg, info25.info.profile_path, "profilePath");
 
3560
                IFSET(SAMR_FIELD_WORKSTATIONS)  
 
3561
                        SET_STRING(msg, info25.info.workstations, "userWorkstations");
 
3562
                IFSET(SAMR_FIELD_LOGON_HOURS)  
 
3563
                        SET_LHOURS(msg, info25.info.logon_hours,  "logonHours");
 
3564
                IFSET(SAMR_FIELD_ACCT_FLAGS)     
 
3565
                        SET_AFLAGS(msg, info25.info.acct_flags,   "userAccountControl");
 
3566
                IFSET(SAMR_FIELD_PARAMETERS)     
 
3567
                        SET_PARAMETERS(msg, info25.info.parameters, "userParameters");
 
3568
                IFSET(SAMR_FIELD_COUNTRY_CODE) 
 
3569
                        SET_UINT  (msg, info25.info.country_code, "countryCode");
 
3570
                IFSET(SAMR_FIELD_CODE_PAGE)    
 
3571
                        SET_UINT  (msg, info25.info.code_page,    "codePage");
 
3572
                IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) {
 
3573
                        status = samr_set_password_ex(dce_call,
 
3574
                                                      a_state->sam_ctx,
 
3575
                                                      a_state->account_dn,
 
3576
                                                      a_state->domain_state->domain_dn,
 
3577
                                                      mem_ctx, msg, 
 
3578
                                                      &r->in.info->info25.password);
 
3579
                } else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) {
 
3580
                        status = samr_set_password_ex(dce_call,
 
3581
                                                      a_state->sam_ctx,
 
3582
                                                      a_state->account_dn,
 
3583
                                                      a_state->domain_state->domain_dn,
 
3584
                                                      mem_ctx, msg, 
 
3585
                                                      &r->in.info->info25.password);
 
3586
                }
 
3587
#undef IFSET
 
3588
                break;
 
3589
 
 
3590
                /* the set password levels are handled separately */
 
3591
        case 26:
 
3592
                status = samr_set_password_ex(dce_call,
 
3593
                                              a_state->sam_ctx,
 
3594
                                              a_state->account_dn,
 
3595
                                              a_state->domain_state->domain_dn,
 
3596
                                              mem_ctx, msg, 
 
3597
                                              &r->in.info->info26.password);
 
3598
                break;
 
3599
                
 
3600
 
 
3601
        default:
 
3602
                /* many info classes are not valid for SetUserInfo */
 
3603
                return NT_STATUS_INVALID_INFO_CLASS;
 
3604
        }
 
3605
 
 
3606
        if (!NT_STATUS_IS_OK(status)) {
 
3607
                return status;
 
3608
        }
 
3609
 
 
3610
        /* modify the samdb record */
 
3611
        ret = ldb_modify(a_state->sam_ctx, msg);
 
3612
        if (ret != 0) {
 
3613
                DEBUG(1,("Failed to modify record %s: %s\n",
 
3614
                         ldb_dn_get_linearized(a_state->account_dn),
 
3615
                         ldb_errstring(a_state->sam_ctx)));
 
3616
 
 
3617
                /* we really need samdb.c to return NTSTATUS */
 
3618
                return NT_STATUS_UNSUCCESSFUL;
 
3619
        }
 
3620
 
 
3621
        return NT_STATUS_OK;
 
3622
}
 
3623
 
 
3624
 
 
3625
/* 
 
3626
  samr_GetGroupsForUser 
 
3627
*/
 
3628
static NTSTATUS dcesrv_samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3629
                       struct samr_GetGroupsForUser *r)
 
3630
{
 
3631
        struct dcesrv_handle *h;
 
3632
        struct samr_account_state *a_state;
 
3633
        struct samr_domain_state *d_state;
 
3634
        struct ldb_message **res;
 
3635
        const char * const attrs[2] = { "objectSid", NULL };
 
3636
        struct samr_RidWithAttributeArray *array;
 
3637
        int count;
 
3638
 
 
3639
        DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
 
3640
 
 
3641
        a_state = h->data;
 
3642
        d_state = a_state->domain_state;
 
3643
 
 
3644
        count = samdb_search_domain(a_state->sam_ctx, mem_ctx, d_state->domain_dn, &res,
 
3645
                                    attrs, d_state->domain_sid,
 
3646
                                    "(&(member=%s)(grouptype=%d)(objectclass=group))",
 
3647
                                    ldb_dn_get_linearized(a_state->account_dn),
 
3648
                                    GTYPE_SECURITY_GLOBAL_GROUP);
 
3649
        if (count < 0)
 
3650
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
3651
 
 
3652
        array = talloc(mem_ctx, struct samr_RidWithAttributeArray);
 
3653
        if (array == NULL)
 
3654
                return NT_STATUS_NO_MEMORY;
 
3655
 
 
3656
        array->count = 0;
 
3657
        array->rids = NULL;
 
3658
 
 
3659
        if (count > 0) {
 
3660
                int i;
 
3661
                array->rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
 
3662
                                            count);
 
3663
 
 
3664
                if (array->rids == NULL)
 
3665
                        return NT_STATUS_NO_MEMORY;
 
3666
 
 
3667
                for (i=0; i<count; i++) {
 
3668
                        struct dom_sid *group_sid;
 
3669
 
 
3670
                        group_sid = samdb_result_dom_sid(mem_ctx, res[i],
 
3671
                                                         "objectSid");
 
3672
                        if (group_sid == NULL) {
 
3673
                                DEBUG(0, ("Couldn't find objectSid attrib\n"));
 
3674
                                continue;
 
3675
                        }
 
3676
 
 
3677
                        array->rids[array->count].rid =
 
3678
                                group_sid->sub_auths[group_sid->num_auths-1];
 
3679
                        array->rids[array->count].attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
 
3680
                        array->count += 1;
 
3681
                }
 
3682
        }
 
3683
 
 
3684
        *r->out.rids = array;
 
3685
 
 
3686
        return NT_STATUS_OK;
 
3687
}
 
3688
 
 
3689
 
 
3690
/* 
 
3691
  samr_QueryDisplayInfo 
 
3692
*/
 
3693
static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3694
                       struct samr_QueryDisplayInfo *r)
 
3695
{
 
3696
        struct dcesrv_handle *h;
 
3697
        struct samr_domain_state *d_state;
 
3698
        struct ldb_message **res;
 
3699
        int ldb_cnt, count, i;
 
3700
        const char * const attrs[] = { "objectSid", "sAMAccountName", "displayName",
 
3701
                                       "description", "userAccountControl", "pwdLastSet", NULL };
 
3702
        struct samr_DispEntryFull *entriesFull = NULL;
 
3703
        struct samr_DispEntryFullGroup *entriesFullGroup = NULL;
 
3704
        struct samr_DispEntryAscii *entriesAscii = NULL;
 
3705
        struct samr_DispEntryGeneral * entriesGeneral = NULL;
 
3706
        const char *filter;
 
3707
 
 
3708
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
3709
 
 
3710
        d_state = h->data;
 
3711
 
 
3712
        switch (r->in.level) {
 
3713
        case 1:
 
3714
        case 4:
 
3715
                filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)"
 
3716
                                         "(sAMAccountType=%u))",
 
3717
                                         ATYPE_NORMAL_ACCOUNT);
 
3718
                break;
 
3719
        case 2:
 
3720
                filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)"
 
3721
                                         "(sAMAccountType=%u))",
 
3722
                                         ATYPE_WORKSTATION_TRUST);
 
3723
                break;
 
3724
        case 3:
 
3725
        case 5:
 
3726
                filter = talloc_asprintf(mem_ctx, "(&(grouptype=%d)"
 
3727
                                         "(objectclass=group))",
 
3728
                                         GTYPE_SECURITY_GLOBAL_GROUP);
 
3729
                break;
 
3730
        default:
 
3731
                return NT_STATUS_INVALID_INFO_CLASS;
 
3732
        }
 
3733
 
 
3734
        /* search for all requested objects in this domain. This could
 
3735
           possibly be cached and resumed based on resume_key */
 
3736
        ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
 
3737
                                      d_state->domain_dn, &res, attrs,
 
3738
                                      d_state->domain_sid, "%s", filter);
 
3739
        if (ldb_cnt == -1) {
 
3740
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
3741
        }
 
3742
        if (ldb_cnt == 0 || r->in.max_entries == 0) {
 
3743
                return NT_STATUS_OK;
 
3744
        }
 
3745
 
 
3746
        switch (r->in.level) {
 
3747
        case 1:
 
3748
                entriesGeneral = talloc_array(mem_ctx,
 
3749
                                                struct samr_DispEntryGeneral,
 
3750
                                                ldb_cnt);
 
3751
                break;
 
3752
        case 2:
 
3753
                entriesFull = talloc_array(mem_ctx,
 
3754
                                             struct samr_DispEntryFull,
 
3755
                                             ldb_cnt);
 
3756
                break;
 
3757
        case 3:
 
3758
                entriesFullGroup = talloc_array(mem_ctx,
 
3759
                                             struct samr_DispEntryFullGroup,
 
3760
                                             ldb_cnt);
 
3761
                break;
 
3762
        case 4:
 
3763
        case 5:
 
3764
                entriesAscii = talloc_array(mem_ctx,
 
3765
                                              struct samr_DispEntryAscii,
 
3766
                                              ldb_cnt);
 
3767
                break;
 
3768
        }
 
3769
 
 
3770
        if ((entriesGeneral == NULL) && (entriesFull == NULL) &&
 
3771
            (entriesAscii == NULL) && (entriesFullGroup == NULL))
 
3772
                return NT_STATUS_NO_MEMORY;
 
3773
 
 
3774
        count = 0;
 
3775
 
 
3776
        for (i=0; i<ldb_cnt; i++) {
 
3777
                struct dom_sid *objectsid;
 
3778
 
 
3779
                objectsid = samdb_result_dom_sid(mem_ctx, res[i],
 
3780
                                                 "objectSid");
 
3781
                if (objectsid == NULL)
 
3782
                        continue;
 
3783
 
 
3784
                switch(r->in.level) {
 
3785
                case 1:
 
3786
                        entriesGeneral[count].idx = count + 1;
 
3787
                        entriesGeneral[count].rid = 
 
3788
                                objectsid->sub_auths[objectsid->num_auths-1];
 
3789
                        entriesGeneral[count].acct_flags =
 
3790
                                samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
 
3791
                                                        res[i], 
 
3792
                                                        d_state->domain_dn);
 
3793
                        entriesGeneral[count].account_name.string =
 
3794
                                samdb_result_string(res[i],
 
3795
                                                    "sAMAccountName", "");
 
3796
                        entriesGeneral[count].full_name.string =
 
3797
                                samdb_result_string(res[i], "displayName", "");
 
3798
                        entriesGeneral[count].description.string =
 
3799
                                samdb_result_string(res[i], "description", "");
 
3800
                        break;
 
3801
                case 2:
 
3802
                        entriesFull[count].idx = count + 1;
 
3803
                        entriesFull[count].rid =
 
3804
                                objectsid->sub_auths[objectsid->num_auths-1];
 
3805
 
 
3806
                        /* No idea why we need to or in ACB_NORMAL here, but this is what Win2k3 seems to do... */
 
3807
                        entriesFull[count].acct_flags =
 
3808
                                samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
 
3809
                                                        res[i], 
 
3810
                                                        d_state->domain_dn) | ACB_NORMAL;
 
3811
                        entriesFull[count].account_name.string =
 
3812
                                samdb_result_string(res[i], "sAMAccountName",
 
3813
                                                    "");
 
3814
                        entriesFull[count].description.string =
 
3815
                                samdb_result_string(res[i], "description", "");
 
3816
                        break;
 
3817
                case 3:
 
3818
                        entriesFullGroup[count].idx = count + 1;
 
3819
                        entriesFullGroup[count].rid =
 
3820
                                objectsid->sub_auths[objectsid->num_auths-1];
 
3821
                        /* We get a "7" here for groups */
 
3822
                        entriesFullGroup[count].acct_flags
 
3823
                                = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
 
3824
                        entriesFullGroup[count].account_name.string =
 
3825
                                samdb_result_string(res[i], "sAMAccountName",
 
3826
                                                    "");
 
3827
                        entriesFullGroup[count].description.string =
 
3828
                                samdb_result_string(res[i], "description", "");
 
3829
                        break;
 
3830
                case 4:
 
3831
                case 5:
 
3832
                        entriesAscii[count].idx = count + 1;
 
3833
                        entriesAscii[count].account_name.string =
 
3834
                                samdb_result_string(res[i], "sAMAccountName",
 
3835
                                                    "");
 
3836
                        break;
 
3837
                }
 
3838
 
 
3839
                count += 1;
 
3840
        }
 
3841
 
 
3842
        *r->out.total_size = count;
 
3843
 
 
3844
        if (r->in.start_idx >= count) {
 
3845
                *r->out.returned_size = 0;
 
3846
                switch(r->in.level) {
 
3847
                case 1:
 
3848
                        r->out.info->info1.count = *r->out.returned_size;
 
3849
                        r->out.info->info1.entries = NULL;
 
3850
                        break;
 
3851
                case 2:
 
3852
                        r->out.info->info2.count = *r->out.returned_size;
 
3853
                        r->out.info->info2.entries = NULL;
 
3854
                        break;
 
3855
                case 3:
 
3856
                        r->out.info->info3.count = *r->out.returned_size;
 
3857
                        r->out.info->info3.entries = NULL;
 
3858
                        break;
 
3859
                case 4:
 
3860
                        r->out.info->info4.count = *r->out.returned_size;
 
3861
                        r->out.info->info4.entries = NULL;
 
3862
                        break;
 
3863
                case 5:
 
3864
                        r->out.info->info5.count = *r->out.returned_size;
 
3865
                        r->out.info->info5.entries = NULL;
 
3866
                        break;
 
3867
                }
 
3868
        } else {
 
3869
                *r->out.returned_size = MIN(count - r->in.start_idx,
 
3870
                                           r->in.max_entries);
 
3871
                switch(r->in.level) {
 
3872
                case 1:
 
3873
                        r->out.info->info1.count = *r->out.returned_size;
 
3874
                        r->out.info->info1.entries =
 
3875
                                &(entriesGeneral[r->in.start_idx]);
 
3876
                        break;
 
3877
                case 2:
 
3878
                        r->out.info->info2.count = *r->out.returned_size;
 
3879
                        r->out.info->info2.entries =
 
3880
                                &(entriesFull[r->in.start_idx]);
 
3881
                        break;
 
3882
                case 3:
 
3883
                        r->out.info->info3.count = *r->out.returned_size;
 
3884
                        r->out.info->info3.entries =
 
3885
                                &(entriesFullGroup[r->in.start_idx]);
 
3886
                        break;
 
3887
                case 4:
 
3888
                        r->out.info->info4.count = *r->out.returned_size;
 
3889
                        r->out.info->info4.entries =
 
3890
                                &(entriesAscii[r->in.start_idx]);
 
3891
                        break;
 
3892
                case 5:
 
3893
                        r->out.info->info5.count = *r->out.returned_size;
 
3894
                        r->out.info->info5.entries =
 
3895
                                &(entriesAscii[r->in.start_idx]);
 
3896
                        break;
 
3897
                }
 
3898
        }
 
3899
 
 
3900
        return (*r->out.returned_size < (count - r->in.start_idx)) ?
 
3901
                STATUS_MORE_ENTRIES : NT_STATUS_OK;
 
3902
}
 
3903
 
 
3904
 
 
3905
/* 
 
3906
  samr_GetDisplayEnumerationIndex 
 
3907
*/
 
3908
static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3909
                       struct samr_GetDisplayEnumerationIndex *r)
 
3910
{
 
3911
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
3912
}
 
3913
 
 
3914
 
 
3915
/* 
 
3916
  samr_TestPrivateFunctionsDomain 
 
3917
*/
 
3918
static NTSTATUS dcesrv_samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3919
                       struct samr_TestPrivateFunctionsDomain *r)
 
3920
{
 
3921
        return NT_STATUS_NOT_IMPLEMENTED;
 
3922
}
 
3923
 
 
3924
 
 
3925
/* 
 
3926
  samr_TestPrivateFunctionsUser 
 
3927
*/
 
3928
static NTSTATUS dcesrv_samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3929
                       struct samr_TestPrivateFunctionsUser *r)
 
3930
{
 
3931
        return NT_STATUS_NOT_IMPLEMENTED;
 
3932
}
 
3933
 
 
3934
 
 
3935
/* 
 
3936
  samr_GetUserPwInfo 
 
3937
*/
 
3938
static NTSTATUS dcesrv_samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3939
                                   struct samr_GetUserPwInfo *r)
 
3940
{
 
3941
        struct dcesrv_handle *h;
 
3942
        struct samr_account_state *a_state;
 
3943
 
 
3944
        ZERO_STRUCTP(r->out.info);
 
3945
 
 
3946
        DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
 
3947
 
 
3948
        a_state = h->data;
 
3949
 
 
3950
        r->out.info->min_password_length = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0,
 
3951
                                                             a_state->domain_state->domain_dn, "minPwdLength",
 
3952
                                                             NULL);
 
3953
        r->out.info->password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0,
 
3954
                                                             a_state->account_dn,
 
3955
                                                             "pwdProperties", NULL);
 
3956
        return NT_STATUS_OK;
 
3957
}
 
3958
 
 
3959
 
 
3960
/* 
 
3961
  samr_RemoveMemberFromForeignDomain 
 
3962
*/
 
3963
static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
3964
                       struct samr_RemoveMemberFromForeignDomain *r)
 
3965
{
 
3966
        struct dcesrv_handle *h;
 
3967
        struct samr_domain_state *d_state;
 
3968
        const char *memberdn;
 
3969
        struct ldb_message **res;
 
3970
        const char * const attrs[3] = { "distinguishedName", "objectSid", NULL };
 
3971
        int i, count;
 
3972
 
 
3973
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
3974
 
 
3975
        d_state = h->data;
 
3976
 
 
3977
        memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
 
3978
                                       "distinguishedName", "(objectSid=%s)", 
 
3979
                                       ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
 
3980
        /* Nothing to do */
 
3981
        if (memberdn == NULL) {
 
3982
                return NT_STATUS_OK;
 
3983
        }
 
3984
 
 
3985
        /* TODO: Does this call only remove alias members, or does it do this
 
3986
         * for domain groups as well? */
 
3987
 
 
3988
        count = samdb_search_domain(d_state->sam_ctx, mem_ctx,
 
3989
                                    d_state->domain_dn, &res, attrs,
 
3990
                                    d_state->domain_sid,
 
3991
                                    "(&(member=%s)(objectClass=group)"
 
3992
                                    "(|(groupType=%d)(groupType=%d)))",
 
3993
                                    memberdn,
 
3994
                                    GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
 
3995
                                    GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
 
3996
 
 
3997
        if (count < 0)
 
3998
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
3999
 
 
4000
        for (i=0; i<count; i++) {
 
4001
                struct ldb_message *mod;
 
4002
 
 
4003
                mod = ldb_msg_new(mem_ctx);
 
4004
                if (mod == NULL) {
 
4005
                        return NT_STATUS_NO_MEMORY;
 
4006
                }
 
4007
 
 
4008
                mod->dn = samdb_result_dn(d_state->sam_ctx, mod, res[i], "distinguishedName", NULL);
 
4009
                if (mod->dn == NULL) {
 
4010
                        talloc_free(mod);
 
4011
                        continue;
 
4012
                }
 
4013
 
 
4014
                if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod,
 
4015
                                         "member", memberdn) != 0)
 
4016
                        return NT_STATUS_NO_MEMORY;
 
4017
 
 
4018
                if (ldb_modify(d_state->sam_ctx, mod) != 0)
 
4019
                        return NT_STATUS_UNSUCCESSFUL;
 
4020
 
 
4021
                talloc_free(mod);
 
4022
        }
 
4023
 
 
4024
        return NT_STATUS_OK;
 
4025
}
 
4026
 
 
4027
 
 
4028
/* 
 
4029
  samr_QueryDomainInfo2 
 
4030
 
 
4031
  just an alias for samr_QueryDomainInfo
 
4032
*/
 
4033
static NTSTATUS dcesrv_samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4034
                       struct samr_QueryDomainInfo2 *r)
 
4035
{
 
4036
        struct samr_QueryDomainInfo r1;
 
4037
        NTSTATUS status;
 
4038
 
 
4039
        ZERO_STRUCT(r1.out);
 
4040
        r1.in.domain_handle = r->in.domain_handle;
 
4041
        r1.in.level  = r->in.level;
 
4042
        r1.out.info  = r->out.info;
 
4043
 
 
4044
        status = dcesrv_samr_QueryDomainInfo(dce_call, mem_ctx, &r1);
 
4045
        
 
4046
        return status;
 
4047
}
 
4048
 
 
4049
 
 
4050
/* 
 
4051
  samr_QueryUserInfo2 
 
4052
 
 
4053
  just an alias for samr_QueryUserInfo
 
4054
*/
 
4055
static NTSTATUS dcesrv_samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4056
                                    struct samr_QueryUserInfo2 *r)
 
4057
{
 
4058
        struct samr_QueryUserInfo r1;
 
4059
        NTSTATUS status;
 
4060
 
 
4061
        r1.in.user_handle = r->in.user_handle;
 
4062
        r1.in.level  = r->in.level;
 
4063
        r1.out.info  = r->out.info;
 
4064
        
 
4065
        status = dcesrv_samr_QueryUserInfo(dce_call, mem_ctx, &r1);
 
4066
 
 
4067
        return status;
 
4068
}
 
4069
 
 
4070
 
 
4071
/* 
 
4072
  samr_QueryDisplayInfo2 
 
4073
*/
 
4074
static NTSTATUS dcesrv_samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4075
                                       struct samr_QueryDisplayInfo2 *r)
 
4076
{
 
4077
        struct samr_QueryDisplayInfo q;
 
4078
        NTSTATUS result;
 
4079
 
 
4080
        q.in.domain_handle = r->in.domain_handle;
 
4081
        q.in.level = r->in.level;
 
4082
        q.in.start_idx = r->in.start_idx;
 
4083
        q.in.max_entries = r->in.max_entries;
 
4084
        q.in.buf_size = r->in.buf_size;
 
4085
        q.out.total_size = r->out.total_size;
 
4086
        q.out.returned_size = r->out.returned_size;
 
4087
        q.out.info = r->out.info;
 
4088
 
 
4089
        result = dcesrv_samr_QueryDisplayInfo(dce_call, mem_ctx, &q);
 
4090
 
 
4091
        return result;
 
4092
}
 
4093
 
 
4094
 
 
4095
/* 
 
4096
  samr_GetDisplayEnumerationIndex2 
 
4097
*/
 
4098
static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4099
                       struct samr_GetDisplayEnumerationIndex2 *r)
 
4100
{
 
4101
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
4102
}
 
4103
 
 
4104
 
 
4105
/* 
 
4106
  samr_QueryDisplayInfo3 
 
4107
*/
 
4108
static NTSTATUS dcesrv_samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4109
                       struct samr_QueryDisplayInfo3 *r)
 
4110
{
 
4111
        struct samr_QueryDisplayInfo q;
 
4112
        NTSTATUS result;
 
4113
 
 
4114
        q.in.domain_handle = r->in.domain_handle;
 
4115
        q.in.level = r->in.level;
 
4116
        q.in.start_idx = r->in.start_idx;
 
4117
        q.in.max_entries = r->in.max_entries;
 
4118
        q.in.buf_size = r->in.buf_size;
 
4119
        q.out.total_size = r->out.total_size;
 
4120
        q.out.returned_size = r->out.returned_size;
 
4121
        q.out.info = r->out.info;
 
4122
 
 
4123
        result = dcesrv_samr_QueryDisplayInfo(dce_call, mem_ctx, &q);
 
4124
 
 
4125
        return result;
 
4126
}
 
4127
 
 
4128
 
 
4129
/* 
 
4130
  samr_AddMultipleMembersToAlias 
 
4131
*/
 
4132
static NTSTATUS dcesrv_samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4133
                       struct samr_AddMultipleMembersToAlias *r)
 
4134
{
 
4135
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
4136
}
 
4137
 
 
4138
 
 
4139
/* 
 
4140
  samr_RemoveMultipleMembersFromAlias 
 
4141
*/
 
4142
static NTSTATUS dcesrv_samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4143
                       struct samr_RemoveMultipleMembersFromAlias *r)
 
4144
{
 
4145
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
4146
}
 
4147
 
 
4148
 
 
4149
/* 
 
4150
  samr_GetDomPwInfo 
 
4151
 
 
4152
  this fetches the default password properties for a domain
 
4153
 
 
4154
  note that w2k3 completely ignores the domain name in this call, and 
 
4155
  always returns the information for the servers primary domain
 
4156
*/
 
4157
static NTSTATUS dcesrv_samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4158
                                  struct samr_GetDomPwInfo *r)
 
4159
{
 
4160
        struct ldb_message **msgs;
 
4161
        int ret;
 
4162
        const char * const attrs[] = {"minPwdLength", "pwdProperties", NULL };
 
4163
        struct ldb_context *sam_ctx;
 
4164
 
 
4165
        ZERO_STRUCTP(r->out.info);
 
4166
 
 
4167
        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 
 
4168
        if (sam_ctx == NULL) {
 
4169
                return NT_STATUS_INVALID_SYSTEM_SERVICE;
 
4170
        }
 
4171
 
 
4172
        /* The domain name in this call is ignored */
 
4173
        ret = gendb_search_dn(sam_ctx, 
 
4174
                           mem_ctx, NULL, &msgs, attrs);
 
4175
        if (ret <= 0) {
 
4176
                return NT_STATUS_NO_SUCH_DOMAIN;
 
4177
        }
 
4178
        if (ret > 1) {
 
4179
                talloc_free(msgs);
 
4180
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
4181
        }
 
4182
 
 
4183
        r->out.info->min_password_length = samdb_result_uint(msgs[0], "minPwdLength", 0);
 
4184
        r->out.info->password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1);
 
4185
 
 
4186
        talloc_free(msgs);
 
4187
 
 
4188
        talloc_free(sam_ctx);
 
4189
        return NT_STATUS_OK;
 
4190
}
 
4191
 
 
4192
 
 
4193
/* 
 
4194
  samr_Connect2 
 
4195
*/
 
4196
static NTSTATUS dcesrv_samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4197
                              struct samr_Connect2 *r)
 
4198
{
 
4199
        struct samr_Connect c;
 
4200
 
 
4201
        c.in.system_name = NULL;
 
4202
        c.in.access_mask = r->in.access_mask;
 
4203
        c.out.connect_handle = r->out.connect_handle;
 
4204
 
 
4205
        return dcesrv_samr_Connect(dce_call, mem_ctx, &c);
 
4206
}
 
4207
 
 
4208
 
 
4209
/* 
 
4210
  samr_SetUserInfo2 
 
4211
 
 
4212
  just an alias for samr_SetUserInfo
 
4213
*/
 
4214
static NTSTATUS dcesrv_samr_SetUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4215
                                  struct samr_SetUserInfo2 *r)
 
4216
{
 
4217
        struct samr_SetUserInfo r2;
 
4218
 
 
4219
        r2.in.user_handle = r->in.user_handle;
 
4220
        r2.in.level = r->in.level;
 
4221
        r2.in.info = r->in.info;
 
4222
 
 
4223
        return dcesrv_samr_SetUserInfo(dce_call, mem_ctx, &r2);
 
4224
}
 
4225
 
 
4226
 
 
4227
/* 
 
4228
  samr_SetBootKeyInformation 
 
4229
*/
 
4230
static NTSTATUS dcesrv_samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4231
                       struct samr_SetBootKeyInformation *r)
 
4232
{
 
4233
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
4234
}
 
4235
 
 
4236
 
 
4237
/* 
 
4238
  samr_GetBootKeyInformation 
 
4239
*/
 
4240
static NTSTATUS dcesrv_samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4241
                       struct samr_GetBootKeyInformation *r)
 
4242
{
 
4243
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
4244
}
 
4245
 
 
4246
 
 
4247
/* 
 
4248
  samr_Connect3 
 
4249
*/
 
4250
static NTSTATUS dcesrv_samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4251
                       struct samr_Connect3 *r)
 
4252
{
 
4253
        struct samr_Connect c;
 
4254
 
 
4255
        c.in.system_name = NULL;
 
4256
        c.in.access_mask = r->in.access_mask;
 
4257
        c.out.connect_handle = r->out.connect_handle;
 
4258
 
 
4259
        return dcesrv_samr_Connect(dce_call, mem_ctx, &c);
 
4260
}
 
4261
 
 
4262
 
 
4263
/* 
 
4264
  samr_Connect4 
 
4265
*/
 
4266
static NTSTATUS dcesrv_samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4267
                       struct samr_Connect4 *r)
 
4268
{
 
4269
        struct samr_Connect c;
 
4270
 
 
4271
        c.in.system_name = NULL;
 
4272
        c.in.access_mask = r->in.access_mask;
 
4273
        c.out.connect_handle = r->out.connect_handle;
 
4274
 
 
4275
        return dcesrv_samr_Connect(dce_call, mem_ctx, &c);
 
4276
}
 
4277
 
 
4278
 
 
4279
/* 
 
4280
  samr_Connect5 
 
4281
*/
 
4282
static NTSTATUS dcesrv_samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4283
                              struct samr_Connect5 *r)
 
4284
{
 
4285
        struct samr_Connect c;
 
4286
        NTSTATUS status;
 
4287
 
 
4288
        c.in.system_name = NULL;
 
4289
        c.in.access_mask = r->in.access_mask;
 
4290
        c.out.connect_handle = r->out.connect_handle;
 
4291
 
 
4292
        status = dcesrv_samr_Connect(dce_call, mem_ctx, &c);
 
4293
 
 
4294
        r->out.info_out->info1.client_version = SAMR_CONNECT_AFTER_W2K;
 
4295
        r->out.info_out->info1.unknown2 = 0;
 
4296
        *r->out.level_out = r->in.level_in;
 
4297
 
 
4298
        return status;
 
4299
}
 
4300
 
 
4301
 
 
4302
/* 
 
4303
  samr_RidToSid 
 
4304
*/
 
4305
static NTSTATUS dcesrv_samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4306
                              struct samr_RidToSid *r)
 
4307
{
 
4308
        struct samr_domain_state *d_state;
 
4309
        struct dcesrv_handle *h;
 
4310
 
 
4311
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
4312
 
 
4313
        d_state = h->data;
 
4314
 
 
4315
        /* form the users SID */
 
4316
        *r->out.sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
 
4317
        if (!*r->out.sid) {
 
4318
                return NT_STATUS_NO_MEMORY;
 
4319
        }
 
4320
 
 
4321
        return NT_STATUS_OK;
 
4322
}
 
4323
 
 
4324
 
 
4325
/* 
 
4326
  samr_SetDsrmPassword 
 
4327
*/
 
4328
static NTSTATUS dcesrv_samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4329
                       struct samr_SetDsrmPassword *r)
 
4330
{
 
4331
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
4332
}
 
4333
 
 
4334
 
 
4335
/* 
 
4336
  samr_ValidatePassword 
 
4337
*/
 
4338
static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
 
4339
                                      struct samr_ValidatePassword *r)
 
4340
{
 
4341
        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
 
4342
}
 
4343
 
 
4344
 
 
4345
/* include the generated boilerplate */
 
4346
#include "librpc/gen_ndr/ndr_samr_s.c"