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.
24 #include "librpc/gen_ndr/ndr_samr.h"
25 #include "rpc_server/common/common.h"
26 #include "rpc_server/samr/dcesrv_samr.h"
31 destroy a general handle.
33 static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h)
41 create a connection to the SAM database
43 static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
44 struct samr_Connect *r)
46 struct samr_connect_state *c_state;
47 struct dcesrv_handle *handle;
49 ZERO_STRUCTP(r->out.connect_handle);
51 c_state = talloc_p(dce_call->conn, struct samr_connect_state);
53 return NT_STATUS_NO_MEMORY;
56 /* make sure the sam database is accessible */
57 c_state->sam_ctx = samdb_connect(c_state);
58 if (c_state->sam_ctx == NULL) {
60 return NT_STATUS_INVALID_SYSTEM_SERVICE;
63 handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_CONNECT);
66 return NT_STATUS_NO_MEMORY;
69 handle->data = c_state;
70 handle->destroy = samr_handle_destroy;
72 c_state->access_mask = r->in.access_mask;
73 *r->out.connect_handle = handle->wire_handle;
82 static NTSTATUS samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
85 struct dcesrv_handle *h;
87 *r->out.handle = *r->in.handle;
89 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
91 /* this causes the callback samr_XXX_destroy() to be called by
92 the handle destroy code which destroys the state associated
94 dcesrv_handle_destroy(dce_call->conn, h);
96 ZERO_STRUCTP(r->out.handle);
105 static NTSTATUS samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
106 struct samr_SetSecurity *r)
108 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
115 static NTSTATUS samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
116 struct samr_QuerySecurity *r)
118 struct dcesrv_handle *h;
119 struct samr_SdBuf *sd;
123 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
125 sd = talloc_p(mem_ctx, struct samr_SdBuf);
127 return NT_STATUS_NO_MEMORY;
130 sd->sd = samdb_default_security_descriptor(mem_ctx);
141 we refuse this operation completely. If a admin wants to shutdown samr
142 in Samba then they should use the samba admin tools to disable the samr pipe
144 static NTSTATUS samr_Shutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
145 struct samr_Shutdown *r)
147 return NT_STATUS_ACCESS_DENIED;
154 this maps from a domain name to a SID
156 static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
157 struct samr_LookupDomain *r)
159 struct samr_connect_state *c_state;
160 struct dcesrv_handle *h;
161 struct dom_sid2 *sid;
166 DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
170 if (r->in.domain->name == NULL) {
171 return NT_STATUS_INVALID_PARAMETER;
174 sidstr = samdb_search_string(c_state->sam_ctx,
175 mem_ctx, NULL, "objectSid",
176 "(&(name=%s)(objectclass=domain))",
178 if (sidstr == NULL) {
179 return NT_STATUS_NO_SUCH_DOMAIN;
182 sid = dom_sid_parse_talloc(mem_ctx, sidstr);
184 DEBUG(0,("samdb: Invalid sid '%s' for domain %s\n",
185 sidstr, r->in.domain->name));
186 return NT_STATUS_INTERNAL_DB_CORRUPTION;
198 list the domains in the SAM
200 static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
201 struct samr_EnumDomains *r)
203 struct samr_connect_state *c_state;
204 struct dcesrv_handle *h;
205 struct samr_SamArray *array;
206 const char **domains;
207 int count, i, start_i;
209 *r->out.resume_handle = 0;
211 r->out.num_entries = 0;
213 DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
217 count = samdb_search_string_multiple(c_state->sam_ctx,
218 mem_ctx, NULL, &domains,
219 "name", "(objectclass=domain)");
221 DEBUG(0,("samdb: no domains found in EnumDomains\n"));
222 return NT_STATUS_INTERNAL_DB_CORRUPTION;
225 *r->out.resume_handle = count;
227 start_i = *r->in.resume_handle;
229 if (start_i >= count) {
230 /* search past end of list is not an error for this call */
234 array = talloc_p(mem_ctx, struct samr_SamArray);
236 return NT_STATUS_NO_MEMORY;
240 array->entries = NULL;
242 array->entries = talloc_array_p(mem_ctx, struct samr_SamEntry, count - start_i);
243 if (array->entries == NULL) {
244 return NT_STATUS_NO_MEMORY;
247 for (i=0;i<count-start_i;i++) {
248 array->entries[i].idx = start_i + i;
249 array->entries[i].name.name = domains[start_i+i];
253 r->out.num_entries = i;
254 array->count = r->out.num_entries;
263 static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
264 struct samr_OpenDomain *r)
266 struct dcesrv_handle *h_conn, *h_domain;
267 const char *sidstr, *domain_name;
268 struct samr_connect_state *c_state;
269 struct samr_domain_state *d_state;
270 const char * const attrs[2] = { "name", NULL};
271 struct ldb_message **msgs;
274 ZERO_STRUCTP(r->out.domain_handle);
276 DCESRV_PULL_HANDLE(h_conn, r->in.connect_handle, SAMR_HANDLE_CONNECT);
278 c_state = h_conn->data;
280 if (r->in.sid == NULL) {
281 return NT_STATUS_INVALID_PARAMETER;
284 sidstr = dom_sid_string(mem_ctx, r->in.sid);
285 if (sidstr == NULL) {
286 return NT_STATUS_INVALID_PARAMETER;
289 ret = samdb_search(c_state->sam_ctx,
290 mem_ctx, NULL, &msgs, attrs,
291 "(&(objectSid=%s)(objectclass=domain))",
294 return NT_STATUS_NO_SUCH_DOMAIN;
297 domain_name = ldb_msg_find_string(msgs[0], "name", NULL);
298 if (domain_name == NULL) {
299 return NT_STATUS_NO_SUCH_DOMAIN;
302 d_state = talloc_p(c_state, struct samr_domain_state);
304 return NT_STATUS_NO_MEMORY;
307 d_state->connect_state = talloc_reference(d_state, c_state);
308 d_state->sam_ctx = c_state->sam_ctx;
309 d_state->domain_sid = talloc_strdup(d_state, sidstr);
310 d_state->domain_name = talloc_strdup(d_state, domain_name);
311 d_state->domain_dn = talloc_strdup(d_state, msgs[0]->dn);
312 if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) {
313 talloc_free(d_state);
314 return NT_STATUS_NO_MEMORY;
316 d_state->access_mask = r->in.access_mask;
318 h_domain = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_DOMAIN);
320 talloc_free(d_state);
321 return NT_STATUS_NO_MEMORY;
324 h_domain->data = d_state;
325 h_domain->destroy = samr_handle_destroy;
326 *r->out.domain_handle = h_domain->wire_handle;
334 static NTSTATUS samr_info_DomInfo2(struct samr_domain_state *state, TALLOC_CTX *mem_ctx,
335 struct samr_DomInfo2 *info)
337 const char * const attrs[] = { "comment", "name", NULL };
339 struct ldb_message **res;
341 ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs,
342 "dn=%s", state->domain_dn);
344 return NT_STATUS_INTERNAL_DB_CORRUPTION;
347 /* where is this supposed to come from? is it settable? */
348 info->force_logoff_time = 0x8000000000000000LL;
350 info->comment.name = samdb_result_string(res[0], "comment", NULL);
351 info->domain.name = samdb_result_string(res[0], "name", NULL);
353 info->primary.name = lp_netbios_name();
354 info->sequence_num = 0;
355 info->role = ROLE_DOMAIN_PDC;
356 info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, NULL, "(objectClass=user)");
357 info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
358 "(&(objectClass=group)(sAMAccountType=%u))",
360 info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
361 "(&(objectClass=group)(sAMAccountType=%u))",
370 static NTSTATUS samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
371 struct samr_QueryDomainInfo *r)
373 struct dcesrv_handle *h;
374 struct samr_domain_state *d_state;
378 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
382 r->out.info = talloc_p(mem_ctx, union samr_DomainInfo);
384 return NT_STATUS_NO_MEMORY;
387 ZERO_STRUCTP(r->out.info);
389 switch (r->in.level) {
391 return samr_info_DomInfo2(d_state, mem_ctx, &r->out.info->info2);
394 return NT_STATUS_INVALID_INFO_CLASS;
401 static NTSTATUS samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
402 struct samr_SetDomainInfo *r)
404 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
408 samr_CreateDomainGroup
410 static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
411 struct samr_CreateDomainGroup *r)
413 struct samr_domain_state *d_state;
414 struct samr_account_state *a_state;
415 struct dcesrv_handle *h;
417 struct ldb_message msg;
419 const char *groupname, *sidstr;
420 time_t now = time(NULL);
421 struct dcesrv_handle *g_handle;
425 ZERO_STRUCTP(r->out.group_handle);
428 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
432 groupname = r->in.name->name;
434 if (groupname == NULL) {
435 return NT_STATUS_INVALID_PARAMETER;
438 /* check if the group already exists */
439 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
441 "(&(sAMAccountName=%s)(objectclass=group))",
444 return NT_STATUS_GROUP_EXISTS;
449 /* pull in all the template attributes */
450 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
451 "(&(name=TemplateGroup)(objectclass=groupTemplate))");
453 DEBUG(0,("Failed to load TemplateGroup from samdb\n"));
454 return NT_STATUS_INTERNAL_DB_CORRUPTION;
458 status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
459 d_state->domain_dn, "nextRid", &rid);
460 if (!NT_STATUS_IS_OK(status)) {
464 /* and the group SID */
465 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
467 return NT_STATUS_NO_MEMORY;
470 /* add core elements to the ldb_message for the user */
471 msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", groupname,
474 return NT_STATUS_NO_MEMORY;
476 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
478 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
480 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
481 "sAMAccountName", groupname);
482 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
483 "objectClass", "group");
484 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
485 "objectSid", sidstr);
486 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg,
488 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg,
491 /* create the group */
492 ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
494 DEBUG(0,("Failed to create group record %s\n", msg.dn));
495 return NT_STATUS_INTERNAL_DB_CORRUPTION;
498 a_state = talloc_p(d_state, struct samr_account_state);
500 return NT_STATUS_NO_MEMORY;
502 a_state->sam_ctx = d_state->sam_ctx;
503 a_state->access_mask = r->in.access_mask;
504 a_state->domain_state = talloc_reference(a_state, d_state);
505 a_state->account_dn = talloc_steal(d_state, msg.dn);
506 a_state->account_sid = talloc_strdup(d_state, sidstr);
507 a_state->account_name = talloc_strdup(d_state, groupname);
508 if (!a_state->account_name || !a_state->account_sid) {
509 talloc_free(a_state);
510 return NT_STATUS_NO_MEMORY;
513 /* create the policy handle */
514 g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
516 return NT_STATUS_NO_MEMORY;
519 g_handle->data = a_state;
520 g_handle->destroy = samr_handle_destroy;
522 *r->out.group_handle = g_handle->wire_handle;
530 samr_EnumDomainGroups
532 static NTSTATUS samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
533 struct samr_EnumDomainGroups *r)
535 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
542 TODO: This should do some form of locking, especially around the rid allocation
544 static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
545 struct samr_CreateUser2 *r)
547 struct samr_domain_state *d_state;
548 struct samr_account_state *a_state;
549 struct dcesrv_handle *h;
551 struct ldb_message msg;
553 const char *account_name, *sidstr;
554 time_t now = time(NULL);
555 struct dcesrv_handle *u_handle;
558 const char *container, *additional_class=NULL;
560 ZERO_STRUCTP(r->out.user_handle);
561 *r->out.access_granted = 0;
564 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
568 account_name = r->in.account_name->name;
570 if (account_name == NULL) {
571 return NT_STATUS_INVALID_PARAMETER;
574 /* check if the user already exists */
575 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
577 "(&(sAMAccountName=%s)(objectclass=user))", account_name);
579 return NT_STATUS_USER_EXISTS;
584 /* This must be one of these values *only* */
585 if (r->in.acct_flags == ACB_NORMAL) {
586 /* pull in all the template attributes */
587 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
588 "(&(name=TemplateUser)(objectclass=userTemplate))");
590 DEBUG(0,("Failed to load TemplateUser from samdb\n"));
591 return NT_STATUS_INTERNAL_DB_CORRUPTION;
596 } else if (r->in.acct_flags == ACB_WSTRUST) {
597 /* pull in all the template attributes */
598 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
599 "(&(name=TemplateMemberServer)(objectclass=userTemplate))");
601 DEBUG(0,("Failed to load TemplateMemberServer from samdb\n"));
602 return NT_STATUS_INTERNAL_DB_CORRUPTION;
605 container = "Computers";
606 additional_class = "computer";
608 } else if (r->in.acct_flags == ACB_SVRTRUST) {
609 /* pull in all the template attributes */
610 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
611 "(&(name=TemplateDomainController)(objectclass=userTemplate))");
613 DEBUG(0,("Failed to load TemplateDomainController from samdb\n"));
614 return NT_STATUS_INTERNAL_DB_CORRUPTION;
617 container = "DomainControllers";
618 additional_class = "computer";
620 } else if (r->in.acct_flags == ACB_DOMTRUST) {
621 /* pull in all the template attributes */
622 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
623 "(&(name=TemplateTrustingDomain)(objectclass=userTemplate))");
625 DEBUG(0,("Failed to load TemplateTrustingDomain from samdb\n"));
626 return NT_STATUS_INTERNAL_DB_CORRUPTION;
629 container = "ForeignDomains"; /* FIXME: Is this correct?*/
630 additional_class = "computer";
633 return NT_STATUS_INVALID_PARAMETER;
637 status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
638 d_state->domain_dn, "nextRid", &rid);
639 if (!NT_STATUS_IS_OK(status)) {
643 /* and the users SID */
644 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
646 return NT_STATUS_NO_MEMORY;
649 /* add core elements to the ldb_message for the user */
650 msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=%s,%s", account_name, container, d_state->domain_dn);
652 return NT_STATUS_NO_MEMORY;
654 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "name", account_name);
655 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "cn", account_name);
656 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "sAMAccountName", account_name);
657 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", "user");
658 if (additional_class) {
659 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", additional_class);
661 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectSid", sidstr);
662 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenCreated", now);
663 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenChanged", now);
665 /* create the user */
666 ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
668 DEBUG(0,("Failed to create user record %s\n", msg.dn));
669 return NT_STATUS_INTERNAL_DB_CORRUPTION;
672 a_state = talloc_p(d_state, struct samr_account_state);
674 return NT_STATUS_NO_MEMORY;
676 a_state->sam_ctx = d_state->sam_ctx;
677 a_state->access_mask = r->in.access_mask;
678 a_state->domain_state = talloc_reference(a_state, d_state);
679 a_state->account_dn = talloc_steal(d_state, msg.dn);
680 a_state->account_sid = talloc_strdup(d_state, sidstr);
681 a_state->account_name = talloc_strdup(d_state, account_name);
682 if (!a_state->account_name || !a_state->account_sid) {
683 talloc_free(a_state);
684 return NT_STATUS_NO_MEMORY;
687 /* create the policy handle */
688 u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
690 talloc_free(a_state);
691 return NT_STATUS_NO_MEMORY;
694 u_handle->data = a_state;
695 u_handle->destroy = samr_handle_destroy;
697 /* the domain state is in use one more time */
700 *r->out.user_handle = u_handle->wire_handle;
701 *r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
711 static NTSTATUS samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
712 struct samr_CreateUser *r)
714 struct samr_CreateUser2 r2;
715 uint32_t access_granted = 0;
718 /* a simple wrapper around samr_CreateUser2 works nicely */
719 r2.in.domain_handle = r->in.domain_handle;
720 r2.in.account_name = r->in.account_name;
721 r2.in.acct_flags = ACB_NORMAL;
722 r2.in.access_mask = r->in.access_mask;
723 r2.out.user_handle = r->out.user_handle;
724 r2.out.access_granted = &access_granted;
725 r2.out.rid = r->out.rid;
727 return samr_CreateUser2(dce_call, mem_ctx, &r2);
731 comparison function for sorting SamEntry array
733 static int compare_SamEntry(struct samr_SamEntry *e1, struct samr_SamEntry *e2)
735 return e1->idx - e2->idx;
741 static NTSTATUS samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
742 struct samr_EnumDomainUsers *r)
744 struct dcesrv_handle *h;
745 struct samr_domain_state *d_state;
746 struct ldb_message **res;
748 struct samr_SamEntry *entries;
749 const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
751 *r->out.resume_handle = 0;
753 r->out.num_entries = 0;
755 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
759 /* search for all users in this domain. This could possibly be cached and
760 resumed based on resume_key */
761 count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
764 return NT_STATUS_INTERNAL_DB_CORRUPTION;
766 if (count == 0 || r->in.max_size == 0) {
770 /* convert to SamEntry format */
771 entries = talloc_array_p(mem_ctx, struct samr_SamEntry, count);
773 return NT_STATUS_NO_MEMORY;
775 for (i=0;i<count;i++) {
776 entries[i].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
777 entries[i].name.name = samdb_result_string(res[i], "sAMAccountName", "");
780 /* sort the results by rid */
781 qsort(entries, count, sizeof(struct samr_SamEntry),
782 (comparison_fn_t)compare_SamEntry);
784 /* find the first entry to return */
786 first<count && entries[first].idx <= *r->in.resume_handle;
789 if (first == count) {
793 /* return the rest, limit by max_size. Note that we
794 use the w2k3 element size value of 54 */
795 r->out.num_entries = count - first;
796 r->out.num_entries = MIN(r->out.num_entries,
797 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
799 r->out.sam = talloc_p(mem_ctx, struct samr_SamArray);
801 return NT_STATUS_NO_MEMORY;
804 r->out.sam->entries = entries+first;
805 r->out.sam->count = r->out.num_entries;
807 if (r->out.num_entries < count - first) {
808 *r->out.resume_handle = entries[first+r->out.num_entries-1].idx;
809 return STATUS_MORE_ENTRIES;
819 static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
820 struct samr_CreateDomAlias *r)
822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
827 samr_EnumDomainAliases
829 static NTSTATUS samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
830 struct samr_EnumDomainAliases *r)
832 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
837 samr_GetAliasMembership
839 static NTSTATUS samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
840 struct samr_GetAliasMembership *r)
842 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
849 static NTSTATUS samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
850 struct samr_LookupNames *r)
852 struct dcesrv_handle *h;
853 struct samr_domain_state *d_state;
855 NTSTATUS status = NT_STATUS_OK;
856 const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
859 ZERO_STRUCT(r->out.rids);
860 ZERO_STRUCT(r->out.types);
862 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
866 if (r->in.num_names == 0) {
870 r->out.rids.ids = talloc_array_p(mem_ctx, uint32_t, r->in.num_names);
871 r->out.types.ids = talloc_array_p(mem_ctx, uint32_t, r->in.num_names);
872 if (!r->out.rids.ids || !r->out.types.ids) {
873 return NT_STATUS_NO_MEMORY;
875 r->out.rids.count = r->in.num_names;
876 r->out.types.count = r->in.num_names;
878 for (i=0;i<r->in.num_names;i++) {
879 struct ldb_message **res;
880 struct dom_sid2 *sid;
882 uint32_t atype, rtype;
884 r->out.rids.ids[i] = 0;
885 r->out.types.ids[i] = SID_NAME_UNKNOWN;
887 count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
888 "sAMAccountName=%s", r->in.names[i].name);
890 status = STATUS_SOME_UNMAPPED;
894 sidstr = samdb_result_string(res[0], "objectSid", NULL);
895 if (sidstr == NULL) {
896 status = STATUS_SOME_UNMAPPED;
900 sid = dom_sid_parse_talloc(mem_ctx, sidstr);
902 status = STATUS_SOME_UNMAPPED;
906 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
908 status = STATUS_SOME_UNMAPPED;
912 rtype = samdb_atype_map(atype);
914 if (rtype == SID_NAME_UNKNOWN) {
915 status = STATUS_SOME_UNMAPPED;
919 r->out.rids.ids[i] = sid->sub_auths[sid->num_auths-1];
920 r->out.types.ids[i] = rtype;
931 static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
932 struct samr_LookupRids *r)
934 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
941 static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
942 struct samr_OpenGroup *r)
944 struct samr_domain_state *d_state;
945 struct samr_account_state *a_state;
946 struct dcesrv_handle *h;
947 const char *groupname, *sidstr;
948 struct ldb_message **msgs;
949 struct dcesrv_handle *g_handle;
950 const char * const attrs[2] = { "sAMAccountName", NULL };
953 ZERO_STRUCTP(r->out.group_handle);
955 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
959 /* form the group SID */
960 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
962 return NT_STATUS_NO_MEMORY;
965 /* search for the group record */
966 ret = samdb_search(d_state->sam_ctx,
967 mem_ctx, d_state->domain_dn, &msgs, attrs,
968 "(&(objectSid=%s)(objectclass=group))",
971 return NT_STATUS_NO_SUCH_GROUP;
974 DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
975 return NT_STATUS_INTERNAL_DB_CORRUPTION;
978 groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
979 if (groupname == NULL) {
980 DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
981 return NT_STATUS_INTERNAL_DB_CORRUPTION;
984 a_state = talloc_p(d_state, struct samr_account_state);
986 return NT_STATUS_NO_MEMORY;
988 a_state->sam_ctx = d_state->sam_ctx;
989 a_state->access_mask = r->in.access_mask;
990 a_state->domain_state = talloc_reference(a_state, d_state);
991 a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
992 a_state->account_sid = talloc_strdup(a_state, sidstr);
993 a_state->account_name = talloc_strdup(a_state, groupname);
994 if (!a_state->account_name || !a_state->account_sid) {
995 return NT_STATUS_NO_MEMORY;
998 /* create the policy handle */
999 g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
1001 return NT_STATUS_NO_MEMORY;
1004 g_handle->data = a_state;
1005 g_handle->destroy = samr_handle_destroy;
1007 *r->out.group_handle = g_handle->wire_handle;
1009 return NT_STATUS_OK;
1012 /* these query macros make samr_Query[User|Group]Info a bit easier to read */
1014 #define QUERY_STRING(msg, field, attr) \
1015 r->out.info->field = samdb_result_string(msg, attr, "");
1016 #define QUERY_UINT(msg, field, attr) \
1017 r->out.info->field = samdb_result_uint(msg, attr, 0);
1018 #define QUERY_RID(msg, field, attr) \
1019 r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
1020 #define QUERY_NTTIME(msg, field, attr) \
1021 r->out.info->field = samdb_result_nttime(msg, attr, 0);
1022 #define QUERY_APASSC(msg, field, attr) \
1023 r->out.info->field = samdb_result_allow_password_change(a_state->sam_ctx, mem_ctx, \
1024 a_state->domain_state->domain_dn, msg, attr);
1025 #define QUERY_FPASSC(msg, field, attr) \
1026 r->out.info->field = samdb_result_force_password_change(a_state->sam_ctx, mem_ctx, \
1027 a_state->domain_state->domain_dn, msg, attr);
1028 #define QUERY_LHOURS(msg, field, attr) \
1029 r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
1030 #define QUERY_AFLAGS(msg, field, attr) \
1031 r->out.info->field = samdb_result_acct_flags(msg, attr);
1034 /* these are used to make the Set[User|Group]Info code easier to follow */
1036 #define SET_STRING(mod, field, attr) do { \
1037 if (r->in.info->field == NULL) return NT_STATUS_INVALID_PARAMETER; \
1038 if (samdb_msg_add_string(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
1039 return NT_STATUS_NO_MEMORY; \
1043 #define SET_UINT(mod, field, attr) do { \
1044 if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
1045 return NT_STATUS_NO_MEMORY; \
1049 #define SET_AFLAGS(msg, field, attr) do { \
1050 if (samdb_msg_add_acct_flags(a_state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
1051 return NT_STATUS_NO_MEMORY; \
1055 #define SET_LHOURS(msg, field, attr) do { \
1056 if (samdb_msg_add_logon_hours(a_state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
1057 return NT_STATUS_NO_MEMORY; \
1064 static NTSTATUS samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1065 struct samr_QueryGroupInfo *r)
1067 struct dcesrv_handle *h;
1068 struct samr_account_state *a_state;
1069 struct ldb_message *msg, **res;
1070 const char * const attrs[4] = { "sAMAccountName", "description",
1071 "numMembers", NULL };
1076 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1080 /* pull all the group attributes */
1081 ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs,
1082 "dn=%s", a_state->account_dn);
1084 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1088 /* allocate the info structure */
1089 r->out.info = talloc_p(mem_ctx, union samr_GroupInfo);
1090 if (r->out.info == NULL) {
1091 return NT_STATUS_NO_MEMORY;
1093 ZERO_STRUCTP(r->out.info);
1095 /* Fill in the level */
1096 switch (r->in.level) {
1098 QUERY_STRING(msg, all.name.name, "sAMAccountName");
1099 r->out.info->all.unknown = 7; /* Do like w2k3 */
1100 QUERY_UINT (msg, all.num_members, "numMembers")
1101 QUERY_STRING(msg, all.description.name, "description");
1104 QUERY_STRING(msg, name.name, "sAMAccountName");
1107 r->out.info->unknown.unknown = 7;
1109 case GroupInfoDescription:
1110 QUERY_STRING(msg, description.name, "description");
1114 return NT_STATUS_INVALID_INFO_CLASS;
1117 return NT_STATUS_OK;
1124 static NTSTATUS samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1125 struct samr_SetGroupInfo *r)
1127 struct dcesrv_handle *h;
1128 struct samr_account_state *a_state;
1129 struct ldb_message mod, *msg = &mod;
1132 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1137 mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
1139 return NT_STATUS_NO_MEMORY;
1142 switch (r->in.level) {
1143 case GroupInfoDescription:
1144 SET_STRING(msg, description.name, "description");
1147 /* On W2k3 this does not change the name, it changes the
1148 * sAMAccountName attribute */
1149 SET_STRING(msg, name.name, "sAMAccountName");
1152 /* This does not do anything obviously visible in W2k3 LDAP */
1155 return NT_STATUS_INVALID_INFO_CLASS;
1158 /* modify the samdb record */
1159 ret = samdb_replace(a_state->sam_ctx, mem_ctx, &mod);
1161 /* we really need samdb.c to return NTSTATUS */
1162 return NT_STATUS_UNSUCCESSFUL;
1165 return NT_STATUS_OK;
1172 static NTSTATUS samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1173 struct samr_AddGroupMember *r)
1175 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1180 samr_DeleteDomainGroup
1182 static NTSTATUS samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1183 struct samr_DeleteDomainGroup *r)
1185 struct dcesrv_handle *h;
1186 struct samr_account_state *a_state;
1189 *r->out.group_handle = *r->in.group_handle;
1191 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1195 ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
1197 return NT_STATUS_UNSUCCESSFUL;
1200 ZERO_STRUCTP(r->out.group_handle);
1202 return NT_STATUS_OK;
1207 samr_DeleteGroupMember
1209 static NTSTATUS samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1210 struct samr_DeleteGroupMember *r)
1212 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1217 samr_QueryGroupMember
1219 static NTSTATUS samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1220 struct samr_QueryGroupMember *r)
1222 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1227 samr_SetMemberAttributesOfGroup
1229 static NTSTATUS samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1230 struct samr_SetMemberAttributesOfGroup *r)
1232 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1239 static NTSTATUS samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1240 struct samr_OpenAlias *r)
1242 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1249 static NTSTATUS samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1250 struct samr_QueryAliasInfo *r)
1252 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1259 static NTSTATUS samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1260 struct samr_SetAliasInfo *r)
1262 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1269 static NTSTATUS samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1270 struct samr_DeleteDomAlias *r)
1272 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1279 static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1280 struct samr_AddAliasMember *r)
1282 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1287 samr_DeleteAliasMember
1289 static NTSTATUS samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1290 struct samr_DeleteAliasMember *r)
1292 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1297 samr_GetMembersInAlias
1299 static NTSTATUS samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1300 struct samr_GetMembersInAlias *r)
1302 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1309 static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1310 struct samr_OpenUser *r)
1312 struct samr_domain_state *d_state;
1313 struct samr_account_state *a_state;
1314 struct dcesrv_handle *h;
1315 const char *account_name, *sidstr;
1316 struct ldb_message **msgs;
1317 struct dcesrv_handle *u_handle;
1318 const char * const attrs[2] = { "sAMAccountName", NULL };
1321 ZERO_STRUCTP(r->out.user_handle);
1323 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
1327 /* form the users SID */
1328 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
1330 return NT_STATUS_NO_MEMORY;
1333 /* search for the user record */
1334 ret = samdb_search(d_state->sam_ctx,
1335 mem_ctx, d_state->domain_dn, &msgs, attrs,
1336 "(&(objectSid=%s)(objectclass=user))",
1339 return NT_STATUS_NO_SUCH_USER;
1342 DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
1343 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1346 account_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
1347 if (account_name == NULL) {
1348 DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
1349 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1352 a_state = talloc_p(d_state, struct samr_account_state);
1354 return NT_STATUS_NO_MEMORY;
1356 a_state->sam_ctx = d_state->sam_ctx;
1357 a_state->access_mask = r->in.access_mask;
1358 a_state->domain_state = talloc_reference(a_state, d_state);
1359 a_state->account_dn = talloc_steal(d_state, msgs[0]->dn);
1360 a_state->account_sid = talloc_strdup(d_state, sidstr);
1361 a_state->account_name = talloc_strdup(d_state, account_name);
1362 if (!a_state->account_name || !a_state->account_sid) {
1363 return NT_STATUS_NO_MEMORY;
1366 /* create the policy handle */
1367 u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
1369 return NT_STATUS_NO_MEMORY;
1372 u_handle->data = a_state;
1373 u_handle->destroy = samr_handle_destroy;
1375 *r->out.user_handle = u_handle->wire_handle;
1377 return NT_STATUS_OK;
1385 static NTSTATUS samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1386 struct samr_DeleteUser *r)
1388 struct dcesrv_handle *h;
1389 struct samr_account_state *a_state;
1392 *r->out.user_handle = *r->in.user_handle;
1394 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1398 ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
1400 return NT_STATUS_UNSUCCESSFUL;
1403 ZERO_STRUCTP(r->out.user_handle);
1405 return NT_STATUS_OK;
1412 static NTSTATUS samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1413 struct samr_QueryUserInfo *r)
1415 struct dcesrv_handle *h;
1416 struct samr_account_state *a_state;
1417 struct ldb_message *msg, **res;
1422 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1426 /* pull all the user attributes */
1427 ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, NULL,
1428 "dn=%s", a_state->account_dn);
1430 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1434 /* allocate the info structure */
1435 r->out.info = talloc_p(mem_ctx, union samr_UserInfo);
1436 if (r->out.info == NULL) {
1437 return NT_STATUS_NO_MEMORY;
1439 ZERO_STRUCTP(r->out.info);
1441 /* fill in the reply */
1442 switch (r->in.level) {
1444 QUERY_STRING(msg, info1.account_name.name,"sAMAccountName");
1445 QUERY_STRING(msg, info1.full_name.name, "displayName");
1446 QUERY_UINT (msg, info1.primary_gid, "primaryGroupID");
1447 QUERY_STRING(msg, info1.description.name, "description");
1448 QUERY_STRING(msg, info1.comment.name, "comment");
1452 QUERY_STRING(msg, info2.comment.name, "comment");
1453 QUERY_UINT (msg, info2.country_code, "countryCode");
1454 QUERY_UINT (msg, info2.code_page, "codePage");
1458 QUERY_STRING(msg, info3.account_name.name, "sAMAccountName");
1459 QUERY_STRING(msg, info3.full_name.name, "displayName");
1460 QUERY_RID (msg, info3.rid, "objectSid");
1461 QUERY_UINT (msg, info3.primary_gid, "primaryGroupID");
1462 QUERY_STRING(msg, info3.home_directory.name, "homeDirectory");
1463 QUERY_STRING(msg, info3.home_drive.name, "homeDrive");
1464 QUERY_STRING(msg, info3.logon_script.name, "scriptPath");
1465 QUERY_STRING(msg, info3.profile_path.name, "profilePath");
1466 QUERY_STRING(msg, info3.workstations.name, "userWorkstations");
1467 QUERY_NTTIME(msg, info3.last_logon, "lastLogon");
1468 QUERY_NTTIME(msg, info3.last_logoff, "lastLogoff");
1469 QUERY_NTTIME(msg, info3.last_password_change,"pwdLastSet");
1470 QUERY_APASSC(msg, info3.allow_password_change,"pwdLastSet");
1471 QUERY_FPASSC(msg, info3.force_password_change,"pwdLastSet");
1472 QUERY_LHOURS(msg, info3.logon_hours, "logonHours");
1473 QUERY_UINT (msg, info3.bad_password_count, "badPwdCount");
1474 QUERY_UINT (msg, info3.num_logons, "logonCount");
1475 QUERY_AFLAGS(msg, info3.acct_flags, "userAccountControl");
1479 QUERY_LHOURS(msg, info4.logon_hours, "logonHours");
1483 QUERY_STRING(msg, info5.account_name.name, "sAMAccountName");
1484 QUERY_STRING(msg, info5.full_name.name, "displayName");
1485 QUERY_RID (msg, info5.rid, "objectSid");
1486 QUERY_UINT (msg, info5.primary_gid, "primaryGroupID");
1487 QUERY_STRING(msg, info5.home_directory.name, "homeDirectory");
1488 QUERY_STRING(msg, info5.home_drive.name, "homeDrive");
1489 QUERY_STRING(msg, info5.logon_script.name, "scriptPath");
1490 QUERY_STRING(msg, info5.profile_path.name, "profilePath");
1491 QUERY_STRING(msg, info5.description.name, "description");
1492 QUERY_STRING(msg, info5.workstations.name, "userWorkstations");
1493 QUERY_NTTIME(msg, info5.last_logon, "lastLogon");
1494 QUERY_NTTIME(msg, info5.last_logoff, "lastLogoff");
1495 QUERY_LHOURS(msg, info5.logon_hours, "logonHours");
1496 QUERY_UINT (msg, info5.bad_password_count, "badPwdCount");
1497 QUERY_UINT (msg, info5.num_logons, "logonCount");
1498 QUERY_NTTIME(msg, info5.last_password_change,"pwdLastSet");
1499 QUERY_NTTIME(msg, info5.acct_expiry, "accountExpires");
1500 QUERY_AFLAGS(msg, info5.acct_flags, "userAccountControl");
1504 QUERY_STRING(msg, info6.account_name.name, "sAMAccountName");
1505 QUERY_STRING(msg, info6.full_name.name, "displayName");
1509 QUERY_STRING(msg, info7.account_name.name, "sAMAccountName");
1513 QUERY_STRING(msg, info8.full_name.name, "displayName");
1517 QUERY_UINT (msg, info9.primary_gid, "primaryGroupID");
1521 QUERY_STRING(msg, info10.home_directory.name, "homeDirectory");
1522 QUERY_STRING(msg, info10.home_drive.name, "homeDrive");
1526 QUERY_STRING(msg, info11.logon_script.name, "scriptPath");
1530 QUERY_STRING(msg, info12.profile_path.name, "profilePath");
1534 QUERY_STRING(msg, info13.description.name, "description");
1538 QUERY_STRING(msg, info14.workstations.name, "userWorkstations");
1542 QUERY_AFLAGS(msg, info16.acct_flags, "userAccountControl");
1546 QUERY_NTTIME(msg, info17.acct_expiry, "accountExpires");
1549 QUERY_STRING(msg, info20.callback.name, "userParameters");
1553 QUERY_NTTIME(msg, info21.last_logon, "lastLogon");
1554 QUERY_NTTIME(msg, info21.last_logoff, "lastLogoff");
1555 QUERY_NTTIME(msg, info21.last_password_change, "pwdLastSet");
1556 QUERY_NTTIME(msg, info21.acct_expiry, "accountExpires");
1557 QUERY_APASSC(msg, info21.allow_password_change,"pwdLastSet");
1558 QUERY_FPASSC(msg, info21.force_password_change,"pwdLastSet");
1559 QUERY_STRING(msg, info21.account_name.name, "sAMAccountName");
1560 QUERY_STRING(msg, info21.full_name.name, "displayName");
1561 QUERY_STRING(msg, info21.home_directory.name, "homeDirectory");
1562 QUERY_STRING(msg, info21.home_drive.name, "homeDrive");
1563 QUERY_STRING(msg, info21.logon_script.name, "scriptPath");
1564 QUERY_STRING(msg, info21.profile_path.name, "profilePath");
1565 QUERY_STRING(msg, info21.description.name, "description");
1566 QUERY_STRING(msg, info21.workstations.name, "userWorkstations");
1567 QUERY_STRING(msg, info21.comment.name, "comment");
1568 QUERY_STRING(msg, info21.callback.name, "userParameters");
1569 QUERY_RID (msg, info21.rid, "objectSid");
1570 QUERY_UINT (msg, info21.primary_gid, "primaryGroupID");
1571 QUERY_AFLAGS(msg, info21.acct_flags, "userAccountControl");
1572 r->out.info->info21.fields_present = 0x00FFFFFF;
1573 QUERY_LHOURS(msg, info21.logon_hours, "logonHours");
1574 QUERY_UINT (msg, info21.bad_password_count, "badPwdCount");
1575 QUERY_UINT (msg, info21.num_logons, "logonCount");
1576 QUERY_UINT (msg, info21.country_code, "countryCode");
1577 QUERY_UINT (msg, info21.code_page, "codePage");
1583 return NT_STATUS_INVALID_INFO_CLASS;
1586 return NT_STATUS_OK;
1593 static NTSTATUS samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1594 struct samr_SetUserInfo *r)
1596 struct dcesrv_handle *h;
1597 struct samr_account_state *a_state;
1598 struct ldb_message mod, *msg = &mod;
1600 NTSTATUS status = NT_STATUS_OK;
1602 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1607 mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
1609 return NT_STATUS_NO_MEMORY;
1612 switch (r->in.level) {
1614 SET_STRING(msg, info2.comment.name, "comment");
1615 SET_UINT (msg, info2.country_code, "countryCode");
1616 SET_UINT (msg, info2.code_page, "codePage");
1620 SET_LHOURS(msg, info4.logon_hours, "logonHours");
1624 SET_STRING(msg, info6.full_name.name, "displayName");
1628 SET_STRING(msg, info8.full_name.name, "displayName");
1632 SET_UINT(msg, info9.primary_gid, "primaryGroupID");
1636 SET_STRING(msg, info10.home_directory.name, "homeDirectory");
1637 SET_STRING(msg, info10.home_drive.name, "homeDrive");
1641 SET_STRING(msg, info11.logon_script.name, "scriptPath");
1645 SET_STRING(msg, info12.profile_path.name, "profilePath");
1649 SET_STRING(msg, info13.description.name, "description");
1653 SET_STRING(msg, info14.workstations.name, "userWorkstations");
1657 SET_AFLAGS(msg, info16.acct_flags, "userAccountControl");
1661 SET_STRING(msg, info20.callback.name, "userParameters");
1665 #define IFSET(bit) if (bit & r->in.info->info21.fields_present)
1666 IFSET(SAMR_FIELD_NAME)
1667 SET_STRING(msg, info21.full_name.name, "displayName");
1668 IFSET(SAMR_FIELD_DESCRIPTION)
1669 SET_STRING(msg, info21.description.name, "description");
1670 IFSET(SAMR_FIELD_COMMENT)
1671 SET_STRING(msg, info21.comment.name, "comment");
1672 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1673 SET_STRING(msg, info21.logon_script.name, "scriptPath");
1674 IFSET(SAMR_FIELD_PROFILE_PATH)
1675 SET_STRING(msg, info21.profile_path.name, "profilePath");
1676 IFSET(SAMR_FIELD_WORKSTATION)
1677 SET_STRING(msg, info21.workstations.name, "userWorkstations");
1678 IFSET(SAMR_FIELD_LOGON_HOURS)
1679 SET_LHOURS(msg, info21.logon_hours, "logonHours");
1680 IFSET(SAMR_FIELD_ACCT_FLAGS)
1681 SET_AFLAGS(msg, info21.acct_flags, "userAccountControl");
1682 IFSET(SAMR_FIELD_CALLBACK)
1683 SET_STRING(msg, info21.callback.name, "userParameters");
1684 IFSET(SAMR_FIELD_COUNTRY_CODE)
1685 SET_UINT (msg, info21.country_code, "countryCode");
1686 IFSET(SAMR_FIELD_CODE_PAGE)
1687 SET_UINT (msg, info21.code_page, "codePage");
1690 /* Any reason the rest of these can't be set? */
1695 #define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
1696 IFSET(SAMR_FIELD_NAME)
1697 SET_STRING(msg, info23.info.full_name.name, "displayName");
1698 IFSET(SAMR_FIELD_DESCRIPTION)
1699 SET_STRING(msg, info23.info.description.name, "description");
1700 IFSET(SAMR_FIELD_COMMENT)
1701 SET_STRING(msg, info23.info.comment.name, "comment");
1702 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1703 SET_STRING(msg, info23.info.logon_script.name, "scriptPath");
1704 IFSET(SAMR_FIELD_PROFILE_PATH)
1705 SET_STRING(msg, info23.info.profile_path.name, "profilePath");
1706 IFSET(SAMR_FIELD_WORKSTATION)
1707 SET_STRING(msg, info23.info.workstations.name, "userWorkstations");
1708 IFSET(SAMR_FIELD_LOGON_HOURS)
1709 SET_LHOURS(msg, info23.info.logon_hours, "logonHours");
1710 IFSET(SAMR_FIELD_ACCT_FLAGS)
1711 SET_AFLAGS(msg, info23.info.acct_flags, "userAccountControl");
1712 IFSET(SAMR_FIELD_CALLBACK)
1713 SET_STRING(msg, info23.info.callback.name, "userParameters");
1714 IFSET(SAMR_FIELD_COUNTRY_CODE)
1715 SET_UINT (msg, info23.info.country_code, "countryCode");
1716 IFSET(SAMR_FIELD_CODE_PAGE)
1717 SET_UINT (msg, info23.info.code_page, "codePage");
1718 IFSET(SAMR_FIELD_PASSWORD) {
1719 status = samr_set_password(dce_call,
1721 a_state->account_dn,
1722 a_state->domain_state->domain_dn,
1724 &r->in.info->info23.password);
1725 } else IFSET(SAMR_FIELD_PASSWORD2) {
1726 status = samr_set_password(dce_call,
1728 a_state->account_dn,
1729 a_state->domain_state->domain_dn,
1731 &r->in.info->info23.password);
1736 /* the set password levels are handled separately */
1738 status = samr_set_password(dce_call,
1740 a_state->account_dn,
1741 a_state->domain_state->domain_dn,
1743 &r->in.info->info24.password);
1747 #define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
1748 IFSET(SAMR_FIELD_NAME)
1749 SET_STRING(msg, info25.info.full_name.name, "displayName");
1750 IFSET(SAMR_FIELD_DESCRIPTION)
1751 SET_STRING(msg, info25.info.description.name, "description");
1752 IFSET(SAMR_FIELD_COMMENT)
1753 SET_STRING(msg, info25.info.comment.name, "comment");
1754 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1755 SET_STRING(msg, info25.info.logon_script.name, "scriptPath");
1756 IFSET(SAMR_FIELD_PROFILE_PATH)
1757 SET_STRING(msg, info25.info.profile_path.name, "profilePath");
1758 IFSET(SAMR_FIELD_WORKSTATION)
1759 SET_STRING(msg, info25.info.workstations.name, "userWorkstations");
1760 IFSET(SAMR_FIELD_LOGON_HOURS)
1761 SET_LHOURS(msg, info25.info.logon_hours, "logonHours");
1762 IFSET(SAMR_FIELD_ACCT_FLAGS)
1763 SET_AFLAGS(msg, info25.info.acct_flags, "userAccountControl");
1764 IFSET(SAMR_FIELD_CALLBACK)
1765 SET_STRING(msg, info25.info.callback.name, "userParameters");
1766 IFSET(SAMR_FIELD_COUNTRY_CODE)
1767 SET_UINT (msg, info25.info.country_code, "countryCode");
1768 IFSET(SAMR_FIELD_CODE_PAGE)
1769 SET_UINT (msg, info25.info.code_page, "codePage");
1770 IFSET(SAMR_FIELD_PASSWORD) {
1771 status = samr_set_password_ex(dce_call,
1773 a_state->account_dn,
1774 a_state->domain_state->domain_dn,
1776 &r->in.info->info25.password);
1777 } else IFSET(SAMR_FIELD_PASSWORD2) {
1778 status = samr_set_password_ex(dce_call,
1780 a_state->account_dn,
1781 a_state->domain_state->domain_dn,
1783 &r->in.info->info25.password);
1788 /* the set password levels are handled separately */
1790 status = samr_set_password_ex(dce_call,
1792 a_state->account_dn,
1793 a_state->domain_state->domain_dn,
1795 &r->in.info->info26.password);
1800 /* many info classes are not valid for SetUserInfo */
1801 return NT_STATUS_INVALID_INFO_CLASS;
1804 if (!NT_STATUS_IS_OK(status)) {
1808 /* modify the samdb record */
1809 ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
1811 /* we really need samdb.c to return NTSTATUS */
1812 return NT_STATUS_UNSUCCESSFUL;
1815 return NT_STATUS_OK;
1820 samr_GetGroupsForUser
1822 static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1823 struct samr_GetGroupsForUser *r)
1825 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1830 samr_QueryDisplayInfo
1832 static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1833 struct samr_QueryDisplayInfo *r)
1835 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1840 samr_GetDisplayEnumerationIndex
1842 static NTSTATUS samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1843 struct samr_GetDisplayEnumerationIndex *r)
1845 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1850 samr_TestPrivateFunctionsDomain
1852 static NTSTATUS samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1853 struct samr_TestPrivateFunctionsDomain *r)
1855 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1860 samr_TestPrivateFunctionsUser
1862 static NTSTATUS samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1863 struct samr_TestPrivateFunctionsUser *r)
1865 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1872 static NTSTATUS samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1873 struct samr_GetUserPwInfo *r)
1875 struct dcesrv_handle *h;
1876 struct samr_account_state *a_state;
1878 ZERO_STRUCT(r->out.info);
1880 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1884 r->out.info.min_password_len = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "minPwdLength",
1885 "dn=%s", a_state->domain_state->domain_dn);
1886 r->out.info.password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "pwdProperties",
1887 "dn=%s", a_state->account_dn);
1888 return NT_STATUS_OK;
1893 samr_RemoveMemberFromForeignDomain
1895 static NTSTATUS samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1896 struct samr_RemoveMemberFromForeignDomain *r)
1898 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1903 samr_QueryDomainInfo2
1905 static NTSTATUS samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1906 struct samr_QueryDomainInfo2 *r)
1908 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1915 just an alias for samr_QueryUserInfo
1917 static NTSTATUS samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1918 struct samr_QueryUserInfo2 *r)
1920 struct samr_QueryUserInfo r1;
1923 r1.in.user_handle = r->in.user_handle;
1924 r1.in.level = r->in.level;
1926 status = samr_QueryUserInfo(dce_call, mem_ctx, &r1);
1928 r->out.info = r1.out.info;
1935 samr_QueryDisplayInfo2
1937 static NTSTATUS samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1938 struct samr_QueryDisplayInfo2 *r)
1940 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1945 samr_GetDisplayEnumerationIndex2
1947 static NTSTATUS samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1948 struct samr_GetDisplayEnumerationIndex2 *r)
1950 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1955 samr_QueryDisplayInfo3
1957 static NTSTATUS samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1958 struct samr_QueryDisplayInfo3 *r)
1960 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1965 samr_AddMultipleMembersToAlias
1967 static NTSTATUS samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1968 struct samr_AddMultipleMembersToAlias *r)
1970 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1975 samr_RemoveMultipleMembersFromAlias
1977 static NTSTATUS samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1978 struct samr_RemoveMultipleMembersFromAlias *r)
1980 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1987 this fetches the default password properties for a domain
1989 note that w2k3 completely ignores the domain name in this call, and
1990 always returns the information for the servers primary domain
1992 static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1993 struct samr_GetDomPwInfo *r)
1995 struct ldb_message **msgs;
1997 const char * const attrs[] = {"minPwdLength", "pwdProperties", NULL };
2000 ZERO_STRUCT(r->out.info);
2002 sam_ctx = samdb_connect(mem_ctx);
2003 if (sam_ctx == NULL) {
2004 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2007 ret = samdb_search(sam_ctx,
2008 mem_ctx, NULL, &msgs, attrs,
2009 "(&(name=%s)(objectclass=domain))",
2012 return NT_STATUS_NO_SUCH_DOMAIN;
2015 samdb_search_free(sam_ctx, mem_ctx, msgs);
2016 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2019 r->out.info.min_password_len = samdb_result_uint(msgs[0], "minPwdLength", 0);
2020 r->out.info.password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1);
2022 samdb_search_free(sam_ctx, mem_ctx, msgs);
2024 talloc_free(sam_ctx);
2025 return NT_STATUS_OK;
2032 static NTSTATUS samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2033 struct samr_Connect2 *r)
2035 struct samr_Connect c;
2037 c.in.system_name = NULL;
2038 c.in.access_mask = r->in.access_mask;
2039 c.out.connect_handle = r->out.connect_handle;
2041 return samr_Connect(dce_call, mem_ctx, &c);
2048 just an alias for samr_SetUserInfo
2050 static NTSTATUS samr_SetUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2051 struct samr_SetUserInfo2 *r)
2053 struct samr_SetUserInfo r2;
2055 r2.in.user_handle = r->in.user_handle;
2056 r2.in.level = r->in.level;
2057 r2.in.info = r->in.info;
2059 return samr_SetUserInfo(dce_call, mem_ctx, &r2);
2064 samr_SetBootKeyInformation
2066 static NTSTATUS samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2067 struct samr_SetBootKeyInformation *r)
2069 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2074 samr_GetBootKeyInformation
2076 static NTSTATUS samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2077 struct samr_GetBootKeyInformation *r)
2079 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2086 static NTSTATUS samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2087 struct samr_Connect3 *r)
2089 struct samr_Connect c;
2091 c.in.system_name = NULL;
2092 c.in.access_mask = r->in.access_mask;
2093 c.out.connect_handle = r->out.connect_handle;
2095 return samr_Connect(dce_call, mem_ctx, &c);
2102 static NTSTATUS samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2103 struct samr_Connect4 *r)
2105 struct samr_Connect c;
2107 c.in.system_name = NULL;
2108 c.in.access_mask = r->in.access_mask;
2109 c.out.connect_handle = r->out.connect_handle;
2111 return samr_Connect(dce_call, mem_ctx, &c);
2118 static NTSTATUS samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2119 struct samr_Connect5 *r)
2121 struct samr_Connect c;
2124 c.in.system_name = NULL;
2125 c.in.access_mask = r->in.access_mask;
2126 c.out.connect_handle = r->out.connect_handle;
2128 status = samr_Connect(dce_call, mem_ctx, &c);
2130 r->out.info->info1.unknown1 = 3;
2131 r->out.info->info1.unknown2 = 0;
2132 r->out.level = r->in.level;
2141 static NTSTATUS samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2142 struct samr_RidToSid *r)
2144 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2149 samr_SetDsrmPassword
2151 static NTSTATUS samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2152 struct samr_SetDsrmPassword *r)
2154 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2159 samr_ValidatePassword
2161 static NTSTATUS samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2162 struct samr_ValidatePassword *r)
2164 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2168 /* include the generated boilerplate */
2169 #include "librpc/gen_ndr/ndr_samr_s.c"