r4320: fix locations of new trusting domains and domsin controller
[Samba/gebeck_regimport.git] / source4 / rpc_server / samr / dcesrv_samr.c
blob710d7830ef5688ee88be9bf8d0621ebb4fe88530
1 /*
2 Unix SMB/CIFS implementation.
4 endpoint server for the samr pipe
6 Copyright (C) Andrew Tridgell 2004
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.
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.
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.
23 #include "includes.h"
24 #include "librpc/gen_ndr/ndr_samr.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "rpc_server/common/common.h"
27 #include "rpc_server/samr/dcesrv_samr.h"
28 #include "system/time.h"
29 #include "lib/ldb/include/ldb.h"
33 destroy a general handle.
35 static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h)
37 talloc_free(h->data);
40 /*
41 samr_Connect
43 create a connection to the SAM database
45 static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
46 struct samr_Connect *r)
48 struct samr_connect_state *c_state;
49 struct dcesrv_handle *handle;
51 ZERO_STRUCTP(r->out.connect_handle);
53 c_state = talloc_p(dce_call->conn, struct samr_connect_state);
54 if (!c_state) {
55 return NT_STATUS_NO_MEMORY;
58 /* make sure the sam database is accessible */
59 c_state->sam_ctx = samdb_connect(c_state);
60 if (c_state->sam_ctx == NULL) {
61 talloc_free(c_state);
62 return NT_STATUS_INVALID_SYSTEM_SERVICE;
65 handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_CONNECT);
66 if (!handle) {
67 talloc_free(c_state);
68 return NT_STATUS_NO_MEMORY;
71 handle->data = c_state;
72 handle->destroy = samr_handle_destroy;
74 c_state->access_mask = r->in.access_mask;
75 *r->out.connect_handle = handle->wire_handle;
77 return NT_STATUS_OK;
81 /*
82 samr_Close
84 static NTSTATUS samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
85 struct samr_Close *r)
87 struct dcesrv_handle *h;
89 *r->out.handle = *r->in.handle;
91 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
93 /* this causes the parameters samr_XXX_destroy() to be called by
94 the handle destroy code which destroys the state associated
95 with the handle */
96 dcesrv_handle_destroy(dce_call->conn, h);
98 ZERO_STRUCTP(r->out.handle);
100 return NT_STATUS_OK;
105 samr_SetSecurity
107 static NTSTATUS samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
108 struct samr_SetSecurity *r)
110 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
115 samr_QuerySecurity
117 static NTSTATUS samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
118 struct samr_QuerySecurity *r)
120 struct dcesrv_handle *h;
121 struct sec_desc_buf *sd;
123 r->out.sdbuf = NULL;
125 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
127 sd = talloc_p(mem_ctx, struct sec_desc_buf);
128 if (sd == NULL) {
129 return NT_STATUS_NO_MEMORY;
132 sd->sd = samdb_default_security_descriptor(mem_ctx);
134 r->out.sdbuf = sd;
136 return NT_STATUS_OK;
141 samr_Shutdown
143 we refuse this operation completely. If a admin wants to shutdown samr
144 in Samba then they should use the samba admin tools to disable the samr pipe
146 static NTSTATUS samr_Shutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
147 struct samr_Shutdown *r)
149 return NT_STATUS_ACCESS_DENIED;
154 samr_LookupDomain
156 this maps from a domain name to a SID
158 static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
159 struct samr_LookupDomain *r)
161 struct samr_connect_state *c_state;
162 struct dcesrv_handle *h;
163 struct dom_sid2 *sid;
164 const char *sidstr;
166 r->out.sid = NULL;
168 DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
170 c_state = h->data;
172 if (r->in.domain->string == NULL) {
173 return NT_STATUS_INVALID_PARAMETER;
176 sidstr = samdb_search_string(c_state->sam_ctx,
177 mem_ctx, NULL, "objectSid",
178 "(&(name=%s)(objectclass=domain))",
179 r->in.domain->string);
180 if (sidstr == NULL) {
181 return NT_STATUS_NO_SUCH_DOMAIN;
184 sid = dom_sid_parse_talloc(mem_ctx, sidstr);
185 if (sid == NULL) {
186 DEBUG(0,("samdb: Invalid sid '%s' for domain %s\n",
187 sidstr, r->in.domain->string));
188 return NT_STATUS_INTERNAL_DB_CORRUPTION;
191 r->out.sid = sid;
193 return NT_STATUS_OK;
198 samr_EnumDomains
200 list the domains in the SAM
202 static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
203 struct samr_EnumDomains *r)
205 struct samr_connect_state *c_state;
206 struct dcesrv_handle *h;
207 struct samr_SamArray *array;
208 const char **domains;
209 int count, i, start_i;
211 *r->out.resume_handle = 0;
212 r->out.sam = NULL;
213 r->out.num_entries = 0;
215 DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
217 c_state = h->data;
219 count = samdb_search_string_multiple(c_state->sam_ctx,
220 mem_ctx, NULL, &domains,
221 "name", "(objectclass=domain)");
222 if (count == -1) {
223 DEBUG(0,("samdb: no domains found in EnumDomains\n"));
224 return NT_STATUS_INTERNAL_DB_CORRUPTION;
227 *r->out.resume_handle = count;
229 start_i = *r->in.resume_handle;
231 if (start_i >= count) {
232 /* search past end of list is not an error for this call */
233 return NT_STATUS_OK;
236 array = talloc_p(mem_ctx, struct samr_SamArray);
237 if (array == NULL) {
238 return NT_STATUS_NO_MEMORY;
241 array->count = 0;
242 array->entries = NULL;
244 array->entries = talloc_array_p(mem_ctx, struct samr_SamEntry, count - start_i);
245 if (array->entries == NULL) {
246 return NT_STATUS_NO_MEMORY;
249 for (i=0;i<count-start_i;i++) {
250 array->entries[i].idx = start_i + i;
251 array->entries[i].name.string = domains[start_i+i];
254 r->out.sam = array;
255 r->out.num_entries = i;
256 array->count = r->out.num_entries;
258 return NT_STATUS_OK;
263 samr_OpenDomain
265 static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
266 struct samr_OpenDomain *r)
268 struct dcesrv_handle *h_conn, *h_domain;
269 const char *sidstr, *domain_name;
270 struct samr_connect_state *c_state;
271 struct samr_domain_state *d_state;
272 const char * const attrs[2] = { "name", NULL};
273 struct ldb_message **msgs;
274 int ret;
276 ZERO_STRUCTP(r->out.domain_handle);
278 DCESRV_PULL_HANDLE(h_conn, r->in.connect_handle, SAMR_HANDLE_CONNECT);
280 c_state = h_conn->data;
282 if (r->in.sid == NULL) {
283 return NT_STATUS_INVALID_PARAMETER;
286 sidstr = dom_sid_string(mem_ctx, r->in.sid);
287 if (sidstr == NULL) {
288 return NT_STATUS_INVALID_PARAMETER;
291 ret = samdb_search(c_state->sam_ctx,
292 mem_ctx, NULL, &msgs, attrs,
293 "(&(objectSid=%s)(objectclass=domain))",
294 sidstr);
295 if (ret != 1) {
296 return NT_STATUS_NO_SUCH_DOMAIN;
299 domain_name = ldb_msg_find_string(msgs[0], "name", NULL);
300 if (domain_name == NULL) {
301 return NT_STATUS_NO_SUCH_DOMAIN;
304 d_state = talloc_p(c_state, struct samr_domain_state);
305 if (!d_state) {
306 return NT_STATUS_NO_MEMORY;
309 d_state->connect_state = talloc_reference(d_state, c_state);
310 d_state->sam_ctx = c_state->sam_ctx;
311 d_state->domain_sid = talloc_strdup(d_state, sidstr);
312 d_state->domain_name = talloc_strdup(d_state, domain_name);
313 d_state->domain_dn = talloc_strdup(d_state, msgs[0]->dn);
314 if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) {
315 talloc_free(d_state);
316 return NT_STATUS_NO_MEMORY;
318 d_state->access_mask = r->in.access_mask;
320 h_domain = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_DOMAIN);
321 if (!h_domain) {
322 talloc_free(d_state);
323 return NT_STATUS_NO_MEMORY;
326 h_domain->data = d_state;
327 h_domain->destroy = samr_handle_destroy;
328 *r->out.domain_handle = h_domain->wire_handle;
330 return NT_STATUS_OK;
334 return DomInfo2
336 static NTSTATUS samr_info_DomInfo2(struct samr_domain_state *state, TALLOC_CTX *mem_ctx,
337 struct samr_DomInfo2 *info)
339 const char * const attrs[] = { "comment", "name", NULL };
340 int ret;
341 struct ldb_message **res;
343 ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs,
344 "dn=%s", state->domain_dn);
345 if (ret != 1) {
346 return NT_STATUS_INTERNAL_DB_CORRUPTION;
349 /* where is this supposed to come from? is it settable? */
350 info->force_logoff_time = 0x8000000000000000LL;
352 info->comment.string = samdb_result_string(res[0], "comment", NULL);
353 info->domain.string = samdb_result_string(res[0], "name", NULL);
355 info->primary.string = lp_netbios_name();
356 info->sequence_num = 0;
357 info->role = ROLE_DOMAIN_PDC;
358 info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, NULL, "(objectClass=user)");
359 info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
360 "(&(objectClass=group)(sAMAccountType=%u))",
361 ATYPE_GLOBAL_GROUP);
362 info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
363 "(&(objectClass=group)(sAMAccountType=%u))",
364 ATYPE_LOCAL_GROUP);
366 return NT_STATUS_OK;
370 samr_QueryDomainInfo
372 static NTSTATUS samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
373 struct samr_QueryDomainInfo *r)
375 struct dcesrv_handle *h;
376 struct samr_domain_state *d_state;
378 r->out.info = NULL;
380 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
382 d_state = h->data;
384 r->out.info = talloc_p(mem_ctx, union samr_DomainInfo);
385 if (!r->out.info) {
386 return NT_STATUS_NO_MEMORY;
389 ZERO_STRUCTP(r->out.info);
391 switch (r->in.level) {
392 case 2:
393 return samr_info_DomInfo2(d_state, mem_ctx, &r->out.info->info2);
396 return NT_STATUS_INVALID_INFO_CLASS;
401 samr_SetDomainInfo
403 static NTSTATUS samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
404 struct samr_SetDomainInfo *r)
406 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
410 samr_CreateDomainGroup
412 static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
413 struct samr_CreateDomainGroup *r)
415 struct samr_domain_state *d_state;
416 struct samr_account_state *a_state;
417 struct dcesrv_handle *h;
418 const char *name;
419 struct ldb_message msg;
420 uint32_t rid;
421 const char *groupname, *sidstr, *guidstr;
422 struct GUID guid;
423 time_t now = time(NULL);
424 struct dcesrv_handle *g_handle;
425 int ret;
426 NTSTATUS status;
428 ZERO_STRUCTP(r->out.group_handle);
429 *r->out.rid = 0;
431 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
433 d_state = h->data;
435 groupname = r->in.name->string;
437 if (groupname == NULL) {
438 return NT_STATUS_INVALID_PARAMETER;
441 /* check if the group already exists */
442 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
443 "sAMAccountName",
444 "(&(sAMAccountName=%s)(objectclass=group))",
445 groupname);
446 if (name != NULL) {
447 return NT_STATUS_GROUP_EXISTS;
450 ZERO_STRUCT(msg);
452 /* pull in all the template attributes */
453 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
454 "(&(name=TemplateGroup)(objectclass=groupTemplate))");
455 if (ret != 0) {
456 DEBUG(0,("Failed to load TemplateGroup from samdb\n"));
457 return NT_STATUS_INTERNAL_DB_CORRUPTION;
460 /* allocate a rid */
461 status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
462 d_state->domain_dn, "nextRid", &rid);
463 if (!NT_STATUS_IS_OK(status)) {
464 return status;
467 /* and the group SID */
468 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
469 if (!sidstr) {
470 return NT_STATUS_NO_MEMORY;
473 /* a new GUID */
474 guid = GUID_random();
475 guidstr = GUID_string(mem_ctx, &guid);
476 if (!guidstr) {
477 return NT_STATUS_NO_MEMORY;
480 /* add core elements to the ldb_message for the user */
481 msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", groupname,
482 d_state->domain_dn);
483 if (!msg.dn) {
484 return NT_STATUS_NO_MEMORY;
486 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "name", groupname);
487 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "cn", groupname);
488 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "sAMAccountName", groupname);
489 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", "group");
490 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectSid", sidstr);
491 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectGUID", guidstr);
492 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenCreated", now);
493 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenChanged", now);
495 /* create the group */
496 ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
497 if (ret != 0) {
498 DEBUG(0,("Failed to create group record %s\n", msg.dn));
499 return NT_STATUS_INTERNAL_DB_CORRUPTION;
502 a_state = talloc_p(d_state, struct samr_account_state);
503 if (!a_state) {
504 return NT_STATUS_NO_MEMORY;
506 a_state->sam_ctx = d_state->sam_ctx;
507 a_state->access_mask = r->in.access_mask;
508 a_state->domain_state = talloc_reference(a_state, d_state);
509 a_state->account_dn = talloc_steal(d_state, msg.dn);
510 a_state->account_sid = talloc_strdup(d_state, sidstr);
511 a_state->account_name = talloc_strdup(d_state, groupname);
512 if (!a_state->account_name || !a_state->account_sid) {
513 talloc_free(a_state);
514 return NT_STATUS_NO_MEMORY;
517 /* create the policy handle */
518 g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
519 if (!g_handle) {
520 return NT_STATUS_NO_MEMORY;
523 g_handle->data = a_state;
524 g_handle->destroy = samr_handle_destroy;
526 *r->out.group_handle = g_handle->wire_handle;
527 *r->out.rid = rid;
529 return NT_STATUS_OK;
534 samr_EnumDomainGroups
536 static NTSTATUS samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
537 struct samr_EnumDomainGroups *r)
539 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
544 samr_CreateUser2
546 TODO: This should do some form of locking, especially around the rid allocation
548 static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
549 struct samr_CreateUser2 *r)
551 struct samr_domain_state *d_state;
552 struct samr_account_state *a_state;
553 struct dcesrv_handle *h;
554 const char *name;
555 struct ldb_message msg;
556 uint32_t rid;
557 const char *account_name, *sidstr, *guidstr;
558 struct GUID guid;
559 time_t now = time(NULL);
560 struct dcesrv_handle *u_handle;
561 int ret;
562 NTSTATUS status;
563 const char *container, *additional_class=NULL;
565 ZERO_STRUCTP(r->out.user_handle);
566 *r->out.access_granted = 0;
567 *r->out.rid = 0;
569 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
571 d_state = h->data;
573 account_name = r->in.account_name->string;
575 if (account_name == NULL) {
576 return NT_STATUS_INVALID_PARAMETER;
579 /* check if the user already exists */
580 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
581 "sAMAccountName",
582 "(&(sAMAccountName=%s)(objectclass=user))", account_name);
583 if (name != NULL) {
584 return NT_STATUS_USER_EXISTS;
587 ZERO_STRUCT(msg);
589 /* This must be one of these values *only* */
590 if (r->in.acct_flags == ACB_NORMAL) {
591 /* pull in all the template attributes */
592 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
593 "(&(name=TemplateUser)(objectclass=userTemplate))");
594 if (ret != 0) {
595 DEBUG(0,("Failed to load TemplateUser from samdb\n"));
596 return NT_STATUS_INTERNAL_DB_CORRUPTION;
599 container = "Users";
601 } else if (r->in.acct_flags == ACB_WSTRUST) {
602 /* pull in all the template attributes */
603 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
604 "(&(name=TemplateMemberServer)(objectclass=userTemplate))");
605 if (ret != 0) {
606 DEBUG(0,("Failed to load TemplateMemberServer from samdb\n"));
607 return NT_STATUS_INTERNAL_DB_CORRUPTION;
610 container = "Computers";
611 additional_class = "computer";
613 } else if (r->in.acct_flags == ACB_SVRTRUST) {
614 /* pull in all the template attributes */
615 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
616 "(&(name=TemplateDomainController)(objectclass=userTemplate))");
617 if (ret != 0) {
618 DEBUG(0,("Failed to load TemplateDomainController from samdb\n"));
619 return NT_STATUS_INTERNAL_DB_CORRUPTION;
622 container = "Domain Controllers";
623 additional_class = "computer";
625 } else if (r->in.acct_flags == ACB_DOMTRUST) {
626 /* pull in all the template attributes */
627 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
628 "(&(name=TemplateTrustingDomain)(objectclass=userTemplate))");
629 if (ret != 0) {
630 DEBUG(0,("Failed to load TemplateTrustingDomain from samdb\n"));
631 return NT_STATUS_INTERNAL_DB_CORRUPTION;
634 container = "Users";
635 additional_class = "computer";
637 } else {
638 return NT_STATUS_INVALID_PARAMETER;
641 /* allocate a rid */
642 status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
643 d_state->domain_dn, "nextRid", &rid);
644 if (!NT_STATUS_IS_OK(status)) {
645 return status;
648 /* and the users SID */
649 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
650 if (!sidstr) {
651 return NT_STATUS_NO_MEMORY;
654 /* a new GUID */
655 guid = GUID_random();
656 guidstr = GUID_string(mem_ctx, &guid);
657 if (!guidstr) {
658 return NT_STATUS_NO_MEMORY;
661 /* add core elements to the ldb_message for the user */
662 msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=%s,%s", account_name, container, d_state->domain_dn);
663 if (!msg.dn) {
664 return NT_STATUS_NO_MEMORY;
666 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "name", account_name);
667 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "cn", account_name);
668 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "sAMAccountName", account_name);
669 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", "user");
670 if (additional_class) {
671 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", additional_class);
673 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectSid", sidstr);
674 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectGUID", guidstr);
675 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenCreated", now);
676 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenChanged", now);
678 /* create the user */
679 ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
680 if (ret != 0) {
681 DEBUG(0,("Failed to create user record %s\n", msg.dn));
682 return NT_STATUS_INTERNAL_DB_CORRUPTION;
685 a_state = talloc_p(d_state, struct samr_account_state);
686 if (!a_state) {
687 return NT_STATUS_NO_MEMORY;
689 a_state->sam_ctx = d_state->sam_ctx;
690 a_state->access_mask = r->in.access_mask;
691 a_state->domain_state = talloc_reference(a_state, d_state);
692 a_state->account_dn = talloc_steal(d_state, msg.dn);
693 a_state->account_sid = talloc_strdup(d_state, sidstr);
694 a_state->account_name = talloc_strdup(d_state, account_name);
695 if (!a_state->account_name || !a_state->account_sid) {
696 talloc_free(a_state);
697 return NT_STATUS_NO_MEMORY;
700 /* create the policy handle */
701 u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
702 if (!u_handle) {
703 talloc_free(a_state);
704 return NT_STATUS_NO_MEMORY;
707 u_handle->data = a_state;
708 u_handle->destroy = samr_handle_destroy;
710 /* the domain state is in use one more time */
713 *r->out.user_handle = u_handle->wire_handle;
714 *r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
715 *r->out.rid = rid;
717 return NT_STATUS_OK;
722 samr_CreateUser
724 static NTSTATUS samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
725 struct samr_CreateUser *r)
727 struct samr_CreateUser2 r2;
728 uint32_t access_granted = 0;
731 /* a simple wrapper around samr_CreateUser2 works nicely */
732 r2.in.domain_handle = r->in.domain_handle;
733 r2.in.account_name = r->in.account_name;
734 r2.in.acct_flags = ACB_NORMAL;
735 r2.in.access_mask = r->in.access_mask;
736 r2.out.user_handle = r->out.user_handle;
737 r2.out.access_granted = &access_granted;
738 r2.out.rid = r->out.rid;
740 return samr_CreateUser2(dce_call, mem_ctx, &r2);
744 comparison function for sorting SamEntry array
746 static int compare_SamEntry(struct samr_SamEntry *e1, struct samr_SamEntry *e2)
748 return e1->idx - e2->idx;
752 samr_EnumDomainUsers
754 static NTSTATUS samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
755 struct samr_EnumDomainUsers *r)
757 struct dcesrv_handle *h;
758 struct samr_domain_state *d_state;
759 struct ldb_message **res;
760 int count, i, first;
761 struct samr_SamEntry *entries;
762 const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
764 *r->out.resume_handle = 0;
765 r->out.sam = NULL;
766 r->out.num_entries = 0;
768 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
770 d_state = h->data;
772 /* search for all users in this domain. This could possibly be cached and
773 resumed based on resume_key */
774 count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
775 "objectclass=user");
776 if (count == -1) {
777 return NT_STATUS_INTERNAL_DB_CORRUPTION;
779 if (count == 0 || r->in.max_size == 0) {
780 return NT_STATUS_OK;
783 /* convert to SamEntry format */
784 entries = talloc_array_p(mem_ctx, struct samr_SamEntry, count);
785 if (!entries) {
786 return NT_STATUS_NO_MEMORY;
788 for (i=0;i<count;i++) {
789 entries[i].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
790 entries[i].name.string = samdb_result_string(res[i], "sAMAccountName", "");
793 /* sort the results by rid */
794 qsort(entries, count, sizeof(struct samr_SamEntry),
795 (comparison_fn_t)compare_SamEntry);
797 /* find the first entry to return */
798 for (first=0;
799 first<count && entries[first].idx <= *r->in.resume_handle;
800 first++) ;
802 if (first == count) {
803 return NT_STATUS_OK;
806 /* return the rest, limit by max_size. Note that we
807 use the w2k3 element size value of 54 */
808 r->out.num_entries = count - first;
809 r->out.num_entries = MIN(r->out.num_entries,
810 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
812 r->out.sam = talloc_p(mem_ctx, struct samr_SamArray);
813 if (!r->out.sam) {
814 return NT_STATUS_NO_MEMORY;
817 r->out.sam->entries = entries+first;
818 r->out.sam->count = r->out.num_entries;
820 if (r->out.num_entries < count - first) {
821 *r->out.resume_handle = entries[first+r->out.num_entries-1].idx;
822 return STATUS_MORE_ENTRIES;
825 return NT_STATUS_OK;
830 samr_CreateDomAlias
832 static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
833 struct samr_CreateDomAlias *r)
835 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
840 samr_EnumDomainAliases
842 static NTSTATUS samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
843 struct samr_EnumDomainAliases *r)
845 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
850 samr_GetAliasMembership
852 static NTSTATUS samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
853 struct samr_GetAliasMembership *r)
855 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
860 samr_LookupNames
862 static NTSTATUS samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
863 struct samr_LookupNames *r)
865 struct dcesrv_handle *h;
866 struct samr_domain_state *d_state;
867 int i;
868 NTSTATUS status = NT_STATUS_OK;
869 const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
870 int count;
872 ZERO_STRUCT(r->out.rids);
873 ZERO_STRUCT(r->out.types);
875 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
877 d_state = h->data;
879 if (r->in.num_names == 0) {
880 return NT_STATUS_OK;
883 r->out.rids.ids = talloc_array_p(mem_ctx, uint32_t, r->in.num_names);
884 r->out.types.ids = talloc_array_p(mem_ctx, uint32_t, r->in.num_names);
885 if (!r->out.rids.ids || !r->out.types.ids) {
886 return NT_STATUS_NO_MEMORY;
888 r->out.rids.count = r->in.num_names;
889 r->out.types.count = r->in.num_names;
891 for (i=0;i<r->in.num_names;i++) {
892 struct ldb_message **res;
893 struct dom_sid2 *sid;
894 const char *sidstr;
895 uint32_t atype, rtype;
897 r->out.rids.ids[i] = 0;
898 r->out.types.ids[i] = SID_NAME_UNKNOWN;
900 count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
901 "sAMAccountName=%s", r->in.names[i].string);
902 if (count != 1) {
903 status = STATUS_SOME_UNMAPPED;
904 continue;
907 sidstr = samdb_result_string(res[0], "objectSid", NULL);
908 if (sidstr == NULL) {
909 status = STATUS_SOME_UNMAPPED;
910 continue;
913 sid = dom_sid_parse_talloc(mem_ctx, sidstr);
914 if (sid == NULL) {
915 status = STATUS_SOME_UNMAPPED;
916 continue;
919 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
920 if (atype == 0) {
921 status = STATUS_SOME_UNMAPPED;
922 continue;
925 rtype = samdb_atype_map(atype);
927 if (rtype == SID_NAME_UNKNOWN) {
928 status = STATUS_SOME_UNMAPPED;
929 continue;
932 r->out.rids.ids[i] = sid->sub_auths[sid->num_auths-1];
933 r->out.types.ids[i] = rtype;
937 return status;
942 samr_LookupRids
944 static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
945 struct samr_LookupRids *r)
947 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
952 samr_OpenGroup
954 static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
955 struct samr_OpenGroup *r)
957 struct samr_domain_state *d_state;
958 struct samr_account_state *a_state;
959 struct dcesrv_handle *h;
960 const char *groupname, *sidstr;
961 struct ldb_message **msgs;
962 struct dcesrv_handle *g_handle;
963 const char * const attrs[2] = { "sAMAccountName", NULL };
964 int ret;
966 ZERO_STRUCTP(r->out.group_handle);
968 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
970 d_state = h->data;
972 /* form the group SID */
973 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
974 if (!sidstr) {
975 return NT_STATUS_NO_MEMORY;
978 /* search for the group record */
979 ret = samdb_search(d_state->sam_ctx,
980 mem_ctx, d_state->domain_dn, &msgs, attrs,
981 "(&(objectSid=%s)(objectclass=group))",
982 sidstr);
983 if (ret == 0) {
984 return NT_STATUS_NO_SUCH_GROUP;
986 if (ret != 1) {
987 DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
988 return NT_STATUS_INTERNAL_DB_CORRUPTION;
991 groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
992 if (groupname == NULL) {
993 DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
994 return NT_STATUS_INTERNAL_DB_CORRUPTION;
997 a_state = talloc_p(d_state, struct samr_account_state);
998 if (!a_state) {
999 return NT_STATUS_NO_MEMORY;
1001 a_state->sam_ctx = d_state->sam_ctx;
1002 a_state->access_mask = r->in.access_mask;
1003 a_state->domain_state = talloc_reference(a_state, d_state);
1004 a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
1005 a_state->account_sid = talloc_strdup(a_state, sidstr);
1006 a_state->account_name = talloc_strdup(a_state, groupname);
1007 if (!a_state->account_name || !a_state->account_sid) {
1008 return NT_STATUS_NO_MEMORY;
1011 /* create the policy handle */
1012 g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
1013 if (!g_handle) {
1014 return NT_STATUS_NO_MEMORY;
1017 g_handle->data = a_state;
1018 g_handle->destroy = samr_handle_destroy;
1020 *r->out.group_handle = g_handle->wire_handle;
1022 return NT_STATUS_OK;
1025 /* these query macros make samr_Query[User|Group]Info a bit easier to read */
1027 #define QUERY_STRING(msg, field, attr) \
1028 r->out.info->field = samdb_result_string(msg, attr, "");
1029 #define QUERY_UINT(msg, field, attr) \
1030 r->out.info->field = samdb_result_uint(msg, attr, 0);
1031 #define QUERY_RID(msg, field, attr) \
1032 r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
1033 #define QUERY_NTTIME(msg, field, attr) \
1034 r->out.info->field = samdb_result_nttime(msg, attr, 0);
1035 #define QUERY_APASSC(msg, field, attr) \
1036 r->out.info->field = samdb_result_allow_password_change(a_state->sam_ctx, mem_ctx, \
1037 a_state->domain_state->domain_dn, msg, attr);
1038 #define QUERY_FPASSC(msg, field, attr) \
1039 r->out.info->field = samdb_result_force_password_change(a_state->sam_ctx, mem_ctx, \
1040 a_state->domain_state->domain_dn, msg, attr);
1041 #define QUERY_LHOURS(msg, field, attr) \
1042 r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
1043 #define QUERY_AFLAGS(msg, field, attr) \
1044 r->out.info->field = samdb_result_acct_flags(msg, attr);
1047 /* these are used to make the Set[User|Group]Info code easier to follow */
1049 #define SET_STRING(mod, field, attr) do { \
1050 if (r->in.info->field == NULL) return NT_STATUS_INVALID_PARAMETER; \
1051 if (samdb_msg_add_string(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
1052 return NT_STATUS_NO_MEMORY; \
1054 } while (0)
1056 #define SET_UINT(mod, field, attr) do { \
1057 if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
1058 return NT_STATUS_NO_MEMORY; \
1060 } while (0)
1062 #define SET_AFLAGS(msg, field, attr) do { \
1063 if (samdb_msg_add_acct_flags(a_state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
1064 return NT_STATUS_NO_MEMORY; \
1066 } while (0)
1068 #define SET_LHOURS(msg, field, attr) do { \
1069 if (samdb_msg_add_logon_hours(a_state->sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
1070 return NT_STATUS_NO_MEMORY; \
1072 } while (0)
1075 samr_QueryGroupInfo
1077 static NTSTATUS samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1078 struct samr_QueryGroupInfo *r)
1080 struct dcesrv_handle *h;
1081 struct samr_account_state *a_state;
1082 struct ldb_message *msg, **res;
1083 const char * const attrs[4] = { "sAMAccountName", "description",
1084 "numMembers", NULL };
1085 int ret;
1087 r->out.info = NULL;
1089 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1091 a_state = h->data;
1093 /* pull all the group attributes */
1094 ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs,
1095 "dn=%s", a_state->account_dn);
1096 if (ret != 1) {
1097 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1099 msg = res[0];
1101 /* allocate the info structure */
1102 r->out.info = talloc_p(mem_ctx, union samr_GroupInfo);
1103 if (r->out.info == NULL) {
1104 return NT_STATUS_NO_MEMORY;
1106 ZERO_STRUCTP(r->out.info);
1108 /* Fill in the level */
1109 switch (r->in.level) {
1110 case GroupInfoAll:
1111 QUERY_STRING(msg, all.name.string, "sAMAccountName");
1112 r->out.info->all.attributes = 7; /* Do like w2k3 */
1113 QUERY_UINT (msg, all.num_members, "numMembers")
1114 QUERY_STRING(msg, all.description.string, "description");
1115 break;
1116 case GroupInfoName:
1117 QUERY_STRING(msg, name.string, "sAMAccountName");
1118 break;
1119 case GroupInfoX:
1120 r->out.info->unknown.unknown = 7;
1121 break;
1122 case GroupInfoDescription:
1123 QUERY_STRING(msg, description.string, "description");
1124 break;
1125 default:
1126 r->out.info = NULL;
1127 return NT_STATUS_INVALID_INFO_CLASS;
1130 return NT_STATUS_OK;
1135 samr_SetGroupInfo
1137 static NTSTATUS samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1138 struct samr_SetGroupInfo *r)
1140 struct dcesrv_handle *h;
1141 struct samr_account_state *a_state;
1142 struct ldb_message mod, *msg = &mod;
1143 int ret;
1145 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1147 a_state = h->data;
1149 ZERO_STRUCT(mod);
1150 mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
1151 if (!mod.dn) {
1152 return NT_STATUS_NO_MEMORY;
1155 switch (r->in.level) {
1156 case GroupInfoDescription:
1157 SET_STRING(msg, description.string, "description");
1158 break;
1159 case GroupInfoName:
1160 /* On W2k3 this does not change the name, it changes the
1161 * sAMAccountName attribute */
1162 SET_STRING(msg, name.string, "sAMAccountName");
1163 break;
1164 case GroupInfoX:
1165 /* This does not do anything obviously visible in W2k3 LDAP */
1166 break;
1167 default:
1168 return NT_STATUS_INVALID_INFO_CLASS;
1171 /* modify the samdb record */
1172 ret = samdb_replace(a_state->sam_ctx, mem_ctx, &mod);
1173 if (ret != 0) {
1174 /* we really need samdb.c to return NTSTATUS */
1175 return NT_STATUS_UNSUCCESSFUL;
1178 return NT_STATUS_OK;
1183 samr_AddGroupMember
1185 static NTSTATUS samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1186 struct samr_AddGroupMember *r)
1188 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1193 samr_DeleteDomainGroup
1195 static NTSTATUS samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1196 struct samr_DeleteDomainGroup *r)
1198 struct dcesrv_handle *h;
1199 struct samr_account_state *a_state;
1200 int ret;
1202 *r->out.group_handle = *r->in.group_handle;
1204 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1206 a_state = h->data;
1208 ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
1209 if (ret != 0) {
1210 return NT_STATUS_UNSUCCESSFUL;
1213 ZERO_STRUCTP(r->out.group_handle);
1215 return NT_STATUS_OK;
1220 samr_DeleteGroupMember
1222 static NTSTATUS samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1223 struct samr_DeleteGroupMember *r)
1225 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1230 samr_QueryGroupMember
1232 static NTSTATUS samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1233 struct samr_QueryGroupMember *r)
1235 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1240 samr_SetMemberAttributesOfGroup
1242 static NTSTATUS samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1243 struct samr_SetMemberAttributesOfGroup *r)
1245 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1250 samr_OpenAlias
1252 static NTSTATUS samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1253 struct samr_OpenAlias *r)
1255 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1260 samr_QueryAliasInfo
1262 static NTSTATUS samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1263 struct samr_QueryAliasInfo *r)
1265 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1270 samr_SetAliasInfo
1272 static NTSTATUS samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1273 struct samr_SetAliasInfo *r)
1275 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1280 samr_DeleteDomAlias
1282 static NTSTATUS samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1283 struct samr_DeleteDomAlias *r)
1285 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1290 samr_AddAliasMember
1292 static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1293 struct samr_AddAliasMember *r)
1295 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1300 samr_DeleteAliasMember
1302 static NTSTATUS samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1303 struct samr_DeleteAliasMember *r)
1305 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1310 samr_GetMembersInAlias
1312 static NTSTATUS samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1313 struct samr_GetMembersInAlias *r)
1315 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1320 samr_OpenUser
1322 static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1323 struct samr_OpenUser *r)
1325 struct samr_domain_state *d_state;
1326 struct samr_account_state *a_state;
1327 struct dcesrv_handle *h;
1328 const char *account_name, *sidstr;
1329 struct ldb_message **msgs;
1330 struct dcesrv_handle *u_handle;
1331 const char * const attrs[2] = { "sAMAccountName", NULL };
1332 int ret;
1334 ZERO_STRUCTP(r->out.user_handle);
1336 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
1338 d_state = h->data;
1340 /* form the users SID */
1341 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
1342 if (!sidstr) {
1343 return NT_STATUS_NO_MEMORY;
1346 /* search for the user record */
1347 ret = samdb_search(d_state->sam_ctx,
1348 mem_ctx, d_state->domain_dn, &msgs, attrs,
1349 "(&(objectSid=%s)(objectclass=user))",
1350 sidstr);
1351 if (ret == 0) {
1352 return NT_STATUS_NO_SUCH_USER;
1354 if (ret != 1) {
1355 DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
1356 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1359 account_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
1360 if (account_name == NULL) {
1361 DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
1362 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1365 a_state = talloc_p(d_state, struct samr_account_state);
1366 if (!a_state) {
1367 return NT_STATUS_NO_MEMORY;
1369 a_state->sam_ctx = d_state->sam_ctx;
1370 a_state->access_mask = r->in.access_mask;
1371 a_state->domain_state = talloc_reference(a_state, d_state);
1372 a_state->account_dn = talloc_steal(d_state, msgs[0]->dn);
1373 a_state->account_sid = talloc_strdup(d_state, sidstr);
1374 a_state->account_name = talloc_strdup(d_state, account_name);
1375 if (!a_state->account_name || !a_state->account_sid) {
1376 return NT_STATUS_NO_MEMORY;
1379 /* create the policy handle */
1380 u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
1381 if (!u_handle) {
1382 return NT_STATUS_NO_MEMORY;
1385 u_handle->data = a_state;
1386 u_handle->destroy = samr_handle_destroy;
1388 *r->out.user_handle = u_handle->wire_handle;
1390 return NT_STATUS_OK;
1396 samr_DeleteUser
1398 static NTSTATUS samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1399 struct samr_DeleteUser *r)
1401 struct dcesrv_handle *h;
1402 struct samr_account_state *a_state;
1403 int ret;
1405 *r->out.user_handle = *r->in.user_handle;
1407 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1409 a_state = h->data;
1411 ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
1412 if (ret != 0) {
1413 return NT_STATUS_UNSUCCESSFUL;
1416 ZERO_STRUCTP(r->out.user_handle);
1418 return NT_STATUS_OK;
1423 samr_QueryUserInfo
1425 static NTSTATUS samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1426 struct samr_QueryUserInfo *r)
1428 struct dcesrv_handle *h;
1429 struct samr_account_state *a_state;
1430 struct ldb_message *msg, **res;
1431 int ret;
1433 r->out.info = NULL;
1435 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1437 a_state = h->data;
1439 /* pull all the user attributes */
1440 ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, NULL,
1441 "dn=%s", a_state->account_dn);
1442 if (ret != 1) {
1443 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1445 msg = res[0];
1447 /* allocate the info structure */
1448 r->out.info = talloc_p(mem_ctx, union samr_UserInfo);
1449 if (r->out.info == NULL) {
1450 return NT_STATUS_NO_MEMORY;
1452 ZERO_STRUCTP(r->out.info);
1454 /* fill in the reply */
1455 switch (r->in.level) {
1456 case 1:
1457 QUERY_STRING(msg, info1.account_name.string, "sAMAccountName");
1458 QUERY_STRING(msg, info1.full_name.string, "displayName");
1459 QUERY_UINT (msg, info1.primary_gid, "primaryGroupID");
1460 QUERY_STRING(msg, info1.description.string, "description");
1461 QUERY_STRING(msg, info1.comment.string, "comment");
1462 break;
1464 case 2:
1465 QUERY_STRING(msg, info2.comment.string, "comment");
1466 QUERY_UINT (msg, info2.country_code, "countryCode");
1467 QUERY_UINT (msg, info2.code_page, "codePage");
1468 break;
1470 case 3:
1471 QUERY_STRING(msg, info3.account_name.string, "sAMAccountName");
1472 QUERY_STRING(msg, info3.full_name.string, "displayName");
1473 QUERY_RID (msg, info3.rid, "objectSid");
1474 QUERY_UINT (msg, info3.primary_gid, "primaryGroupID");
1475 QUERY_STRING(msg, info3.home_directory.string, "homeDirectory");
1476 QUERY_STRING(msg, info3.home_drive.string, "homeDrive");
1477 QUERY_STRING(msg, info3.logon_script.string, "scriptPath");
1478 QUERY_STRING(msg, info3.profile_path.string, "profilePath");
1479 QUERY_STRING(msg, info3.workstations.string, "userWorkstations");
1480 QUERY_NTTIME(msg, info3.last_logon, "lastLogon");
1481 QUERY_NTTIME(msg, info3.last_logoff, "lastLogoff");
1482 QUERY_NTTIME(msg, info3.last_password_change, "pwdLastSet");
1483 QUERY_APASSC(msg, info3.allow_password_change, "pwdLastSet");
1484 QUERY_FPASSC(msg, info3.force_password_change, "pwdLastSet");
1485 QUERY_LHOURS(msg, info3.logon_hours, "logonHours");
1486 QUERY_UINT (msg, info3.bad_password_count, "badPwdCount");
1487 QUERY_UINT (msg, info3.logon_count, "logonCount");
1488 QUERY_AFLAGS(msg, info3.acct_flags, "userAccountControl");
1489 break;
1491 case 4:
1492 QUERY_LHOURS(msg, info4.logon_hours, "logonHours");
1493 break;
1495 case 5:
1496 QUERY_STRING(msg, info5.account_name.string, "sAMAccountName");
1497 QUERY_STRING(msg, info5.full_name.string, "displayName");
1498 QUERY_RID (msg, info5.rid, "objectSid");
1499 QUERY_UINT (msg, info5.primary_gid, "primaryGroupID");
1500 QUERY_STRING(msg, info5.home_directory.string, "homeDirectory");
1501 QUERY_STRING(msg, info5.home_drive.string, "homeDrive");
1502 QUERY_STRING(msg, info5.logon_script.string, "scriptPath");
1503 QUERY_STRING(msg, info5.profile_path.string, "profilePath");
1504 QUERY_STRING(msg, info5.description.string, "description");
1505 QUERY_STRING(msg, info5.workstations.string, "userWorkstations");
1506 QUERY_NTTIME(msg, info5.last_logon, "lastLogon");
1507 QUERY_NTTIME(msg, info5.last_logoff, "lastLogoff");
1508 QUERY_LHOURS(msg, info5.logon_hours, "logonHours");
1509 QUERY_UINT (msg, info5.bad_password_count, "badPwdCount");
1510 QUERY_UINT (msg, info5.logon_count, "logonCount");
1511 QUERY_NTTIME(msg, info5.last_password_change, "pwdLastSet");
1512 QUERY_NTTIME(msg, info5.acct_expiry, "accountExpires");
1513 QUERY_AFLAGS(msg, info5.acct_flags, "userAccountControl");
1514 break;
1516 case 6:
1517 QUERY_STRING(msg, info6.account_name.string, "sAMAccountName");
1518 QUERY_STRING(msg, info6.full_name.string, "displayName");
1519 break;
1521 case 7:
1522 QUERY_STRING(msg, info7.account_name.string, "sAMAccountName");
1523 break;
1525 case 8:
1526 QUERY_STRING(msg, info8.full_name.string, "displayName");
1527 break;
1529 case 9:
1530 QUERY_UINT (msg, info9.primary_gid, "primaryGroupID");
1531 break;
1533 case 10:
1534 QUERY_STRING(msg, info10.home_directory.string,"homeDirectory");
1535 QUERY_STRING(msg, info10.home_drive.string, "homeDrive");
1536 break;
1538 case 11:
1539 QUERY_STRING(msg, info11.logon_script.string, "scriptPath");
1540 break;
1542 case 12:
1543 QUERY_STRING(msg, info12.profile_path.string, "profilePath");
1544 break;
1546 case 13:
1547 QUERY_STRING(msg, info13.description.string, "description");
1548 break;
1550 case 14:
1551 QUERY_STRING(msg, info14.workstations.string, "userWorkstations");
1552 break;
1554 case 16:
1555 QUERY_AFLAGS(msg, info16.acct_flags, "userAccountControl");
1556 break;
1558 case 17:
1559 QUERY_NTTIME(msg, info17.acct_expiry, "accountExpires");
1561 case 20:
1562 QUERY_STRING(msg, info20.parameters.string, "userParameters");
1563 break;
1565 case 21:
1566 QUERY_NTTIME(msg, info21.last_logon, "lastLogon");
1567 QUERY_NTTIME(msg, info21.last_logoff, "lastLogoff");
1568 QUERY_NTTIME(msg, info21.last_password_change, "pwdLastSet");
1569 QUERY_NTTIME(msg, info21.acct_expiry, "accountExpires");
1570 QUERY_APASSC(msg, info21.allow_password_change,"pwdLastSet");
1571 QUERY_FPASSC(msg, info21.force_password_change,"pwdLastSet");
1572 QUERY_STRING(msg, info21.account_name.string, "sAMAccountName");
1573 QUERY_STRING(msg, info21.full_name.string, "displayName");
1574 QUERY_STRING(msg, info21.home_directory.string,"homeDirectory");
1575 QUERY_STRING(msg, info21.home_drive.string, "homeDrive");
1576 QUERY_STRING(msg, info21.logon_script.string, "scriptPath");
1577 QUERY_STRING(msg, info21.profile_path.string, "profilePath");
1578 QUERY_STRING(msg, info21.description.string, "description");
1579 QUERY_STRING(msg, info21.workstations.string, "userWorkstations");
1580 QUERY_STRING(msg, info21.comment.string, "comment");
1581 QUERY_STRING(msg, info21.parameters.string, "userParameters");
1582 QUERY_RID (msg, info21.rid, "objectSid");
1583 QUERY_UINT (msg, info21.primary_gid, "primaryGroupID");
1584 QUERY_AFLAGS(msg, info21.acct_flags, "userAccountControl");
1585 r->out.info->info21.fields_present = 0x00FFFFFF;
1586 QUERY_LHOURS(msg, info21.logon_hours, "logonHours");
1587 QUERY_UINT (msg, info21.bad_password_count, "badPwdCount");
1588 QUERY_UINT (msg, info21.logon_count, "logonCount");
1589 QUERY_UINT (msg, info21.country_code, "countryCode");
1590 QUERY_UINT (msg, info21.code_page, "codePage");
1591 break;
1594 default:
1595 r->out.info = NULL;
1596 return NT_STATUS_INVALID_INFO_CLASS;
1599 return NT_STATUS_OK;
1604 samr_SetUserInfo
1606 static NTSTATUS samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1607 struct samr_SetUserInfo *r)
1609 struct dcesrv_handle *h;
1610 struct samr_account_state *a_state;
1611 struct ldb_message mod, *msg = &mod;
1612 int ret;
1613 NTSTATUS status = NT_STATUS_OK;
1615 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1617 a_state = h->data;
1619 ZERO_STRUCT(mod);
1620 mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
1621 if (!mod.dn) {
1622 return NT_STATUS_NO_MEMORY;
1625 switch (r->in.level) {
1626 case 2:
1627 SET_STRING(msg, info2.comment.string, "comment");
1628 SET_UINT (msg, info2.country_code, "countryCode");
1629 SET_UINT (msg, info2.code_page, "codePage");
1630 break;
1632 case 4:
1633 SET_LHOURS(msg, info4.logon_hours, "logonHours");
1634 break;
1636 case 6:
1637 SET_STRING(msg, info6.full_name.string, "displayName");
1638 break;
1640 case 8:
1641 SET_STRING(msg, info8.full_name.string, "displayName");
1642 break;
1644 case 9:
1645 SET_UINT(msg, info9.primary_gid, "primaryGroupID");
1646 break;
1648 case 10:
1649 SET_STRING(msg, info10.home_directory.string, "homeDirectory");
1650 SET_STRING(msg, info10.home_drive.string, "homeDrive");
1651 break;
1653 case 11:
1654 SET_STRING(msg, info11.logon_script.string, "scriptPath");
1655 break;
1657 case 12:
1658 SET_STRING(msg, info12.profile_path.string, "profilePath");
1659 break;
1661 case 13:
1662 SET_STRING(msg, info13.description.string, "description");
1663 break;
1665 case 14:
1666 SET_STRING(msg, info14.workstations.string, "userWorkstations");
1667 break;
1669 case 16:
1670 SET_AFLAGS(msg, info16.acct_flags, "userAccountControl");
1671 break;
1673 case 20:
1674 SET_STRING(msg, info20.parameters.string, "userParameters");
1675 break;
1677 case 21:
1678 #define IFSET(bit) if (bit & r->in.info->info21.fields_present)
1679 IFSET(SAMR_FIELD_NAME)
1680 SET_STRING(msg, info21.full_name.string, "displayName");
1681 IFSET(SAMR_FIELD_DESCRIPTION)
1682 SET_STRING(msg, info21.description.string, "description");
1683 IFSET(SAMR_FIELD_COMMENT)
1684 SET_STRING(msg, info21.comment.string, "comment");
1685 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1686 SET_STRING(msg, info21.logon_script.string, "scriptPath");
1687 IFSET(SAMR_FIELD_PROFILE_PATH)
1688 SET_STRING(msg, info21.profile_path.string, "profilePath");
1689 IFSET(SAMR_FIELD_WORKSTATION)
1690 SET_STRING(msg, info21.workstations.string, "userWorkstations");
1691 IFSET(SAMR_FIELD_LOGON_HOURS)
1692 SET_LHOURS(msg, info21.logon_hours, "logonHours");
1693 IFSET(SAMR_FIELD_ACCT_FLAGS)
1694 SET_AFLAGS(msg, info21.acct_flags, "userAccountControl");
1695 IFSET(SAMR_FIELD_PARAMETERS)
1696 SET_STRING(msg, info21.parameters.string, "userParameters");
1697 IFSET(SAMR_FIELD_COUNTRY_CODE)
1698 SET_UINT (msg, info21.country_code, "countryCode");
1699 IFSET(SAMR_FIELD_CODE_PAGE)
1700 SET_UINT (msg, info21.code_page, "codePage");
1703 /* Any reason the rest of these can't be set? */
1704 #undef IFSET
1705 break;
1707 case 23:
1708 #define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
1709 IFSET(SAMR_FIELD_NAME)
1710 SET_STRING(msg, info23.info.full_name.string, "displayName");
1711 IFSET(SAMR_FIELD_DESCRIPTION)
1712 SET_STRING(msg, info23.info.description.string, "description");
1713 IFSET(SAMR_FIELD_COMMENT)
1714 SET_STRING(msg, info23.info.comment.string, "comment");
1715 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1716 SET_STRING(msg, info23.info.logon_script.string, "scriptPath");
1717 IFSET(SAMR_FIELD_PROFILE_PATH)
1718 SET_STRING(msg, info23.info.profile_path.string, "profilePath");
1719 IFSET(SAMR_FIELD_WORKSTATION)
1720 SET_STRING(msg, info23.info.workstations.string, "userWorkstations");
1721 IFSET(SAMR_FIELD_LOGON_HOURS)
1722 SET_LHOURS(msg, info23.info.logon_hours, "logonHours");
1723 IFSET(SAMR_FIELD_ACCT_FLAGS)
1724 SET_AFLAGS(msg, info23.info.acct_flags, "userAccountControl");
1725 IFSET(SAMR_FIELD_PARAMETERS)
1726 SET_STRING(msg, info23.info.parameters.string, "userParameters");
1727 IFSET(SAMR_FIELD_COUNTRY_CODE)
1728 SET_UINT (msg, info23.info.country_code, "countryCode");
1729 IFSET(SAMR_FIELD_CODE_PAGE)
1730 SET_UINT (msg, info23.info.code_page, "codePage");
1731 IFSET(SAMR_FIELD_PASSWORD) {
1732 status = samr_set_password(dce_call,
1733 a_state->sam_ctx,
1734 a_state->account_dn,
1735 a_state->domain_state->domain_dn,
1736 mem_ctx, msg,
1737 &r->in.info->info23.password);
1738 } else IFSET(SAMR_FIELD_PASSWORD2) {
1739 status = samr_set_password(dce_call,
1740 a_state->sam_ctx,
1741 a_state->account_dn,
1742 a_state->domain_state->domain_dn,
1743 mem_ctx, msg,
1744 &r->in.info->info23.password);
1746 #undef IFSET
1747 break;
1749 /* the set password levels are handled separately */
1750 case 24:
1751 status = samr_set_password(dce_call,
1752 a_state->sam_ctx,
1753 a_state->account_dn,
1754 a_state->domain_state->domain_dn,
1755 mem_ctx, msg,
1756 &r->in.info->info24.password);
1757 break;
1759 case 25:
1760 #define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
1761 IFSET(SAMR_FIELD_NAME)
1762 SET_STRING(msg, info25.info.full_name.string, "displayName");
1763 IFSET(SAMR_FIELD_DESCRIPTION)
1764 SET_STRING(msg, info25.info.description.string, "description");
1765 IFSET(SAMR_FIELD_COMMENT)
1766 SET_STRING(msg, info25.info.comment.string, "comment");
1767 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1768 SET_STRING(msg, info25.info.logon_script.string, "scriptPath");
1769 IFSET(SAMR_FIELD_PROFILE_PATH)
1770 SET_STRING(msg, info25.info.profile_path.string, "profilePath");
1771 IFSET(SAMR_FIELD_WORKSTATION)
1772 SET_STRING(msg, info25.info.workstations.string, "userWorkstations");
1773 IFSET(SAMR_FIELD_LOGON_HOURS)
1774 SET_LHOURS(msg, info25.info.logon_hours, "logonHours");
1775 IFSET(SAMR_FIELD_ACCT_FLAGS)
1776 SET_AFLAGS(msg, info25.info.acct_flags, "userAccountControl");
1777 IFSET(SAMR_FIELD_PARAMETERS)
1778 SET_STRING(msg, info25.info.parameters.string, "userParameters");
1779 IFSET(SAMR_FIELD_COUNTRY_CODE)
1780 SET_UINT (msg, info25.info.country_code, "countryCode");
1781 IFSET(SAMR_FIELD_CODE_PAGE)
1782 SET_UINT (msg, info25.info.code_page, "codePage");
1783 IFSET(SAMR_FIELD_PASSWORD) {
1784 status = samr_set_password_ex(dce_call,
1785 a_state->sam_ctx,
1786 a_state->account_dn,
1787 a_state->domain_state->domain_dn,
1788 mem_ctx, msg,
1789 &r->in.info->info25.password);
1790 } else IFSET(SAMR_FIELD_PASSWORD2) {
1791 status = samr_set_password_ex(dce_call,
1792 a_state->sam_ctx,
1793 a_state->account_dn,
1794 a_state->domain_state->domain_dn,
1795 mem_ctx, msg,
1796 &r->in.info->info25.password);
1798 #undef IFSET
1799 break;
1801 /* the set password levels are handled separately */
1802 case 26:
1803 status = samr_set_password_ex(dce_call,
1804 a_state->sam_ctx,
1805 a_state->account_dn,
1806 a_state->domain_state->domain_dn,
1807 mem_ctx, msg,
1808 &r->in.info->info26.password);
1809 break;
1812 default:
1813 /* many info classes are not valid for SetUserInfo */
1814 return NT_STATUS_INVALID_INFO_CLASS;
1817 if (!NT_STATUS_IS_OK(status)) {
1818 return status;
1821 /* modify the samdb record */
1822 ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
1823 if (ret != 0) {
1824 /* we really need samdb.c to return NTSTATUS */
1825 return NT_STATUS_UNSUCCESSFUL;
1828 return NT_STATUS_OK;
1833 samr_GetGroupsForUser
1835 static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1836 struct samr_GetGroupsForUser *r)
1838 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1843 samr_QueryDisplayInfo
1845 static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1846 struct samr_QueryDisplayInfo *r)
1848 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1853 samr_GetDisplayEnumerationIndex
1855 static NTSTATUS samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1856 struct samr_GetDisplayEnumerationIndex *r)
1858 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1863 samr_TestPrivateFunctionsDomain
1865 static NTSTATUS samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1866 struct samr_TestPrivateFunctionsDomain *r)
1868 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1873 samr_TestPrivateFunctionsUser
1875 static NTSTATUS samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1876 struct samr_TestPrivateFunctionsUser *r)
1878 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1883 samr_GetUserPwInfo
1885 static NTSTATUS samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1886 struct samr_GetUserPwInfo *r)
1888 struct dcesrv_handle *h;
1889 struct samr_account_state *a_state;
1891 ZERO_STRUCT(r->out.info);
1893 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1895 a_state = h->data;
1897 r->out.info.min_password_length = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "minPwdLength",
1898 "dn=%s", a_state->domain_state->domain_dn);
1899 r->out.info.password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "pwdProperties",
1900 "dn=%s", a_state->account_dn);
1901 return NT_STATUS_OK;
1906 samr_RemoveMemberFromForeignDomain
1908 static NTSTATUS samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1909 struct samr_RemoveMemberFromForeignDomain *r)
1911 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1916 samr_QueryDomainInfo2
1918 static NTSTATUS samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1919 struct samr_QueryDomainInfo2 *r)
1921 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1926 samr_QueryUserInfo2
1928 just an alias for samr_QueryUserInfo
1930 static NTSTATUS samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1931 struct samr_QueryUserInfo2 *r)
1933 struct samr_QueryUserInfo r1;
1934 NTSTATUS status;
1936 r1.in.user_handle = r->in.user_handle;
1937 r1.in.level = r->in.level;
1939 status = samr_QueryUserInfo(dce_call, mem_ctx, &r1);
1941 r->out.info = r1.out.info;
1943 return status;
1948 samr_QueryDisplayInfo2
1950 static NTSTATUS samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1951 struct samr_QueryDisplayInfo2 *r)
1953 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1958 samr_GetDisplayEnumerationIndex2
1960 static NTSTATUS samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1961 struct samr_GetDisplayEnumerationIndex2 *r)
1963 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1968 samr_QueryDisplayInfo3
1970 static NTSTATUS samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1971 struct samr_QueryDisplayInfo3 *r)
1973 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1978 samr_AddMultipleMembersToAlias
1980 static NTSTATUS samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1981 struct samr_AddMultipleMembersToAlias *r)
1983 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1988 samr_RemoveMultipleMembersFromAlias
1990 static NTSTATUS samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1991 struct samr_RemoveMultipleMembersFromAlias *r)
1993 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1998 samr_GetDomPwInfo
2000 this fetches the default password properties for a domain
2002 note that w2k3 completely ignores the domain name in this call, and
2003 always returns the information for the servers primary domain
2005 static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2006 struct samr_GetDomPwInfo *r)
2008 struct ldb_message **msgs;
2009 int ret;
2010 const char * const attrs[] = {"minPwdLength", "pwdProperties", NULL };
2011 void *sam_ctx;
2013 ZERO_STRUCT(r->out.info);
2015 sam_ctx = samdb_connect(mem_ctx);
2016 if (sam_ctx == NULL) {
2017 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2020 ret = samdb_search(sam_ctx,
2021 mem_ctx, NULL, &msgs, attrs,
2022 "(&(name=%s)(objectclass=domain))",
2023 lp_workgroup());
2024 if (ret <= 0) {
2025 return NT_STATUS_NO_SUCH_DOMAIN;
2027 if (ret > 1) {
2028 samdb_search_free(sam_ctx, mem_ctx, msgs);
2029 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2032 r->out.info.min_password_length = samdb_result_uint(msgs[0], "minPwdLength", 0);
2033 r->out.info.password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1);
2035 samdb_search_free(sam_ctx, mem_ctx, msgs);
2037 talloc_free(sam_ctx);
2038 return NT_STATUS_OK;
2043 samr_Connect2
2045 static NTSTATUS samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2046 struct samr_Connect2 *r)
2048 struct samr_Connect c;
2050 c.in.system_name = NULL;
2051 c.in.access_mask = r->in.access_mask;
2052 c.out.connect_handle = r->out.connect_handle;
2054 return samr_Connect(dce_call, mem_ctx, &c);
2059 samr_SetUserInfo2
2061 just an alias for samr_SetUserInfo
2063 static NTSTATUS samr_SetUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2064 struct samr_SetUserInfo2 *r)
2066 struct samr_SetUserInfo r2;
2068 r2.in.user_handle = r->in.user_handle;
2069 r2.in.level = r->in.level;
2070 r2.in.info = r->in.info;
2072 return samr_SetUserInfo(dce_call, mem_ctx, &r2);
2077 samr_SetBootKeyInformation
2079 static NTSTATUS samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2080 struct samr_SetBootKeyInformation *r)
2082 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2087 samr_GetBootKeyInformation
2089 static NTSTATUS samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2090 struct samr_GetBootKeyInformation *r)
2092 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2097 samr_Connect3
2099 static NTSTATUS samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2100 struct samr_Connect3 *r)
2102 struct samr_Connect c;
2104 c.in.system_name = NULL;
2105 c.in.access_mask = r->in.access_mask;
2106 c.out.connect_handle = r->out.connect_handle;
2108 return samr_Connect(dce_call, mem_ctx, &c);
2113 samr_Connect4
2115 static NTSTATUS samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2116 struct samr_Connect4 *r)
2118 struct samr_Connect c;
2120 c.in.system_name = NULL;
2121 c.in.access_mask = r->in.access_mask;
2122 c.out.connect_handle = r->out.connect_handle;
2124 return samr_Connect(dce_call, mem_ctx, &c);
2129 samr_Connect5
2131 static NTSTATUS samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2132 struct samr_Connect5 *r)
2134 struct samr_Connect c;
2135 NTSTATUS status;
2137 c.in.system_name = NULL;
2138 c.in.access_mask = r->in.access_mask;
2139 c.out.connect_handle = r->out.connect_handle;
2141 status = samr_Connect(dce_call, mem_ctx, &c);
2143 r->out.info->info1.unknown1 = 3;
2144 r->out.info->info1.unknown2 = 0;
2145 r->out.level = r->in.level;
2147 return status;
2152 samr_RidToSid
2154 static NTSTATUS samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2155 struct samr_RidToSid *r)
2157 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2162 samr_SetDsrmPassword
2164 static NTSTATUS samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2165 struct samr_SetDsrmPassword *r)
2167 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2172 samr_ValidatePassword
2174 static NTSTATUS samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2175 struct samr_ValidatePassword *r)
2177 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2181 /* include the generated boilerplate */
2182 #include "librpc/gen_ndr/ndr_samr_s.c"