2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-1997,
6 * Copyright (C) Gerald (Jerry) Carter 2006.
7 * Copyright (C) Guenther Deschner 2007-2008.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 /* This is the implementation of the wks interface. */
26 #include "librpc/gen_ndr/libnet_join.h"
27 #include "libnet/libnet_join.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "../librpc/gen_ndr/srv_wkssvc.h"
30 #include "../libcli/security/security.h"
34 #define DBGC_CLASS DBGC_RPC_SRV
48 struct timeval login_time;
51 static int usr_info_cmp(const struct usrinfo *usr1, const struct usrinfo *usr2)
53 /* Called from qsort to compare two users in a usrinfo_t array for
54 * sorting by login time. Return >0 if usr1 login time was later than
55 * usr2 login time, <0 if it was earlier */
56 return timeval_compare(&usr1->login_time, &usr2->login_time);
59 /*******************************************************************
60 Get a list of the names of all users logged into this machine
61 ********************************************************************/
63 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
67 struct usrinfo *usr_infos = NULL;
70 while ((u = getutxent()) != NULL) {
72 if (u->ut_type != USER_PROCESS) {
75 for (i = 0; i < num_users; i++) {
76 /* getutxent can return multiple user entries for the
77 * same user, so ignore any dups */
78 if (strcmp(u->ut_user, usr_infos[i].name) == 0) {
86 tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
94 usr_infos[num_users].name = talloc_strdup(usr_infos,
96 if (usr_infos[num_users].name == NULL) {
97 TALLOC_FREE(usr_infos);
101 usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
102 usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
106 /* Sort the user list by time, oldest first */
107 TYPESAFE_QSORT(usr_infos, num_users, usr_info_cmp);
109 users = (char**)talloc_array(mem_ctx, char*, num_users);
111 for (i = 0; i < num_users; i++) {
112 users[i] = talloc_move(users, &usr_infos[i].name);
115 TALLOC_FREE(usr_infos);
123 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
130 static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
132 /* Called from qsort to compare two domain users in a dom_usr_t array
133 * for sorting by login time. Return >0 if usr1 login time was later
134 * than usr2 login time, <0 if it was earlier */
135 return (usr1->login_time - usr2->login_time);
138 /*******************************************************************
139 Get a list of the names of all users of this machine who are
140 logged into the domain.
142 This should return a list of the users on this machine who are
143 logged into the domain (i.e. have been authenticated by the domain's
144 password server) but that doesn't fit well with the normal Samba
145 scenario where accesses out to the domain are made through smbclient
146 with each such session individually authenticated. So about the best
147 we can do currently is to list sessions of local users connected to
148 this server, which means that to get themself included in the list a
149 local user must create a session to the local samba server by running:
150 smbclient \\\\localhost\\share
152 FIXME: find a better way to get local users logged into the domain
154 ********************************************************************/
156 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
158 struct sessionid *session_list = NULL;
159 char *machine_name, *p, *nm;
161 struct dom_usr *users, *tmp;
162 int i, num_users, num_sessions;
164 sep = lp_winbind_separator();
169 num_sessions = list_sessions(mem_ctx, &session_list);
170 if (num_sessions == 0) {
175 users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
177 TALLOC_FREE(session_list);
181 for (i=num_users=0; i<num_sessions; i++) {
182 if (!session_list[i].username
183 || !session_list[i].remote_machine) {
186 p = strpbrk(session_list[i].remote_machine, "./");
190 machine_name = talloc_asprintf_strupper_m(
191 users, "%s", session_list[i].remote_machine);
192 if (machine_name == NULL) {
193 DEBUG(10, ("talloc_asprintf failed\n"));
196 if (strcmp(machine_name, global_myname()) == 0) {
197 p = session_list[i].username;
201 * "domain+name" format so split domain and
206 users[num_users].domain =
207 talloc_asprintf_strupper_m(users,
209 users[num_users].name = talloc_strdup(users,
213 * Simple user name so get domain from smb.conf
215 users[num_users].domain =
216 talloc_strdup(users, lp_workgroup());
217 users[num_users].name = talloc_strdup(users,
220 users[num_users].login_time =
221 session_list[i].connect_start;
224 TALLOC_FREE(machine_name);
226 TALLOC_FREE(session_list);
228 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
234 /* Sort the user list by time, oldest first */
235 TYPESAFE_QSORT(users, num_users, dom_user_cmp);
241 /*******************************************************************
242 RPC Workstation Service request NetWkstaGetInfo with level 100.
243 Returns to the requester:
245 - The smb version number
247 Returns a filled in wkssvc_NetWkstaInfo100 struct.
248 ********************************************************************/
250 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
252 struct wkssvc_NetWkstaInfo100 *info100;
254 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
255 if (info100 == NULL) {
259 info100->platform_id = PLATFORM_ID_NT; /* unknown */
260 info100->version_major = lp_major_announce_version();
261 info100->version_minor = lp_minor_announce_version();
263 info100->server_name = talloc_asprintf_strupper_m(
264 info100, "%s", global_myname());
265 info100->domain_name = talloc_asprintf_strupper_m(
266 info100, "%s", lp_workgroup());
271 /*******************************************************************
272 RPC Workstation Service request NetWkstaGetInfo with level 101.
273 Returns to the requester:
274 - As per NetWkstaGetInfo with level 100, plus:
275 - The LANMAN directory path (not currently supported).
276 Returns a filled in wkssvc_NetWkstaInfo101 struct.
277 ********************************************************************/
279 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
281 struct wkssvc_NetWkstaInfo101 *info101;
283 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
284 if (info101 == NULL) {
288 info101->platform_id = PLATFORM_ID_NT; /* unknown */
289 info101->version_major = lp_major_announce_version();
290 info101->version_minor = lp_minor_announce_version();
292 info101->server_name = talloc_asprintf_strupper_m(
293 info101, "%s", global_myname());
294 info101->domain_name = talloc_asprintf_strupper_m(
295 info101, "%s", lp_workgroup());
296 info101->lan_root = "";
301 /*******************************************************************
302 RPC Workstation Service request NetWkstaGetInfo with level 102.
303 Returns to the requester:
304 - As per NetWkstaGetInfo with level 101, plus:
305 - The number of logged in users.
306 Returns a filled in wkssvc_NetWkstaInfo102 struct.
307 ********************************************************************/
309 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
311 struct wkssvc_NetWkstaInfo102 *info102;
314 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
315 if (info102 == NULL) {
319 info102->platform_id = PLATFORM_ID_NT; /* unknown */
320 info102->version_major = lp_major_announce_version();
321 info102->version_minor = lp_minor_announce_version();
323 info102->server_name = talloc_asprintf_strupper_m(
324 info102, "%s", global_myname());
325 info102->domain_name = talloc_asprintf_strupper_m(
326 info102, "%s", lp_workgroup());
327 info102->lan_root = "";
329 users = get_logged_on_userlist(talloc_tos());
330 info102->logged_on_users = talloc_array_length(users);
337 /********************************************************************
338 Handling for RPC Workstation Service request NetWkstaGetInfo
339 ********************************************************************/
341 WERROR _wkssvc_NetWkstaGetInfo(struct pipes_struct *p,
342 struct wkssvc_NetWkstaGetInfo *r)
344 switch (r->in.level) {
346 /* Level 100 can be allowed from anyone including anonymous
347 * so no access checks are needed for this case */
348 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
349 if (r->out.info->info100 == NULL) {
354 /* Level 101 can be allowed from any logged in user */
355 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
356 p->session_info->security_token)) {
357 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
359 DEBUGADD(3,(" - does not have sid for Authenticated "
362 &global_sid_Authenticated_Users)));
363 security_token_debug(DBGC_CLASS, 3,
364 p->session_info->security_token);
365 return WERR_ACCESS_DENIED;
367 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
368 if (r->out.info->info101 == NULL) {
373 /* Level 102 Should only be allowed from a domain administrator */
374 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
375 p->session_info->security_token)) {
376 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
378 DEBUGADD(3,(" - does not have sid for Administrators "
379 "group %s, sids are:\n",
380 sid_string_dbg(&global_sid_Builtin_Administrators)));
381 security_token_debug(DBGC_CLASS, 3,
382 p->session_info->security_token);
383 return WERR_ACCESS_DENIED;
385 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
386 if (r->out.info->info102 == NULL) {
391 return WERR_UNKNOWN_LEVEL;
397 /********************************************************************
398 ********************************************************************/
400 WERROR _wkssvc_NetWkstaSetInfo(struct pipes_struct *p,
401 struct wkssvc_NetWkstaSetInfo *r)
403 /* FIXME: Add implementation code here */
404 p->rng_fault_state = True;
405 return WERR_NOT_SUPPORTED;
408 /********************************************************************
409 RPC Workstation Service request NetWkstaEnumUsers with level 0:
410 Returns to the requester:
411 - the user names of the logged in users.
412 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
413 ********************************************************************/
415 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
418 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
422 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
427 users = get_logged_on_userlist(talloc_tos());
428 if (users == NULL && errno != 0) {
429 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
430 errno, strerror(errno)));
435 num_users = talloc_array_length(users);
436 ctr0->entries_read = num_users;
437 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
439 if (ctr0->user0 == NULL) {
445 for (i=0; i<num_users; i++) {
446 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
452 /********************************************************************
453 RPC Workstation Service request NetWkstaEnumUsers with level 1.
454 Returns to the requester:
455 - the user names of the logged in users,
456 - the domain or machine each is logged into,
457 - the password server that was used to authenticate each,
458 - other domains each user is logged into (not currently supported).
459 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
460 ********************************************************************/
462 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
465 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
467 struct dom_usr *dom_users;
468 const char *pwd_server;
470 int i, j, num_users, num_dom_users;
472 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
477 users = get_logged_on_userlist(talloc_tos());
478 if (users == NULL && errno != 0) {
479 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
480 errno, strerror(errno)));
484 num_users = talloc_array_length(users);
486 dom_users = get_domain_userlist(talloc_tos());
487 if (dom_users == NULL && errno != 0) {
492 num_dom_users = talloc_array_length(dom_users);
494 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
495 num_users+num_dom_users);
496 if (ctr1->user1 == NULL) {
499 TALLOC_FREE(dom_users);
505 if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) {
506 /* The configured password server is a full DNS name but
507 * for the logon server we need to return just the first
508 * component (machine name) of it in upper-case */
509 char *p = strchr(pwd_tmp, '.');
513 p = pwd_tmp + strlen(pwd_tmp);
515 while (--p >= pwd_tmp) {
518 pwd_server = pwd_tmp;
521 /* Put in local users first */
522 for (i=0; i<num_users; i++) {
523 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
525 /* For a local user the domain name and logon server are
526 * both returned as the local machine's NetBIOS name */
527 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
528 talloc_asprintf_strupper_m(ctr1->user1, "%s", global_myname());
530 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */
533 /* Now domain users */
534 for (j=0; j<num_dom_users; j++) {
535 ctr1->user1[i].user_name =
536 talloc_strdup(ctr1->user1, dom_users[j].name);
537 ctr1->user1[i].logon_domain =
538 talloc_strdup(ctr1->user1, dom_users[j].domain);
539 ctr1->user1[i].logon_server = pwd_server;
541 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
544 ctr1->entries_read = i;
547 TALLOC_FREE(dom_users);
551 /********************************************************************
552 Handling for RPC Workstation Service request NetWkstaEnumUsers
553 (a.k.a Windows NetWkstaUserEnum)
554 ********************************************************************/
556 WERROR _wkssvc_NetWkstaEnumUsers(struct pipes_struct *p,
557 struct wkssvc_NetWkstaEnumUsers *r)
559 /* This with any level should only be allowed from a domain administrator */
560 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
561 p->session_info->security_token)) {
562 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
563 DEBUGADD(3,(" - does not have sid for Administrators group "
564 "%s\n", sid_string_dbg(
565 &global_sid_Builtin_Administrators)));
566 security_token_debug(DBGC_CLASS, 3, p->session_info->security_token);
567 return WERR_ACCESS_DENIED;
570 switch (r->in.info->level) {
572 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
573 if (r->out.info->ctr.user0 == NULL) {
576 r->out.info->level = r->in.info->level;
577 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
578 *r->out.resume_handle = 0;
581 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
582 if (r->out.info->ctr.user1 == NULL) {
585 r->out.info->level = r->in.info->level;
586 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
587 *r->out.resume_handle = 0;
590 return WERR_UNKNOWN_LEVEL;
596 /********************************************************************
597 ********************************************************************/
599 WERROR _wkssvc_NetrWkstaUserGetInfo(struct pipes_struct *p,
600 struct wkssvc_NetrWkstaUserGetInfo *r)
602 /* FIXME: Add implementation code here */
603 p->rng_fault_state = True;
604 return WERR_NOT_SUPPORTED;
607 /********************************************************************
608 ********************************************************************/
610 WERROR _wkssvc_NetrWkstaUserSetInfo(struct pipes_struct *p,
611 struct wkssvc_NetrWkstaUserSetInfo *r)
613 /* FIXME: Add implementation code here */
614 p->rng_fault_state = True;
615 return WERR_NOT_SUPPORTED;
618 /********************************************************************
619 ********************************************************************/
621 WERROR _wkssvc_NetWkstaTransportEnum(struct pipes_struct *p,
622 struct wkssvc_NetWkstaTransportEnum *r)
624 /* FIXME: Add implementation code here */
625 p->rng_fault_state = True;
626 return WERR_NOT_SUPPORTED;
629 /********************************************************************
630 ********************************************************************/
632 WERROR _wkssvc_NetrWkstaTransportAdd(struct pipes_struct *p,
633 struct wkssvc_NetrWkstaTransportAdd *r)
635 /* FIXME: Add implementation code here */
636 p->rng_fault_state = True;
637 return WERR_NOT_SUPPORTED;
640 /********************************************************************
641 ********************************************************************/
643 WERROR _wkssvc_NetrWkstaTransportDel(struct pipes_struct *p,
644 struct wkssvc_NetrWkstaTransportDel *r)
646 /* FIXME: Add implementation code here */
647 p->rng_fault_state = True;
648 return WERR_NOT_SUPPORTED;
651 /********************************************************************
652 ********************************************************************/
654 WERROR _wkssvc_NetrUseAdd(struct pipes_struct *p,
655 struct wkssvc_NetrUseAdd *r)
657 /* FIXME: Add implementation code here */
658 p->rng_fault_state = True;
659 return WERR_NOT_SUPPORTED;
662 /********************************************************************
663 ********************************************************************/
665 WERROR _wkssvc_NetrUseGetInfo(struct pipes_struct *p,
666 struct wkssvc_NetrUseGetInfo *r)
668 /* FIXME: Add implementation code here */
669 p->rng_fault_state = True;
670 return WERR_NOT_SUPPORTED;
673 /********************************************************************
674 ********************************************************************/
676 WERROR _wkssvc_NetrUseDel(struct pipes_struct *p,
677 struct wkssvc_NetrUseDel *r)
679 /* FIXME: Add implementation code here */
680 p->rng_fault_state = True;
681 return WERR_NOT_SUPPORTED;
684 /********************************************************************
685 ********************************************************************/
687 WERROR _wkssvc_NetrUseEnum(struct pipes_struct *p,
688 struct wkssvc_NetrUseEnum *r)
690 /* FIXME: Add implementation code here */
691 p->rng_fault_state = True;
692 return WERR_NOT_SUPPORTED;
695 /********************************************************************
696 ********************************************************************/
698 WERROR _wkssvc_NetrMessageBufferSend(struct pipes_struct *p,
699 struct wkssvc_NetrMessageBufferSend *r)
701 /* FIXME: Add implementation code here */
702 p->rng_fault_state = True;
703 return WERR_NOT_SUPPORTED;
706 /********************************************************************
707 ********************************************************************/
709 WERROR _wkssvc_NetrWorkstationStatisticsGet(struct pipes_struct *p,
710 struct wkssvc_NetrWorkstationStatisticsGet *r)
712 /* FIXME: Add implementation code here */
713 p->rng_fault_state = True;
714 return WERR_NOT_SUPPORTED;
717 /********************************************************************
718 ********************************************************************/
720 WERROR _wkssvc_NetrLogonDomainNameAdd(struct pipes_struct *p,
721 struct wkssvc_NetrLogonDomainNameAdd *r)
723 /* FIXME: Add implementation code here */
724 p->rng_fault_state = True;
725 return WERR_NOT_SUPPORTED;
728 /********************************************************************
729 ********************************************************************/
731 WERROR _wkssvc_NetrLogonDomainNameDel(struct pipes_struct *p,
732 struct wkssvc_NetrLogonDomainNameDel *r)
734 /* FIXME: Add implementation code here */
735 p->rng_fault_state = True;
736 return WERR_NOT_SUPPORTED;
739 /********************************************************************
740 ********************************************************************/
742 WERROR _wkssvc_NetrJoinDomain(struct pipes_struct *p,
743 struct wkssvc_NetrJoinDomain *r)
745 /* FIXME: Add implementation code here */
746 p->rng_fault_state = True;
747 return WERR_NOT_SUPPORTED;
750 /********************************************************************
751 ********************************************************************/
753 WERROR _wkssvc_NetrUnjoinDomain(struct pipes_struct *p,
754 struct wkssvc_NetrUnjoinDomain *r)
756 /* FIXME: Add implementation code here */
757 p->rng_fault_state = True;
758 return WERR_NOT_SUPPORTED;
761 /********************************************************************
762 ********************************************************************/
764 WERROR _wkssvc_NetrRenameMachineInDomain(struct pipes_struct *p,
765 struct wkssvc_NetrRenameMachineInDomain *r)
767 /* FIXME: Add implementation code here */
768 p->rng_fault_state = True;
769 return WERR_NOT_SUPPORTED;
772 /********************************************************************
773 ********************************************************************/
775 WERROR _wkssvc_NetrValidateName(struct pipes_struct *p,
776 struct wkssvc_NetrValidateName *r)
778 /* FIXME: Add implementation code here */
779 p->rng_fault_state = True;
780 return WERR_NOT_SUPPORTED;
783 /********************************************************************
784 ********************************************************************/
786 WERROR _wkssvc_NetrGetJoinInformation(struct pipes_struct *p,
787 struct wkssvc_NetrGetJoinInformation *r)
789 /* FIXME: Add implementation code here */
790 p->rng_fault_state = True;
791 return WERR_NOT_SUPPORTED;
794 /********************************************************************
795 ********************************************************************/
797 WERROR _wkssvc_NetrGetJoinableOus(struct pipes_struct *p,
798 struct wkssvc_NetrGetJoinableOus *r)
800 /* FIXME: Add implementation code here */
801 p->rng_fault_state = True;
802 return WERR_NOT_SUPPORTED;
805 /********************************************************************
806 _wkssvc_NetrJoinDomain2
807 ********************************************************************/
809 WERROR _wkssvc_NetrJoinDomain2(struct pipes_struct *p,
810 struct wkssvc_NetrJoinDomain2 *r)
812 struct libnet_JoinCtx *j = NULL;
813 char *cleartext_pwd = NULL;
814 char *admin_domain = NULL;
815 char *admin_account = NULL;
817 struct security_token *token = p->session_info->security_token;
819 if (!r->in.domain_name) {
820 return WERR_INVALID_PARAM;
823 if (!r->in.admin_account || !r->in.encrypted_password) {
824 return WERR_INVALID_PARAM;
827 if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
828 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
829 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
830 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
831 "sufficient privileges\n"));
832 return WERR_ACCESS_DENIED;
835 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
836 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
837 return WERR_NOT_SUPPORTED;
840 werr = decode_wkssvc_join_password_buffer(
841 p->mem_ctx, r->in.encrypted_password,
842 &p->session_info->user_session_key, &cleartext_pwd);
843 if (!W_ERROR_IS_OK(werr)) {
847 split_domain_user(p->mem_ctx,
852 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
853 if (!W_ERROR_IS_OK(werr)) {
857 j->in.domain_name = r->in.domain_name;
858 j->in.account_ou = r->in.account_ou;
859 j->in.join_flags = r->in.join_flags;
860 j->in.admin_account = admin_account;
861 j->in.admin_password = cleartext_pwd;
863 j->in.modify_config = lp_config_backend_is_registry();
864 j->in.msg_ctx = p->msg_ctx;
867 werr = libnet_Join(p->mem_ctx, j);
870 if (!W_ERROR_IS_OK(werr)) {
871 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
872 j->out.error_string ? j->out.error_string :
880 /********************************************************************
881 _wkssvc_NetrUnjoinDomain2
882 ********************************************************************/
884 WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p,
885 struct wkssvc_NetrUnjoinDomain2 *r)
887 struct libnet_UnjoinCtx *u = NULL;
888 char *cleartext_pwd = NULL;
889 char *admin_domain = NULL;
890 char *admin_account = NULL;
892 struct security_token *token = p->session_info->security_token;
894 if (!r->in.account || !r->in.encrypted_password) {
895 return WERR_INVALID_PARAM;
898 if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
899 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
900 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
901 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
902 "sufficient privileges\n"));
903 return WERR_ACCESS_DENIED;
906 werr = decode_wkssvc_join_password_buffer(
907 p->mem_ctx, r->in.encrypted_password,
908 &p->session_info->user_session_key, &cleartext_pwd);
909 if (!W_ERROR_IS_OK(werr)) {
913 split_domain_user(p->mem_ctx,
918 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
919 if (!W_ERROR_IS_OK(werr)) {
923 u->in.domain_name = lp_realm();
924 u->in.unjoin_flags = r->in.unjoin_flags |
925 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
926 u->in.admin_account = admin_account;
927 u->in.admin_password = cleartext_pwd;
929 u->in.modify_config = lp_config_backend_is_registry();
930 u->in.msg_ctx = p->msg_ctx;
933 werr = libnet_Unjoin(p->mem_ctx, u);
936 if (!W_ERROR_IS_OK(werr)) {
937 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
938 u->out.error_string ? u->out.error_string :
946 /********************************************************************
947 ********************************************************************/
949 WERROR _wkssvc_NetrRenameMachineInDomain2(struct pipes_struct *p,
950 struct wkssvc_NetrRenameMachineInDomain2 *r)
952 /* for now just return not supported */
953 return WERR_NOT_SUPPORTED;
956 /********************************************************************
957 ********************************************************************/
959 WERROR _wkssvc_NetrValidateName2(struct pipes_struct *p,
960 struct wkssvc_NetrValidateName2 *r)
962 /* FIXME: Add implementation code here */
963 p->rng_fault_state = True;
964 return WERR_NOT_SUPPORTED;
967 /********************************************************************
968 ********************************************************************/
970 WERROR _wkssvc_NetrGetJoinableOus2(struct pipes_struct *p,
971 struct wkssvc_NetrGetJoinableOus2 *r)
973 /* FIXME: Add implementation code here */
974 p->rng_fault_state = True;
975 return WERR_NOT_SUPPORTED;
978 /********************************************************************
979 ********************************************************************/
981 WERROR _wkssvc_NetrAddAlternateComputerName(struct pipes_struct *p,
982 struct wkssvc_NetrAddAlternateComputerName *r)
984 /* FIXME: Add implementation code here */
985 p->rng_fault_state = True;
986 return WERR_NOT_SUPPORTED;
989 /********************************************************************
990 ********************************************************************/
992 WERROR _wkssvc_NetrRemoveAlternateComputerName(struct pipes_struct *p,
993 struct wkssvc_NetrRemoveAlternateComputerName *r)
995 /* FIXME: Add implementation code here */
996 p->rng_fault_state = True;
997 return WERR_NOT_SUPPORTED;
1000 /********************************************************************
1001 ********************************************************************/
1003 WERROR _wkssvc_NetrSetPrimaryComputername(struct pipes_struct *p,
1004 struct wkssvc_NetrSetPrimaryComputername *r)
1006 /* FIXME: Add implementation code here */
1007 p->rng_fault_state = True;
1008 return WERR_NOT_SUPPORTED;
1011 /********************************************************************
1012 ********************************************************************/
1014 WERROR _wkssvc_NetrEnumerateComputerNames(struct pipes_struct *p,
1015 struct wkssvc_NetrEnumerateComputerNames *r)
1017 /* FIXME: Add implementation code here */
1018 p->rng_fault_state = True;
1019 return WERR_NOT_SUPPORTED;