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/dcerpc_server.h"
26 #include "rpc_server/common/common.h"
27 #include "rpc_server/samr/dcesrv_samr.h"
28 #include "system/time.h"
33 destroy a general handle.
35 static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h)
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);
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) {
62 return NT_STATUS_INVALID_SYSTEM_SERVICE;
65 handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_CONNECT);
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;
84 static NTSTATUS samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
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
96 dcesrv_handle_destroy(dce_call->conn, h);
98 ZERO_STRUCTP(r->out.handle);
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);
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 samr_SdBuf *sd;
125 DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
127 sd = talloc_p(mem_ctx, struct samr_SdBuf);
129 return NT_STATUS_NO_MEMORY;
132 sd->sd = samdb_default_security_descriptor(mem_ctx);
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;
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;
168 DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
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);
186 DEBUG(0,("samdb: Invalid sid '%s' for domain %s\n",
187 sidstr, r->in.domain->string));
188 return NT_STATUS_INTERNAL_DB_CORRUPTION;
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;
213 r->out.num_entries = 0;
215 DCESRV_PULL_HANDLE(h, r->in.connect_handle, SAMR_HANDLE_CONNECT);
219 count = samdb_search_string_multiple(c_state->sam_ctx,
220 mem_ctx, NULL, &domains,
221 "name", "(objectclass=domain)");
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 */
236 array = talloc_p(mem_ctx, struct samr_SamArray);
238 return NT_STATUS_NO_MEMORY;
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];
255 r->out.num_entries = i;
256 array->count = r->out.num_entries;
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;
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))",
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);
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);
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;
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 };
341 struct ldb_message **res;
343 ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs,
344 "dn=%s", state->domain_dn);
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))",
362 info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, NULL,
363 "(&(objectClass=group)(sAMAccountType=%u))",
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;
380 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
384 r->out.info = talloc_p(mem_ctx, union samr_DomainInfo);
386 return NT_STATUS_NO_MEMORY;
389 ZERO_STRUCTP(r->out.info);
391 switch (r->in.level) {
393 return samr_info_DomInfo2(d_state, mem_ctx, &r->out.info->info2);
396 return NT_STATUS_INVALID_INFO_CLASS;
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;
419 struct ldb_message msg;
421 const char *groupname, *sidstr;
422 time_t now = time(NULL);
423 struct dcesrv_handle *g_handle;
427 ZERO_STRUCTP(r->out.group_handle);
430 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
434 groupname = r->in.name->string;
436 if (groupname == NULL) {
437 return NT_STATUS_INVALID_PARAMETER;
440 /* check if the group already exists */
441 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
443 "(&(sAMAccountName=%s)(objectclass=group))",
446 return NT_STATUS_GROUP_EXISTS;
451 /* pull in all the template attributes */
452 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
453 "(&(name=TemplateGroup)(objectclass=groupTemplate))");
455 DEBUG(0,("Failed to load TemplateGroup from samdb\n"));
456 return NT_STATUS_INTERNAL_DB_CORRUPTION;
460 status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
461 d_state->domain_dn, "nextRid", &rid);
462 if (!NT_STATUS_IS_OK(status)) {
466 /* and the group SID */
467 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
469 return NT_STATUS_NO_MEMORY;
472 /* add core elements to the ldb_message for the user */
473 msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", groupname,
476 return NT_STATUS_NO_MEMORY;
478 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
480 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
482 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
483 "sAMAccountName", groupname);
484 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
485 "objectClass", "group");
486 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg,
487 "objectSid", sidstr);
488 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg,
490 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg,
493 /* create the group */
494 ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
496 DEBUG(0,("Failed to create group record %s\n", msg.dn));
497 return NT_STATUS_INTERNAL_DB_CORRUPTION;
500 a_state = talloc_p(d_state, struct samr_account_state);
502 return NT_STATUS_NO_MEMORY;
504 a_state->sam_ctx = d_state->sam_ctx;
505 a_state->access_mask = r->in.access_mask;
506 a_state->domain_state = talloc_reference(a_state, d_state);
507 a_state->account_dn = talloc_steal(d_state, msg.dn);
508 a_state->account_sid = talloc_strdup(d_state, sidstr);
509 a_state->account_name = talloc_strdup(d_state, groupname);
510 if (!a_state->account_name || !a_state->account_sid) {
511 talloc_free(a_state);
512 return NT_STATUS_NO_MEMORY;
515 /* create the policy handle */
516 g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
518 return NT_STATUS_NO_MEMORY;
521 g_handle->data = a_state;
522 g_handle->destroy = samr_handle_destroy;
524 *r->out.group_handle = g_handle->wire_handle;
532 samr_EnumDomainGroups
534 static NTSTATUS samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
535 struct samr_EnumDomainGroups *r)
537 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
544 TODO: This should do some form of locking, especially around the rid allocation
546 static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
547 struct samr_CreateUser2 *r)
549 struct samr_domain_state *d_state;
550 struct samr_account_state *a_state;
551 struct dcesrv_handle *h;
553 struct ldb_message msg;
555 const char *account_name, *sidstr;
556 time_t now = time(NULL);
557 struct dcesrv_handle *u_handle;
560 const char *container, *additional_class=NULL;
562 ZERO_STRUCTP(r->out.user_handle);
563 *r->out.access_granted = 0;
566 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
570 account_name = r->in.account_name->string;
572 if (account_name == NULL) {
573 return NT_STATUS_INVALID_PARAMETER;
576 /* check if the user already exists */
577 name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
579 "(&(sAMAccountName=%s)(objectclass=user))", account_name);
581 return NT_STATUS_USER_EXISTS;
586 /* This must be one of these values *only* */
587 if (r->in.acct_flags == ACB_NORMAL) {
588 /* pull in all the template attributes */
589 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
590 "(&(name=TemplateUser)(objectclass=userTemplate))");
592 DEBUG(0,("Failed to load TemplateUser from samdb\n"));
593 return NT_STATUS_INTERNAL_DB_CORRUPTION;
598 } else if (r->in.acct_flags == ACB_WSTRUST) {
599 /* pull in all the template attributes */
600 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
601 "(&(name=TemplateMemberServer)(objectclass=userTemplate))");
603 DEBUG(0,("Failed to load TemplateMemberServer from samdb\n"));
604 return NT_STATUS_INTERNAL_DB_CORRUPTION;
607 container = "Computers";
608 additional_class = "computer";
610 } else if (r->in.acct_flags == ACB_SVRTRUST) {
611 /* pull in all the template attributes */
612 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
613 "(&(name=TemplateDomainController)(objectclass=userTemplate))");
615 DEBUG(0,("Failed to load TemplateDomainController from samdb\n"));
616 return NT_STATUS_INTERNAL_DB_CORRUPTION;
619 container = "DomainControllers";
620 additional_class = "computer";
622 } else if (r->in.acct_flags == ACB_DOMTRUST) {
623 /* pull in all the template attributes */
624 ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
625 "(&(name=TemplateTrustingDomain)(objectclass=userTemplate))");
627 DEBUG(0,("Failed to load TemplateTrustingDomain from samdb\n"));
628 return NT_STATUS_INTERNAL_DB_CORRUPTION;
631 container = "ForeignDomains"; /* FIXME: Is this correct?*/
632 additional_class = "computer";
635 return NT_STATUS_INVALID_PARAMETER;
639 status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx,
640 d_state->domain_dn, "nextRid", &rid);
641 if (!NT_STATUS_IS_OK(status)) {
645 /* and the users SID */
646 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
648 return NT_STATUS_NO_MEMORY;
651 /* add core elements to the ldb_message for the user */
652 msg.dn = talloc_asprintf(mem_ctx, "CN=%s,CN=%s,%s", account_name, container, d_state->domain_dn);
654 return NT_STATUS_NO_MEMORY;
656 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "name", account_name);
657 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "cn", account_name);
658 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "sAMAccountName", account_name);
659 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", "user");
660 if (additional_class) {
661 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", additional_class);
663 samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectSid", sidstr);
664 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenCreated", now);
665 samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenChanged", now);
667 /* create the user */
668 ret = samdb_add(d_state->sam_ctx, mem_ctx, &msg);
670 DEBUG(0,("Failed to create user record %s\n", msg.dn));
671 return NT_STATUS_INTERNAL_DB_CORRUPTION;
674 a_state = talloc_p(d_state, struct samr_account_state);
676 return NT_STATUS_NO_MEMORY;
678 a_state->sam_ctx = d_state->sam_ctx;
679 a_state->access_mask = r->in.access_mask;
680 a_state->domain_state = talloc_reference(a_state, d_state);
681 a_state->account_dn = talloc_steal(d_state, msg.dn);
682 a_state->account_sid = talloc_strdup(d_state, sidstr);
683 a_state->account_name = talloc_strdup(d_state, account_name);
684 if (!a_state->account_name || !a_state->account_sid) {
685 talloc_free(a_state);
686 return NT_STATUS_NO_MEMORY;
689 /* create the policy handle */
690 u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
692 talloc_free(a_state);
693 return NT_STATUS_NO_MEMORY;
696 u_handle->data = a_state;
697 u_handle->destroy = samr_handle_destroy;
699 /* the domain state is in use one more time */
702 *r->out.user_handle = u_handle->wire_handle;
703 *r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
713 static NTSTATUS samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
714 struct samr_CreateUser *r)
716 struct samr_CreateUser2 r2;
717 uint32_t access_granted = 0;
720 /* a simple wrapper around samr_CreateUser2 works nicely */
721 r2.in.domain_handle = r->in.domain_handle;
722 r2.in.account_name = r->in.account_name;
723 r2.in.acct_flags = ACB_NORMAL;
724 r2.in.access_mask = r->in.access_mask;
725 r2.out.user_handle = r->out.user_handle;
726 r2.out.access_granted = &access_granted;
727 r2.out.rid = r->out.rid;
729 return samr_CreateUser2(dce_call, mem_ctx, &r2);
733 comparison function for sorting SamEntry array
735 static int compare_SamEntry(struct samr_SamEntry *e1, struct samr_SamEntry *e2)
737 return e1->idx - e2->idx;
743 static NTSTATUS samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
744 struct samr_EnumDomainUsers *r)
746 struct dcesrv_handle *h;
747 struct samr_domain_state *d_state;
748 struct ldb_message **res;
750 struct samr_SamEntry *entries;
751 const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
753 *r->out.resume_handle = 0;
755 r->out.num_entries = 0;
757 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
761 /* search for all users in this domain. This could possibly be cached and
762 resumed based on resume_key */
763 count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
766 return NT_STATUS_INTERNAL_DB_CORRUPTION;
768 if (count == 0 || r->in.max_size == 0) {
772 /* convert to SamEntry format */
773 entries = talloc_array_p(mem_ctx, struct samr_SamEntry, count);
775 return NT_STATUS_NO_MEMORY;
777 for (i=0;i<count;i++) {
778 entries[i].idx = samdb_result_rid_from_sid(mem_ctx, res[i], "objectSid", 0);
779 entries[i].name.string = samdb_result_string(res[i], "sAMAccountName", "");
782 /* sort the results by rid */
783 qsort(entries, count, sizeof(struct samr_SamEntry),
784 (comparison_fn_t)compare_SamEntry);
786 /* find the first entry to return */
788 first<count && entries[first].idx <= *r->in.resume_handle;
791 if (first == count) {
795 /* return the rest, limit by max_size. Note that we
796 use the w2k3 element size value of 54 */
797 r->out.num_entries = count - first;
798 r->out.num_entries = MIN(r->out.num_entries,
799 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
801 r->out.sam = talloc_p(mem_ctx, struct samr_SamArray);
803 return NT_STATUS_NO_MEMORY;
806 r->out.sam->entries = entries+first;
807 r->out.sam->count = r->out.num_entries;
809 if (r->out.num_entries < count - first) {
810 *r->out.resume_handle = entries[first+r->out.num_entries-1].idx;
811 return STATUS_MORE_ENTRIES;
821 static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
822 struct samr_CreateDomAlias *r)
824 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
829 samr_EnumDomainAliases
831 static NTSTATUS samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
832 struct samr_EnumDomainAliases *r)
834 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
839 samr_GetAliasMembership
841 static NTSTATUS samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
842 struct samr_GetAliasMembership *r)
844 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
851 static NTSTATUS samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
852 struct samr_LookupNames *r)
854 struct dcesrv_handle *h;
855 struct samr_domain_state *d_state;
857 NTSTATUS status = NT_STATUS_OK;
858 const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
861 ZERO_STRUCT(r->out.rids);
862 ZERO_STRUCT(r->out.types);
864 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
868 if (r->in.num_names == 0) {
872 r->out.rids.ids = talloc_array_p(mem_ctx, uint32_t, r->in.num_names);
873 r->out.types.ids = talloc_array_p(mem_ctx, uint32_t, r->in.num_names);
874 if (!r->out.rids.ids || !r->out.types.ids) {
875 return NT_STATUS_NO_MEMORY;
877 r->out.rids.count = r->in.num_names;
878 r->out.types.count = r->in.num_names;
880 for (i=0;i<r->in.num_names;i++) {
881 struct ldb_message **res;
882 struct dom_sid2 *sid;
884 uint32_t atype, rtype;
886 r->out.rids.ids[i] = 0;
887 r->out.types.ids[i] = SID_NAME_UNKNOWN;
889 count = samdb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
890 "sAMAccountName=%s", r->in.names[i].string);
892 status = STATUS_SOME_UNMAPPED;
896 sidstr = samdb_result_string(res[0], "objectSid", NULL);
897 if (sidstr == NULL) {
898 status = STATUS_SOME_UNMAPPED;
902 sid = dom_sid_parse_talloc(mem_ctx, sidstr);
904 status = STATUS_SOME_UNMAPPED;
908 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
910 status = STATUS_SOME_UNMAPPED;
914 rtype = samdb_atype_map(atype);
916 if (rtype == SID_NAME_UNKNOWN) {
917 status = STATUS_SOME_UNMAPPED;
921 r->out.rids.ids[i] = sid->sub_auths[sid->num_auths-1];
922 r->out.types.ids[i] = rtype;
933 static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
934 struct samr_LookupRids *r)
936 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
943 static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
944 struct samr_OpenGroup *r)
946 struct samr_domain_state *d_state;
947 struct samr_account_state *a_state;
948 struct dcesrv_handle *h;
949 const char *groupname, *sidstr;
950 struct ldb_message **msgs;
951 struct dcesrv_handle *g_handle;
952 const char * const attrs[2] = { "sAMAccountName", NULL };
955 ZERO_STRUCTP(r->out.group_handle);
957 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
961 /* form the group SID */
962 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
964 return NT_STATUS_NO_MEMORY;
967 /* search for the group record */
968 ret = samdb_search(d_state->sam_ctx,
969 mem_ctx, d_state->domain_dn, &msgs, attrs,
970 "(&(objectSid=%s)(objectclass=group))",
973 return NT_STATUS_NO_SUCH_GROUP;
976 DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
977 return NT_STATUS_INTERNAL_DB_CORRUPTION;
980 groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
981 if (groupname == NULL) {
982 DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
983 return NT_STATUS_INTERNAL_DB_CORRUPTION;
986 a_state = talloc_p(d_state, struct samr_account_state);
988 return NT_STATUS_NO_MEMORY;
990 a_state->sam_ctx = d_state->sam_ctx;
991 a_state->access_mask = r->in.access_mask;
992 a_state->domain_state = talloc_reference(a_state, d_state);
993 a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);
994 a_state->account_sid = talloc_strdup(a_state, sidstr);
995 a_state->account_name = talloc_strdup(a_state, groupname);
996 if (!a_state->account_name || !a_state->account_sid) {
997 return NT_STATUS_NO_MEMORY;
1000 /* create the policy handle */
1001 g_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_GROUP);
1003 return NT_STATUS_NO_MEMORY;
1006 g_handle->data = a_state;
1007 g_handle->destroy = samr_handle_destroy;
1009 *r->out.group_handle = g_handle->wire_handle;
1011 return NT_STATUS_OK;
1014 /* these query macros make samr_Query[User|Group]Info a bit easier to read */
1016 #define QUERY_STRING(msg, field, attr) \
1017 r->out.info->field = samdb_result_string(msg, attr, "");
1018 #define QUERY_UINT(msg, field, attr) \
1019 r->out.info->field = samdb_result_uint(msg, attr, 0);
1020 #define QUERY_RID(msg, field, attr) \
1021 r->out.info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
1022 #define QUERY_NTTIME(msg, field, attr) \
1023 r->out.info->field = samdb_result_nttime(msg, attr, 0);
1024 #define QUERY_APASSC(msg, field, attr) \
1025 r->out.info->field = samdb_result_allow_password_change(a_state->sam_ctx, mem_ctx, \
1026 a_state->domain_state->domain_dn, msg, attr);
1027 #define QUERY_FPASSC(msg, field, attr) \
1028 r->out.info->field = samdb_result_force_password_change(a_state->sam_ctx, mem_ctx, \
1029 a_state->domain_state->domain_dn, msg, attr);
1030 #define QUERY_LHOURS(msg, field, attr) \
1031 r->out.info->field = samdb_result_logon_hours(mem_ctx, msg, attr);
1032 #define QUERY_AFLAGS(msg, field, attr) \
1033 r->out.info->field = samdb_result_acct_flags(msg, attr);
1036 /* these are used to make the Set[User|Group]Info code easier to follow */
1038 #define SET_STRING(mod, field, attr) do { \
1039 if (r->in.info->field == NULL) return NT_STATUS_INVALID_PARAMETER; \
1040 if (samdb_msg_add_string(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
1041 return NT_STATUS_NO_MEMORY; \
1045 #define SET_UINT(mod, field, attr) do { \
1046 if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, mod, attr, r->in.info->field) != 0) { \
1047 return NT_STATUS_NO_MEMORY; \
1051 #define SET_AFLAGS(msg, field, attr) do { \
1052 if (samdb_msg_add_acct_flags(a_state->sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
1053 return NT_STATUS_NO_MEMORY; \
1057 #define SET_LHOURS(msg, field, attr) do { \
1058 if (samdb_msg_add_logon_hours(a_state->sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
1059 return NT_STATUS_NO_MEMORY; \
1066 static NTSTATUS samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1067 struct samr_QueryGroupInfo *r)
1069 struct dcesrv_handle *h;
1070 struct samr_account_state *a_state;
1071 struct ldb_message *msg, **res;
1072 const char * const attrs[4] = { "sAMAccountName", "description",
1073 "numMembers", NULL };
1078 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1082 /* pull all the group attributes */
1083 ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs,
1084 "dn=%s", a_state->account_dn);
1086 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1090 /* allocate the info structure */
1091 r->out.info = talloc_p(mem_ctx, union samr_GroupInfo);
1092 if (r->out.info == NULL) {
1093 return NT_STATUS_NO_MEMORY;
1095 ZERO_STRUCTP(r->out.info);
1097 /* Fill in the level */
1098 switch (r->in.level) {
1100 QUERY_STRING(msg, all.name.string, "sAMAccountName");
1101 r->out.info->all.unknown = 7; /* Do like w2k3 */
1102 QUERY_UINT (msg, all.num_members, "numMembers")
1103 QUERY_STRING(msg, all.description.string, "description");
1106 QUERY_STRING(msg, name.string, "sAMAccountName");
1109 r->out.info->unknown.unknown = 7;
1111 case GroupInfoDescription:
1112 QUERY_STRING(msg, description.string, "description");
1116 return NT_STATUS_INVALID_INFO_CLASS;
1119 return NT_STATUS_OK;
1126 static NTSTATUS samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1127 struct samr_SetGroupInfo *r)
1129 struct dcesrv_handle *h;
1130 struct samr_account_state *a_state;
1131 struct ldb_message mod, *msg = &mod;
1134 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1139 mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
1141 return NT_STATUS_NO_MEMORY;
1144 switch (r->in.level) {
1145 case GroupInfoDescription:
1146 SET_STRING(msg, description.string, "description");
1149 /* On W2k3 this does not change the name, it changes the
1150 * sAMAccountName attribute */
1151 SET_STRING(msg, name.string, "sAMAccountName");
1154 /* This does not do anything obviously visible in W2k3 LDAP */
1157 return NT_STATUS_INVALID_INFO_CLASS;
1160 /* modify the samdb record */
1161 ret = samdb_replace(a_state->sam_ctx, mem_ctx, &mod);
1163 /* we really need samdb.c to return NTSTATUS */
1164 return NT_STATUS_UNSUCCESSFUL;
1167 return NT_STATUS_OK;
1174 static NTSTATUS samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1175 struct samr_AddGroupMember *r)
1177 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1182 samr_DeleteDomainGroup
1184 static NTSTATUS samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1185 struct samr_DeleteDomainGroup *r)
1187 struct dcesrv_handle *h;
1188 struct samr_account_state *a_state;
1191 *r->out.group_handle = *r->in.group_handle;
1193 DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
1197 ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
1199 return NT_STATUS_UNSUCCESSFUL;
1202 ZERO_STRUCTP(r->out.group_handle);
1204 return NT_STATUS_OK;
1209 samr_DeleteGroupMember
1211 static NTSTATUS samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1212 struct samr_DeleteGroupMember *r)
1214 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1219 samr_QueryGroupMember
1221 static NTSTATUS samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1222 struct samr_QueryGroupMember *r)
1224 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1229 samr_SetMemberAttributesOfGroup
1231 static NTSTATUS samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1232 struct samr_SetMemberAttributesOfGroup *r)
1234 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1241 static NTSTATUS samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1242 struct samr_OpenAlias *r)
1244 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1251 static NTSTATUS samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1252 struct samr_QueryAliasInfo *r)
1254 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1261 static NTSTATUS samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1262 struct samr_SetAliasInfo *r)
1264 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1271 static NTSTATUS samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1272 struct samr_DeleteDomAlias *r)
1274 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1281 static NTSTATUS samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1282 struct samr_AddAliasMember *r)
1284 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1289 samr_DeleteAliasMember
1291 static NTSTATUS samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1292 struct samr_DeleteAliasMember *r)
1294 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1299 samr_GetMembersInAlias
1301 static NTSTATUS samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1302 struct samr_GetMembersInAlias *r)
1304 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1311 static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1312 struct samr_OpenUser *r)
1314 struct samr_domain_state *d_state;
1315 struct samr_account_state *a_state;
1316 struct dcesrv_handle *h;
1317 const char *account_name, *sidstr;
1318 struct ldb_message **msgs;
1319 struct dcesrv_handle *u_handle;
1320 const char * const attrs[2] = { "sAMAccountName", NULL };
1323 ZERO_STRUCTP(r->out.user_handle);
1325 DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
1329 /* form the users SID */
1330 sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, r->in.rid);
1332 return NT_STATUS_NO_MEMORY;
1335 /* search for the user record */
1336 ret = samdb_search(d_state->sam_ctx,
1337 mem_ctx, d_state->domain_dn, &msgs, attrs,
1338 "(&(objectSid=%s)(objectclass=user))",
1341 return NT_STATUS_NO_SUCH_USER;
1344 DEBUG(0,("Found %d records matching sid %s\n", ret, sidstr));
1345 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1348 account_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
1349 if (account_name == NULL) {
1350 DEBUG(0,("sAMAccountName field missing for sid %s\n", sidstr));
1351 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1354 a_state = talloc_p(d_state, struct samr_account_state);
1356 return NT_STATUS_NO_MEMORY;
1358 a_state->sam_ctx = d_state->sam_ctx;
1359 a_state->access_mask = r->in.access_mask;
1360 a_state->domain_state = talloc_reference(a_state, d_state);
1361 a_state->account_dn = talloc_steal(d_state, msgs[0]->dn);
1362 a_state->account_sid = talloc_strdup(d_state, sidstr);
1363 a_state->account_name = talloc_strdup(d_state, account_name);
1364 if (!a_state->account_name || !a_state->account_sid) {
1365 return NT_STATUS_NO_MEMORY;
1368 /* create the policy handle */
1369 u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER);
1371 return NT_STATUS_NO_MEMORY;
1374 u_handle->data = a_state;
1375 u_handle->destroy = samr_handle_destroy;
1377 *r->out.user_handle = u_handle->wire_handle;
1379 return NT_STATUS_OK;
1387 static NTSTATUS samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1388 struct samr_DeleteUser *r)
1390 struct dcesrv_handle *h;
1391 struct samr_account_state *a_state;
1394 *r->out.user_handle = *r->in.user_handle;
1396 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1400 ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
1402 return NT_STATUS_UNSUCCESSFUL;
1405 ZERO_STRUCTP(r->out.user_handle);
1407 return NT_STATUS_OK;
1414 static NTSTATUS samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1415 struct samr_QueryUserInfo *r)
1417 struct dcesrv_handle *h;
1418 struct samr_account_state *a_state;
1419 struct ldb_message *msg, **res;
1424 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1428 /* pull all the user attributes */
1429 ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, NULL,
1430 "dn=%s", a_state->account_dn);
1432 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1436 /* allocate the info structure */
1437 r->out.info = talloc_p(mem_ctx, union samr_UserInfo);
1438 if (r->out.info == NULL) {
1439 return NT_STATUS_NO_MEMORY;
1441 ZERO_STRUCTP(r->out.info);
1443 /* fill in the reply */
1444 switch (r->in.level) {
1446 QUERY_STRING(msg, info1.account_name.string, "sAMAccountName");
1447 QUERY_STRING(msg, info1.full_name.string, "displayName");
1448 QUERY_UINT (msg, info1.primary_gid, "primaryGroupID");
1449 QUERY_STRING(msg, info1.description.string, "description");
1450 QUERY_STRING(msg, info1.comment.string, "comment");
1454 QUERY_STRING(msg, info2.comment.string, "comment");
1455 QUERY_UINT (msg, info2.country_code, "countryCode");
1456 QUERY_UINT (msg, info2.code_page, "codePage");
1460 QUERY_STRING(msg, info3.account_name.string, "sAMAccountName");
1461 QUERY_STRING(msg, info3.full_name.string, "displayName");
1462 QUERY_RID (msg, info3.rid, "objectSid");
1463 QUERY_UINT (msg, info3.primary_gid, "primaryGroupID");
1464 QUERY_STRING(msg, info3.home_directory.string, "homeDirectory");
1465 QUERY_STRING(msg, info3.home_drive.string, "homeDrive");
1466 QUERY_STRING(msg, info3.logon_script.string, "scriptPath");
1467 QUERY_STRING(msg, info3.profile_path.string, "profilePath");
1468 QUERY_STRING(msg, info3.workstations.string, "userWorkstations");
1469 QUERY_NTTIME(msg, info3.last_logon, "lastLogon");
1470 QUERY_NTTIME(msg, info3.last_logoff, "lastLogoff");
1471 QUERY_NTTIME(msg, info3.last_password_change, "pwdLastSet");
1472 QUERY_APASSC(msg, info3.allow_password_change, "pwdLastSet");
1473 QUERY_FPASSC(msg, info3.force_password_change, "pwdLastSet");
1474 QUERY_LHOURS(msg, info3.logon_hours, "logonHours");
1475 QUERY_UINT (msg, info3.bad_password_count, "badPwdCount");
1476 QUERY_UINT (msg, info3.logon_count, "logonCount");
1477 QUERY_AFLAGS(msg, info3.acct_flags, "userAccountControl");
1481 QUERY_LHOURS(msg, info4.logon_hours, "logonHours");
1485 QUERY_STRING(msg, info5.account_name.string, "sAMAccountName");
1486 QUERY_STRING(msg, info5.full_name.string, "displayName");
1487 QUERY_RID (msg, info5.rid, "objectSid");
1488 QUERY_UINT (msg, info5.primary_gid, "primaryGroupID");
1489 QUERY_STRING(msg, info5.home_directory.string, "homeDirectory");
1490 QUERY_STRING(msg, info5.home_drive.string, "homeDrive");
1491 QUERY_STRING(msg, info5.logon_script.string, "scriptPath");
1492 QUERY_STRING(msg, info5.profile_path.string, "profilePath");
1493 QUERY_STRING(msg, info5.description.string, "description");
1494 QUERY_STRING(msg, info5.workstations.string, "userWorkstations");
1495 QUERY_NTTIME(msg, info5.last_logon, "lastLogon");
1496 QUERY_NTTIME(msg, info5.last_logoff, "lastLogoff");
1497 QUERY_LHOURS(msg, info5.logon_hours, "logonHours");
1498 QUERY_UINT (msg, info5.bad_password_count, "badPwdCount");
1499 QUERY_UINT (msg, info5.logon_count, "logonCount");
1500 QUERY_NTTIME(msg, info5.last_password_change, "pwdLastSet");
1501 QUERY_NTTIME(msg, info5.acct_expiry, "accountExpires");
1502 QUERY_AFLAGS(msg, info5.acct_flags, "userAccountControl");
1506 QUERY_STRING(msg, info6.account_name.string, "sAMAccountName");
1507 QUERY_STRING(msg, info6.full_name.string, "displayName");
1511 QUERY_STRING(msg, info7.account_name.string, "sAMAccountName");
1515 QUERY_STRING(msg, info8.full_name.string, "displayName");
1519 QUERY_UINT (msg, info9.primary_gid, "primaryGroupID");
1523 QUERY_STRING(msg, info10.home_directory.string,"homeDirectory");
1524 QUERY_STRING(msg, info10.home_drive.string, "homeDrive");
1528 QUERY_STRING(msg, info11.logon_script.string, "scriptPath");
1532 QUERY_STRING(msg, info12.profile_path.string, "profilePath");
1536 QUERY_STRING(msg, info13.description.string, "description");
1540 QUERY_STRING(msg, info14.workstations.string, "userWorkstations");
1544 QUERY_AFLAGS(msg, info16.acct_flags, "userAccountControl");
1548 QUERY_NTTIME(msg, info17.acct_expiry, "accountExpires");
1551 QUERY_STRING(msg, info20.parameters.string, "userParameters");
1555 QUERY_NTTIME(msg, info21.last_logon, "lastLogon");
1556 QUERY_NTTIME(msg, info21.last_logoff, "lastLogoff");
1557 QUERY_NTTIME(msg, info21.last_password_change, "pwdLastSet");
1558 QUERY_NTTIME(msg, info21.acct_expiry, "accountExpires");
1559 QUERY_APASSC(msg, info21.allow_password_change,"pwdLastSet");
1560 QUERY_FPASSC(msg, info21.force_password_change,"pwdLastSet");
1561 QUERY_STRING(msg, info21.account_name.string, "sAMAccountName");
1562 QUERY_STRING(msg, info21.full_name.string, "displayName");
1563 QUERY_STRING(msg, info21.home_directory.string,"homeDirectory");
1564 QUERY_STRING(msg, info21.home_drive.string, "homeDrive");
1565 QUERY_STRING(msg, info21.logon_script.string, "scriptPath");
1566 QUERY_STRING(msg, info21.profile_path.string, "profilePath");
1567 QUERY_STRING(msg, info21.description.string, "description");
1568 QUERY_STRING(msg, info21.workstations.string, "userWorkstations");
1569 QUERY_STRING(msg, info21.comment.string, "comment");
1570 QUERY_STRING(msg, info21.parameters.string, "userParameters");
1571 QUERY_RID (msg, info21.rid, "objectSid");
1572 QUERY_UINT (msg, info21.primary_gid, "primaryGroupID");
1573 QUERY_AFLAGS(msg, info21.acct_flags, "userAccountControl");
1574 r->out.info->info21.fields_present = 0x00FFFFFF;
1575 QUERY_LHOURS(msg, info21.logon_hours, "logonHours");
1576 QUERY_UINT (msg, info21.bad_password_count, "badPwdCount");
1577 QUERY_UINT (msg, info21.logon_count, "logonCount");
1578 QUERY_UINT (msg, info21.country_code, "countryCode");
1579 QUERY_UINT (msg, info21.code_page, "codePage");
1585 return NT_STATUS_INVALID_INFO_CLASS;
1588 return NT_STATUS_OK;
1595 static NTSTATUS samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1596 struct samr_SetUserInfo *r)
1598 struct dcesrv_handle *h;
1599 struct samr_account_state *a_state;
1600 struct ldb_message mod, *msg = &mod;
1602 NTSTATUS status = NT_STATUS_OK;
1604 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1609 mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
1611 return NT_STATUS_NO_MEMORY;
1614 switch (r->in.level) {
1616 SET_STRING(msg, info2.comment.string, "comment");
1617 SET_UINT (msg, info2.country_code, "countryCode");
1618 SET_UINT (msg, info2.code_page, "codePage");
1622 SET_LHOURS(msg, info4.logon_hours, "logonHours");
1626 SET_STRING(msg, info6.full_name.string, "displayName");
1630 SET_STRING(msg, info8.full_name.string, "displayName");
1634 SET_UINT(msg, info9.primary_gid, "primaryGroupID");
1638 SET_STRING(msg, info10.home_directory.string, "homeDirectory");
1639 SET_STRING(msg, info10.home_drive.string, "homeDrive");
1643 SET_STRING(msg, info11.logon_script.string, "scriptPath");
1647 SET_STRING(msg, info12.profile_path.string, "profilePath");
1651 SET_STRING(msg, info13.description.string, "description");
1655 SET_STRING(msg, info14.workstations.string, "userWorkstations");
1659 SET_AFLAGS(msg, info16.acct_flags, "userAccountControl");
1663 SET_STRING(msg, info20.parameters.string, "userParameters");
1667 #define IFSET(bit) if (bit & r->in.info->info21.fields_present)
1668 IFSET(SAMR_FIELD_NAME)
1669 SET_STRING(msg, info21.full_name.string, "displayName");
1670 IFSET(SAMR_FIELD_DESCRIPTION)
1671 SET_STRING(msg, info21.description.string, "description");
1672 IFSET(SAMR_FIELD_COMMENT)
1673 SET_STRING(msg, info21.comment.string, "comment");
1674 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1675 SET_STRING(msg, info21.logon_script.string, "scriptPath");
1676 IFSET(SAMR_FIELD_PROFILE_PATH)
1677 SET_STRING(msg, info21.profile_path.string, "profilePath");
1678 IFSET(SAMR_FIELD_WORKSTATION)
1679 SET_STRING(msg, info21.workstations.string, "userWorkstations");
1680 IFSET(SAMR_FIELD_LOGON_HOURS)
1681 SET_LHOURS(msg, info21.logon_hours, "logonHours");
1682 IFSET(SAMR_FIELD_ACCT_FLAGS)
1683 SET_AFLAGS(msg, info21.acct_flags, "userAccountControl");
1684 IFSET(SAMR_FIELD_PARAMETERS)
1685 SET_STRING(msg, info21.parameters.string, "userParameters");
1686 IFSET(SAMR_FIELD_COUNTRY_CODE)
1687 SET_UINT (msg, info21.country_code, "countryCode");
1688 IFSET(SAMR_FIELD_CODE_PAGE)
1689 SET_UINT (msg, info21.code_page, "codePage");
1692 /* Any reason the rest of these can't be set? */
1697 #define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
1698 IFSET(SAMR_FIELD_NAME)
1699 SET_STRING(msg, info23.info.full_name.string, "displayName");
1700 IFSET(SAMR_FIELD_DESCRIPTION)
1701 SET_STRING(msg, info23.info.description.string, "description");
1702 IFSET(SAMR_FIELD_COMMENT)
1703 SET_STRING(msg, info23.info.comment.string, "comment");
1704 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1705 SET_STRING(msg, info23.info.logon_script.string, "scriptPath");
1706 IFSET(SAMR_FIELD_PROFILE_PATH)
1707 SET_STRING(msg, info23.info.profile_path.string, "profilePath");
1708 IFSET(SAMR_FIELD_WORKSTATION)
1709 SET_STRING(msg, info23.info.workstations.string, "userWorkstations");
1710 IFSET(SAMR_FIELD_LOGON_HOURS)
1711 SET_LHOURS(msg, info23.info.logon_hours, "logonHours");
1712 IFSET(SAMR_FIELD_ACCT_FLAGS)
1713 SET_AFLAGS(msg, info23.info.acct_flags, "userAccountControl");
1714 IFSET(SAMR_FIELD_PARAMETERS)
1715 SET_STRING(msg, info23.info.parameters.string, "userParameters");
1716 IFSET(SAMR_FIELD_COUNTRY_CODE)
1717 SET_UINT (msg, info23.info.country_code, "countryCode");
1718 IFSET(SAMR_FIELD_CODE_PAGE)
1719 SET_UINT (msg, info23.info.code_page, "codePage");
1720 IFSET(SAMR_FIELD_PASSWORD) {
1721 status = samr_set_password(dce_call,
1723 a_state->account_dn,
1724 a_state->domain_state->domain_dn,
1726 &r->in.info->info23.password);
1727 } else IFSET(SAMR_FIELD_PASSWORD2) {
1728 status = samr_set_password(dce_call,
1730 a_state->account_dn,
1731 a_state->domain_state->domain_dn,
1733 &r->in.info->info23.password);
1738 /* the set password levels are handled separately */
1740 status = samr_set_password(dce_call,
1742 a_state->account_dn,
1743 a_state->domain_state->domain_dn,
1745 &r->in.info->info24.password);
1749 #define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
1750 IFSET(SAMR_FIELD_NAME)
1751 SET_STRING(msg, info25.info.full_name.string, "displayName");
1752 IFSET(SAMR_FIELD_DESCRIPTION)
1753 SET_STRING(msg, info25.info.description.string, "description");
1754 IFSET(SAMR_FIELD_COMMENT)
1755 SET_STRING(msg, info25.info.comment.string, "comment");
1756 IFSET(SAMR_FIELD_LOGON_SCRIPT)
1757 SET_STRING(msg, info25.info.logon_script.string, "scriptPath");
1758 IFSET(SAMR_FIELD_PROFILE_PATH)
1759 SET_STRING(msg, info25.info.profile_path.string, "profilePath");
1760 IFSET(SAMR_FIELD_WORKSTATION)
1761 SET_STRING(msg, info25.info.workstations.string, "userWorkstations");
1762 IFSET(SAMR_FIELD_LOGON_HOURS)
1763 SET_LHOURS(msg, info25.info.logon_hours, "logonHours");
1764 IFSET(SAMR_FIELD_ACCT_FLAGS)
1765 SET_AFLAGS(msg, info25.info.acct_flags, "userAccountControl");
1766 IFSET(SAMR_FIELD_PARAMETERS)
1767 SET_STRING(msg, info25.info.parameters.string, "userParameters");
1768 IFSET(SAMR_FIELD_COUNTRY_CODE)
1769 SET_UINT (msg, info25.info.country_code, "countryCode");
1770 IFSET(SAMR_FIELD_CODE_PAGE)
1771 SET_UINT (msg, info25.info.code_page, "codePage");
1772 IFSET(SAMR_FIELD_PASSWORD) {
1773 status = samr_set_password_ex(dce_call,
1775 a_state->account_dn,
1776 a_state->domain_state->domain_dn,
1778 &r->in.info->info25.password);
1779 } else IFSET(SAMR_FIELD_PASSWORD2) {
1780 status = samr_set_password_ex(dce_call,
1782 a_state->account_dn,
1783 a_state->domain_state->domain_dn,
1785 &r->in.info->info25.password);
1790 /* the set password levels are handled separately */
1792 status = samr_set_password_ex(dce_call,
1794 a_state->account_dn,
1795 a_state->domain_state->domain_dn,
1797 &r->in.info->info26.password);
1802 /* many info classes are not valid for SetUserInfo */
1803 return NT_STATUS_INVALID_INFO_CLASS;
1806 if (!NT_STATUS_IS_OK(status)) {
1810 /* modify the samdb record */
1811 ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
1813 /* we really need samdb.c to return NTSTATUS */
1814 return NT_STATUS_UNSUCCESSFUL;
1817 return NT_STATUS_OK;
1822 samr_GetGroupsForUser
1824 static NTSTATUS samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1825 struct samr_GetGroupsForUser *r)
1827 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1832 samr_QueryDisplayInfo
1834 static NTSTATUS samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1835 struct samr_QueryDisplayInfo *r)
1837 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1842 samr_GetDisplayEnumerationIndex
1844 static NTSTATUS samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1845 struct samr_GetDisplayEnumerationIndex *r)
1847 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1852 samr_TestPrivateFunctionsDomain
1854 static NTSTATUS samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1855 struct samr_TestPrivateFunctionsDomain *r)
1857 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1862 samr_TestPrivateFunctionsUser
1864 static NTSTATUS samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1865 struct samr_TestPrivateFunctionsUser *r)
1867 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1874 static NTSTATUS samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1875 struct samr_GetUserPwInfo *r)
1877 struct dcesrv_handle *h;
1878 struct samr_account_state *a_state;
1880 ZERO_STRUCT(r->out.info);
1882 DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
1886 r->out.info.min_password_len = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "minPwdLength",
1887 "dn=%s", a_state->domain_state->domain_dn);
1888 r->out.info.password_properties = samdb_search_uint(a_state->sam_ctx, mem_ctx, 0, NULL, "pwdProperties",
1889 "dn=%s", a_state->account_dn);
1890 return NT_STATUS_OK;
1895 samr_RemoveMemberFromForeignDomain
1897 static NTSTATUS samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1898 struct samr_RemoveMemberFromForeignDomain *r)
1900 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1905 samr_QueryDomainInfo2
1907 static NTSTATUS samr_QueryDomainInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1908 struct samr_QueryDomainInfo2 *r)
1910 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1917 just an alias for samr_QueryUserInfo
1919 static NTSTATUS samr_QueryUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1920 struct samr_QueryUserInfo2 *r)
1922 struct samr_QueryUserInfo r1;
1925 r1.in.user_handle = r->in.user_handle;
1926 r1.in.level = r->in.level;
1928 status = samr_QueryUserInfo(dce_call, mem_ctx, &r1);
1930 r->out.info = r1.out.info;
1937 samr_QueryDisplayInfo2
1939 static NTSTATUS samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1940 struct samr_QueryDisplayInfo2 *r)
1942 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1947 samr_GetDisplayEnumerationIndex2
1949 static NTSTATUS samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1950 struct samr_GetDisplayEnumerationIndex2 *r)
1952 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1957 samr_QueryDisplayInfo3
1959 static NTSTATUS samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1960 struct samr_QueryDisplayInfo3 *r)
1962 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1967 samr_AddMultipleMembersToAlias
1969 static NTSTATUS samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1970 struct samr_AddMultipleMembersToAlias *r)
1972 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1977 samr_RemoveMultipleMembersFromAlias
1979 static NTSTATUS samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1980 struct samr_RemoveMultipleMembersFromAlias *r)
1982 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1989 this fetches the default password properties for a domain
1991 note that w2k3 completely ignores the domain name in this call, and
1992 always returns the information for the servers primary domain
1994 static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1995 struct samr_GetDomPwInfo *r)
1997 struct ldb_message **msgs;
1999 const char * const attrs[] = {"minPwdLength", "pwdProperties", NULL };
2002 ZERO_STRUCT(r->out.info);
2004 sam_ctx = samdb_connect(mem_ctx);
2005 if (sam_ctx == NULL) {
2006 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2009 ret = samdb_search(sam_ctx,
2010 mem_ctx, NULL, &msgs, attrs,
2011 "(&(name=%s)(objectclass=domain))",
2014 return NT_STATUS_NO_SUCH_DOMAIN;
2017 samdb_search_free(sam_ctx, mem_ctx, msgs);
2018 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2021 r->out.info.min_password_len = samdb_result_uint(msgs[0], "minPwdLength", 0);
2022 r->out.info.password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1);
2024 samdb_search_free(sam_ctx, mem_ctx, msgs);
2026 talloc_free(sam_ctx);
2027 return NT_STATUS_OK;
2034 static NTSTATUS samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2035 struct samr_Connect2 *r)
2037 struct samr_Connect c;
2039 c.in.system_name = NULL;
2040 c.in.access_mask = r->in.access_mask;
2041 c.out.connect_handle = r->out.connect_handle;
2043 return samr_Connect(dce_call, mem_ctx, &c);
2050 just an alias for samr_SetUserInfo
2052 static NTSTATUS samr_SetUserInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2053 struct samr_SetUserInfo2 *r)
2055 struct samr_SetUserInfo r2;
2057 r2.in.user_handle = r->in.user_handle;
2058 r2.in.level = r->in.level;
2059 r2.in.info = r->in.info;
2061 return samr_SetUserInfo(dce_call, mem_ctx, &r2);
2066 samr_SetBootKeyInformation
2068 static NTSTATUS samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2069 struct samr_SetBootKeyInformation *r)
2071 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2076 samr_GetBootKeyInformation
2078 static NTSTATUS samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2079 struct samr_GetBootKeyInformation *r)
2081 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2088 static NTSTATUS samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2089 struct samr_Connect3 *r)
2091 struct samr_Connect c;
2093 c.in.system_name = NULL;
2094 c.in.access_mask = r->in.access_mask;
2095 c.out.connect_handle = r->out.connect_handle;
2097 return samr_Connect(dce_call, mem_ctx, &c);
2104 static NTSTATUS samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2105 struct samr_Connect4 *r)
2107 struct samr_Connect c;
2109 c.in.system_name = NULL;
2110 c.in.access_mask = r->in.access_mask;
2111 c.out.connect_handle = r->out.connect_handle;
2113 return samr_Connect(dce_call, mem_ctx, &c);
2120 static NTSTATUS samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2121 struct samr_Connect5 *r)
2123 struct samr_Connect c;
2126 c.in.system_name = NULL;
2127 c.in.access_mask = r->in.access_mask;
2128 c.out.connect_handle = r->out.connect_handle;
2130 status = samr_Connect(dce_call, mem_ctx, &c);
2132 r->out.info->info1.unknown1 = 3;
2133 r->out.info->info1.unknown2 = 0;
2134 r->out.level = r->in.level;
2143 static NTSTATUS samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2144 struct samr_RidToSid *r)
2146 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2151 samr_SetDsrmPassword
2153 static NTSTATUS samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2154 struct samr_SetDsrmPassword *r)
2156 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2161 samr_ValidatePassword
2163 static NTSTATUS samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2164 struct samr_ValidatePassword *r)
2166 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2170 /* include the generated boilerplate */
2171 #include "librpc/gen_ndr/ndr_samr_s.c"