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. */
27 #include "librpc/gen_ndr/libnet_join.h"
28 #include "libnet/libnet_join.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/srv_wkssvc.h"
31 #include "../libcli/security/security.h"
33 #include "smbd/smbd.h"
38 #define DBGC_CLASS DBGC_RPC_SRV
52 struct timeval login_time;
55 static int usr_info_cmp(const struct usrinfo *usr1, const struct usrinfo *usr2)
57 /* Called from qsort to compare two users in a usrinfo_t array for
58 * sorting by login time. Return >0 if usr1 login time was later than
59 * usr2 login time, <0 if it was earlier */
60 return timeval_compare(&usr1->login_time, &usr2->login_time);
63 /*******************************************************************
64 Get a list of the names of all users logged into this machine
65 ********************************************************************/
67 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
71 struct usrinfo *usr_infos = NULL;
74 while ((u = getutxent()) != NULL) {
76 if (u->ut_type != USER_PROCESS) {
79 for (i = 0; i < num_users; i++) {
80 /* getutxent can return multiple user entries for the
81 * same user, so ignore any dups */
82 if (strcmp(u->ut_user, usr_infos[i].name) == 0) {
90 tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
98 usr_infos[num_users].name = talloc_strdup(usr_infos,
100 if (usr_infos[num_users].name == NULL) {
101 TALLOC_FREE(usr_infos);
105 usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
106 usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
110 /* Sort the user list by time, oldest first */
111 TYPESAFE_QSORT(usr_infos, num_users, usr_info_cmp);
113 users = (char**)talloc_array(mem_ctx, char*, num_users);
115 for (i = 0; i < num_users; i++) {
116 users[i] = talloc_move(users, &usr_infos[i].name);
119 TALLOC_FREE(usr_infos);
127 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
134 static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
136 /* Called from qsort to compare two domain users in a dom_usr_t array
137 * for sorting by login time. Return >0 if usr1 login time was later
138 * than usr2 login time, <0 if it was earlier */
139 return (usr1->login_time - usr2->login_time);
142 /*******************************************************************
143 Get a list of the names of all users of this machine who are
144 logged into the domain.
146 This should return a list of the users on this machine who are
147 logged into the domain (i.e. have been authenticated by the domain's
148 password server) but that doesn't fit well with the normal Samba
149 scenario where accesses out to the domain are made through smbclient
150 with each such session individually authenticated. So about the best
151 we can do currently is to list sessions of local users connected to
152 this server, which means that to get themself included in the list a
153 local user must create a session to the local samba server by running:
154 smbclient \\\\localhost\\share
156 FIXME: find a better way to get local users logged into the domain
158 ********************************************************************/
160 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
162 struct sessionid *session_list = NULL;
163 char *machine_name, *p, *nm;
165 struct dom_usr *users, *tmp;
166 int i, num_users, num_sessions;
168 sep = lp_winbind_separator();
173 num_sessions = list_sessions(mem_ctx, &session_list);
174 if (num_sessions == 0) {
179 users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
181 TALLOC_FREE(session_list);
185 for (i=num_users=0; i<num_sessions; i++) {
186 if (session_list[i].username[0] == '\0' ||
187 session_list[i].remote_machine[0] == '\0') {
190 p = strpbrk(session_list[i].remote_machine, "./");
194 machine_name = talloc_asprintf_strupper_m(
195 users, "%s", session_list[i].remote_machine);
196 if (machine_name == NULL) {
197 DEBUG(10, ("talloc_asprintf failed\n"));
200 if (strcmp(machine_name, lp_netbios_name()) == 0) {
201 p = session_list[i].username;
205 * "domain+name" format so split domain and
210 users[num_users].domain =
211 talloc_asprintf_strupper_m(users,
213 users[num_users].name = talloc_strdup(users,
217 * Simple user name so get domain from smb.conf
219 users[num_users].domain =
220 talloc_strdup(users, lp_workgroup());
221 users[num_users].name = talloc_strdup(users,
224 users[num_users].login_time =
225 session_list[i].connect_start;
228 TALLOC_FREE(machine_name);
230 TALLOC_FREE(session_list);
232 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
238 /* Sort the user list by time, oldest first */
239 TYPESAFE_QSORT(users, num_users, dom_user_cmp);
245 /*******************************************************************
246 RPC Workstation Service request NetWkstaGetInfo with level 100.
247 Returns to the requester:
249 - The smb version number
251 Returns a filled in wkssvc_NetWkstaInfo100 struct.
252 ********************************************************************/
254 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
256 struct wkssvc_NetWkstaInfo100 *info100;
258 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
259 if (info100 == NULL) {
263 info100->platform_id = PLATFORM_ID_NT; /* unknown */
264 info100->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
265 info100->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
267 info100->server_name = talloc_asprintf_strupper_m(
268 info100, "%s", lp_netbios_name());
269 info100->domain_name = talloc_asprintf_strupper_m(
270 info100, "%s", lp_workgroup());
275 /*******************************************************************
276 RPC Workstation Service request NetWkstaGetInfo with level 101.
277 Returns to the requester:
278 - As per NetWkstaGetInfo with level 100, plus:
279 - The LANMAN directory path (not currently supported).
280 Returns a filled in wkssvc_NetWkstaInfo101 struct.
281 ********************************************************************/
283 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
285 struct wkssvc_NetWkstaInfo101 *info101;
287 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
288 if (info101 == NULL) {
292 info101->platform_id = PLATFORM_ID_NT; /* unknown */
293 info101->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
294 info101->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
296 info101->server_name = talloc_asprintf_strupper_m(
297 info101, "%s", lp_netbios_name());
298 info101->domain_name = talloc_asprintf_strupper_m(
299 info101, "%s", lp_workgroup());
300 info101->lan_root = "";
305 /*******************************************************************
306 RPC Workstation Service request NetWkstaGetInfo with level 102.
307 Returns to the requester:
308 - As per NetWkstaGetInfo with level 101, plus:
309 - The number of logged in users.
310 Returns a filled in wkssvc_NetWkstaInfo102 struct.
311 ********************************************************************/
313 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
315 struct wkssvc_NetWkstaInfo102 *info102;
318 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
319 if (info102 == NULL) {
323 info102->platform_id = PLATFORM_ID_NT; /* unknown */
324 info102->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
325 info102->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
327 info102->server_name = talloc_asprintf_strupper_m(
328 info102, "%s", lp_netbios_name());
329 info102->domain_name = talloc_asprintf_strupper_m(
330 info102, "%s", lp_workgroup());
331 info102->lan_root = "";
333 users = get_logged_on_userlist(talloc_tos());
334 info102->logged_on_users = talloc_array_length(users);
341 /********************************************************************
342 Handling for RPC Workstation Service request NetWkstaGetInfo
343 ********************************************************************/
345 WERROR _wkssvc_NetWkstaGetInfo(struct pipes_struct *p,
346 struct wkssvc_NetWkstaGetInfo *r)
348 struct dom_sid_buf buf;
350 switch (r->in.level) {
352 /* Level 100 can be allowed from anyone including anonymous
353 * so no access checks are needed for this case */
354 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
355 if (r->out.info->info100 == NULL) {
356 return WERR_NOT_ENOUGH_MEMORY;
360 /* Level 101 can be allowed from any logged in user */
361 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
362 p->session_info->security_token)) {
363 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
365 DEBUGADD(3,(" - does not have sid for Authenticated "
368 &global_sid_Authenticated_Users,
370 security_token_debug(DBGC_CLASS, 3,
371 p->session_info->security_token);
372 return WERR_ACCESS_DENIED;
374 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
375 if (r->out.info->info101 == NULL) {
376 return WERR_NOT_ENOUGH_MEMORY;
380 /* Level 102 Should only be allowed from a domain administrator */
381 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
382 p->session_info->security_token)) {
383 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
385 DEBUGADD(3,(" - does not have sid for Administrators "
386 "group %s, sids are:\n",
388 &global_sid_Builtin_Administrators,
390 security_token_debug(DBGC_CLASS, 3,
391 p->session_info->security_token);
392 return WERR_ACCESS_DENIED;
394 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
395 if (r->out.info->info102 == NULL) {
396 return WERR_NOT_ENOUGH_MEMORY;
400 return WERR_INVALID_LEVEL;
406 /********************************************************************
407 ********************************************************************/
409 WERROR _wkssvc_NetWkstaSetInfo(struct pipes_struct *p,
410 struct wkssvc_NetWkstaSetInfo *r)
412 /* FIXME: Add implementation code here */
413 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
414 return WERR_NOT_SUPPORTED;
417 /********************************************************************
418 RPC Workstation Service request NetWkstaEnumUsers with level 0:
419 Returns to the requester:
420 - the user names of the logged in users.
421 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
422 ********************************************************************/
424 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
427 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
431 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
436 users = get_logged_on_userlist(talloc_tos());
437 if (users == NULL && errno != 0) {
438 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
439 errno, strerror(errno)));
444 num_users = talloc_array_length(users);
445 ctr0->entries_read = num_users;
446 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
448 if (ctr0->user0 == NULL) {
454 for (i=0; i<num_users; i++) {
455 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
461 /********************************************************************
462 RPC Workstation Service request NetWkstaEnumUsers with level 1.
463 Returns to the requester:
464 - the user names of the logged in users,
465 - the domain or machine each is logged into,
466 - the password server that was used to authenticate each,
467 - other domains each user is logged into (not currently supported).
468 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
469 ********************************************************************/
471 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
474 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
476 struct dom_usr *dom_users;
477 const char *pwd_server;
479 int i, j, num_users, num_dom_users;
481 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
486 users = get_logged_on_userlist(talloc_tos());
487 if (users == NULL && errno != 0) {
488 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
489 errno, strerror(errno)));
493 num_users = talloc_array_length(users);
495 dom_users = get_domain_userlist(talloc_tos());
496 if (dom_users == NULL && errno != 0) {
501 num_dom_users = talloc_array_length(dom_users);
503 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
504 num_users+num_dom_users);
505 if (ctr1->user1 == NULL) {
508 TALLOC_FREE(dom_users);
514 if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_password_server()))) {
515 /* The configured password server is a full DNS name but
516 * for the logon server we need to return just the first
517 * component (machine name) of it in upper-case */
518 char *p = strchr(pwd_tmp, '.');
522 p = pwd_tmp + strlen(pwd_tmp);
524 while (--p >= pwd_tmp) {
527 pwd_server = pwd_tmp;
530 /* Put in local users first */
531 for (i=0; i<num_users; i++) {
532 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
534 /* For a local user the domain name and logon server are
535 * both returned as the local machine's NetBIOS name */
536 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
537 talloc_asprintf_strupper_m(ctr1->user1, "%s", lp_netbios_name());
539 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */
542 /* Now domain users */
543 for (j=0; j<num_dom_users; j++) {
544 ctr1->user1[i].user_name =
545 talloc_strdup(ctr1->user1, dom_users[j].name);
546 ctr1->user1[i].logon_domain =
547 talloc_strdup(ctr1->user1, dom_users[j].domain);
548 ctr1->user1[i].logon_server = pwd_server;
550 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
553 ctr1->entries_read = i;
556 TALLOC_FREE(dom_users);
560 /********************************************************************
561 Handling for RPC Workstation Service request NetWkstaEnumUsers
562 (a.k.a Windows NetWkstaUserEnum)
563 ********************************************************************/
565 WERROR _wkssvc_NetWkstaEnumUsers(struct pipes_struct *p,
566 struct wkssvc_NetWkstaEnumUsers *r)
568 /* This with any level should only be allowed from a domain administrator */
569 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
570 p->session_info->security_token)) {
571 struct dom_sid_buf buf;
572 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
573 DEBUGADD(3,(" - does not have sid for Administrators group "
576 &global_sid_Builtin_Administrators,
578 security_token_debug(DBGC_CLASS, 3, p->session_info->security_token);
579 return WERR_ACCESS_DENIED;
582 switch (r->in.info->level) {
584 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
585 if (r->out.info->ctr.user0 == NULL) {
586 return WERR_NOT_ENOUGH_MEMORY;
588 r->out.info->level = r->in.info->level;
589 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
590 if (r->out.resume_handle != NULL) {
591 *r->out.resume_handle = 0;
595 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
596 if (r->out.info->ctr.user1 == NULL) {
597 return WERR_NOT_ENOUGH_MEMORY;
599 r->out.info->level = r->in.info->level;
600 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
601 if (r->out.resume_handle != NULL) {
602 *r->out.resume_handle = 0;
606 return WERR_INVALID_LEVEL;
612 /********************************************************************
613 ********************************************************************/
615 WERROR _wkssvc_NetrWkstaUserGetInfo(struct pipes_struct *p,
616 struct wkssvc_NetrWkstaUserGetInfo *r)
618 /* FIXME: Add implementation code here */
619 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
620 return WERR_NOT_SUPPORTED;
623 /********************************************************************
624 ********************************************************************/
626 WERROR _wkssvc_NetrWkstaUserSetInfo(struct pipes_struct *p,
627 struct wkssvc_NetrWkstaUserSetInfo *r)
629 /* FIXME: Add implementation code here */
630 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
631 return WERR_NOT_SUPPORTED;
634 /********************************************************************
635 ********************************************************************/
637 WERROR _wkssvc_NetWkstaTransportEnum(struct pipes_struct *p,
638 struct wkssvc_NetWkstaTransportEnum *r)
640 /* FIXME: Add implementation code here */
641 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
642 return WERR_NOT_SUPPORTED;
645 /********************************************************************
646 ********************************************************************/
648 WERROR _wkssvc_NetrWkstaTransportAdd(struct pipes_struct *p,
649 struct wkssvc_NetrWkstaTransportAdd *r)
651 /* FIXME: Add implementation code here */
652 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
653 return WERR_NOT_SUPPORTED;
656 /********************************************************************
657 ********************************************************************/
659 WERROR _wkssvc_NetrWkstaTransportDel(struct pipes_struct *p,
660 struct wkssvc_NetrWkstaTransportDel *r)
662 /* FIXME: Add implementation code here */
663 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
664 return WERR_NOT_SUPPORTED;
667 /********************************************************************
668 ********************************************************************/
670 WERROR _wkssvc_NetrUseAdd(struct pipes_struct *p,
671 struct wkssvc_NetrUseAdd *r)
673 /* FIXME: Add implementation code here */
674 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
675 return WERR_NOT_SUPPORTED;
678 /********************************************************************
679 ********************************************************************/
681 WERROR _wkssvc_NetrUseGetInfo(struct pipes_struct *p,
682 struct wkssvc_NetrUseGetInfo *r)
684 /* FIXME: Add implementation code here */
685 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
686 return WERR_NOT_SUPPORTED;
689 /********************************************************************
690 ********************************************************************/
692 WERROR _wkssvc_NetrUseDel(struct pipes_struct *p,
693 struct wkssvc_NetrUseDel *r)
695 /* FIXME: Add implementation code here */
696 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
697 return WERR_NOT_SUPPORTED;
700 /********************************************************************
701 ********************************************************************/
703 WERROR _wkssvc_NetrUseEnum(struct pipes_struct *p,
704 struct wkssvc_NetrUseEnum *r)
706 /* FIXME: Add implementation code here */
707 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
708 return WERR_NOT_SUPPORTED;
711 /********************************************************************
712 ********************************************************************/
714 WERROR _wkssvc_NetrMessageBufferSend(struct pipes_struct *p,
715 struct wkssvc_NetrMessageBufferSend *r)
717 /* FIXME: Add implementation code here */
718 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
719 return WERR_NOT_SUPPORTED;
722 /********************************************************************
723 ********************************************************************/
725 WERROR _wkssvc_NetrWorkstationStatisticsGet(struct pipes_struct *p,
726 struct wkssvc_NetrWorkstationStatisticsGet *r)
728 /* FIXME: Add implementation code here */
729 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
730 return WERR_NOT_SUPPORTED;
733 /********************************************************************
734 ********************************************************************/
736 WERROR _wkssvc_NetrLogonDomainNameAdd(struct pipes_struct *p,
737 struct wkssvc_NetrLogonDomainNameAdd *r)
739 /* FIXME: Add implementation code here */
740 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
741 return WERR_NOT_SUPPORTED;
744 /********************************************************************
745 ********************************************************************/
747 WERROR _wkssvc_NetrLogonDomainNameDel(struct pipes_struct *p,
748 struct wkssvc_NetrLogonDomainNameDel *r)
750 /* FIXME: Add implementation code here */
751 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
752 return WERR_NOT_SUPPORTED;
755 /********************************************************************
756 ********************************************************************/
758 WERROR _wkssvc_NetrJoinDomain(struct pipes_struct *p,
759 struct wkssvc_NetrJoinDomain *r)
761 /* FIXME: Add implementation code here */
762 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
763 return WERR_NOT_SUPPORTED;
766 /********************************************************************
767 ********************************************************************/
769 WERROR _wkssvc_NetrUnjoinDomain(struct pipes_struct *p,
770 struct wkssvc_NetrUnjoinDomain *r)
772 /* FIXME: Add implementation code here */
773 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
774 return WERR_NOT_SUPPORTED;
777 /********************************************************************
778 ********************************************************************/
780 WERROR _wkssvc_NetrRenameMachineInDomain(struct pipes_struct *p,
781 struct wkssvc_NetrRenameMachineInDomain *r)
783 /* FIXME: Add implementation code here */
784 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
785 return WERR_NOT_SUPPORTED;
788 /********************************************************************
789 ********************************************************************/
791 WERROR _wkssvc_NetrValidateName(struct pipes_struct *p,
792 struct wkssvc_NetrValidateName *r)
794 /* FIXME: Add implementation code here */
795 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
796 return WERR_NOT_SUPPORTED;
799 /********************************************************************
800 ********************************************************************/
802 WERROR _wkssvc_NetrGetJoinInformation(struct pipes_struct *p,
803 struct wkssvc_NetrGetJoinInformation *r)
805 /* FIXME: Add implementation code here */
806 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
807 return WERR_NOT_SUPPORTED;
810 /********************************************************************
811 ********************************************************************/
813 WERROR _wkssvc_NetrGetJoinableOus(struct pipes_struct *p,
814 struct wkssvc_NetrGetJoinableOus *r)
816 /* FIXME: Add implementation code here */
817 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
818 return WERR_NOT_SUPPORTED;
821 /********************************************************************
822 _wkssvc_NetrJoinDomain2
823 ********************************************************************/
825 WERROR _wkssvc_NetrJoinDomain2(struct pipes_struct *p,
826 struct wkssvc_NetrJoinDomain2 *r)
828 struct libnet_JoinCtx *j = NULL;
829 char *cleartext_pwd = NULL;
830 char *admin_domain = NULL;
831 char *admin_account = NULL;
833 struct security_token *token = p->session_info->security_token;
835 DATA_BLOB session_key;
838 if (!r->in.domain_name) {
839 return WERR_INVALID_PARAMETER;
842 if (!r->in.admin_account || !r->in.encrypted_password) {
843 return WERR_INVALID_PARAMETER;
846 if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
847 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
848 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
849 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
850 "sufficient privileges\n"));
851 return WERR_ACCESS_DENIED;
854 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
855 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
856 return WERR_NOT_SUPPORTED;
859 status = session_extract_session_key(p->session_info,
862 if(!NT_STATUS_IS_OK(status)) {
863 DEBUG(5,("_wkssvc_NetrJoinDomain2: no session key %s\n",
865 return WERR_NO_USER_SESSION_KEY;
868 werr = decode_wkssvc_join_password_buffer(
869 p->mem_ctx, r->in.encrypted_password,
870 &session_key, &cleartext_pwd);
871 if (!W_ERROR_IS_OK(werr)) {
875 ok = split_domain_user(p->mem_ctx,
880 return WERR_NOT_ENOUGH_MEMORY;
883 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
884 if (!W_ERROR_IS_OK(werr)) {
888 j->in.domain_name = r->in.domain_name;
889 j->in.account_ou = r->in.account_ou;
890 j->in.join_flags = r->in.join_flags;
891 j->in.admin_account = admin_account;
892 j->in.admin_password = cleartext_pwd;
894 j->in.modify_config = lp_config_backend_is_registry();
895 j->in.msg_ctx = p->msg_ctx;
898 setenv(KRB5_ENV_CCNAME, "MEMORY:_wkssvc_NetrJoinDomain2", 1);
899 werr = libnet_Join(p->mem_ctx, j);
900 unsetenv(KRB5_ENV_CCNAME);
903 if (!W_ERROR_IS_OK(werr)) {
904 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
905 j->out.error_string ? j->out.error_string :
913 /********************************************************************
914 _wkssvc_NetrUnjoinDomain2
915 ********************************************************************/
917 WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p,
918 struct wkssvc_NetrUnjoinDomain2 *r)
920 struct libnet_UnjoinCtx *u = NULL;
921 char *cleartext_pwd = NULL;
922 char *admin_domain = NULL;
923 char *admin_account = NULL;
925 struct security_token *token = p->session_info->security_token;
927 DATA_BLOB session_key;
930 if (!r->in.account || !r->in.encrypted_password) {
931 return WERR_INVALID_PARAMETER;
934 if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
935 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
936 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
937 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
938 "sufficient privileges\n"));
939 return WERR_ACCESS_DENIED;
942 status = session_extract_session_key(p->session_info,
945 if (!NT_STATUS_IS_OK(status)) {
946 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: no session key %s\n",
948 return WERR_NO_USER_SESSION_KEY;
951 werr = decode_wkssvc_join_password_buffer(
952 p->mem_ctx, r->in.encrypted_password,
953 &session_key, &cleartext_pwd);
954 if (!W_ERROR_IS_OK(werr)) {
958 ok = split_domain_user(p->mem_ctx,
963 return WERR_NOT_ENOUGH_MEMORY;
966 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
967 if (!W_ERROR_IS_OK(werr)) {
971 u->in.domain_name = lp_realm();
972 u->in.unjoin_flags = r->in.unjoin_flags |
973 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
974 u->in.admin_account = admin_account;
975 u->in.admin_password = cleartext_pwd;
977 u->in.modify_config = lp_config_backend_is_registry();
978 u->in.msg_ctx = p->msg_ctx;
981 setenv(KRB5_ENV_CCNAME, "MEMORY:_wkssvc_NetrUnjoinDomain2", 1);
982 werr = libnet_Unjoin(p->mem_ctx, u);
983 unsetenv(KRB5_ENV_CCNAME);
986 if (!W_ERROR_IS_OK(werr)) {
987 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
988 u->out.error_string ? u->out.error_string :
996 /********************************************************************
997 ********************************************************************/
999 WERROR _wkssvc_NetrRenameMachineInDomain2(struct pipes_struct *p,
1000 struct wkssvc_NetrRenameMachineInDomain2 *r)
1002 /* for now just return not supported */
1003 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1004 return WERR_NOT_SUPPORTED;
1007 /********************************************************************
1008 ********************************************************************/
1010 WERROR _wkssvc_NetrValidateName2(struct pipes_struct *p,
1011 struct wkssvc_NetrValidateName2 *r)
1013 /* FIXME: Add implementation code here */
1014 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1015 return WERR_NOT_SUPPORTED;
1018 /********************************************************************
1019 ********************************************************************/
1021 WERROR _wkssvc_NetrGetJoinableOus2(struct pipes_struct *p,
1022 struct wkssvc_NetrGetJoinableOus2 *r)
1024 /* FIXME: Add implementation code here */
1025 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1026 return WERR_NOT_SUPPORTED;
1029 /********************************************************************
1030 ********************************************************************/
1032 WERROR _wkssvc_NetrAddAlternateComputerName(struct pipes_struct *p,
1033 struct wkssvc_NetrAddAlternateComputerName *r)
1035 /* FIXME: Add implementation code here */
1036 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1037 return WERR_NOT_SUPPORTED;
1040 /********************************************************************
1041 ********************************************************************/
1043 WERROR _wkssvc_NetrRemoveAlternateComputerName(struct pipes_struct *p,
1044 struct wkssvc_NetrRemoveAlternateComputerName *r)
1046 /* FIXME: Add implementation code here */
1047 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1048 return WERR_NOT_SUPPORTED;
1051 /********************************************************************
1052 ********************************************************************/
1054 WERROR _wkssvc_NetrSetPrimaryComputername(struct pipes_struct *p,
1055 struct wkssvc_NetrSetPrimaryComputername *r)
1057 /* FIXME: Add implementation code here */
1058 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1059 return WERR_NOT_SUPPORTED;
1062 /********************************************************************
1063 ********************************************************************/
1065 WERROR _wkssvc_NetrEnumerateComputerNames(struct pipes_struct *p,
1066 struct wkssvc_NetrEnumerateComputerNames *r)
1068 /* FIXME: Add implementation code here */
1069 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1070 return WERR_NOT_SUPPORTED;