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 "libnet/libnet.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../librpc/gen_ndr/srv_wkssvc.h"
31 #define DBGC_CLASS DBGC_RPC_SRV
45 struct timeval login_time;
48 static int usr_info_cmp(const void *p1, const void *p2)
50 const struct usrinfo *usr1 = (const struct usrinfo *)p1;
51 const struct usrinfo *usr2 = (const struct usrinfo *)p2;
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 ((usr1->login_time.tv_sec == usr2->login_time.tv_sec)
57 ? usr1->login_time.tv_usec - usr2->login_time.tv_usec
58 : usr1->login_time.tv_sec - usr2->login_time.tv_sec);
61 /*******************************************************************
62 Get a list of the names of all users logged into this machine
63 ********************************************************************/
65 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
69 struct usrinfo *usr_infos = NULL;
72 while ((u = getutxent()) != NULL) {
74 if (u->ut_type != USER_PROCESS) {
77 for (i = 0; i < num_users; i++) {
78 /* getutxent can return multiple user entries for the
79 * same user, so ignore any dups */
80 if (strcmp(u->ut_user, usr_infos[i].name) == 0) {
88 tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
96 usr_infos[num_users].name = talloc_strdup(usr_infos,
98 if (usr_infos[num_users].name == NULL) {
99 TALLOC_FREE(usr_infos);
103 usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
104 usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
108 /* Sort the user list by time, oldest first */
110 qsort(usr_infos, num_users, sizeof(struct usrinfo),
114 users = (char**)talloc_array(mem_ctx, char*, num_users);
116 for (i = 0; i < num_users; i++) {
117 users[i] = talloc_move(users, &usr_infos[i].name);
120 TALLOC_FREE(usr_infos);
128 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
135 static int dom_user_cmp(const void *p1, const void *p2)
137 /* Called from qsort to compare two domain users in a dom_usr_t array
138 * for sorting by login time. Return >0 if usr1 login time was later
139 * than usr2 login time, <0 if it was earlier */
140 const struct dom_usr *usr1 = (const struct dom_usr *)p1;
141 const struct dom_usr *usr2 = (const struct dom_usr *)p2;
143 return (usr1->login_time - usr2->login_time);
146 /*******************************************************************
147 Get a list of the names of all users of this machine who are
148 logged into the domain.
150 This should return a list of the users on this machine who are
151 logged into the domain (i.e. have been authenticated by the domain's
152 password server) but that doesn't fit well with the normal Samba
153 scenario where accesses out to the domain are made through smbclient
154 with each such session individually authenticated. So about the best
155 we can do currently is to list sessions of local users connected to
156 this server, which means that to get themself included in the list a
157 local user must create a session to the local samba server by running:
158 smbclient \\\\localhost\\share
160 FIXME: find a better way to get local users logged into the domain
162 ********************************************************************/
164 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
166 struct sessionid *session_list = NULL;
167 char *machine_name, *p, *nm;
169 struct dom_usr *users, *tmp;
170 int i, num_users, num_sessions;
172 sep = lp_winbind_separator();
177 num_sessions = list_sessions(mem_ctx, &session_list);
178 if (num_sessions == 0) {
183 users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
185 TALLOC_FREE(session_list);
189 for (i=num_users=0; i<num_sessions; i++) {
190 if (!session_list[i].username
191 || !session_list[i].remote_machine) {
194 p = strpbrk(session_list[i].remote_machine, "./");
198 machine_name = talloc_asprintf_strupper_m(
199 users, "%s", session_list[i].remote_machine);
200 if (machine_name == NULL) {
201 DEBUG(10, ("talloc_asprintf failed\n"));
204 if (strcmp(machine_name, global_myname()) == 0) {
205 p = session_list[i].username;
209 * "domain+name" format so split domain and
214 users[num_users].domain =
215 talloc_asprintf_strupper_m(users,
217 users[num_users].name = talloc_strdup(users,
221 * Simple user name so get domain from smb.conf
223 users[num_users].domain =
224 talloc_strdup(users, lp_workgroup());
225 users[num_users].name = talloc_strdup(users,
228 users[num_users].login_time =
229 session_list[i].connect_start;
232 TALLOC_FREE(machine_name);
234 TALLOC_FREE(session_list);
236 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
242 /* Sort the user list by time, oldest first */
244 qsort(users, num_users, sizeof(struct dom_usr), dom_user_cmp);
251 /*******************************************************************
252 RPC Workstation Service request NetWkstaGetInfo with level 100.
253 Returns to the requester:
255 - The smb version number
257 Returns a filled in wkssvc_NetWkstaInfo100 struct.
258 ********************************************************************/
260 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
262 struct wkssvc_NetWkstaInfo100 *info100;
264 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
265 if (info100 == NULL) {
269 info100->platform_id = PLATFORM_ID_NT; /* unknown */
270 info100->version_major = lp_major_announce_version();
271 info100->version_minor = lp_minor_announce_version();
273 info100->server_name = talloc_asprintf_strupper_m(
274 info100, "%s", global_myname());
275 info100->domain_name = talloc_asprintf_strupper_m(
276 info100, "%s", lp_workgroup());
281 /*******************************************************************
282 RPC Workstation Service request NetWkstaGetInfo with level 101.
283 Returns to the requester:
284 - As per NetWkstaGetInfo with level 100, plus:
285 - The LANMAN directory path (not currently supported).
286 Returns a filled in wkssvc_NetWkstaInfo101 struct.
287 ********************************************************************/
289 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
291 struct wkssvc_NetWkstaInfo101 *info101;
293 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
294 if (info101 == NULL) {
298 info101->platform_id = PLATFORM_ID_NT; /* unknown */
299 info101->version_major = lp_major_announce_version();
300 info101->version_minor = lp_minor_announce_version();
302 info101->server_name = talloc_asprintf_strupper_m(
303 info101, "%s", global_myname());
304 info101->domain_name = talloc_asprintf_strupper_m(
305 info101, "%s", lp_workgroup());
306 info101->lan_root = "";
311 /*******************************************************************
312 RPC Workstation Service request NetWkstaGetInfo with level 102.
313 Returns to the requester:
314 - As per NetWkstaGetInfo with level 101, plus:
315 - The number of logged in users.
316 Returns a filled in wkssvc_NetWkstaInfo102 struct.
317 ********************************************************************/
319 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
321 struct wkssvc_NetWkstaInfo102 *info102;
324 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
325 if (info102 == NULL) {
329 info102->platform_id = PLATFORM_ID_NT; /* unknown */
330 info102->version_major = lp_major_announce_version();
331 info102->version_minor = lp_minor_announce_version();
333 info102->server_name = talloc_asprintf_strupper_m(
334 info102, "%s", global_myname());
335 info102->domain_name = talloc_asprintf_strupper_m(
336 info102, "%s", lp_workgroup());
337 info102->lan_root = "";
339 users = get_logged_on_userlist(talloc_tos());
340 info102->logged_on_users = talloc_array_length(users);
347 /********************************************************************
348 Handling for RPC Workstation Service request NetWkstaGetInfo
349 ********************************************************************/
351 WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
353 switch (r->in.level) {
355 /* Level 100 can be allowed from anyone including anonymous
356 * so no access checks are needed for this case */
357 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
358 if (r->out.info->info100 == NULL) {
363 /* Level 101 can be allowed from any logged in user */
364 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
365 p->server_info->ptok)) {
366 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
368 DEBUGADD(3,(" - does not have sid for Authenticated "
371 &global_sid_Authenticated_Users)));
372 debug_nt_user_token(DBGC_CLASS, 3,
373 p->server_info->ptok);
374 return WERR_ACCESS_DENIED;
376 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
377 if (r->out.info->info101 == NULL) {
382 /* Level 102 Should only be allowed from a domain administrator */
383 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
384 p->server_info->ptok)) {
385 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
387 DEBUGADD(3,(" - does not have sid for Administrators "
388 "group %s, sids are:\n",
389 sid_string_dbg(&global_sid_Builtin_Administrators)));
390 debug_nt_user_token(DBGC_CLASS, 3,
391 p->server_info->ptok);
392 return WERR_ACCESS_DENIED;
394 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
395 if (r->out.info->info102 == NULL) {
400 return WERR_UNKNOWN_LEVEL;
406 /********************************************************************
407 ********************************************************************/
409 WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r)
411 /* FIXME: Add implementation code here */
412 p->rng_fault_state = True;
413 return WERR_NOT_SUPPORTED;
416 /********************************************************************
417 RPC Workstation Service request NetWkstaEnumUsers with level 0:
418 Returns to the requester:
419 - the user names of the logged in users.
420 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
421 ********************************************************************/
423 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
426 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
430 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
435 users = get_logged_on_userlist(talloc_tos());
436 if (users == NULL && errno != 0) {
437 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
438 errno, strerror(errno)));
443 num_users = (users) ? talloc_array_length(users) : 0;
444 ctr0->entries_read = num_users;
445 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
447 if (ctr0->user0 == NULL) {
453 for (i=0; i<num_users; i++) {
454 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
460 /********************************************************************
461 RPC Workstation Service request NetWkstaEnumUsers with level 1.
462 Returns to the requester:
463 - the user names of the logged in users,
464 - the domain or machine each is logged into,
465 - the password server that was used to authenticate each,
466 - other domains each user is logged into (not currently supported).
467 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
468 ********************************************************************/
470 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
473 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
475 struct dom_usr *dom_users;
477 int i, j, num_users, num_dom_users;
479 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
484 users = get_logged_on_userlist(talloc_tos());
485 if (users == NULL && errno != 0) {
486 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
487 errno, strerror(errno)));
491 num_users = (users) ? talloc_array_length(users) : 0;
493 dom_users = get_domain_userlist(talloc_tos());
494 if (dom_users == NULL && errno != 0) {
499 num_dom_users = (dom_users) ? talloc_array_length(dom_users) : 0;
501 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
502 num_users+num_dom_users);
503 if (ctr1->user1 == NULL) {
506 TALLOC_FREE(dom_users);
510 if ((pwd_server = talloc_strdup(ctr1->user1, lp_passwordserver()))) {
511 /* The configured password server is a full DNS name but
512 * for the logon server we need to return just the first
513 * component (machine name) of it in upper-case */
514 char *p = strchr(pwd_server, '.');
518 p = pwd_server + strlen(pwd_server);
520 while (--p >= pwd_server) {
527 /* Put in local users first */
528 for (i=0; i<num_users; i++) {
529 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
531 /* For a local user the domain name and logon server are
532 * both returned as the local machine's NetBIOS name */
533 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
534 talloc_asprintf_strupper_m(ctr1->user1, "%s", global_myname());
536 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */
539 /* Now domain users */
540 for (j=0; j<num_dom_users; j++) {
541 ctr1->user1[i].user_name =
542 talloc_strdup(ctr1->user1, dom_users[j].name);
543 ctr1->user1[i].logon_domain =
544 talloc_strdup(ctr1->user1, dom_users[j].domain);
545 ctr1->user1[i].logon_server = pwd_server;
547 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
550 ctr1->entries_read = i;
553 TALLOC_FREE(dom_users);
557 /********************************************************************
558 Handling for RPC Workstation Service request NetWkstaEnumUsers
559 (a.k.a Windows NetWkstaUserEnum)
560 ********************************************************************/
562 WERROR _wkssvc_NetWkstaEnumUsers(pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r)
564 /* This with any level should only be allowed from a domain administrator */
565 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
566 p->server_info->ptok)) {
567 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
568 DEBUGADD(3,(" - does not have sid for Administrators group "
569 "%s\n", sid_string_dbg(
570 &global_sid_Builtin_Administrators)));
571 debug_nt_user_token(DBGC_CLASS, 3, p->server_info->ptok);
572 return WERR_ACCESS_DENIED;
575 switch (r->in.info->level) {
577 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
578 if (r->out.info->ctr.user0 == NULL) {
581 r->out.info->level = r->in.info->level;
582 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
583 *r->out.resume_handle = 0;
586 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
587 if (r->out.info->ctr.user1 == NULL) {
590 r->out.info->level = r->in.info->level;
591 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
592 *r->out.resume_handle = 0;
595 return WERR_UNKNOWN_LEVEL;
601 /********************************************************************
602 ********************************************************************/
604 WERROR _wkssvc_NetrWkstaUserGetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserGetInfo *r)
606 /* FIXME: Add implementation code here */
607 p->rng_fault_state = True;
608 return WERR_NOT_SUPPORTED;
611 /********************************************************************
612 ********************************************************************/
614 WERROR _wkssvc_NetrWkstaUserSetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserSetInfo *r)
616 /* FIXME: Add implementation code here */
617 p->rng_fault_state = True;
618 return WERR_NOT_SUPPORTED;
621 /********************************************************************
622 ********************************************************************/
624 WERROR _wkssvc_NetWkstaTransportEnum(pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r)
626 /* FIXME: Add implementation code here */
627 p->rng_fault_state = True;
628 return WERR_NOT_SUPPORTED;
631 /********************************************************************
632 ********************************************************************/
634 WERROR _wkssvc_NetrWkstaTransportAdd(pipes_struct *p, struct wkssvc_NetrWkstaTransportAdd *r)
636 /* FIXME: Add implementation code here */
637 p->rng_fault_state = True;
638 return WERR_NOT_SUPPORTED;
641 /********************************************************************
642 ********************************************************************/
644 WERROR _wkssvc_NetrWkstaTransportDel(pipes_struct *p, 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(pipes_struct *p, struct wkssvc_NetrUseAdd *r)
656 /* FIXME: Add implementation code here */
657 p->rng_fault_state = True;
658 return WERR_NOT_SUPPORTED;
661 /********************************************************************
662 ********************************************************************/
664 WERROR _wkssvc_NetrUseGetInfo(pipes_struct *p, struct wkssvc_NetrUseGetInfo *r)
666 /* FIXME: Add implementation code here */
667 p->rng_fault_state = True;
668 return WERR_NOT_SUPPORTED;
671 /********************************************************************
672 ********************************************************************/
674 WERROR _wkssvc_NetrUseDel(pipes_struct *p, struct wkssvc_NetrUseDel *r)
676 /* FIXME: Add implementation code here */
677 p->rng_fault_state = True;
678 return WERR_NOT_SUPPORTED;
681 /********************************************************************
682 ********************************************************************/
684 WERROR _wkssvc_NetrUseEnum(pipes_struct *p, struct wkssvc_NetrUseEnum *r)
686 /* FIXME: Add implementation code here */
687 p->rng_fault_state = True;
688 return WERR_NOT_SUPPORTED;
691 /********************************************************************
692 ********************************************************************/
694 WERROR _wkssvc_NetrMessageBufferSend(pipes_struct *p, struct wkssvc_NetrMessageBufferSend *r)
696 /* FIXME: Add implementation code here */
697 p->rng_fault_state = True;
698 return WERR_NOT_SUPPORTED;
701 /********************************************************************
702 ********************************************************************/
704 WERROR _wkssvc_NetrWorkstationStatisticsGet(pipes_struct *p, struct wkssvc_NetrWorkstationStatisticsGet *r)
706 /* FIXME: Add implementation code here */
707 p->rng_fault_state = True;
708 return WERR_NOT_SUPPORTED;
711 /********************************************************************
712 ********************************************************************/
714 WERROR _wkssvc_NetrLogonDomainNameAdd(pipes_struct *p, struct wkssvc_NetrLogonDomainNameAdd *r)
716 /* FIXME: Add implementation code here */
717 p->rng_fault_state = True;
718 return WERR_NOT_SUPPORTED;
721 /********************************************************************
722 ********************************************************************/
724 WERROR _wkssvc_NetrLogonDomainNameDel(pipes_struct *p, struct wkssvc_NetrLogonDomainNameDel *r)
726 /* FIXME: Add implementation code here */
727 p->rng_fault_state = True;
728 return WERR_NOT_SUPPORTED;
731 /********************************************************************
732 ********************************************************************/
734 WERROR _wkssvc_NetrJoinDomain(pipes_struct *p, struct wkssvc_NetrJoinDomain *r)
736 /* FIXME: Add implementation code here */
737 p->rng_fault_state = True;
738 return WERR_NOT_SUPPORTED;
741 /********************************************************************
742 ********************************************************************/
744 WERROR _wkssvc_NetrUnjoinDomain(pipes_struct *p, struct wkssvc_NetrUnjoinDomain *r)
746 /* FIXME: Add implementation code here */
747 p->rng_fault_state = True;
748 return WERR_NOT_SUPPORTED;
751 /********************************************************************
752 ********************************************************************/
754 WERROR _wkssvc_NetrRenameMachineInDomain(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain *r)
756 /* FIXME: Add implementation code here */
757 p->rng_fault_state = True;
758 return WERR_NOT_SUPPORTED;
761 /********************************************************************
762 ********************************************************************/
764 WERROR _wkssvc_NetrValidateName(pipes_struct *p, struct wkssvc_NetrValidateName *r)
766 /* FIXME: Add implementation code here */
767 p->rng_fault_state = True;
768 return WERR_NOT_SUPPORTED;
771 /********************************************************************
772 ********************************************************************/
774 WERROR _wkssvc_NetrGetJoinInformation(pipes_struct *p, struct wkssvc_NetrGetJoinInformation *r)
776 /* FIXME: Add implementation code here */
777 p->rng_fault_state = True;
778 return WERR_NOT_SUPPORTED;
781 /********************************************************************
782 ********************************************************************/
784 WERROR _wkssvc_NetrGetJoinableOus(pipes_struct *p, struct wkssvc_NetrGetJoinableOus *r)
786 /* FIXME: Add implementation code here */
787 p->rng_fault_state = True;
788 return WERR_NOT_SUPPORTED;
791 /********************************************************************
792 _wkssvc_NetrJoinDomain2
793 ********************************************************************/
795 WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p,
796 struct wkssvc_NetrJoinDomain2 *r)
798 struct libnet_JoinCtx *j = NULL;
799 char *cleartext_pwd = NULL;
800 char *admin_domain = NULL;
801 char *admin_account = NULL;
803 struct nt_user_token *token = p->server_info->ptok;
805 if (!r->in.domain_name) {
806 return WERR_INVALID_PARAM;
809 if (!r->in.admin_account || !r->in.encrypted_password) {
810 return WERR_INVALID_PARAM;
813 if (!user_has_privileges(token, &se_machine_account) &&
814 !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) &&
815 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
816 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
817 "sufficient privileges\n"));
818 return WERR_ACCESS_DENIED;
821 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
822 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
823 return WERR_NOT_SUPPORTED;
826 werr = decode_wkssvc_join_password_buffer(
827 p->mem_ctx, r->in.encrypted_password,
828 &p->server_info->user_session_key, &cleartext_pwd);
829 if (!W_ERROR_IS_OK(werr)) {
833 split_domain_user(p->mem_ctx,
838 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
839 if (!W_ERROR_IS_OK(werr)) {
843 j->in.domain_name = r->in.domain_name;
844 j->in.account_ou = r->in.account_ou;
845 j->in.join_flags = r->in.join_flags;
846 j->in.admin_account = admin_account;
847 j->in.admin_password = cleartext_pwd;
849 j->in.modify_config = lp_config_backend_is_registry();
850 j->in.msg_ctx = smbd_messaging_context();
853 werr = libnet_Join(p->mem_ctx, j);
856 if (!W_ERROR_IS_OK(werr)) {
857 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
858 j->out.error_string ? j->out.error_string :
866 /********************************************************************
867 _wkssvc_NetrUnjoinDomain2
868 ********************************************************************/
870 WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p,
871 struct wkssvc_NetrUnjoinDomain2 *r)
873 struct libnet_UnjoinCtx *u = NULL;
874 char *cleartext_pwd = NULL;
875 char *admin_domain = NULL;
876 char *admin_account = NULL;
878 struct nt_user_token *token = p->server_info->ptok;
880 if (!r->in.account || !r->in.encrypted_password) {
881 return WERR_INVALID_PARAM;
884 if (!user_has_privileges(token, &se_machine_account) &&
885 !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) &&
886 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
887 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
888 "sufficient privileges\n"));
889 return WERR_ACCESS_DENIED;
892 werr = decode_wkssvc_join_password_buffer(
893 p->mem_ctx, r->in.encrypted_password,
894 &p->server_info->user_session_key, &cleartext_pwd);
895 if (!W_ERROR_IS_OK(werr)) {
899 split_domain_user(p->mem_ctx,
904 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
905 if (!W_ERROR_IS_OK(werr)) {
909 u->in.domain_name = lp_realm();
910 u->in.unjoin_flags = r->in.unjoin_flags |
911 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
912 u->in.admin_account = admin_account;
913 u->in.admin_password = cleartext_pwd;
915 u->in.modify_config = lp_config_backend_is_registry();
916 u->in.msg_ctx = smbd_messaging_context();
919 werr = libnet_Unjoin(p->mem_ctx, u);
922 if (!W_ERROR_IS_OK(werr)) {
923 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
924 u->out.error_string ? u->out.error_string :
932 /********************************************************************
933 ********************************************************************/
935 WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r)
937 /* for now just return not supported */
938 return WERR_NOT_SUPPORTED;
941 /********************************************************************
942 ********************************************************************/
944 WERROR _wkssvc_NetrValidateName2(pipes_struct *p, struct wkssvc_NetrValidateName2 *r)
946 /* FIXME: Add implementation code here */
947 p->rng_fault_state = True;
948 return WERR_NOT_SUPPORTED;
951 /********************************************************************
952 ********************************************************************/
954 WERROR _wkssvc_NetrGetJoinableOus2(pipes_struct *p, struct wkssvc_NetrGetJoinableOus2 *r)
956 /* FIXME: Add implementation code here */
957 p->rng_fault_state = True;
958 return WERR_NOT_SUPPORTED;
961 /********************************************************************
962 ********************************************************************/
964 WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r)
966 /* FIXME: Add implementation code here */
967 p->rng_fault_state = True;
968 return WERR_NOT_SUPPORTED;
971 /********************************************************************
972 ********************************************************************/
974 WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *r)
976 /* FIXME: Add implementation code here */
977 p->rng_fault_state = True;
978 return WERR_NOT_SUPPORTED;
981 /********************************************************************
982 ********************************************************************/
984 WERROR _wkssvc_NetrSetPrimaryComputername(pipes_struct *p, struct wkssvc_NetrSetPrimaryComputername *r)
986 /* FIXME: Add implementation code here */
987 p->rng_fault_state = True;
988 return WERR_NOT_SUPPORTED;
991 /********************************************************************
992 ********************************************************************/
994 WERROR _wkssvc_NetrEnumerateComputerNames(pipes_struct *p, struct wkssvc_NetrEnumerateComputerNames *r)
996 /* FIXME: Add implementation code here */
997 p->rng_fault_state = True;
998 return WERR_NOT_SUPPORTED;