s3-wkssvc: Use struct pipes_struct.
[Samba/gbeck.git] / source3 / rpc_server / srv_wkssvc_nt.c
blob200a02bc215c2f3f0c37419d8c4e2017cae4282d
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 "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"
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
34 struct dom_usr {
35 char *name;
36 char *domain;
37 time_t login_time;
40 #ifdef HAVE_GETUTXENT
42 #include <utmpx.h>
44 struct usrinfo {
45 char *name;
46 struct timeval login_time;
49 static int usr_info_cmp(const struct usrinfo *usr1, const struct usrinfo *usr2)
51 /* Called from qsort to compare two users in a usrinfo_t array for
52 * sorting by login time. Return >0 if usr1 login time was later than
53 * usr2 login time, <0 if it was earlier */
54 return timeval_compare(&usr1->login_time, &usr2->login_time);
57 /*******************************************************************
58 Get a list of the names of all users logged into this machine
59 ********************************************************************/
61 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
63 char **users;
64 int i, num_users = 0;
65 struct usrinfo *usr_infos = NULL;
66 struct utmpx *u;
68 while ((u = getutxent()) != NULL) {
69 struct usrinfo *tmp;
70 if (u->ut_type != USER_PROCESS) {
71 continue;
73 for (i = 0; i < num_users; i++) {
74 /* getutxent can return multiple user entries for the
75 * same user, so ignore any dups */
76 if (strcmp(u->ut_user, usr_infos[i].name) == 0) {
77 break;
80 if (i < num_users) {
81 continue;
84 tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
85 num_users+1);
86 if (tmp == NULL) {
87 TALLOC_FREE(tmp);
88 endutxent();
89 return NULL;
91 usr_infos = tmp;
92 usr_infos[num_users].name = talloc_strdup(usr_infos,
93 u->ut_user);
94 if (usr_infos[num_users].name == NULL) {
95 TALLOC_FREE(usr_infos);
96 endutxent();
97 return NULL;
99 usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
100 usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
101 num_users += 1;
104 /* Sort the user list by time, oldest first */
105 TYPESAFE_QSORT(usr_infos, num_users, usr_info_cmp);
107 users = (char**)talloc_array(mem_ctx, char*, num_users);
108 if (users) {
109 for (i = 0; i < num_users; i++) {
110 users[i] = talloc_move(users, &usr_infos[i].name);
113 TALLOC_FREE(usr_infos);
114 endutxent();
115 errno = 0;
116 return users;
119 #else
121 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
123 return NULL;
126 #endif
128 static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
130 /* Called from qsort to compare two domain users in a dom_usr_t array
131 * for sorting by login time. Return >0 if usr1 login time was later
132 * than usr2 login time, <0 if it was earlier */
133 return (usr1->login_time - usr2->login_time);
136 /*******************************************************************
137 Get a list of the names of all users of this machine who are
138 logged into the domain.
140 This should return a list of the users on this machine who are
141 logged into the domain (i.e. have been authenticated by the domain's
142 password server) but that doesn't fit well with the normal Samba
143 scenario where accesses out to the domain are made through smbclient
144 with each such session individually authenticated. So about the best
145 we can do currently is to list sessions of local users connected to
146 this server, which means that to get themself included in the list a
147 local user must create a session to the local samba server by running:
148 smbclient \\\\localhost\\share
150 FIXME: find a better way to get local users logged into the domain
151 in this list.
152 ********************************************************************/
154 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
156 struct sessionid *session_list = NULL;
157 char *machine_name, *p, *nm;
158 const char *sep;
159 struct dom_usr *users, *tmp;
160 int i, num_users, num_sessions;
162 sep = lp_winbind_separator();
163 if (!sep) {
164 sep = "\\";
167 num_sessions = list_sessions(mem_ctx, &session_list);
168 if (num_sessions == 0) {
169 errno = 0;
170 return NULL;
173 users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
174 if (users == NULL) {
175 TALLOC_FREE(session_list);
176 return NULL;
179 for (i=num_users=0; i<num_sessions; i++) {
180 if (!session_list[i].username
181 || !session_list[i].remote_machine) {
182 continue;
184 p = strpbrk(session_list[i].remote_machine, "./");
185 if (p) {
186 *p = '\0';
188 machine_name = talloc_asprintf_strupper_m(
189 users, "%s", session_list[i].remote_machine);
190 if (machine_name == NULL) {
191 DEBUG(10, ("talloc_asprintf failed\n"));
192 continue;
194 if (strcmp(machine_name, global_myname()) == 0) {
195 p = session_list[i].username;
196 nm = strstr(p, sep);
197 if (nm) {
199 * "domain+name" format so split domain and
200 * name components
202 *nm = '\0';
203 nm += strlen(sep);
204 users[num_users].domain =
205 talloc_asprintf_strupper_m(users,
206 "%s", p);
207 users[num_users].name = talloc_strdup(users,
208 nm);
209 } else {
211 * Simple user name so get domain from smb.conf
213 users[num_users].domain =
214 talloc_strdup(users, lp_workgroup());
215 users[num_users].name = talloc_strdup(users,
218 users[num_users].login_time =
219 session_list[i].connect_start;
220 num_users++;
222 TALLOC_FREE(machine_name);
224 TALLOC_FREE(session_list);
226 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
227 if (tmp == NULL) {
228 return NULL;
230 users = tmp;
232 /* Sort the user list by time, oldest first */
233 TYPESAFE_QSORT(users, num_users, dom_user_cmp);
235 errno = 0;
236 return users;
239 /*******************************************************************
240 RPC Workstation Service request NetWkstaGetInfo with level 100.
241 Returns to the requester:
242 - The machine name.
243 - The smb version number
244 - The domain name.
245 Returns a filled in wkssvc_NetWkstaInfo100 struct.
246 ********************************************************************/
248 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
250 struct wkssvc_NetWkstaInfo100 *info100;
252 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
253 if (info100 == NULL) {
254 return NULL;
257 info100->platform_id = PLATFORM_ID_NT; /* unknown */
258 info100->version_major = lp_major_announce_version();
259 info100->version_minor = lp_minor_announce_version();
261 info100->server_name = talloc_asprintf_strupper_m(
262 info100, "%s", global_myname());
263 info100->domain_name = talloc_asprintf_strupper_m(
264 info100, "%s", lp_workgroup());
266 return info100;
269 /*******************************************************************
270 RPC Workstation Service request NetWkstaGetInfo with level 101.
271 Returns to the requester:
272 - As per NetWkstaGetInfo with level 100, plus:
273 - The LANMAN directory path (not currently supported).
274 Returns a filled in wkssvc_NetWkstaInfo101 struct.
275 ********************************************************************/
277 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
279 struct wkssvc_NetWkstaInfo101 *info101;
281 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
282 if (info101 == NULL) {
283 return NULL;
286 info101->platform_id = PLATFORM_ID_NT; /* unknown */
287 info101->version_major = lp_major_announce_version();
288 info101->version_minor = lp_minor_announce_version();
290 info101->server_name = talloc_asprintf_strupper_m(
291 info101, "%s", global_myname());
292 info101->domain_name = talloc_asprintf_strupper_m(
293 info101, "%s", lp_workgroup());
294 info101->lan_root = "";
296 return info101;
299 /*******************************************************************
300 RPC Workstation Service request NetWkstaGetInfo with level 102.
301 Returns to the requester:
302 - As per NetWkstaGetInfo with level 101, plus:
303 - The number of logged in users.
304 Returns a filled in wkssvc_NetWkstaInfo102 struct.
305 ********************************************************************/
307 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
309 struct wkssvc_NetWkstaInfo102 *info102;
310 char **users;
312 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
313 if (info102 == NULL) {
314 return NULL;
317 info102->platform_id = PLATFORM_ID_NT; /* unknown */
318 info102->version_major = lp_major_announce_version();
319 info102->version_minor = lp_minor_announce_version();
321 info102->server_name = talloc_asprintf_strupper_m(
322 info102, "%s", global_myname());
323 info102->domain_name = talloc_asprintf_strupper_m(
324 info102, "%s", lp_workgroup());
325 info102->lan_root = "";
327 users = get_logged_on_userlist(talloc_tos());
328 info102->logged_on_users = talloc_array_length(users);
330 TALLOC_FREE(users);
332 return info102;
335 /********************************************************************
336 Handling for RPC Workstation Service request NetWkstaGetInfo
337 ********************************************************************/
339 WERROR _wkssvc_NetWkstaGetInfo(struct pipes_struct *p,
340 struct wkssvc_NetWkstaGetInfo *r)
342 switch (r->in.level) {
343 case 100:
344 /* Level 100 can be allowed from anyone including anonymous
345 * so no access checks are needed for this case */
346 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
347 if (r->out.info->info100 == NULL) {
348 return WERR_NOMEM;
350 break;
351 case 101:
352 /* Level 101 can be allowed from any logged in user */
353 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
354 p->server_info->ptok)) {
355 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
356 "101\n"));
357 DEBUGADD(3,(" - does not have sid for Authenticated "
358 "Users %s:\n",
359 sid_string_dbg(
360 &global_sid_Authenticated_Users)));
361 debug_nt_user_token(DBGC_CLASS, 3,
362 p->server_info->ptok);
363 return WERR_ACCESS_DENIED;
365 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
366 if (r->out.info->info101 == NULL) {
367 return WERR_NOMEM;
369 break;
370 case 102:
371 /* Level 102 Should only be allowed from a domain administrator */
372 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
373 p->server_info->ptok)) {
374 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
375 "102\n"));
376 DEBUGADD(3,(" - does not have sid for Administrators "
377 "group %s, sids are:\n",
378 sid_string_dbg(&global_sid_Builtin_Administrators)));
379 debug_nt_user_token(DBGC_CLASS, 3,
380 p->server_info->ptok);
381 return WERR_ACCESS_DENIED;
383 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
384 if (r->out.info->info102 == NULL) {
385 return WERR_NOMEM;
387 break;
388 default:
389 return WERR_UNKNOWN_LEVEL;
392 return WERR_OK;
395 /********************************************************************
396 ********************************************************************/
398 WERROR _wkssvc_NetWkstaSetInfo(struct pipes_struct *p,
399 struct wkssvc_NetWkstaSetInfo *r)
401 /* FIXME: Add implementation code here */
402 p->rng_fault_state = True;
403 return WERR_NOT_SUPPORTED;
406 /********************************************************************
407 RPC Workstation Service request NetWkstaEnumUsers with level 0:
408 Returns to the requester:
409 - the user names of the logged in users.
410 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
411 ********************************************************************/
413 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
414 TALLOC_CTX *mem_ctx)
416 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
417 char **users;
418 int i, num_users;
420 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
421 if (ctr0 == NULL) {
422 return NULL;
425 users = get_logged_on_userlist(talloc_tos());
426 if (users == NULL && errno != 0) {
427 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
428 errno, strerror(errno)));
429 TALLOC_FREE(ctr0);
430 return NULL;
433 num_users = talloc_array_length(users);
434 ctr0->entries_read = num_users;
435 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
436 num_users);
437 if (ctr0->user0 == NULL) {
438 TALLOC_FREE(ctr0);
439 TALLOC_FREE(users);
440 return NULL;
443 for (i=0; i<num_users; i++) {
444 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
446 TALLOC_FREE(users);
447 return ctr0;
450 /********************************************************************
451 RPC Workstation Service request NetWkstaEnumUsers with level 1.
452 Returns to the requester:
453 - the user names of the logged in users,
454 - the domain or machine each is logged into,
455 - the password server that was used to authenticate each,
456 - other domains each user is logged into (not currently supported).
457 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
458 ********************************************************************/
460 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
461 TALLOC_CTX *mem_ctx)
463 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
464 char **users;
465 struct dom_usr *dom_users;
466 const char *pwd_server;
467 char *pwd_tmp;
468 int i, j, num_users, num_dom_users;
470 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
471 if (ctr1 == NULL) {
472 return NULL;
475 users = get_logged_on_userlist(talloc_tos());
476 if (users == NULL && errno != 0) {
477 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
478 errno, strerror(errno)));
479 TALLOC_FREE(ctr1);
480 return NULL;
482 num_users = talloc_array_length(users);
484 dom_users = get_domain_userlist(talloc_tos());
485 if (dom_users == NULL && errno != 0) {
486 TALLOC_FREE(ctr1);
487 TALLOC_FREE(users);
488 return NULL;
490 num_dom_users = talloc_array_length(dom_users);
492 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
493 num_users+num_dom_users);
494 if (ctr1->user1 == NULL) {
495 TALLOC_FREE(ctr1);
496 TALLOC_FREE(users);
497 TALLOC_FREE(dom_users);
498 return NULL;
501 pwd_server = "";
503 if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) {
504 /* The configured password server is a full DNS name but
505 * for the logon server we need to return just the first
506 * component (machine name) of it in upper-case */
507 char *p = strchr(pwd_tmp, '.');
508 if (p) {
509 *p = '\0';
510 } else {
511 p = pwd_tmp + strlen(pwd_tmp);
513 while (--p >= pwd_tmp) {
514 *p = toupper(*p);
516 pwd_server = pwd_tmp;
519 /* Put in local users first */
520 for (i=0; i<num_users; i++) {
521 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
523 /* For a local user the domain name and logon server are
524 * both returned as the local machine's NetBIOS name */
525 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
526 talloc_asprintf_strupper_m(ctr1->user1, "%s", global_myname());
528 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */
531 /* Now domain users */
532 for (j=0; j<num_dom_users; j++) {
533 ctr1->user1[i].user_name =
534 talloc_strdup(ctr1->user1, dom_users[j].name);
535 ctr1->user1[i].logon_domain =
536 talloc_strdup(ctr1->user1, dom_users[j].domain);
537 ctr1->user1[i].logon_server = pwd_server;
539 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
542 ctr1->entries_read = i;
544 TALLOC_FREE(users);
545 TALLOC_FREE(dom_users);
546 return ctr1;
549 /********************************************************************
550 Handling for RPC Workstation Service request NetWkstaEnumUsers
551 (a.k.a Windows NetWkstaUserEnum)
552 ********************************************************************/
554 WERROR _wkssvc_NetWkstaEnumUsers(struct pipes_struct *p,
555 struct wkssvc_NetWkstaEnumUsers *r)
557 /* This with any level should only be allowed from a domain administrator */
558 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
559 p->server_info->ptok)) {
560 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
561 DEBUGADD(3,(" - does not have sid for Administrators group "
562 "%s\n", sid_string_dbg(
563 &global_sid_Builtin_Administrators)));
564 debug_nt_user_token(DBGC_CLASS, 3, p->server_info->ptok);
565 return WERR_ACCESS_DENIED;
568 switch (r->in.info->level) {
569 case 0:
570 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
571 if (r->out.info->ctr.user0 == NULL) {
572 return WERR_NOMEM;
574 r->out.info->level = r->in.info->level;
575 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
576 *r->out.resume_handle = 0;
577 break;
578 case 1:
579 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
580 if (r->out.info->ctr.user1 == NULL) {
581 return WERR_NOMEM;
583 r->out.info->level = r->in.info->level;
584 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
585 *r->out.resume_handle = 0;
586 break;
587 default:
588 return WERR_UNKNOWN_LEVEL;
591 return WERR_OK;
594 /********************************************************************
595 ********************************************************************/
597 WERROR _wkssvc_NetrWkstaUserGetInfo(struct pipes_struct *p,
598 struct wkssvc_NetrWkstaUserGetInfo *r)
600 /* FIXME: Add implementation code here */
601 p->rng_fault_state = True;
602 return WERR_NOT_SUPPORTED;
605 /********************************************************************
606 ********************************************************************/
608 WERROR _wkssvc_NetrWkstaUserSetInfo(struct pipes_struct *p,
609 struct wkssvc_NetrWkstaUserSetInfo *r)
611 /* FIXME: Add implementation code here */
612 p->rng_fault_state = True;
613 return WERR_NOT_SUPPORTED;
616 /********************************************************************
617 ********************************************************************/
619 WERROR _wkssvc_NetWkstaTransportEnum(struct pipes_struct *p,
620 struct wkssvc_NetWkstaTransportEnum *r)
622 /* FIXME: Add implementation code here */
623 p->rng_fault_state = True;
624 return WERR_NOT_SUPPORTED;
627 /********************************************************************
628 ********************************************************************/
630 WERROR _wkssvc_NetrWkstaTransportAdd(struct pipes_struct *p,
631 struct wkssvc_NetrWkstaTransportAdd *r)
633 /* FIXME: Add implementation code here */
634 p->rng_fault_state = True;
635 return WERR_NOT_SUPPORTED;
638 /********************************************************************
639 ********************************************************************/
641 WERROR _wkssvc_NetrWkstaTransportDel(struct pipes_struct *p,
642 struct wkssvc_NetrWkstaTransportDel *r)
644 /* FIXME: Add implementation code here */
645 p->rng_fault_state = True;
646 return WERR_NOT_SUPPORTED;
649 /********************************************************************
650 ********************************************************************/
652 WERROR _wkssvc_NetrUseAdd(struct pipes_struct *p,
653 struct wkssvc_NetrUseAdd *r)
655 /* FIXME: Add implementation code here */
656 p->rng_fault_state = True;
657 return WERR_NOT_SUPPORTED;
660 /********************************************************************
661 ********************************************************************/
663 WERROR _wkssvc_NetrUseGetInfo(struct pipes_struct *p,
664 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(struct pipes_struct *p,
675 struct wkssvc_NetrUseDel *r)
677 /* FIXME: Add implementation code here */
678 p->rng_fault_state = True;
679 return WERR_NOT_SUPPORTED;
682 /********************************************************************
683 ********************************************************************/
685 WERROR _wkssvc_NetrUseEnum(struct pipes_struct *p,
686 struct wkssvc_NetrUseEnum *r)
688 /* FIXME: Add implementation code here */
689 p->rng_fault_state = True;
690 return WERR_NOT_SUPPORTED;
693 /********************************************************************
694 ********************************************************************/
696 WERROR _wkssvc_NetrMessageBufferSend(struct pipes_struct *p,
697 struct wkssvc_NetrMessageBufferSend *r)
699 /* FIXME: Add implementation code here */
700 p->rng_fault_state = True;
701 return WERR_NOT_SUPPORTED;
704 /********************************************************************
705 ********************************************************************/
707 WERROR _wkssvc_NetrWorkstationStatisticsGet(struct pipes_struct *p,
708 struct wkssvc_NetrWorkstationStatisticsGet *r)
710 /* FIXME: Add implementation code here */
711 p->rng_fault_state = True;
712 return WERR_NOT_SUPPORTED;
715 /********************************************************************
716 ********************************************************************/
718 WERROR _wkssvc_NetrLogonDomainNameAdd(struct pipes_struct *p,
719 struct wkssvc_NetrLogonDomainNameAdd *r)
721 /* FIXME: Add implementation code here */
722 p->rng_fault_state = True;
723 return WERR_NOT_SUPPORTED;
726 /********************************************************************
727 ********************************************************************/
729 WERROR _wkssvc_NetrLogonDomainNameDel(struct pipes_struct *p,
730 struct wkssvc_NetrLogonDomainNameDel *r)
732 /* FIXME: Add implementation code here */
733 p->rng_fault_state = True;
734 return WERR_NOT_SUPPORTED;
737 /********************************************************************
738 ********************************************************************/
740 WERROR _wkssvc_NetrJoinDomain(struct pipes_struct *p,
741 struct wkssvc_NetrJoinDomain *r)
743 /* FIXME: Add implementation code here */
744 p->rng_fault_state = True;
745 return WERR_NOT_SUPPORTED;
748 /********************************************************************
749 ********************************************************************/
751 WERROR _wkssvc_NetrUnjoinDomain(struct pipes_struct *p,
752 struct wkssvc_NetrUnjoinDomain *r)
754 /* FIXME: Add implementation code here */
755 p->rng_fault_state = True;
756 return WERR_NOT_SUPPORTED;
759 /********************************************************************
760 ********************************************************************/
762 WERROR _wkssvc_NetrRenameMachineInDomain(struct pipes_struct *p,
763 struct wkssvc_NetrRenameMachineInDomain *r)
765 /* FIXME: Add implementation code here */
766 p->rng_fault_state = True;
767 return WERR_NOT_SUPPORTED;
770 /********************************************************************
771 ********************************************************************/
773 WERROR _wkssvc_NetrValidateName(struct pipes_struct *p,
774 struct wkssvc_NetrValidateName *r)
776 /* FIXME: Add implementation code here */
777 p->rng_fault_state = True;
778 return WERR_NOT_SUPPORTED;
781 /********************************************************************
782 ********************************************************************/
784 WERROR _wkssvc_NetrGetJoinInformation(struct pipes_struct *p,
785 struct wkssvc_NetrGetJoinInformation *r)
787 /* FIXME: Add implementation code here */
788 p->rng_fault_state = True;
789 return WERR_NOT_SUPPORTED;
792 /********************************************************************
793 ********************************************************************/
795 WERROR _wkssvc_NetrGetJoinableOus(struct pipes_struct *p,
796 struct wkssvc_NetrGetJoinableOus *r)
798 /* FIXME: Add implementation code here */
799 p->rng_fault_state = True;
800 return WERR_NOT_SUPPORTED;
803 /********************************************************************
804 _wkssvc_NetrJoinDomain2
805 ********************************************************************/
807 WERROR _wkssvc_NetrJoinDomain2(struct pipes_struct *p,
808 struct wkssvc_NetrJoinDomain2 *r)
810 struct libnet_JoinCtx *j = NULL;
811 char *cleartext_pwd = NULL;
812 char *admin_domain = NULL;
813 char *admin_account = NULL;
814 WERROR werr;
815 struct nt_user_token *token = p->server_info->ptok;
817 if (!r->in.domain_name) {
818 return WERR_INVALID_PARAM;
821 if (!r->in.admin_account || !r->in.encrypted_password) {
822 return WERR_INVALID_PARAM;
825 if (!user_has_privileges(token, &se_machine_account) &&
826 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
827 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
828 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
829 "sufficient privileges\n"));
830 return WERR_ACCESS_DENIED;
833 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
834 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
835 return WERR_NOT_SUPPORTED;
838 werr = decode_wkssvc_join_password_buffer(
839 p->mem_ctx, r->in.encrypted_password,
840 &p->server_info->user_session_key, &cleartext_pwd);
841 if (!W_ERROR_IS_OK(werr)) {
842 return werr;
845 split_domain_user(p->mem_ctx,
846 r->in.admin_account,
847 &admin_domain,
848 &admin_account);
850 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
851 if (!W_ERROR_IS_OK(werr)) {
852 return werr;
855 j->in.domain_name = r->in.domain_name;
856 j->in.account_ou = r->in.account_ou;
857 j->in.join_flags = r->in.join_flags;
858 j->in.admin_account = admin_account;
859 j->in.admin_password = cleartext_pwd;
860 j->in.debug = true;
861 j->in.modify_config = lp_config_backend_is_registry();
862 j->in.msg_ctx = smbd_messaging_context();
864 become_root();
865 werr = libnet_Join(p->mem_ctx, j);
866 unbecome_root();
868 if (!W_ERROR_IS_OK(werr)) {
869 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
870 j->out.error_string ? j->out.error_string :
871 win_errstr(werr)));
874 TALLOC_FREE(j);
875 return werr;
878 /********************************************************************
879 _wkssvc_NetrUnjoinDomain2
880 ********************************************************************/
882 WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p,
883 struct wkssvc_NetrUnjoinDomain2 *r)
885 struct libnet_UnjoinCtx *u = NULL;
886 char *cleartext_pwd = NULL;
887 char *admin_domain = NULL;
888 char *admin_account = NULL;
889 WERROR werr;
890 struct nt_user_token *token = p->server_info->ptok;
892 if (!r->in.account || !r->in.encrypted_password) {
893 return WERR_INVALID_PARAM;
896 if (!user_has_privileges(token, &se_machine_account) &&
897 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
898 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
899 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
900 "sufficient privileges\n"));
901 return WERR_ACCESS_DENIED;
904 werr = decode_wkssvc_join_password_buffer(
905 p->mem_ctx, r->in.encrypted_password,
906 &p->server_info->user_session_key, &cleartext_pwd);
907 if (!W_ERROR_IS_OK(werr)) {
908 return werr;
911 split_domain_user(p->mem_ctx,
912 r->in.account,
913 &admin_domain,
914 &admin_account);
916 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
917 if (!W_ERROR_IS_OK(werr)) {
918 return werr;
921 u->in.domain_name = lp_realm();
922 u->in.unjoin_flags = r->in.unjoin_flags |
923 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
924 u->in.admin_account = admin_account;
925 u->in.admin_password = cleartext_pwd;
926 u->in.debug = true;
927 u->in.modify_config = lp_config_backend_is_registry();
928 u->in.msg_ctx = smbd_messaging_context();
930 become_root();
931 werr = libnet_Unjoin(p->mem_ctx, u);
932 unbecome_root();
934 if (!W_ERROR_IS_OK(werr)) {
935 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
936 u->out.error_string ? u->out.error_string :
937 win_errstr(werr)));
940 TALLOC_FREE(u);
941 return werr;
944 /********************************************************************
945 ********************************************************************/
947 WERROR _wkssvc_NetrRenameMachineInDomain2(struct pipes_struct *p,
948 struct wkssvc_NetrRenameMachineInDomain2 *r)
950 /* for now just return not supported */
951 return WERR_NOT_SUPPORTED;
954 /********************************************************************
955 ********************************************************************/
957 WERROR _wkssvc_NetrValidateName2(struct pipes_struct *p,
958 struct wkssvc_NetrValidateName2 *r)
960 /* FIXME: Add implementation code here */
961 p->rng_fault_state = True;
962 return WERR_NOT_SUPPORTED;
965 /********************************************************************
966 ********************************************************************/
968 WERROR _wkssvc_NetrGetJoinableOus2(struct pipes_struct *p,
969 struct wkssvc_NetrGetJoinableOus2 *r)
971 /* FIXME: Add implementation code here */
972 p->rng_fault_state = True;
973 return WERR_NOT_SUPPORTED;
976 /********************************************************************
977 ********************************************************************/
979 WERROR _wkssvc_NetrAddAlternateComputerName(struct pipes_struct *p,
980 struct wkssvc_NetrAddAlternateComputerName *r)
982 /* FIXME: Add implementation code here */
983 p->rng_fault_state = True;
984 return WERR_NOT_SUPPORTED;
987 /********************************************************************
988 ********************************************************************/
990 WERROR _wkssvc_NetrRemoveAlternateComputerName(struct pipes_struct *p,
991 struct wkssvc_NetrRemoveAlternateComputerName *r)
993 /* FIXME: Add implementation code here */
994 p->rng_fault_state = True;
995 return WERR_NOT_SUPPORTED;
998 /********************************************************************
999 ********************************************************************/
1001 WERROR _wkssvc_NetrSetPrimaryComputername(struct pipes_struct *p,
1002 struct wkssvc_NetrSetPrimaryComputername *r)
1004 /* FIXME: Add implementation code here */
1005 p->rng_fault_state = True;
1006 return WERR_NOT_SUPPORTED;
1009 /********************************************************************
1010 ********************************************************************/
1012 WERROR _wkssvc_NetrEnumerateComputerNames(struct pipes_struct *p,
1013 struct wkssvc_NetrEnumerateComputerNames *r)
1015 /* FIXME: Add implementation code here */
1016 p->rng_fault_state = True;
1017 return WERR_NOT_SUPPORTED;