Revert "s3-libnet: allow to use default krb5 ccache in libnet_Join/libnet_Unjoin."
[Samba.git] / source3 / rpc_server / wkssvc / srv_wkssvc_nt.c
blob0dd89aed36413b472602787531f7c4f241c94b80
1 /*
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. */
25 #include "includes.h"
26 #include "ntdomain.h"
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"
32 #include "session.h"
33 #include "smbd/smbd.h"
34 #include "auth.h"
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_RPC_SRV
39 struct dom_usr {
40 char *name;
41 char *domain;
42 time_t login_time;
45 #ifdef HAVE_GETUTXENT
47 #include <utmpx.h>
49 struct usrinfo {
50 char *name;
51 struct timeval login_time;
54 static int usr_info_cmp(const struct usrinfo *usr1, const struct usrinfo *usr2)
56 /* Called from qsort to compare two users in a usrinfo_t array for
57 * sorting by login time. Return >0 if usr1 login time was later than
58 * usr2 login time, <0 if it was earlier */
59 return timeval_compare(&usr1->login_time, &usr2->login_time);
62 /*******************************************************************
63 Get a list of the names of all users logged into this machine
64 ********************************************************************/
66 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
68 char **users;
69 int i, num_users = 0;
70 struct usrinfo *usr_infos = NULL;
71 struct utmpx *u;
73 while ((u = getutxent()) != NULL) {
74 struct usrinfo *tmp;
75 if (u->ut_type != USER_PROCESS) {
76 continue;
78 for (i = 0; i < num_users; i++) {
79 /* getutxent can return multiple user entries for the
80 * same user, so ignore any dups */
81 if (strcmp(u->ut_user, usr_infos[i].name) == 0) {
82 break;
85 if (i < num_users) {
86 continue;
89 tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
90 num_users+1);
91 if (tmp == NULL) {
92 TALLOC_FREE(tmp);
93 endutxent();
94 return NULL;
96 usr_infos = tmp;
97 usr_infos[num_users].name = talloc_strdup(usr_infos,
98 u->ut_user);
99 if (usr_infos[num_users].name == NULL) {
100 TALLOC_FREE(usr_infos);
101 endutxent();
102 return NULL;
104 usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
105 usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
106 num_users += 1;
109 /* Sort the user list by time, oldest first */
110 TYPESAFE_QSORT(usr_infos, num_users, usr_info_cmp);
112 users = (char**)talloc_array(mem_ctx, char*, num_users);
113 if (users) {
114 for (i = 0; i < num_users; i++) {
115 users[i] = talloc_move(users, &usr_infos[i].name);
118 TALLOC_FREE(usr_infos);
119 endutxent();
120 errno = 0;
121 return users;
124 #else
126 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
128 return NULL;
131 #endif
133 static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
135 /* Called from qsort to compare two domain users in a dom_usr_t array
136 * for sorting by login time. Return >0 if usr1 login time was later
137 * than usr2 login time, <0 if it was earlier */
138 return (usr1->login_time - usr2->login_time);
141 /*******************************************************************
142 Get a list of the names of all users of this machine who are
143 logged into the domain.
145 This should return a list of the users on this machine who are
146 logged into the domain (i.e. have been authenticated by the domain's
147 password server) but that doesn't fit well with the normal Samba
148 scenario where accesses out to the domain are made through smbclient
149 with each such session individually authenticated. So about the best
150 we can do currently is to list sessions of local users connected to
151 this server, which means that to get themself included in the list a
152 local user must create a session to the local samba server by running:
153 smbclient \\\\localhost\\share
155 FIXME: find a better way to get local users logged into the domain
156 in this list.
157 ********************************************************************/
159 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
161 struct sessionid *session_list = NULL;
162 char *machine_name, *p, *nm;
163 const char *sep;
164 struct dom_usr *users, *tmp;
165 int i, num_users, num_sessions;
167 sep = lp_winbind_separator();
168 if (!sep) {
169 sep = "\\";
172 num_sessions = list_sessions(mem_ctx, &session_list);
173 if (num_sessions == 0) {
174 errno = 0;
175 return NULL;
178 users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
179 if (users == NULL) {
180 TALLOC_FREE(session_list);
181 return NULL;
184 for (i=num_users=0; i<num_sessions; i++) {
185 if (!session_list[i].username
186 || !session_list[i].remote_machine) {
187 continue;
189 p = strpbrk(session_list[i].remote_machine, "./");
190 if (p) {
191 *p = '\0';
193 machine_name = talloc_asprintf_strupper_m(
194 users, "%s", session_list[i].remote_machine);
195 if (machine_name == NULL) {
196 DEBUG(10, ("talloc_asprintf failed\n"));
197 continue;
199 if (strcmp(machine_name, global_myname()) == 0) {
200 p = session_list[i].username;
201 nm = strstr(p, sep);
202 if (nm) {
204 * "domain+name" format so split domain and
205 * name components
207 *nm = '\0';
208 nm += strlen(sep);
209 users[num_users].domain =
210 talloc_asprintf_strupper_m(users,
211 "%s", p);
212 users[num_users].name = talloc_strdup(users,
213 nm);
214 } else {
216 * Simple user name so get domain from smb.conf
218 users[num_users].domain =
219 talloc_strdup(users, lp_workgroup());
220 users[num_users].name = talloc_strdup(users,
223 users[num_users].login_time =
224 session_list[i].connect_start;
225 num_users++;
227 TALLOC_FREE(machine_name);
229 TALLOC_FREE(session_list);
231 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
232 if (tmp == NULL) {
233 return NULL;
235 users = tmp;
237 /* Sort the user list by time, oldest first */
238 TYPESAFE_QSORT(users, num_users, dom_user_cmp);
240 errno = 0;
241 return users;
244 /*******************************************************************
245 RPC Workstation Service request NetWkstaGetInfo with level 100.
246 Returns to the requester:
247 - The machine name.
248 - The smb version number
249 - The domain name.
250 Returns a filled in wkssvc_NetWkstaInfo100 struct.
251 ********************************************************************/
253 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
255 struct wkssvc_NetWkstaInfo100 *info100;
257 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
258 if (info100 == NULL) {
259 return NULL;
262 info100->platform_id = PLATFORM_ID_NT; /* unknown */
263 info100->version_major = lp_major_announce_version();
264 info100->version_minor = lp_minor_announce_version();
266 info100->server_name = talloc_asprintf_strupper_m(
267 info100, "%s", global_myname());
268 info100->domain_name = talloc_asprintf_strupper_m(
269 info100, "%s", lp_workgroup());
271 return info100;
274 /*******************************************************************
275 RPC Workstation Service request NetWkstaGetInfo with level 101.
276 Returns to the requester:
277 - As per NetWkstaGetInfo with level 100, plus:
278 - The LANMAN directory path (not currently supported).
279 Returns a filled in wkssvc_NetWkstaInfo101 struct.
280 ********************************************************************/
282 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
284 struct wkssvc_NetWkstaInfo101 *info101;
286 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
287 if (info101 == NULL) {
288 return NULL;
291 info101->platform_id = PLATFORM_ID_NT; /* unknown */
292 info101->version_major = lp_major_announce_version();
293 info101->version_minor = lp_minor_announce_version();
295 info101->server_name = talloc_asprintf_strupper_m(
296 info101, "%s", global_myname());
297 info101->domain_name = talloc_asprintf_strupper_m(
298 info101, "%s", lp_workgroup());
299 info101->lan_root = "";
301 return info101;
304 /*******************************************************************
305 RPC Workstation Service request NetWkstaGetInfo with level 102.
306 Returns to the requester:
307 - As per NetWkstaGetInfo with level 101, plus:
308 - The number of logged in users.
309 Returns a filled in wkssvc_NetWkstaInfo102 struct.
310 ********************************************************************/
312 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
314 struct wkssvc_NetWkstaInfo102 *info102;
315 char **users;
317 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
318 if (info102 == NULL) {
319 return NULL;
322 info102->platform_id = PLATFORM_ID_NT; /* unknown */
323 info102->version_major = lp_major_announce_version();
324 info102->version_minor = lp_minor_announce_version();
326 info102->server_name = talloc_asprintf_strupper_m(
327 info102, "%s", global_myname());
328 info102->domain_name = talloc_asprintf_strupper_m(
329 info102, "%s", lp_workgroup());
330 info102->lan_root = "";
332 users = get_logged_on_userlist(talloc_tos());
333 info102->logged_on_users = talloc_array_length(users);
335 TALLOC_FREE(users);
337 return info102;
340 /********************************************************************
341 Handling for RPC Workstation Service request NetWkstaGetInfo
342 ********************************************************************/
344 WERROR _wkssvc_NetWkstaGetInfo(struct pipes_struct *p,
345 struct wkssvc_NetWkstaGetInfo *r)
347 switch (r->in.level) {
348 case 100:
349 /* Level 100 can be allowed from anyone including anonymous
350 * so no access checks are needed for this case */
351 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
352 if (r->out.info->info100 == NULL) {
353 return WERR_NOMEM;
355 break;
356 case 101:
357 /* Level 101 can be allowed from any logged in user */
358 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
359 p->session_info->security_token)) {
360 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
361 "101\n"));
362 DEBUGADD(3,(" - does not have sid for Authenticated "
363 "Users %s:\n",
364 sid_string_dbg(
365 &global_sid_Authenticated_Users)));
366 security_token_debug(DBGC_CLASS, 3,
367 p->session_info->security_token);
368 return WERR_ACCESS_DENIED;
370 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
371 if (r->out.info->info101 == NULL) {
372 return WERR_NOMEM;
374 break;
375 case 102:
376 /* Level 102 Should only be allowed from a domain administrator */
377 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
378 p->session_info->security_token)) {
379 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
380 "102\n"));
381 DEBUGADD(3,(" - does not have sid for Administrators "
382 "group %s, sids are:\n",
383 sid_string_dbg(&global_sid_Builtin_Administrators)));
384 security_token_debug(DBGC_CLASS, 3,
385 p->session_info->security_token);
386 return WERR_ACCESS_DENIED;
388 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
389 if (r->out.info->info102 == NULL) {
390 return WERR_NOMEM;
392 break;
393 default:
394 return WERR_UNKNOWN_LEVEL;
397 return WERR_OK;
400 /********************************************************************
401 ********************************************************************/
403 WERROR _wkssvc_NetWkstaSetInfo(struct pipes_struct *p,
404 struct wkssvc_NetWkstaSetInfo *r)
406 /* FIXME: Add implementation code here */
407 p->rng_fault_state = True;
408 return WERR_NOT_SUPPORTED;
411 /********************************************************************
412 RPC Workstation Service request NetWkstaEnumUsers with level 0:
413 Returns to the requester:
414 - the user names of the logged in users.
415 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
416 ********************************************************************/
418 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
419 TALLOC_CTX *mem_ctx)
421 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
422 char **users;
423 int i, num_users;
425 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
426 if (ctr0 == NULL) {
427 return NULL;
430 users = get_logged_on_userlist(talloc_tos());
431 if (users == NULL && errno != 0) {
432 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
433 errno, strerror(errno)));
434 TALLOC_FREE(ctr0);
435 return NULL;
438 num_users = talloc_array_length(users);
439 ctr0->entries_read = num_users;
440 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
441 num_users);
442 if (ctr0->user0 == NULL) {
443 TALLOC_FREE(ctr0);
444 TALLOC_FREE(users);
445 return NULL;
448 for (i=0; i<num_users; i++) {
449 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
451 TALLOC_FREE(users);
452 return ctr0;
455 /********************************************************************
456 RPC Workstation Service request NetWkstaEnumUsers with level 1.
457 Returns to the requester:
458 - the user names of the logged in users,
459 - the domain or machine each is logged into,
460 - the password server that was used to authenticate each,
461 - other domains each user is logged into (not currently supported).
462 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
463 ********************************************************************/
465 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
466 TALLOC_CTX *mem_ctx)
468 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
469 char **users;
470 struct dom_usr *dom_users;
471 const char *pwd_server;
472 char *pwd_tmp;
473 int i, j, num_users, num_dom_users;
475 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
476 if (ctr1 == NULL) {
477 return NULL;
480 users = get_logged_on_userlist(talloc_tos());
481 if (users == NULL && errno != 0) {
482 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
483 errno, strerror(errno)));
484 TALLOC_FREE(ctr1);
485 return NULL;
487 num_users = talloc_array_length(users);
489 dom_users = get_domain_userlist(talloc_tos());
490 if (dom_users == NULL && errno != 0) {
491 TALLOC_FREE(ctr1);
492 TALLOC_FREE(users);
493 return NULL;
495 num_dom_users = talloc_array_length(dom_users);
497 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
498 num_users+num_dom_users);
499 if (ctr1->user1 == NULL) {
500 TALLOC_FREE(ctr1);
501 TALLOC_FREE(users);
502 TALLOC_FREE(dom_users);
503 return NULL;
506 pwd_server = "";
508 if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) {
509 /* The configured password server is a full DNS name but
510 * for the logon server we need to return just the first
511 * component (machine name) of it in upper-case */
512 char *p = strchr(pwd_tmp, '.');
513 if (p) {
514 *p = '\0';
515 } else {
516 p = pwd_tmp + strlen(pwd_tmp);
518 while (--p >= pwd_tmp) {
519 *p = toupper(*p);
521 pwd_server = pwd_tmp;
524 /* Put in local users first */
525 for (i=0; i<num_users; i++) {
526 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
528 /* For a local user the domain name and logon server are
529 * both returned as the local machine's NetBIOS name */
530 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
531 talloc_asprintf_strupper_m(ctr1->user1, "%s", global_myname());
533 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */
536 /* Now domain users */
537 for (j=0; j<num_dom_users; j++) {
538 ctr1->user1[i].user_name =
539 talloc_strdup(ctr1->user1, dom_users[j].name);
540 ctr1->user1[i].logon_domain =
541 talloc_strdup(ctr1->user1, dom_users[j].domain);
542 ctr1->user1[i].logon_server = pwd_server;
544 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
547 ctr1->entries_read = i;
549 TALLOC_FREE(users);
550 TALLOC_FREE(dom_users);
551 return ctr1;
554 /********************************************************************
555 Handling for RPC Workstation Service request NetWkstaEnumUsers
556 (a.k.a Windows NetWkstaUserEnum)
557 ********************************************************************/
559 WERROR _wkssvc_NetWkstaEnumUsers(struct pipes_struct *p,
560 struct wkssvc_NetWkstaEnumUsers *r)
562 /* This with any level should only be allowed from a domain administrator */
563 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
564 p->session_info->security_token)) {
565 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
566 DEBUGADD(3,(" - does not have sid for Administrators group "
567 "%s\n", sid_string_dbg(
568 &global_sid_Builtin_Administrators)));
569 security_token_debug(DBGC_CLASS, 3, p->session_info->security_token);
570 return WERR_ACCESS_DENIED;
573 switch (r->in.info->level) {
574 case 0:
575 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
576 if (r->out.info->ctr.user0 == NULL) {
577 return WERR_NOMEM;
579 r->out.info->level = r->in.info->level;
580 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
581 *r->out.resume_handle = 0;
582 break;
583 case 1:
584 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
585 if (r->out.info->ctr.user1 == NULL) {
586 return WERR_NOMEM;
588 r->out.info->level = r->in.info->level;
589 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
590 *r->out.resume_handle = 0;
591 break;
592 default:
593 return WERR_UNKNOWN_LEVEL;
596 return WERR_OK;
599 /********************************************************************
600 ********************************************************************/
602 WERROR _wkssvc_NetrWkstaUserGetInfo(struct pipes_struct *p,
603 struct wkssvc_NetrWkstaUserGetInfo *r)
605 /* FIXME: Add implementation code here */
606 p->rng_fault_state = True;
607 return WERR_NOT_SUPPORTED;
610 /********************************************************************
611 ********************************************************************/
613 WERROR _wkssvc_NetrWkstaUserSetInfo(struct pipes_struct *p,
614 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(struct pipes_struct *p,
625 struct wkssvc_NetWkstaTransportEnum *r)
627 /* FIXME: Add implementation code here */
628 p->rng_fault_state = True;
629 return WERR_NOT_SUPPORTED;
632 /********************************************************************
633 ********************************************************************/
635 WERROR _wkssvc_NetrWkstaTransportAdd(struct pipes_struct *p,
636 struct wkssvc_NetrWkstaTransportAdd *r)
638 /* FIXME: Add implementation code here */
639 p->rng_fault_state = True;
640 return WERR_NOT_SUPPORTED;
643 /********************************************************************
644 ********************************************************************/
646 WERROR _wkssvc_NetrWkstaTransportDel(struct pipes_struct *p,
647 struct wkssvc_NetrWkstaTransportDel *r)
649 /* FIXME: Add implementation code here */
650 p->rng_fault_state = True;
651 return WERR_NOT_SUPPORTED;
654 /********************************************************************
655 ********************************************************************/
657 WERROR _wkssvc_NetrUseAdd(struct pipes_struct *p,
658 struct wkssvc_NetrUseAdd *r)
660 /* FIXME: Add implementation code here */
661 p->rng_fault_state = True;
662 return WERR_NOT_SUPPORTED;
665 /********************************************************************
666 ********************************************************************/
668 WERROR _wkssvc_NetrUseGetInfo(struct pipes_struct *p,
669 struct wkssvc_NetrUseGetInfo *r)
671 /* FIXME: Add implementation code here */
672 p->rng_fault_state = True;
673 return WERR_NOT_SUPPORTED;
676 /********************************************************************
677 ********************************************************************/
679 WERROR _wkssvc_NetrUseDel(struct pipes_struct *p,
680 struct wkssvc_NetrUseDel *r)
682 /* FIXME: Add implementation code here */
683 p->rng_fault_state = True;
684 return WERR_NOT_SUPPORTED;
687 /********************************************************************
688 ********************************************************************/
690 WERROR _wkssvc_NetrUseEnum(struct pipes_struct *p,
691 struct wkssvc_NetrUseEnum *r)
693 /* FIXME: Add implementation code here */
694 p->rng_fault_state = True;
695 return WERR_NOT_SUPPORTED;
698 /********************************************************************
699 ********************************************************************/
701 WERROR _wkssvc_NetrMessageBufferSend(struct pipes_struct *p,
702 struct wkssvc_NetrMessageBufferSend *r)
704 /* FIXME: Add implementation code here */
705 p->rng_fault_state = True;
706 return WERR_NOT_SUPPORTED;
709 /********************************************************************
710 ********************************************************************/
712 WERROR _wkssvc_NetrWorkstationStatisticsGet(struct pipes_struct *p,
713 struct wkssvc_NetrWorkstationStatisticsGet *r)
715 /* FIXME: Add implementation code here */
716 p->rng_fault_state = True;
717 return WERR_NOT_SUPPORTED;
720 /********************************************************************
721 ********************************************************************/
723 WERROR _wkssvc_NetrLogonDomainNameAdd(struct pipes_struct *p,
724 struct wkssvc_NetrLogonDomainNameAdd *r)
726 /* FIXME: Add implementation code here */
727 p->rng_fault_state = True;
728 return WERR_NOT_SUPPORTED;
731 /********************************************************************
732 ********************************************************************/
734 WERROR _wkssvc_NetrLogonDomainNameDel(struct pipes_struct *p,
735 struct wkssvc_NetrLogonDomainNameDel *r)
737 /* FIXME: Add implementation code here */
738 p->rng_fault_state = True;
739 return WERR_NOT_SUPPORTED;
742 /********************************************************************
743 ********************************************************************/
745 WERROR _wkssvc_NetrJoinDomain(struct pipes_struct *p,
746 struct wkssvc_NetrJoinDomain *r)
748 /* FIXME: Add implementation code here */
749 p->rng_fault_state = True;
750 return WERR_NOT_SUPPORTED;
753 /********************************************************************
754 ********************************************************************/
756 WERROR _wkssvc_NetrUnjoinDomain(struct pipes_struct *p,
757 struct wkssvc_NetrUnjoinDomain *r)
759 /* FIXME: Add implementation code here */
760 p->rng_fault_state = True;
761 return WERR_NOT_SUPPORTED;
764 /********************************************************************
765 ********************************************************************/
767 WERROR _wkssvc_NetrRenameMachineInDomain(struct pipes_struct *p,
768 struct wkssvc_NetrRenameMachineInDomain *r)
770 /* FIXME: Add implementation code here */
771 p->rng_fault_state = True;
772 return WERR_NOT_SUPPORTED;
775 /********************************************************************
776 ********************************************************************/
778 WERROR _wkssvc_NetrValidateName(struct pipes_struct *p,
779 struct wkssvc_NetrValidateName *r)
781 /* FIXME: Add implementation code here */
782 p->rng_fault_state = True;
783 return WERR_NOT_SUPPORTED;
786 /********************************************************************
787 ********************************************************************/
789 WERROR _wkssvc_NetrGetJoinInformation(struct pipes_struct *p,
790 struct wkssvc_NetrGetJoinInformation *r)
792 /* FIXME: Add implementation code here */
793 p->rng_fault_state = True;
794 return WERR_NOT_SUPPORTED;
797 /********************************************************************
798 ********************************************************************/
800 WERROR _wkssvc_NetrGetJoinableOus(struct pipes_struct *p,
801 struct wkssvc_NetrGetJoinableOus *r)
803 /* FIXME: Add implementation code here */
804 p->rng_fault_state = True;
805 return WERR_NOT_SUPPORTED;
808 /********************************************************************
809 _wkssvc_NetrJoinDomain2
810 ********************************************************************/
812 WERROR _wkssvc_NetrJoinDomain2(struct pipes_struct *p,
813 struct wkssvc_NetrJoinDomain2 *r)
815 struct libnet_JoinCtx *j = NULL;
816 char *cleartext_pwd = NULL;
817 char *admin_domain = NULL;
818 char *admin_account = NULL;
819 WERROR werr;
820 struct security_token *token = p->session_info->security_token;
822 if (!r->in.domain_name) {
823 return WERR_INVALID_PARAM;
826 if (!r->in.admin_account || !r->in.encrypted_password) {
827 return WERR_INVALID_PARAM;
830 if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
831 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
832 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
833 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
834 "sufficient privileges\n"));
835 return WERR_ACCESS_DENIED;
838 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
839 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
840 return WERR_NOT_SUPPORTED;
843 werr = decode_wkssvc_join_password_buffer(
844 p->mem_ctx, r->in.encrypted_password,
845 &p->session_info->user_session_key, &cleartext_pwd);
846 if (!W_ERROR_IS_OK(werr)) {
847 return werr;
850 split_domain_user(p->mem_ctx,
851 r->in.admin_account,
852 &admin_domain,
853 &admin_account);
855 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
856 if (!W_ERROR_IS_OK(werr)) {
857 return werr;
860 j->in.domain_name = r->in.domain_name;
861 j->in.account_ou = r->in.account_ou;
862 j->in.join_flags = r->in.join_flags;
863 j->in.admin_account = admin_account;
864 j->in.admin_password = cleartext_pwd;
865 j->in.debug = true;
866 j->in.modify_config = lp_config_backend_is_registry();
867 j->in.msg_ctx = p->msg_ctx;
869 become_root();
870 werr = libnet_Join(p->mem_ctx, j);
871 unbecome_root();
873 if (!W_ERROR_IS_OK(werr)) {
874 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
875 j->out.error_string ? j->out.error_string :
876 win_errstr(werr)));
879 TALLOC_FREE(j);
880 return werr;
883 /********************************************************************
884 _wkssvc_NetrUnjoinDomain2
885 ********************************************************************/
887 WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p,
888 struct wkssvc_NetrUnjoinDomain2 *r)
890 struct libnet_UnjoinCtx *u = NULL;
891 char *cleartext_pwd = NULL;
892 char *admin_domain = NULL;
893 char *admin_account = NULL;
894 WERROR werr;
895 struct security_token *token = p->session_info->security_token;
897 if (!r->in.account || !r->in.encrypted_password) {
898 return WERR_INVALID_PARAM;
901 if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
902 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
903 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
904 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
905 "sufficient privileges\n"));
906 return WERR_ACCESS_DENIED;
909 werr = decode_wkssvc_join_password_buffer(
910 p->mem_ctx, r->in.encrypted_password,
911 &p->session_info->user_session_key, &cleartext_pwd);
912 if (!W_ERROR_IS_OK(werr)) {
913 return werr;
916 split_domain_user(p->mem_ctx,
917 r->in.account,
918 &admin_domain,
919 &admin_account);
921 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
922 if (!W_ERROR_IS_OK(werr)) {
923 return werr;
926 u->in.domain_name = lp_realm();
927 u->in.unjoin_flags = r->in.unjoin_flags |
928 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
929 u->in.admin_account = admin_account;
930 u->in.admin_password = cleartext_pwd;
931 u->in.debug = true;
932 u->in.modify_config = lp_config_backend_is_registry();
933 u->in.msg_ctx = p->msg_ctx;
935 become_root();
936 werr = libnet_Unjoin(p->mem_ctx, u);
937 unbecome_root();
939 if (!W_ERROR_IS_OK(werr)) {
940 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
941 u->out.error_string ? u->out.error_string :
942 win_errstr(werr)));
945 TALLOC_FREE(u);
946 return werr;
949 /********************************************************************
950 ********************************************************************/
952 WERROR _wkssvc_NetrRenameMachineInDomain2(struct pipes_struct *p,
953 struct wkssvc_NetrRenameMachineInDomain2 *r)
955 /* for now just return not supported */
956 return WERR_NOT_SUPPORTED;
959 /********************************************************************
960 ********************************************************************/
962 WERROR _wkssvc_NetrValidateName2(struct pipes_struct *p,
963 struct wkssvc_NetrValidateName2 *r)
965 /* FIXME: Add implementation code here */
966 p->rng_fault_state = True;
967 return WERR_NOT_SUPPORTED;
970 /********************************************************************
971 ********************************************************************/
973 WERROR _wkssvc_NetrGetJoinableOus2(struct pipes_struct *p,
974 struct wkssvc_NetrGetJoinableOus2 *r)
976 /* FIXME: Add implementation code here */
977 p->rng_fault_state = True;
978 return WERR_NOT_SUPPORTED;
981 /********************************************************************
982 ********************************************************************/
984 WERROR _wkssvc_NetrAddAlternateComputerName(struct pipes_struct *p,
985 struct wkssvc_NetrAddAlternateComputerName *r)
987 /* FIXME: Add implementation code here */
988 p->rng_fault_state = True;
989 return WERR_NOT_SUPPORTED;
992 /********************************************************************
993 ********************************************************************/
995 WERROR _wkssvc_NetrRemoveAlternateComputerName(struct pipes_struct *p,
996 struct wkssvc_NetrRemoveAlternateComputerName *r)
998 /* FIXME: Add implementation code here */
999 p->rng_fault_state = True;
1000 return WERR_NOT_SUPPORTED;
1003 /********************************************************************
1004 ********************************************************************/
1006 WERROR _wkssvc_NetrSetPrimaryComputername(struct pipes_struct *p,
1007 struct wkssvc_NetrSetPrimaryComputername *r)
1009 /* FIXME: Add implementation code here */
1010 p->rng_fault_state = True;
1011 return WERR_NOT_SUPPORTED;
1014 /********************************************************************
1015 ********************************************************************/
1017 WERROR _wkssvc_NetrEnumerateComputerNames(struct pipes_struct *p,
1018 struct wkssvc_NetrEnumerateComputerNames *r)
1020 /* FIXME: Add implementation code here */
1021 p->rng_fault_state = True;
1022 return WERR_NOT_SUPPORTED;