r2247: talloc_destroy -> talloc_free
[jelmer/samba4-debian.git] / source / rpc_server / samr / dcesrv_samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the samr pipe
5
6    Copyright (C) Andrew Tridgell 2004
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "rpc_server/common/common.h"
25 #include "rpc_server/samr/dcesrv_samr.h"
26
27
28
29 /*
30   destroy a general handle. This relies on the talloc destructor being set up correctly
31 */
32 static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h)
33 {
34         talloc_free(h->data);
35 }
36
37 /* 
38   samr_Connect 
39
40   create a connection to the SAM database
41 */
42 static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
43                              struct samr_Connect *r)
44 {
45         struct samr_connect_state *c_state;
46         struct dcesrv_handle *handle;
47
48         ZERO_STRUCTP(r->out.handle);
49
50         c_state = talloc_p(NULL, struct samr_connect_state);
51         if (!c_state) {
52                 return NT_STATUS_NO_MEMORY;
53         }
54
55         /* make sure the sam database is accessible */
56         c_state->sam_ctx = samdb_connect(mem_ctx);
57         if (c_state->sam_ctx == NULL) {
58                 talloc_free(c_state);
59                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
60         }
61
62         handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_CONNECT);
63         if (!handle) {
64                 talloc_free(c_state);
65                 return NT_STATUS_NO_MEMORY;
66         }
67
68         handle->data = c_state;
69         handle->destroy = samr_handle_destroy;
70
71         c_state->access_mask = r->in.access_mask;
72         *r->out.handle = handle->wire_handle;
73
74         return NT_STATUS_OK;
75 }
76
77
78 /* 
79   samr_Close 
80 */
81 static NTSTATUS samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
82                            struct samr_Close *r)
83 {
84         struct dcesrv_handle *h;
85
86         *r->out.handle = *r->in.handle;
87
88         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
89
90         /* this causes the callback samr_XXX_destroy() to be called by
91            the handle destroy code which destroys the state associated
92            with the handle */
93         dcesrv_handle_destroy(dce_call->conn, h);
94
95         ZERO_STRUCTP(r->out.handle);
96
97         return NT_STATUS_OK;
98 }
99
100
101 /* 
102   samr_SetSecurity 
103 */
104 static NTSTATUS samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
105                                  struct samr_SetSecurity *r)
106 {
107         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
108 }
109
110
111 /* 
112   samr_QuerySecurity 
113 */
114 static NTSTATUS samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
115                                    struct samr_QuerySecurity *r)
116 {
117         struct dcesrv_handle *h;
118         struct samr_SdBuf *sd;
119
120         r->out.sdbuf = NULL;
121
122         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
123
124         sd = talloc_p(mem_ctx, struct samr_SdBuf);
125         if (sd == NULL) {
126                 return NT_STATUS_NO_MEMORY;
127         }
128
129         sd->sd = samdb_default_security_descriptor(mem_ctx);
130
131         r->out.sdbuf = sd;
132
133         return NT_STATUS_OK;
134 }
135
136
137 /* 
138   samr_Shutdown 
139
140   we refuse this operation completely. If a admin wants to shutdown samr
141   in Samba then they should use the samba admin tools to disable the samr pipe
142 */
143 static NTSTATUS samr_Shutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
144                               struct samr_Shutdown *r)
145 {
146         return NT_STATUS_ACCESS_DENIED;
147 }
148
149
150 /* 
151   samr_LookupDomain 
152
153   this maps from a domain name to a SID
154 */
155 static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
156                                   struct samr_LookupDomain *r)
157 {
158         struct samr_connect_state *c_state;
159         struct dcesrv_handle *h;
160         struct dom_sid2 *sid;
161         const char *sidstr;
162                 
163         r->out.sid = NULL;
164
165         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_CONNECT);
166
167         c_state = h->data;
168
169         if (r->in.domain->name == NULL) {
170                 return NT_STATUS_INVALID_PARAMETER;
171         }
172
173         sidstr = samdb_search_string(c_state->sam_ctx,
174                                      mem_ctx, NULL, "objectSid",
175                                      "(&(name=%s)(objectclass=domain))",
176                                      r->in.domain->name);
177         if (sidstr == NULL) {
178                 return NT_STATUS_NO_SUCH_DOMAIN;
179         }
180
181         sid = dom_sid_parse_talloc(mem_ctx, sidstr);
182         if (sid == NULL) {
183                 DEBUG(0,("samdb: Invalid sid '%s' for domain %s\n",
184                          sidstr, r->in.domain->name));
185                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
186         }
187
188         r->out.sid = sid;
189
190         return NT_STATUS_OK;
191 }
192
193
194 /* 
195   samr_EnumDomains 
196
197   list the domains in the SAM
198 */
199 static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
200                                  struct samr_EnumDomains *r)
201 {
202         struct samr_connect_state *c_state;
203         struct dcesrv_handle *h;
204         struct samr_SamArray *array;
205         const char **domains;
206         int count, i, start_i;
207
208         *r->out.resume_handle = 0;
209         r->out.sam = NULL;
210         r->out.num_entries = 0;
211
212         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_CONNECT);
213
214         c_state = h->data;
215
216         count = samdb_search_string_multiple(c_state->sam_ctx,
217                                              mem_ctx, NULL, &domains, 
218                                              "name", "(objectclass=domain)");
219         if (count == -1) {
220                 DEBUG(0,("samdb: no domains found in EnumDomains\n"));
221                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
222         }
223
224         *r->out.resume_handle = count;
225
226         start_i = *r->in.resume_handle;
227
228         if (start_i >= count) {
229                 /* search past end of list is not an error for this call */
230                 return NT_STATUS_OK;
231         }
232
233         array = talloc_p(mem_ctx, struct samr_SamArray);
234         if (array == NULL) {
235                 return NT_STATUS_NO_MEMORY;
236         }
237                 
238         array->count = 0;
239         array->entries = NULL;
240
241         array->entries = talloc_array_p(mem_ctx, struct samr_SamEntry, count - start_i);
242         if (array->entries == NULL) {
243                 return NT_STATUS_NO_MEMORY;
244         }
245
246         for (i=0;i<count-start_i;i++) {
247                 array->entries[i].idx = start_i + i;
248                 array->entries[i].name.name = domains[start_i+i];
249         }
250
251         r->out.sam = array;
252         r->out.num_entries = i;
253         array->count = r->out.num_entries;
254
255         return NT_STATUS_OK;
256 }
257
258
259 /*
260   close an open domain context
261 */
262 static int samr_Domain_destructor(void *ptr)
263 {
264         struct samr_domain_state *d_state = ptr;
265         /* we need to explicitly free the connect state to lower the
266            reference count */
267         talloc_free(d_state->connect_state);
268         return 0;
269 }
270
271 /* 
272   samr_OpenDomain 
273 */
274 static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
275                                 struct samr_OpenDomain *r)
276 {
277         struct dcesrv_handle *h_conn, *h_domain;
278         const char *sidstr, *domain_name;
279         struct samr_connect_state *c_state;
280         struct samr_domain_state *d_state;
281         const char * const attrs[2] = { "name", NULL};
282         struct ldb_message **msgs;
283         int ret;
284
285         ZERO_STRUCTP(r->out.domain_handle);
286
287         DCESRV_PULL_HANDLE(h_conn, r->in.handle, SAMR_HANDLE_CONNECT);
288
289         c_state = h_conn->data;
290
291         if (r->in.sid == NULL) {
292                 return NT_STATUS_INVALID_PARAMETER;
293         }
294
295         sidstr = dom_sid_string(mem_ctx, r->in.sid);
296         if (sidstr == NULL) {
297                 return NT_STATUS_INVALID_PARAMETER;
298         }
299
300         ret = samdb_search(c_state->sam_ctx,
301                            mem_ctx, NULL, &msgs, attrs,
302                            "(&(objectSid=%s)(objectclass=domain))", 
303                            sidstr);
304         if (ret != 1) {
305                 return NT_STATUS_NO_SUCH_DOMAIN;
306         }
307
308         domain_name = ldb_msg_find_string(msgs[0], "name", NULL);
309         if (domain_name == NULL) {
310                 return NT_STATUS_NO_SUCH_DOMAIN;
311         }
312
313         d_state = talloc_p(c_state, struct samr_domain_state);
314         if (!d_state) {
315                 return NT_STATUS_NO_MEMORY;
316         }
317
318         d_state->connect_state = c_state;
319         d_state->sam_ctx = c_state->sam_ctx;
320         d_state->domain_sid = talloc_strdup(d_state, sidstr);
321         d_state->domain_name = talloc_strdup(d_state, domain_name);
322         d_state->domain_dn = talloc_strdup(d_state, msgs[0]->dn);
323         if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) {
324                 talloc_free(d_state);
325                 return NT_STATUS_NO_MEMORY;             
326         }
327         d_state->access_mask = r->in.access_mask;
328
329         h_domain = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_DOMAIN);
330         if (!h_domain) {
331                 talloc_free(d_state);
332                 return NT_STATUS_NO_MEMORY;
333         }
334         talloc_set_destructor(d_state, samr_Domain_destructor);
335         talloc_increase_ref_count(c_state);
336
337         h_domain->data = d_state;
338         h_domain->destroy = samr_handle_destroy;
339         *r->out.domain_handle = h_domain->wire_handle;
340
341         return NT_STATUS_OK;
342 }
343
344 /*
345   return DomInfo2
346 */
347 static NTSTATUS samr_info_DomInfo2(struct samr_domain_state *state, TALLOC_CTX *mem_ctx,
348                                    struct samr_DomInfo2 *info)
349 {
350         const char * const attrs[] = { "comment", "name", NULL };
351         int ret;
352         struct ldb_message **res;
353
354         ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
355                            "dn=%s", state->domain_dn);
356         if (ret != 1) {
357                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
358         }
359
360         /* where is this supposed to come from? is it settable? */
361         info->force_logoff_time = 0x8000000000000000LL;
362
363         info->comment.name = samdb_result_string(res[0], "comment", NULL);
364         info->domain.name  = samdb_result_string(res[0], "name", NULL);
365
366         info->primary.name = lp_netbios_name();
367         info->sequence_num = 0;
368         info->role = ROLE_DOMAIN_PDC;
369         info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, NULL, "(objectClass=user)");
370         info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
371                                               "(&(objectClass=group)(sAMAccountType=%u))",
372                                               ATYPE_GLOBAL_GROUP);
373         info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
374                                                "(&(objectClass=group)(sAMAccountType=%u))",
375                                                ATYPE_LOCAL_GROUP);
376
377         return NT_STATUS_OK;
378 }
379
380 /* 
381   samr_QueryDomainInfo 
382 */
383 static NTSTATUS samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
384                                      struct samr_QueryDomainInfo *r)
385 {
386         struct dcesrv_handle *h;
387         struct samr_domain_state *d_state;
388
389         r->out.info = NULL;
390
391         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_DOMAIN);
392
393         d_state = h->data;
394
395         r->out.info = talloc_p(mem_ctx, union samr_DomainInfo);
396         if (!r->out.info) {
397                 return NT_STATUS_NO_MEMORY;
398         }
399
400         ZERO_STRUCTP(r->out.info);
401
402         switch (r->in.level) {
403         case 2:
404                 return samr_info_DomInfo2(d_state, mem_ctx, &r->out.info->info2);
405         }
406
407         return NT_STATUS_INVALID_INFO_CLASS;
408 }
409
410
411 /* 
412   samr_SetDomainInfo 
413 */
414 static NTSTATUS samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
415                        struct samr_SetDomainInfo *r)
416 {
417         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
418 }
419
420 /*
421   close an open domain context
422 */
423 static int samr_Account_destructor(void *ptr)
424 {
425         struct samr_account_state *a_state = ptr;
426         /* we need to explicitly free the domain state to lower the
427            reference count */
428         talloc_free(a_state->domain_state);
429         return 0;
430 }
431
432 /* 
433   samr_CreateDomainGroup 
434 */
435 static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
436                                        struct samr_CreateDomainGroup *r)
437 {
438         struct samr_domain_state *d_state;
439         struct samr_account_state *a_state;
440         struct dcesrv_handle *h;
441         const char *name;
442         struct ldb_message msg;
443         uint32_t rid;
444         const char *groupname, *sidstr;
445         time_t now = time(NULL);
446         struct dcesrv_handle *g_handle;
447         int ret;
448         NTSTATUS status;
449
450         ZERO_STRUCTP(r->out.group_handle);
451         *r->out.rid = 0;
452
453         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_DOMAIN);
454
455         d_state = h->data;
456
457         groupname = r->in.name->name;
458
459         if (groupname == NULL) {
460                 return NT_STATUS_INVALID_PARAMETER;
461         }
462
463         /* check if the group already exists */
464         name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 
465                                    "sAMAccountName",
466                                    "(&(sAMAccountName=%s)(objectclass=group))",
467                                    groupname);
468         if (name != NULL) {
469                 return NT_STATUS_GROUP_EXISTS;
470         }
471
472         ZERO_STRUCT(msg);
473
474         /* pull in all the template attributes */
475         ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg, 
476                                   "(&(name=TemplateGroup)(objectclass=groupTemplate))");
477         if (ret != 0) {
478                 DEBUG(0,("Failed to load TemplateGroup from samdb\n"));
479                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
480         }
481
482         /* allocate a rid */
483         status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx, 
484                                         d_state->domain_dn, "nextRid", &rid);
485         if (!NT_STATUS_IS_OK(status)) {
486                 return status;
487         }
488
489         /* and the group SID */
490         sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
491         if (!sidstr) {
492                 return NT_STATUS_NO_MEMORY;
493         }
494
495         /* add core elements to the ldb_message for the user */
496         msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", groupname,
497                                  d_state->domain_dn);
498         if (!msg.dn) {
499                 return NT_STATUS_NO_MEMORY;
500         }
501         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
502                              "name", groupname);
503         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
504                              "cn", groupname);
505         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
506                              "sAMAccountName", groupname);
507         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
508                              "objectClass", "group");
509         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
510                              "objectSid", sidstr);
511         samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg,
512                                "whenCreated", now);
513         samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg,
514                                "whenChanged", now);
515                              
516         /* create the group */
517         ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
518         if (ret != 0) {
519                 DEBUG(0,("Failed to create group record %s\n", msg.dn));
520                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
521         }
522
523         a_state = talloc_p(d_state, struct samr_account_state);
524         if (!a_state) {
525                 return NT_STATUS_NO_MEMORY;
526         }
527         a_state->sam_ctx = d_state->sam_ctx;
528         a_state->access_mask = r->in.access_mask;
529         a_state->domain_state = d_state;
530         a_state->account_dn = talloc_steal(d_state, msg.dn);
531         a_state->account_sid = talloc_strdup(d_state, sidstr);
532         a_state->account_name = talloc_strdup(d_state, groupname);
533         if (!a_state->account_name || !a_state->account_sid) {
534                 return NT_STATUS_NO_MEMORY;
535         }
536
537         /* create the policy handle */
538         g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
539         if (!g_handle) {
540                 return NT_STATUS_NO_MEMORY;
541         }
542
543         g_handle->data = a_state;
544         g_handle->destroy = samr_handle_destroy;
545
546         /* the domain state is in use one more time */
547         talloc_increase_ref_count(d_state);
548         talloc_set_destructor(a_state, samr_Account_destructor);
549
550         *r->out.group_handle = g_handle->wire_handle;
551         *r->out.rid = rid;      
552
553         return NT_STATUS_OK;
554 }
555
556
557 /* 
558   samr_EnumDomainGroups 
559 */
560 static NTSTATUS samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
561                                       struct samr_EnumDomainGroups *r)
562 {
563         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
564 }
565
566
567 /* 
568   samr_CreateUser2 
569
570   TODO: This should do some form of locking, especially around the rid allocation
571 */
572 static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
573                                  struct samr_CreateUser2 *r)
574 {
575         struct samr_domain_state *d_state;
576         struct samr_account_state *a_state;
577         struct dcesrv_handle *h;
578         const char *name;
579         struct ldb_message msg;
580         uint32_t rid;
581         const char *account_name, *sidstr;
582         time_t now = time(NULL);
583         struct dcesrv_handle *u_handle;
584         int ret;
585         NTSTATUS status;
586         const char *container, *additional_class=NULL;
587
588         ZERO_STRUCTP(r->out.acct_handle);
589         *r->out.access_granted = 0;
590         *r->out.rid = 0;
591
592         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_DOMAIN);
593
594         d_state = h->data;
595
596         account_name = r->in.account_name->name;
597
598         if (account_name == NULL) {
599                 return NT_STATUS_INVALID_PARAMETER;
600         }
601
602         /* check if the user already exists */
603         name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 
604                                    "sAMAccountName", 
605                                    "(&(sAMAccountName=%s)(objectclass=user))", account_name);
606         if (name != NULL) {
607                 return NT_STATUS_USER_EXISTS;
608         }
609
610         ZERO_STRUCT(msg);
611
612         /* This must be one of these values *only* */
613         if (r->in.acct_flags == ACB_NORMAL) {
614                 /* pull in all the template attributes */
615                 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg, 
616                                           "(&(name=TemplateUser)(objectclass=userTemplate))");
617                 if (ret != 0) {
618                         DEBUG(0,("Failed to load TemplateUser from samdb\n"));
619                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
620                 }
621
622                 container = "Users";
623
624         } else if (r->in.acct_flags == ACB_WSTRUST) {
625                 /* pull in all the template attributes */
626                 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg, 
627                                           "(&(name=TemplateMemberServer)(objectclass=userTemplate))");
628                 if (ret != 0) {
629                         DEBUG(0,("Failed to load TemplateMemberServer from samdb\n"));
630                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
631                 }
632
633                 container = "Computers";
634                 additional_class = "computer";
635
636         } else if (r->in.acct_flags == ACB_SVRTRUST) {
637                 /* pull in all the template attributes */
638                 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg, 
639                                           "(&(name=TemplateDomainController)(objectclass=userTemplate))");
640                 if (ret != 0) {
641                         DEBUG(0,("Failed to load TemplateDomainController from samdb\n"));
642                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
643                 }
644
645                 container = "DomainControllers";
646                 additional_class = "computer";
647
648         } else if (r->in.acct_flags == ACB_DOMTRUST) {
649                 /* pull in all the template attributes */
650                 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg, 
651                                           "(&(name=TemplateTrustingDomain)(objectclass=userTemplate))");
652                 if (ret != 0) {
653                         DEBUG(0,("Failed to load TemplateTrustingDomain from samdb\n"));
654                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
655                 }
656
657                 container = "ForeignDomains";  /* FIXME: Is this correct?*/
658                 additional_class = "computer";
659
660         } else {
661                 return NT_STATUS_INVALID_PARAMETER;
662         }
663
664         /* allocate a rid */
665         status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx, 
666                                         d_state->domain_dn, "nextRid", &rid);
667         if (!NT_STATUS_IS_OK(status)) {
668                 return status;
669         }
670
671         /* and the users SID */
672         sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
673         if (!sidstr) {
674                 return NT_STATUS_NO_MEMORY;
675         }
676
677         /* add core elements to the ldb_message for the user */
678         msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=%s,%s", account_name, container, d_state->domain_dn);
679         if (!msg.dn) {
680                 return NT_STATUS_NO_MEMORY;             
681         }
682         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "name", account_name);
683         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "cn", account_name);
684         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "sAMAccountName", account_name);
685         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", "user");
686         if (additional_class) {
687                 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", additional_class);
688         }
689         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectSid", sidstr);
690         samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenCreated", now);
691         samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenChanged", now);
692
693         /* create the user */
694         ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
695         if (ret != 0) {
696                 DEBUG(0,("Failed to create user record %s\n", msg.dn));
697                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
698         }
699
700         a_state = talloc_p(d_state, struct samr_account_state);
701         if (!a_state) {
702                 return NT_STATUS_NO_MEMORY;
703         }
704         a_state->sam_ctx = d_state->sam_ctx;
705         a_state->access_mask = r->in.access_mask;
706         a_state->domain_state = d_state;
707         a_state->account_dn = talloc_steal(d_state, msg.dn);
708         a_state->account_sid = talloc_strdup(d_state, sidstr);
709         a_state->account_name = talloc_strdup(d_state, account_name);
710         if (!a_state->account_name || !a_state->account_sid) {
711                 return NT_STATUS_NO_MEMORY;
712         }
713
714         /* create the policy handle */
715         u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
716         if (!u_handle) {
717                 return NT_STATUS_NO_MEMORY;
718         }
719
720         u_handle->data = a_state;
721         u_handle->destroy = samr_handle_destroy;
722
723         /* the domain state is in use one more time */
724         talloc_increase_ref_count(d_state);
725         talloc_set_destructor(a_state, samr_Account_destructor);
726
727         *r->out.acct_handle = u_handle->wire_handle;
728         *r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
729         *r->out.rid = rid;      
730
731         return NT_STATUS_OK;
732 }
733
734
735 /* 
736   samr_CreateUser 
737 */
738 static NTSTATUS samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
739                                 struct samr_CreateUser *r)
740 {
741         struct samr_CreateUser2 r2;
742         uint32_t access_granted = 0;
743
744
745         /* a simple wrapper around samr_CreateUser2 works nicely */
746         r2.in.handle = r->in.handle;
747         r2.in.account_name = r->in.account_name;
748         r2.in.acct_flags = ACB_NORMAL;
749         r2.in.access_mask = r->in.access_mask;
750         r2.out.acct_handle = r->out.acct_handle;
751         r2.out.access_granted = &access_granted;
752         r2.out.rid = r->out.rid;
753
754         return samr_CreateUser2(dce_call, mem_ctx, &r2);
755 }
756
757 /*
758   comparison function for sorting SamEntry array
759 */
760 static int compare_SamEntry(struct samr_SamEntry *e1, struct samr_SamEntry *e2)
761 {
762         return e1->idx - e2->idx;
763 }
764
765 /* 
766   samr_EnumDomainUsers 
767 */
768 static NTSTATUS samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
769                                      struct samr_EnumDomainUsers *r)
770 {
771         struct dcesrv_handle *h;
772         struct samr_domain_state *d_state;
773         struct ldb_message **res;
774         int count, i, first;
775         struct samr_SamEntry *entries;
776         const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
777
778         *r->out.resume_handle = 0;
779         r->out.sam = NULL;
780         r->out.num_entries = 0;
781
782         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_DOMAIN);
783
784         d_state = h->data;
785         
786         /* search for all users in this domain. This could possibly be cached and 
787            resumed based on resume_key */
788         count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, 
789                              "objectclass=user");
790         if (count == -1) {
791                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
792         }
793         if (count == 0 || r->in.max_size == 0) {
794                 return NT_STATUS_OK;
795         }
796
797         /* convert to SamEntry format */
798         entries = talloc_array_p(mem_ctx, struct samr_SamEntry, count);
799         if (!entries) {
800                 return NT_STATUS_NO_MEMORY;
801         }
802         for (i=0;i<count;i++) {
803                 entries[i].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
804                 entries[i].name.name = samdb_result_string(res[i], "sAMAccountName", "");
805         }
806
807         /* sort the results by rid */
808         qsort(entries, count, sizeof(struct samr_SamEntry), 
809               (comparison_fn_t)compare_SamEntry);
810
811         /* find the first entry to return */
812         for (first=0;
813              first<count && entries[first].idx <= *r->in.resume_handle;
814              first++) ;
815
816         if (first == count) {
817                 return NT_STATUS_OK;
818         }
819
820         /* return the rest, limit by max_size. Note that we 
821            use the w2k3 element size value of 54 */
822         r->out.num_entries = count - first;
823         r->out.num_entries = MIN(r->out.num_entries, 
824                                  1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
825
826         r->out.sam = talloc_p(mem_ctx, struct samr_SamArray);
827         if (!r->out.sam) {
828                 return NT_STATUS_NO_MEMORY;
829         }
830
831         r->out.sam->entries = entries+first;
832         r->out.sam->count = r->out.num_entries;
833
834         if (r->out.num_entries < count - first) {
835                 *r->out.resume_handle = entries[first+r->out.num_entries-1].idx;
836                 return STATUS_MORE_ENTRIES;
837         }
838
839         return NT_STATUS_OK;
840 }
841
842
843 /* 
844   samr_CreateDomAlias 
845 */
846 static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
847                        struct samr_CreateDomAlias *r)
848 {
849         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
850 }
851
852
853 /* 
854   samr_EnumDomainAliases 
855 */
856 static NTSTATUS samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
857                        struct samr_EnumDomainAliases *r)
858 {
859         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
860 }
861
862
863 /* 
864   samr_GetAliasMembership 
865 */
866 static NTSTATUS samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
867                        struct samr_GetAliasMembership *r)
868 {
869         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
870 }
871
872
873 /* 
874   samr_LookupNames 
875 */
876 static NTSTATUS samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
877                                  struct samr_LookupNames *r)
878 {
879         struct dcesrv_handle *h;
880         struct samr_domain_state *d_state;
881         int i;
882         NTSTATUS status = NT_STATUS_OK;
883         const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
884         int count;
885
886         ZERO_STRUCT(r->out.rids);
887         ZERO_STRUCT(r->out.types);
888
889         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_DOMAIN);
890
891         d_state = h->data;
892
893         if (r->in.num_names == 0) {
894                 return NT_STATUS_OK;
895         }
896
897         r->out.rids.ids = talloc_array_p(mem_ctx, uint32_t, r->in.num_names);
898         r->out.types.ids = talloc_array_p(mem_ctx, uint32_t, r->in.num_names);
899         if (!r->out.rids.ids || !r->out.types.ids) {
900                 return NT_STATUS_NO_MEMORY;
901         }
902         r->out.rids.count = r->in.num_names;
903         r->out.types.count = r->in.num_names;
904
905         for (i=0;i<r->in.num_names;i++) {
906                 struct ldb_message **res;
907                 struct dom_sid2 *sid;
908                 const char *sidstr;
909                 uint32_t atype, rtype;
910
911                 r->out.rids.ids[i] = 0;
912                 r->out.types.ids[i] = SID_NAME_UNKNOWN;
913
914                 count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, 
915                                      "sAMAccountName=%s", r->in.names[i].name);
916                 if (count != 1) {
917                         status = STATUS_SOME_UNMAPPED;
918                         continue;
919                 }
920
921                 sidstr = samdb_result_string(res[0], "objectSid", NULL);
922                 if (sidstr == NULL) {
923                         status = STATUS_SOME_UNMAPPED;
924                         continue;
925                 }
926                 
927                 sid = dom_sid_parse_talloc(mem_ctx, sidstr);
928                 if (sid == NULL) {
929                         status = STATUS_SOME_UNMAPPED;
930                         continue;
931                 }
932
933                 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
934                 if (atype == 0) {
935                         status = STATUS_SOME_UNMAPPED;
936                         continue;
937                 }
938
939                 rtype = samdb_atype_map(atype);
940                 
941                 if (rtype == SID_NAME_UNKNOWN) {
942                         status = STATUS_SOME_UNMAPPED;
943                         continue;
944                 }
945
946                 r->out.rids.ids[i] = sid->sub_auths[sid->num_auths-1];
947                 r->out.types.ids[i] = rtype;
948         }
949         
950
951         return status;
952 }
953
954
955 /* 
956   samr_LookupRids 
957 */
958 static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
959                        struct samr_LookupRids *r)
960 {
961         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
962 }
963
964
965 /* 
966   samr_OpenGroup 
967 */
968 static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
969                        struct samr_OpenGroup *r)
970 {
971         struct samr_domain_state *d_state;
972         struct samr_account_state *a_state;
973         struct dcesrv_handle *h;
974         const char *groupname, *sidstr;
975         struct ldb_message **msgs;
976         struct dcesrv_handle *g_handle;
977         const char * const attrs[2] = { "sAMAccountName", NULL };
978         int ret;
979
980         ZERO_STRUCTP(r->out.acct_handle);
981
982         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_DOMAIN);
983
984         d_state = h->data;
985
986         /* form the group SID */
987         sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
988         if (!sidstr) {
989                 return NT_STATUS_NO_MEMORY;
990         }
991
992         /* search for the group record */
993         ret = samdb_search(d_state->sam_ctx,
994                            mem_ctx, d_state->domain_dn, &msgs, attrs,
995                            "(&(objectSid=%s)(objectclass=group))", 
996                            sidstr);
997         if (ret == 0) {
998                 return NT_STATUS_NO_SUCH_GROUP;
999         }
1000         if (ret != 1) {
1001                 DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
1002                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1003         }
1004
1005         groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
1006         if (groupname == NULL) {
1007                 DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
1008                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1009         }
1010
1011         a_state = talloc_p(d_state, struct samr_account_state);
1012         if (!a_state) {
1013                 return NT_STATUS_NO_MEMORY;
1014         }
1015         a_state->sam_ctx = d_state->sam_ctx;
1016         a_state->access_mask = r->in.access_mask;
1017         a_state->domain_state = d_state;
1018         a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
1019         a_state->account_sid = talloc_strdup(a_state, sidstr);
1020         a_state->account_name = talloc_strdup(a_state, groupname);
1021         if (!a_state->account_name || !a_state->account_sid) {
1022                 return NT_STATUS_NO_MEMORY;
1023         }
1024
1025         /* create the policy handle */
1026         g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
1027         if (!g_handle) {
1028                 return NT_STATUS_NO_MEMORY;
1029         }
1030
1031         g_handle->data = a_state;
1032         g_handle->destroy = samr_handle_destroy;
1033
1034         /* the domain state is in use one more time */
1035         talloc_increase_ref_count(d_state);
1036         talloc_set_destructor(a_state, samr_Account_destructor);
1037
1038         *r->out.acct_handle = g_handle->wire_handle;
1039
1040         return NT_STATUS_OK;
1041 }
1042
1043 /* these query macros make samr_Query[User|Group]Info a bit easier to read */
1044
1045 #define QUERY_STRING(msg, field, attr) \
1046         r->out.info->field = samdb_result_string(msg, attr, "");
1047 #define QUERY_UINT(msg, field, attr) \
1048         r->out.info->field = samdb_result_uint(msg, attr, 0);
1049 #define QUERY_RID(msg, field, attr) \
1050         r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
1051 #define QUERY_NTTIME(msg, field, attr) \
1052         r->out.info->field = samdb_result_nttime(msg, attr, 0);
1053 #define QUERY_APASSC(msg, field, attr) \
1054         r->out.info->field = samdb_result_allow_password_change(a_state->sam_ctx, mem_ctx, \
1055                                                            a_state->domain_state->domain_dn, msg, attr);
1056 #define QUERY_FPASSC(msg, field, attr) \
1057         r->out.info->field = samdb_result_force_password_change(a_state->sam_ctx, mem_ctx, \
1058                                                            a_state->domain_state->domain_dn, msg, attr);
1059 #define QUERY_LHOURS(msg, field, attr) \
1060         r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
1061 #define QUERY_AFLAGS(msg, field, attr) \
1062         r->out.info->field = samdb_result_acct_flags(msg, attr);
1063
1064
1065 /* these are used to make the Set[User|Group]Info code easier to follow */
1066
1067 #define SET_STRING(mod, field, attr) do { \
1068         if (r->in.info->field == NULL) return NT_STATUS_INVALID_PARAMETER; \
1069         if (samdb_msg_add_string(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
1070                 return NT_STATUS_NO_MEMORY; \
1071         } \
1072 } while (0)
1073
1074 #define SET_UINT(mod, field, attr) do { \
1075         if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
1076                 return NT_STATUS_NO_MEMORY; \
1077         } \
1078 } while (0)
1079
1080 #define SET_AFLAGS(msg, field, attr) do { \
1081         if (samdb_msg_add_acct_flags(a_state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
1082                 return NT_STATUS_NO_MEMORY; \
1083         } \
1084 } while (0)
1085
1086 #define SET_LHOURS(msg, field, attr) do { \
1087         if (samdb_msg_add_logon_hours(a_state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
1088                 return NT_STATUS_NO_MEMORY; \
1089         } \
1090 } while (0)
1091
1092 /* 
1093   samr_QueryGroupInfo 
1094 */
1095 static NTSTATUS samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1096                        struct samr_QueryGroupInfo *r)
1097 {
1098         struct dcesrv_handle *h;
1099         struct samr_account_state *a_state;
1100         struct ldb_message *msg, **res;
1101         const char * const attrs[4] = { "sAMAccountName", "description",
1102                                         "numMembers", NULL };
1103         int ret;
1104
1105         r->out.info = NULL;
1106
1107         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_GROUP);
1108
1109         a_state = h->data;
1110
1111         /* pull all the group attributes */
1112         ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs,
1113                            "dn=%s", a_state->account_dn);
1114         if (ret != 1) {
1115                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1116         }
1117         msg = res[0];
1118
1119         /* allocate the info structure */
1120         r->out.info = talloc_p(mem_ctx, union samr_GroupInfo);
1121         if (r->out.info == NULL) {
1122                 return NT_STATUS_NO_MEMORY;
1123         }
1124         ZERO_STRUCTP(r->out.info);
1125
1126         /* Fill in the level */
1127         switch (r->in.level) {
1128         case GroupInfoAll:
1129                 QUERY_STRING(msg, all.name.name,        "sAMAccountName");
1130                 r->out.info->all.unknown = 7; /* Do like w2k3 */
1131                 QUERY_UINT  (msg, all.num_members,      "numMembers")
1132                 QUERY_STRING(msg, all.description.name, "description");
1133                 break;
1134         case GroupInfoName:
1135                 QUERY_STRING(msg, name.name,            "sAMAccountName");
1136                 break;
1137         case GroupInfoX:
1138                 r->out.info->unknown.unknown = 7;
1139                 break;
1140         case GroupInfoDescription:
1141                 QUERY_STRING(msg, description.name, "description");
1142                 break;
1143         default:
1144                 r->out.info = NULL;
1145                 return NT_STATUS_INVALID_INFO_CLASS;
1146         }
1147         
1148         return NT_STATUS_OK;
1149 }
1150
1151
1152 /* 
1153   samr_SetGroupInfo 
1154 */
1155 static NTSTATUS samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1156                        struct samr_SetGroupInfo *r)
1157 {
1158         struct dcesrv_handle *h;
1159         struct samr_account_state *a_state;
1160         struct ldb_message mod, *msg = &mod;
1161         int ret;
1162
1163         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_GROUP);
1164
1165         a_state = h->data;
1166
1167         ZERO_STRUCT(mod);
1168         mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
1169         if (!mod.dn) {
1170                 return NT_STATUS_NO_MEMORY;
1171         }
1172
1173         switch (r->in.level) {
1174         case GroupInfoDescription:
1175                 SET_STRING(msg, description.name,         "description");
1176                 break;
1177         case GroupInfoName:
1178                 /* On W2k3 this does not change the name, it changes the
1179                  * sAMAccountName attribute */
1180                 SET_STRING(msg, name.name,                "sAMAccountName");
1181                 break;
1182         case GroupInfoX:
1183                 /* This does not do anything obviously visible in W2k3 LDAP */
1184                 break;
1185         default:
1186                 return NT_STATUS_INVALID_INFO_CLASS;
1187         }
1188
1189         /* modify the samdb record */
1190         ret = samdb_replace(a_state->sam_ctx, mem_ctx, &mod);
1191         if (ret != 0) {
1192                 /* we really need samdb.c to return NTSTATUS */
1193                 return NT_STATUS_UNSUCCESSFUL;
1194         }
1195
1196         return NT_STATUS_OK;
1197 }
1198
1199
1200 /* 
1201   samr_AddGroupMember 
1202 */
1203 static NTSTATUS samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1204                        struct samr_AddGroupMember *r)
1205 {
1206         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1207 }
1208
1209
1210 /* 
1211   samr_DeleteDomainGroup 
1212 */
1213 static NTSTATUS samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1214                        struct samr_DeleteDomainGroup *r)
1215 {
1216         struct dcesrv_handle *h;
1217         struct samr_account_state *a_state;
1218         int ret;
1219
1220         *r->out.handle = *r->in.handle;
1221
1222         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_GROUP);
1223
1224         a_state = h->data;
1225
1226         ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
1227         if (ret != 0) {
1228                 return NT_STATUS_UNSUCCESSFUL;
1229         }
1230
1231         ZERO_STRUCTP(r->out.handle);
1232
1233         return NT_STATUS_OK;
1234 }
1235
1236
1237 /* 
1238   samr_DeleteGroupMember 
1239 */
1240 static NTSTATUS samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1241                        struct samr_DeleteGroupMember *r)
1242 {
1243         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1244 }
1245
1246
1247 /* 
1248   samr_QueryGroupMember 
1249 */
1250 static NTSTATUS samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1251                        struct samr_QueryGroupMember *r)
1252 {
1253         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1254 }
1255
1256
1257 /* 
1258   samr_SetMemberAttributesOfGroup 
1259 */
1260 static NTSTATUS samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1261                        struct samr_SetMemberAttributesOfGroup *r)
1262 {
1263         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1264 }
1265
1266
1267 /* 
1268   samr_OpenAlias 
1269 */
1270 static NTSTATUS samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1271                        struct samr_OpenAlias *r)
1272 {
1273         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1274 }
1275
1276
1277 /* 
1278   samr_QueryAliasInfo 
1279 */
1280 static NTSTATUS samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1281                        struct samr_QueryAliasInfo *r)
1282 {
1283         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1284 }
1285
1286
1287 /* 
1288   samr_SetAliasInfo 
1289 */
1290 static NTSTATUS samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1291                        struct samr_SetAliasInfo *r)
1292 {
1293         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1294 }
1295
1296
1297 /* 
1298   samr_DeleteDomAlias 
1299 */
1300 static NTSTATUS samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1301                        struct samr_DeleteDomAlias *r)
1302 {
1303         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1304 }
1305
1306
1307 /* 
1308   samr_AddAliasMember 
1309 */
1310 static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1311                        struct samr_AddAliasMember *r)
1312 {
1313         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1314 }
1315
1316
1317 /* 
1318   samr_DeleteAliasMember 
1319 */
1320 static NTSTATUS samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1321                        struct samr_DeleteAliasMember *r)
1322 {
1323         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1324 }
1325
1326
1327 /* 
1328   samr_GetMembersInAlias 
1329 */
1330 static NTSTATUS samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1331                        struct samr_GetMembersInAlias *r)
1332 {
1333         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1334 }
1335
1336
1337 /* 
1338   samr_OpenUser 
1339 */
1340 static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1341                               struct samr_OpenUser *r)
1342 {
1343         struct samr_domain_state *d_state;
1344         struct samr_account_state *a_state;
1345         struct dcesrv_handle *h;
1346         const char *account_name, *sidstr;
1347         struct ldb_message **msgs;
1348         struct dcesrv_handle *u_handle;
1349         const char * const attrs[2] = { "sAMAccountName", NULL };
1350         int ret;
1351
1352         ZERO_STRUCTP(r->out.acct_handle);
1353
1354         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_DOMAIN);
1355
1356         d_state = h->data;
1357
1358         /* form the users SID */
1359         sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
1360         if (!sidstr) {
1361                 return NT_STATUS_NO_MEMORY;
1362         }
1363
1364         /* search for the user record */
1365         ret = samdb_search(d_state->sam_ctx,
1366                            mem_ctx, d_state->domain_dn, &msgs, attrs,
1367                            "(&(objectSid=%s)(objectclass=user))", 
1368                            sidstr);
1369         if (ret == 0) {
1370                 return NT_STATUS_NO_SUCH_USER;
1371         }
1372         if (ret != 1) {
1373                 DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
1374                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1375         }
1376
1377         account_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
1378         if (account_name == NULL) {
1379                 DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
1380                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1381         }
1382
1383         a_state = talloc_p(d_state, struct samr_account_state);
1384         if (!a_state) {
1385                 return NT_STATUS_NO_MEMORY;
1386         }
1387         a_state->sam_ctx = d_state->sam_ctx;
1388         a_state->access_mask = r->in.access_mask;
1389         a_state->domain_state = d_state;
1390         a_state->account_dn = talloc_steal(d_state, msgs[0]->dn);
1391         a_state->account_sid = talloc_strdup(d_state, sidstr);
1392         a_state->account_name = talloc_strdup(d_state, account_name);
1393         if (!a_state->account_name || !a_state->account_sid) {
1394                 return NT_STATUS_NO_MEMORY;
1395         }
1396
1397         /* create the policy handle */
1398         u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
1399         if (!u_handle) {
1400                 return NT_STATUS_NO_MEMORY;
1401         }
1402
1403         u_handle->data = a_state;
1404         u_handle->destroy = samr_handle_destroy;
1405
1406         /* the domain state is in use one more time */
1407         talloc_increase_ref_count(d_state);
1408         talloc_set_destructor(a_state, samr_Account_destructor);
1409
1410         *r->out.acct_handle = u_handle->wire_handle;
1411
1412         return NT_STATUS_OK;
1413
1414 }
1415
1416
1417 /* 
1418   samr_DeleteUser 
1419 */
1420 static NTSTATUS samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1421                                 struct samr_DeleteUser *r)
1422 {
1423         struct dcesrv_handle *h;
1424         struct samr_account_state *a_state;
1425         int ret;
1426
1427         *r->out.handle = *r->in.handle;
1428
1429         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_USER);
1430
1431         a_state = h->data;
1432
1433         ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
1434         if (ret != 0) {
1435                 return NT_STATUS_UNSUCCESSFUL;
1436         }
1437
1438         ZERO_STRUCTP(r->out.handle);
1439
1440         return NT_STATUS_OK;
1441 }
1442
1443
1444 /* 
1445   samr_QueryUserInfo 
1446 */
1447 static NTSTATUS samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1448                                    struct samr_QueryUserInfo *r)
1449 {
1450         struct dcesrv_handle *h;
1451         struct samr_account_state *a_state;
1452         struct ldb_message *msg, **res;
1453         int ret;
1454
1455         r->out.info = NULL;
1456
1457         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_USER);
1458
1459         a_state = h->data;
1460
1461         /* pull all the user attributes */
1462         ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, NULL,
1463                            "dn=%s", a_state->account_dn);
1464         if (ret != 1) {
1465                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1466         }
1467         msg = res[0];
1468
1469         /* allocate the info structure */
1470         r->out.info = talloc_p(mem_ctx, union samr_UserInfo);
1471         if (r->out.info == NULL) {
1472                 return NT_STATUS_NO_MEMORY;
1473         }
1474         ZERO_STRUCTP(r->out.info);
1475
1476         /* fill in the reply */
1477         switch (r->in.level) {
1478         case 1:
1479                 QUERY_STRING(msg, info1.account_name.name,"sAMAccountName");
1480                 QUERY_STRING(msg, info1.full_name.name,   "displayName");
1481                 QUERY_UINT  (msg, info1.primary_gid,      "primaryGroupID");
1482                 QUERY_STRING(msg, info1.description.name, "description");
1483                 QUERY_STRING(msg, info1.comment.name,     "comment");
1484                 break;
1485
1486         case 2:
1487                 QUERY_STRING(msg, info2.comment.name,     "comment");
1488                 QUERY_UINT  (msg, info2.country_code,     "countryCode");
1489                 QUERY_UINT  (msg, info2.code_page,        "codePage");
1490                 break;
1491
1492         case 3:
1493                 QUERY_STRING(msg, info3.account_name.name,   "sAMAccountName");
1494                 QUERY_STRING(msg, info3.full_name.name,      "displayName");
1495                 QUERY_RID   (msg, info3.rid,                 "objectSid");
1496                 QUERY_UINT  (msg, info3.primary_gid,         "primaryGroupID");
1497                 QUERY_STRING(msg, info3.home_directory.name, "homeDirectory");
1498                 QUERY_STRING(msg, info3.home_drive.name,     "homeDrive");
1499                 QUERY_STRING(msg, info3.logon_script.name,   "scriptPath");
1500                 QUERY_STRING(msg, info3.profile_path.name,   "profilePath");
1501                 QUERY_STRING(msg, info3.workstations.name,   "userWorkstations");
1502                 QUERY_NTTIME(msg, info3.last_logon,          "lastLogon");
1503                 QUERY_NTTIME(msg, info3.last_logoff,         "lastLogoff");
1504                 QUERY_NTTIME(msg, info3.last_password_change,"pwdLastSet");
1505                 QUERY_APASSC(msg, info3.allow_password_change,"pwdLastSet");
1506                 QUERY_FPASSC(msg, info3.force_password_change,"pwdLastSet");
1507                 QUERY_LHOURS(msg, info3.logon_hours,         "logonHours");
1508                 QUERY_UINT  (msg, info3.bad_password_count,  "badPwdCount");
1509                 QUERY_UINT  (msg, info3.num_logons,          "logonCount");
1510                 QUERY_AFLAGS(msg, info3.acct_flags,          "userAccountControl");
1511                 break;
1512
1513         case 4:
1514                 QUERY_LHOURS(msg, info4.logon_hours,         "logonHours");
1515                 break;
1516
1517         case 5:
1518                 QUERY_STRING(msg, info5.account_name.name,   "sAMAccountName");
1519                 QUERY_STRING(msg, info5.full_name.name,      "displayName");
1520                 QUERY_RID   (msg, info5.rid,                 "objectSid");
1521                 QUERY_UINT  (msg, info5.primary_gid,         "primaryGroupID");
1522                 QUERY_STRING(msg, info5.home_directory.name, "homeDirectory");
1523                 QUERY_STRING(msg, info5.home_drive.name,     "homeDrive");
1524                 QUERY_STRING(msg, info5.logon_script.name,   "scriptPath");
1525                 QUERY_STRING(msg, info5.profile_path.name,   "profilePath");
1526                 QUERY_STRING(msg, info5.description.name,    "description");
1527                 QUERY_STRING(msg, info5.workstations.name,   "userWorkstations");
1528                 QUERY_NTTIME(msg, info5.last_logon,          "lastLogon");
1529                 QUERY_NTTIME(msg, info5.last_logoff,         "lastLogoff");
1530                 QUERY_LHOURS(msg, info5.logon_hours,         "logonHours");
1531                 QUERY_UINT  (msg, info5.bad_password_count,  "badPwdCount");
1532                 QUERY_UINT  (msg, info5.num_logons,          "logonCount");
1533                 QUERY_NTTIME(msg, info5.last_password_change,"pwdLastSet");
1534                 QUERY_NTTIME(msg, info5.acct_expiry,         "accountExpires");
1535                 QUERY_AFLAGS(msg, info5.acct_flags,          "userAccountControl");
1536                 break;
1537
1538         case 6:
1539                 QUERY_STRING(msg, info6.account_name.name,   "sAMAccountName");
1540                 QUERY_STRING(msg, info6.full_name.name,      "displayName");
1541                 break;
1542
1543         case 7:
1544                 QUERY_STRING(msg, info7.account_name.name,   "sAMAccountName");
1545                 break;
1546
1547         case 8:
1548                 QUERY_STRING(msg, info8.full_name.name,      "displayName");
1549                 break;
1550
1551         case 9:
1552                 QUERY_UINT  (msg, info9.primary_gid,         "primaryGroupID");
1553                 break;
1554
1555         case 10:
1556                 QUERY_STRING(msg, info10.home_directory.name, "homeDirectory");
1557                 QUERY_STRING(msg, info10.home_drive.name,     "homeDrive");
1558                 break;
1559
1560         case 11:
1561                 QUERY_STRING(msg, info11.logon_script.name,   "scriptPath");
1562                 break;
1563
1564         case 12:
1565                 QUERY_STRING(msg, info12.profile_path.name,   "profilePath");
1566                 break;
1567
1568         case 13:
1569                 QUERY_STRING(msg, info13.description.name,    "description");
1570                 break;
1571
1572         case 14:
1573                 QUERY_STRING(msg, info14.workstations.name,   "userWorkstations");
1574                 break;
1575
1576         case 16:
1577                 QUERY_AFLAGS(msg, info16.acct_flags,          "userAccountControl");
1578                 break;
1579
1580         case 17:
1581                 QUERY_NTTIME(msg, info17.acct_expiry,         "accountExpires");
1582
1583         case 20:
1584                 QUERY_STRING(msg, info20.callback.name,       "userParameters");
1585                 break;
1586
1587         case 21:
1588                 QUERY_NTTIME(msg, info21.last_logon,          "lastLogon");
1589                 QUERY_NTTIME(msg, info21.last_logoff,         "lastLogoff");
1590                 QUERY_NTTIME(msg, info21.last_password_change,     "pwdLastSet");
1591                 QUERY_NTTIME(msg, info21.acct_expiry,         "accountExpires");
1592                 QUERY_APASSC(msg, info21.allow_password_change,"pwdLastSet");
1593                 QUERY_FPASSC(msg, info21.force_password_change,"pwdLastSet");
1594                 QUERY_STRING(msg, info21.account_name.name,   "sAMAccountName");
1595                 QUERY_STRING(msg, info21.full_name.name,      "displayName");
1596                 QUERY_STRING(msg, info21.home_directory.name, "homeDirectory");
1597                 QUERY_STRING(msg, info21.home_drive.name,     "homeDrive");
1598                 QUERY_STRING(msg, info21.logon_script.name,   "scriptPath");
1599                 QUERY_STRING(msg, info21.profile_path.name,   "profilePath");
1600                 QUERY_STRING(msg, info21.description.name,    "description");
1601                 QUERY_STRING(msg, info21.workstations.name,   "userWorkstations");
1602                 QUERY_STRING(msg, info21.comment.name,        "comment");
1603                 QUERY_STRING(msg, info21.callback.name,       "userParameters");
1604                 QUERY_RID   (msg, info21.rid,                 "objectSid");
1605                 QUERY_UINT  (msg, info21.primary_gid,         "primaryGroupID");
1606                 QUERY_AFLAGS(msg, info21.acct_flags,          "userAccountControl");
1607                 r->out.info->info21.fields_present = 0x00FFFFFF;
1608                 QUERY_LHOURS(msg, info21.logon_hours,         "logonHours");
1609                 QUERY_UINT  (msg, info21.bad_password_count,  "badPwdCount");
1610                 QUERY_UINT  (msg, info21.num_logons,          "logonCount");
1611                 QUERY_UINT  (msg, info21.country_code,        "countryCode");
1612                 QUERY_UINT  (msg, info21.code_page,           "codePage");
1613                 break;
1614                 
1615
1616         default:
1617                 r->out.info = NULL;
1618                 return NT_STATUS_INVALID_INFO_CLASS;
1619         }
1620         
1621         return NT_STATUS_OK;
1622 }
1623
1624
1625 /* 
1626   samr_SetUserInfo 
1627 */
1628 static NTSTATUS samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1629                                  struct samr_SetUserInfo *r)
1630 {
1631         struct dcesrv_handle *h;
1632         struct samr_account_state *a_state;
1633         struct ldb_message mod, *msg = &mod;
1634         int ret;
1635         NTSTATUS status = NT_STATUS_OK;
1636
1637         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_USER);
1638
1639         a_state = h->data;
1640
1641         ZERO_STRUCT(mod);
1642         mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
1643         if (!mod.dn) {
1644                 return NT_STATUS_NO_MEMORY;
1645         }
1646
1647         switch (r->in.level) {
1648         case 2:
1649                 SET_STRING(msg, info2.comment.name,         "comment");
1650                 SET_UINT  (msg, info2.country_code,         "countryCode");
1651                 SET_UINT  (msg, info2.code_page,            "codePage");
1652                 break;
1653
1654         case 4:
1655                 SET_LHOURS(msg, info4.logon_hours,          "logonHours");
1656                 break;
1657
1658         case 6:
1659                 SET_STRING(msg, info6.full_name.name,       "displayName");
1660                 break;
1661
1662         case 8:
1663                 SET_STRING(msg, info8.full_name.name,       "displayName");
1664                 break;
1665
1666         case 9:
1667                 SET_UINT(msg, info9.primary_gid,            "primaryGroupID");
1668                 break;
1669
1670         case 10:
1671                 SET_STRING(msg, info10.home_directory.name, "homeDirectory");
1672                 SET_STRING(msg, info10.home_drive.name,     "homeDrive");
1673                 break;
1674
1675         case 11:
1676                 SET_STRING(msg, info11.logon_script.name,   "scriptPath");
1677                 break;
1678
1679         case 12:
1680                 SET_STRING(msg, info12.profile_path.name,   "profilePath");
1681                 break;
1682
1683         case 13:
1684                 SET_STRING(msg, info13.description.name,    "description");
1685                 break;
1686
1687         case 14:
1688                 SET_STRING(msg, info14.workstations.name,   "userWorkstations");
1689                 break;
1690
1691         case 16:
1692                 SET_AFLAGS(msg, info16.acct_flags,          "userAccountControl");
1693                 break;
1694
1695         case 20:
1696                 SET_STRING(msg, info20.callback.name,       "userParameters");
1697                 break;
1698
1699         case 21:
1700 #define IFSET(bit) if (bit & r->in.info->info21.fields_present)
1701                 IFSET(SAMR_FIELD_NAME)         
1702                         SET_STRING(msg, info21.full_name.name,    "displayName");
1703                 IFSET(SAMR_FIELD_DESCRIPTION)  
1704                         SET_STRING(msg, info21.description.name,  "description");
1705                 IFSET(SAMR_FIELD_COMMENT)      
1706                         SET_STRING(msg, info21.comment.name,      "comment");
1707                 IFSET(SAMR_FIELD_LOGON_SCRIPT) 
1708                         SET_STRING(msg, info21.logon_script.name, "scriptPath");
1709                 IFSET(SAMR_FIELD_PROFILE_PATH)      
1710                         SET_STRING(msg, info21.profile_path.name, "profilePath");
1711                 IFSET(SAMR_FIELD_WORKSTATION)  
1712                         SET_STRING(msg, info21.workstations.name, "userWorkstations");
1713                 IFSET(SAMR_FIELD_LOGON_HOURS)  
1714                         SET_LHOURS(msg, info21.logon_hours,       "logonHours");
1715                 IFSET(SAMR_FIELD_CALLBACK)     
1716                         SET_STRING(msg, info21.callback.name,     "userParameters");
1717                 IFSET(SAMR_FIELD_COUNTRY_CODE) 
1718                         SET_UINT  (msg, info21.country_code,      "countryCode");
1719                 IFSET(SAMR_FIELD_CODE_PAGE)    
1720                         SET_UINT  (msg, info21.code_page,         "codePage");
1721 #undef IFSET
1722                 break;
1723
1724         case 23:
1725 #define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
1726                 IFSET(SAMR_FIELD_NAME)         
1727                         SET_STRING(msg, info23.info.full_name.name,    "displayName");
1728                 IFSET(SAMR_FIELD_DESCRIPTION)  
1729                         SET_STRING(msg, info23.info.description.name,  "description");
1730                 IFSET(SAMR_FIELD_COMMENT)      
1731                         SET_STRING(msg, info23.info.comment.name,      "comment");
1732                 IFSET(SAMR_FIELD_LOGON_SCRIPT) 
1733                         SET_STRING(msg, info23.info.logon_script.name, "scriptPath");
1734                 IFSET(SAMR_FIELD_PROFILE_PATH)      
1735                         SET_STRING(msg, info23.info.profile_path.name, "profilePath");
1736                 IFSET(SAMR_FIELD_WORKSTATION)  
1737                         SET_STRING(msg, info23.info.workstations.name, "userWorkstations");
1738                 IFSET(SAMR_FIELD_LOGON_HOURS)  
1739                         SET_LHOURS(msg, info23.info.logon_hours,       "logonHours");
1740                 IFSET(SAMR_FIELD_CALLBACK)     
1741                         SET_STRING(msg, info23.info.callback.name,     "userParameters");
1742                 IFSET(SAMR_FIELD_COUNTRY_CODE) 
1743                         SET_UINT  (msg, info23.info.country_code,      "countryCode");
1744                 IFSET(SAMR_FIELD_CODE_PAGE)    
1745                         SET_UINT  (msg, info23.info.code_page,         "codePage");
1746                 IFSET(SAMR_FIELD_PASSWORD) {
1747                         status = samr_set_password(dce_call,
1748                                                    a_state->sam_ctx,
1749                                                    a_state->account_dn,
1750                                                    a_state->domain_state->domain_dn,
1751                                                    mem_ctx, msg, 
1752                                                    &r->in.info->info23.password);
1753                 }
1754 #undef IFSET
1755                 break;
1756
1757                 /* the set password levels are handled separately */
1758         case 24:
1759                 status = samr_set_password(dce_call,
1760                                            a_state->sam_ctx,
1761                                            a_state->account_dn,
1762                                            a_state->domain_state->domain_dn,
1763                                            mem_ctx, msg, 
1764                                            &r->in.info->info24.password);
1765                 break;
1766
1767         case 25:
1768 #define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
1769                 IFSET(SAMR_FIELD_NAME)         
1770                         SET_STRING(msg, info25.info.full_name.name,    "displayName");
1771                 IFSET(SAMR_FIELD_DESCRIPTION)  
1772                         SET_STRING(msg, info25.info.description.name,  "description");
1773                 IFSET(SAMR_FIELD_COMMENT)      
1774                         SET_STRING(msg, info25.info.comment.name,      "comment");
1775                 IFSET(SAMR_FIELD_LOGON_SCRIPT) 
1776                         SET_STRING(msg, info25.info.logon_script.name, "scriptPath");
1777                 IFSET(SAMR_FIELD_PROFILE_PATH)      
1778                         SET_STRING(msg, info25.info.profile_path.name, "profilePath");
1779                 IFSET(SAMR_FIELD_WORKSTATION)  
1780                         SET_STRING(msg, info25.info.workstations.name, "userWorkstations");
1781                 IFSET(SAMR_FIELD_LOGON_HOURS)  
1782                         SET_LHOURS(msg, info25.info.logon_hours,       "logonHours");
1783                 IFSET(SAMR_FIELD_CALLBACK)     
1784                         SET_STRING(msg, info25.info.callback.name,     "userParameters");
1785                 IFSET(SAMR_FIELD_COUNTRY_CODE) 
1786                         SET_UINT  (msg, info25.info.country_code,      "countryCode");
1787                 IFSET(SAMR_FIELD_CODE_PAGE)    
1788                         SET_UINT  (msg, info25.info.code_page,         "codePage");
1789                 IFSET(SAMR_FIELD_PASSWORD) {
1790                         status = samr_set_password_ex(dce_call,
1791                                                       a_state->sam_ctx,
1792                                                       a_state->account_dn,
1793                                                       a_state->domain_state->domain_dn,
1794                                                       mem_ctx, msg, 
1795                                                       &r->in.info->info25.password);
1796                 }
1797 #undef IFSET
1798                 break;
1799
1800                 /* the set password levels are handled separately */
1801         case 26:
1802                 status = samr_set_password_ex(dce_call,
1803                                               a_state->sam_ctx,
1804                                               a_state->account_dn,
1805                                               a_state->domain_state->domain_dn,
1806                                               mem_ctx, msg, 
1807                                               &r->in.info->info26.password);
1808                 break;
1809                 
1810
1811         default:
1812                 /* many info classes are not valid for SetUserInfo */
1813                 return NT_STATUS_INVALID_INFO_CLASS;
1814         }
1815
1816         if (!NT_STATUS_IS_OK(status)) {
1817                 return status;
1818         }
1819
1820         /* modify the samdb record */
1821         ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
1822         if (ret != 0) {
1823                 /* we really need samdb.c to return NTSTATUS */
1824                 return NT_STATUS_UNSUCCESSFUL;
1825         }
1826
1827         return NT_STATUS_OK;
1828 }
1829
1830
1831 /* 
1832   samr_GetGroupsForUser 
1833 */
1834 static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1835                        struct samr_GetGroupsForUser *r)
1836 {
1837         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1838 }
1839
1840
1841 /* 
1842   samr_QueryDisplayInfo 
1843 */
1844 static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1845                        struct samr_QueryDisplayInfo *r)
1846 {
1847         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1848 }
1849
1850
1851 /* 
1852   samr_GetDisplayEnumerationIndex 
1853 */
1854 static NTSTATUS samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1855                        struct samr_GetDisplayEnumerationIndex *r)
1856 {
1857         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1858 }
1859
1860
1861 /* 
1862   samr_TestPrivateFunctionsDomain 
1863 */
1864 static NTSTATUS samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1865                        struct samr_TestPrivateFunctionsDomain *r)
1866 {
1867         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1868 }
1869
1870
1871 /* 
1872   samr_TestPrivateFunctionsUser 
1873 */
1874 static NTSTATUS samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1875                        struct samr_TestPrivateFunctionsUser *r)
1876 {
1877         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1878 }
1879
1880
1881 /* 
1882   samr_GetUserPwInfo 
1883 */
1884 static NTSTATUS samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1885                                    struct samr_GetUserPwInfo *r)
1886 {
1887         struct dcesrv_handle *h;
1888         struct samr_account_state *a_state;
1889
1890         ZERO_STRUCT(r->out.info);
1891
1892         DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_USER);
1893
1894         a_state = h->data;
1895
1896         r->out.info.min_password_len = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "minPwdLength", 
1897                                                     "dn=%s", a_state->domain_state->domain_dn);
1898         r->out.info.password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "pwdProperties", 
1899                                                             "dn=%s", a_state->account_dn);
1900         return NT_STATUS_OK;
1901 }
1902
1903
1904 /* 
1905   samr_RemoveMemberFromForeignDomain 
1906 */
1907 static NTSTATUS samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1908                        struct samr_RemoveMemberFromForeignDomain *r)
1909 {
1910         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1911 }
1912
1913
1914 /* 
1915   samr_QueryDomainInfo2 
1916 */
1917 static NTSTATUS samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1918                        struct samr_QueryDomainInfo2 *r)
1919 {
1920         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1921 }
1922
1923
1924 /* 
1925   samr_QueryUserInfo2 
1926
1927   just an alias for samr_QueryUserInfo
1928 */
1929 static NTSTATUS samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1930                                     struct samr_QueryUserInfo2 *r)
1931 {
1932         struct samr_QueryUserInfo r1;
1933         NTSTATUS status;
1934
1935         r1.in.handle = r->in.handle;
1936         r1.in.level  = r->in.level;
1937         
1938         status = samr_QueryUserInfo(dce_call, mem_ctx, &r1);
1939         
1940         r->out.info = r1.out.info;
1941
1942         return status;
1943 }
1944
1945
1946 /* 
1947   samr_QueryDisplayInfo2 
1948 */
1949 static NTSTATUS samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1950                        struct samr_QueryDisplayInfo2 *r)
1951 {
1952         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1953 }
1954
1955
1956 /* 
1957   samr_GetDisplayEnumerationIndex2 
1958 */
1959 static NTSTATUS samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1960                        struct samr_GetDisplayEnumerationIndex2 *r)
1961 {
1962         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1963 }
1964
1965
1966 /* 
1967   samr_QueryDisplayInfo3 
1968 */
1969 static NTSTATUS samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1970                        struct samr_QueryDisplayInfo3 *r)
1971 {
1972         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1973 }
1974
1975
1976 /* 
1977   samr_AddMultipleMembersToAlias 
1978 */
1979 static NTSTATUS samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1980                        struct samr_AddMultipleMembersToAlias *r)
1981 {
1982         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1983 }
1984
1985
1986 /* 
1987   samr_RemoveMultipleMembersFromAlias 
1988 */
1989 static NTSTATUS samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1990                        struct samr_RemoveMultipleMembersFromAlias *r)
1991 {
1992         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1993 }
1994
1995
1996 /* 
1997   samr_GetDomPwInfo 
1998
1999   this fetches the default password properties for a domain
2000
2001   note that w2k3 completely ignores the domain name in this call, and 
2002   always returns the information for the servers primary domain
2003 */
2004 static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2005                                   struct samr_GetDomPwInfo *r)
2006 {
2007         struct ldb_message **msgs;
2008         int ret;
2009         const char * const attrs[] = {"minPwdLength", "pwdProperties", NULL };
2010         void *sam_ctx;
2011
2012         ZERO_STRUCT(r->out.info);
2013
2014         sam_ctx = samdb_connect(mem_ctx);
2015         if (sam_ctx == NULL) {
2016                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2017         }
2018
2019         ret = samdb_search(sam_ctx, 
2020                            mem_ctx, NULL, &msgs, attrs, 
2021                            "(&(name=%s)(objectclass=domain))",
2022                            lp_workgroup());
2023         if (ret <= 0) {
2024                 return NT_STATUS_NO_SUCH_DOMAIN;
2025         }
2026         if (ret > 1) {
2027                 samdb_search_free(sam_ctx, mem_ctx, msgs);
2028                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2029         }
2030
2031         r->out.info.min_password_len         = samdb_result_uint(msgs[0], "minPwdLength", 0);
2032         r->out.info.password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1);
2033
2034         samdb_search_free(sam_ctx, mem_ctx, msgs);
2035
2036         talloc_free(sam_ctx);
2037         return NT_STATUS_OK;
2038 }
2039
2040
2041 /* 
2042   samr_Connect2 
2043 */
2044 static NTSTATUS samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2045                               struct samr_Connect2 *r)
2046 {
2047         struct samr_Connect c;
2048
2049         c.in.system_name = NULL;
2050         c.in.access_mask = r->in.access_mask;
2051         c.out.handle = r->out.handle;
2052
2053         return samr_Connect(dce_call, mem_ctx, &c);
2054 }
2055
2056
2057 /* 
2058   samr_SetUserInfo2 
2059
2060   just an alias for samr_SetUserInfo
2061 */
2062 static NTSTATUS samr_SetUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2063                                   struct samr_SetUserInfo2 *r)
2064 {
2065         struct samr_SetUserInfo r2;
2066
2067         r2.in.handle = r->in.handle;
2068         r2.in.level = r->in.level;
2069         r2.in.info = r->in.info;
2070
2071         return samr_SetUserInfo(dce_call, mem_ctx, &r2);
2072 }
2073
2074
2075 /* 
2076   samr_SetBootKeyInformation 
2077 */
2078 static NTSTATUS samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2079                        struct samr_SetBootKeyInformation *r)
2080 {
2081         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2082 }
2083
2084
2085 /* 
2086   samr_GetBootKeyInformation 
2087 */
2088 static NTSTATUS samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2089                        struct samr_GetBootKeyInformation *r)
2090 {
2091         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2092 }
2093
2094
2095 /* 
2096   samr_Connect3 
2097 */
2098 static NTSTATUS samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2099                        struct samr_Connect3 *r)
2100 {
2101         struct samr_Connect c;
2102
2103         c.in.system_name = NULL;
2104         c.in.access_mask = r->in.access_mask;
2105         c.out.handle = r->out.handle;
2106
2107         return samr_Connect(dce_call, mem_ctx, &c);
2108 }
2109
2110
2111 /* 
2112   samr_Connect4 
2113 */
2114 static NTSTATUS samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2115                        struct samr_Connect4 *r)
2116 {
2117         struct samr_Connect c;
2118
2119         c.in.system_name = NULL;
2120         c.in.access_mask = r->in.access_mask;
2121         c.out.handle = r->out.handle;
2122
2123         return samr_Connect(dce_call, mem_ctx, &c);
2124 }
2125
2126
2127 /* 
2128   samr_Connect5 
2129 */
2130 static NTSTATUS samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2131                               struct samr_Connect5 *r)
2132 {
2133         struct samr_Connect c;
2134         NTSTATUS status;
2135
2136         c.in.system_name = NULL;
2137         c.in.access_mask = r->in.access_mask;
2138         c.out.handle = r->out.handle;
2139
2140         status = samr_Connect(dce_call, mem_ctx, &c);
2141
2142         r->out.info->info1.unknown1 = 3;
2143         r->out.info->info1.unknown2 = 0;
2144         r->out.level = r->in.level;
2145
2146         return status;
2147 }
2148
2149
2150 /* 
2151   samr_RidToSid 
2152 */
2153 static NTSTATUS samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2154                        struct samr_RidToSid *r)
2155 {
2156         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2157 }
2158
2159
2160 /* 
2161   samr_SetDsrmPassword 
2162 */
2163 static NTSTATUS samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2164                        struct samr_SetDsrmPassword *r)
2165 {
2166         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2167 }
2168
2169
2170 /* 
2171   samr_ValidatePassword 
2172 */
2173 static NTSTATUS samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2174                                       struct samr_ValidatePassword *r)
2175 {
2176         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2177 }
2178
2179
2180 /* include the generated boilerplate */
2181 #include "librpc/gen_ndr/ndr_samr_s.c"