s3-srvsvc: Use struct pipes_struct.
[Samba/gbeck.git] / source3 / rpc_server / srv_wkssvc_nt.c
blobd9f788142d931ef64158ed6392da7e786f8d9f46
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(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
341 switch (r->in.level) {
342 case 100:
343 /* Level 100 can be allowed from anyone including anonymous
344 * so no access checks are needed for this case */
345 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
346 if (r->out.info->info100 == NULL) {
347 return WERR_NOMEM;
349 break;
350 case 101:
351 /* Level 101 can be allowed from any logged in user */
352 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
353 p->server_info->ptok)) {
354 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
355 "101\n"));
356 DEBUGADD(3,(" - does not have sid for Authenticated "
357 "Users %s:\n",
358 sid_string_dbg(
359 &global_sid_Authenticated_Users)));
360 debug_nt_user_token(DBGC_CLASS, 3,
361 p->server_info->ptok);
362 return WERR_ACCESS_DENIED;
364 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
365 if (r->out.info->info101 == NULL) {
366 return WERR_NOMEM;
368 break;
369 case 102:
370 /* Level 102 Should only be allowed from a domain administrator */
371 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
372 p->server_info->ptok)) {
373 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
374 "102\n"));
375 DEBUGADD(3,(" - does not have sid for Administrators "
376 "group %s, sids are:\n",
377 sid_string_dbg(&global_sid_Builtin_Administrators)));
378 debug_nt_user_token(DBGC_CLASS, 3,
379 p->server_info->ptok);
380 return WERR_ACCESS_DENIED;
382 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
383 if (r->out.info->info102 == NULL) {
384 return WERR_NOMEM;
386 break;
387 default:
388 return WERR_UNKNOWN_LEVEL;
391 return WERR_OK;
394 /********************************************************************
395 ********************************************************************/
397 WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r)
399 /* FIXME: Add implementation code here */
400 p->rng_fault_state = True;
401 return WERR_NOT_SUPPORTED;
404 /********************************************************************
405 RPC Workstation Service request NetWkstaEnumUsers with level 0:
406 Returns to the requester:
407 - the user names of the logged in users.
408 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
409 ********************************************************************/
411 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
412 TALLOC_CTX *mem_ctx)
414 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
415 char **users;
416 int i, num_users;
418 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
419 if (ctr0 == NULL) {
420 return NULL;
423 users = get_logged_on_userlist(talloc_tos());
424 if (users == NULL && errno != 0) {
425 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
426 errno, strerror(errno)));
427 TALLOC_FREE(ctr0);
428 return NULL;
431 num_users = talloc_array_length(users);
432 ctr0->entries_read = num_users;
433 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
434 num_users);
435 if (ctr0->user0 == NULL) {
436 TALLOC_FREE(ctr0);
437 TALLOC_FREE(users);
438 return NULL;
441 for (i=0; i<num_users; i++) {
442 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
444 TALLOC_FREE(users);
445 return ctr0;
448 /********************************************************************
449 RPC Workstation Service request NetWkstaEnumUsers with level 1.
450 Returns to the requester:
451 - the user names of the logged in users,
452 - the domain or machine each is logged into,
453 - the password server that was used to authenticate each,
454 - other domains each user is logged into (not currently supported).
455 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
456 ********************************************************************/
458 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
459 TALLOC_CTX *mem_ctx)
461 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
462 char **users;
463 struct dom_usr *dom_users;
464 const char *pwd_server;
465 char *pwd_tmp;
466 int i, j, num_users, num_dom_users;
468 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
469 if (ctr1 == NULL) {
470 return NULL;
473 users = get_logged_on_userlist(talloc_tos());
474 if (users == NULL && errno != 0) {
475 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
476 errno, strerror(errno)));
477 TALLOC_FREE(ctr1);
478 return NULL;
480 num_users = talloc_array_length(users);
482 dom_users = get_domain_userlist(talloc_tos());
483 if (dom_users == NULL && errno != 0) {
484 TALLOC_FREE(ctr1);
485 TALLOC_FREE(users);
486 return NULL;
488 num_dom_users = talloc_array_length(dom_users);
490 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
491 num_users+num_dom_users);
492 if (ctr1->user1 == NULL) {
493 TALLOC_FREE(ctr1);
494 TALLOC_FREE(users);
495 TALLOC_FREE(dom_users);
496 return NULL;
499 pwd_server = "";
501 if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) {
502 /* The configured password server is a full DNS name but
503 * for the logon server we need to return just the first
504 * component (machine name) of it in upper-case */
505 char *p = strchr(pwd_tmp, '.');
506 if (p) {
507 *p = '\0';
508 } else {
509 p = pwd_tmp + strlen(pwd_tmp);
511 while (--p >= pwd_tmp) {
512 *p = toupper(*p);
514 pwd_server = pwd_tmp;
517 /* Put in local users first */
518 for (i=0; i<num_users; i++) {
519 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
521 /* For a local user the domain name and logon server are
522 * both returned as the local machine's NetBIOS name */
523 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
524 talloc_asprintf_strupper_m(ctr1->user1, "%s", global_myname());
526 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */
529 /* Now domain users */
530 for (j=0; j<num_dom_users; j++) {
531 ctr1->user1[i].user_name =
532 talloc_strdup(ctr1->user1, dom_users[j].name);
533 ctr1->user1[i].logon_domain =
534 talloc_strdup(ctr1->user1, dom_users[j].domain);
535 ctr1->user1[i].logon_server = pwd_server;
537 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
540 ctr1->entries_read = i;
542 TALLOC_FREE(users);
543 TALLOC_FREE(dom_users);
544 return ctr1;
547 /********************************************************************
548 Handling for RPC Workstation Service request NetWkstaEnumUsers
549 (a.k.a Windows NetWkstaUserEnum)
550 ********************************************************************/
552 WERROR _wkssvc_NetWkstaEnumUsers(pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r)
554 /* This with any level should only be allowed from a domain administrator */
555 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
556 p->server_info->ptok)) {
557 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
558 DEBUGADD(3,(" - does not have sid for Administrators group "
559 "%s\n", sid_string_dbg(
560 &global_sid_Builtin_Administrators)));
561 debug_nt_user_token(DBGC_CLASS, 3, p->server_info->ptok);
562 return WERR_ACCESS_DENIED;
565 switch (r->in.info->level) {
566 case 0:
567 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
568 if (r->out.info->ctr.user0 == NULL) {
569 return WERR_NOMEM;
571 r->out.info->level = r->in.info->level;
572 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
573 *r->out.resume_handle = 0;
574 break;
575 case 1:
576 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
577 if (r->out.info->ctr.user1 == NULL) {
578 return WERR_NOMEM;
580 r->out.info->level = r->in.info->level;
581 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
582 *r->out.resume_handle = 0;
583 break;
584 default:
585 return WERR_UNKNOWN_LEVEL;
588 return WERR_OK;
591 /********************************************************************
592 ********************************************************************/
594 WERROR _wkssvc_NetrWkstaUserGetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserGetInfo *r)
596 /* FIXME: Add implementation code here */
597 p->rng_fault_state = True;
598 return WERR_NOT_SUPPORTED;
601 /********************************************************************
602 ********************************************************************/
604 WERROR _wkssvc_NetrWkstaUserSetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserSetInfo *r)
606 /* FIXME: Add implementation code here */
607 p->rng_fault_state = True;
608 return WERR_NOT_SUPPORTED;
611 /********************************************************************
612 ********************************************************************/
614 WERROR _wkssvc_NetWkstaTransportEnum(pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r)
616 /* FIXME: Add implementation code here */
617 p->rng_fault_state = True;
618 return WERR_NOT_SUPPORTED;
621 /********************************************************************
622 ********************************************************************/
624 WERROR _wkssvc_NetrWkstaTransportAdd(pipes_struct *p, struct wkssvc_NetrWkstaTransportAdd *r)
626 /* FIXME: Add implementation code here */
627 p->rng_fault_state = True;
628 return WERR_NOT_SUPPORTED;
631 /********************************************************************
632 ********************************************************************/
634 WERROR _wkssvc_NetrWkstaTransportDel(pipes_struct *p, struct wkssvc_NetrWkstaTransportDel *r)
636 /* FIXME: Add implementation code here */
637 p->rng_fault_state = True;
638 return WERR_NOT_SUPPORTED;
641 /********************************************************************
642 ********************************************************************/
644 WERROR _wkssvc_NetrUseAdd(pipes_struct *p, struct wkssvc_NetrUseAdd *r)
646 /* FIXME: Add implementation code here */
647 p->rng_fault_state = True;
648 return WERR_NOT_SUPPORTED;
651 /********************************************************************
652 ********************************************************************/
654 WERROR _wkssvc_NetrUseGetInfo(pipes_struct *p, struct wkssvc_NetrUseGetInfo *r)
656 /* FIXME: Add implementation code here */
657 p->rng_fault_state = True;
658 return WERR_NOT_SUPPORTED;
661 /********************************************************************
662 ********************************************************************/
664 WERROR _wkssvc_NetrUseDel(pipes_struct *p, struct wkssvc_NetrUseDel *r)
666 /* FIXME: Add implementation code here */
667 p->rng_fault_state = True;
668 return WERR_NOT_SUPPORTED;
671 /********************************************************************
672 ********************************************************************/
674 WERROR _wkssvc_NetrUseEnum(pipes_struct *p, struct wkssvc_NetrUseEnum *r)
676 /* FIXME: Add implementation code here */
677 p->rng_fault_state = True;
678 return WERR_NOT_SUPPORTED;
681 /********************************************************************
682 ********************************************************************/
684 WERROR _wkssvc_NetrMessageBufferSend(pipes_struct *p, struct wkssvc_NetrMessageBufferSend *r)
686 /* FIXME: Add implementation code here */
687 p->rng_fault_state = True;
688 return WERR_NOT_SUPPORTED;
691 /********************************************************************
692 ********************************************************************/
694 WERROR _wkssvc_NetrWorkstationStatisticsGet(pipes_struct *p, struct wkssvc_NetrWorkstationStatisticsGet *r)
696 /* FIXME: Add implementation code here */
697 p->rng_fault_state = True;
698 return WERR_NOT_SUPPORTED;
701 /********************************************************************
702 ********************************************************************/
704 WERROR _wkssvc_NetrLogonDomainNameAdd(pipes_struct *p, struct wkssvc_NetrLogonDomainNameAdd *r)
706 /* FIXME: Add implementation code here */
707 p->rng_fault_state = True;
708 return WERR_NOT_SUPPORTED;
711 /********************************************************************
712 ********************************************************************/
714 WERROR _wkssvc_NetrLogonDomainNameDel(pipes_struct *p, struct wkssvc_NetrLogonDomainNameDel *r)
716 /* FIXME: Add implementation code here */
717 p->rng_fault_state = True;
718 return WERR_NOT_SUPPORTED;
721 /********************************************************************
722 ********************************************************************/
724 WERROR _wkssvc_NetrJoinDomain(pipes_struct *p, struct wkssvc_NetrJoinDomain *r)
726 /* FIXME: Add implementation code here */
727 p->rng_fault_state = True;
728 return WERR_NOT_SUPPORTED;
731 /********************************************************************
732 ********************************************************************/
734 WERROR _wkssvc_NetrUnjoinDomain(pipes_struct *p, struct wkssvc_NetrUnjoinDomain *r)
736 /* FIXME: Add implementation code here */
737 p->rng_fault_state = True;
738 return WERR_NOT_SUPPORTED;
741 /********************************************************************
742 ********************************************************************/
744 WERROR _wkssvc_NetrRenameMachineInDomain(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain *r)
746 /* FIXME: Add implementation code here */
747 p->rng_fault_state = True;
748 return WERR_NOT_SUPPORTED;
751 /********************************************************************
752 ********************************************************************/
754 WERROR _wkssvc_NetrValidateName(pipes_struct *p, struct wkssvc_NetrValidateName *r)
756 /* FIXME: Add implementation code here */
757 p->rng_fault_state = True;
758 return WERR_NOT_SUPPORTED;
761 /********************************************************************
762 ********************************************************************/
764 WERROR _wkssvc_NetrGetJoinInformation(pipes_struct *p, struct wkssvc_NetrGetJoinInformation *r)
766 /* FIXME: Add implementation code here */
767 p->rng_fault_state = True;
768 return WERR_NOT_SUPPORTED;
771 /********************************************************************
772 ********************************************************************/
774 WERROR _wkssvc_NetrGetJoinableOus(pipes_struct *p, struct wkssvc_NetrGetJoinableOus *r)
776 /* FIXME: Add implementation code here */
777 p->rng_fault_state = True;
778 return WERR_NOT_SUPPORTED;
781 /********************************************************************
782 _wkssvc_NetrJoinDomain2
783 ********************************************************************/
785 WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p,
786 struct wkssvc_NetrJoinDomain2 *r)
788 struct libnet_JoinCtx *j = NULL;
789 char *cleartext_pwd = NULL;
790 char *admin_domain = NULL;
791 char *admin_account = NULL;
792 WERROR werr;
793 struct nt_user_token *token = p->server_info->ptok;
795 if (!r->in.domain_name) {
796 return WERR_INVALID_PARAM;
799 if (!r->in.admin_account || !r->in.encrypted_password) {
800 return WERR_INVALID_PARAM;
803 if (!user_has_privileges(token, &se_machine_account) &&
804 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
805 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
806 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
807 "sufficient privileges\n"));
808 return WERR_ACCESS_DENIED;
811 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
812 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
813 return WERR_NOT_SUPPORTED;
816 werr = decode_wkssvc_join_password_buffer(
817 p->mem_ctx, r->in.encrypted_password,
818 &p->server_info->user_session_key, &cleartext_pwd);
819 if (!W_ERROR_IS_OK(werr)) {
820 return werr;
823 split_domain_user(p->mem_ctx,
824 r->in.admin_account,
825 &admin_domain,
826 &admin_account);
828 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
829 if (!W_ERROR_IS_OK(werr)) {
830 return werr;
833 j->in.domain_name = r->in.domain_name;
834 j->in.account_ou = r->in.account_ou;
835 j->in.join_flags = r->in.join_flags;
836 j->in.admin_account = admin_account;
837 j->in.admin_password = cleartext_pwd;
838 j->in.debug = true;
839 j->in.modify_config = lp_config_backend_is_registry();
840 j->in.msg_ctx = smbd_messaging_context();
842 become_root();
843 werr = libnet_Join(p->mem_ctx, j);
844 unbecome_root();
846 if (!W_ERROR_IS_OK(werr)) {
847 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
848 j->out.error_string ? j->out.error_string :
849 win_errstr(werr)));
852 TALLOC_FREE(j);
853 return werr;
856 /********************************************************************
857 _wkssvc_NetrUnjoinDomain2
858 ********************************************************************/
860 WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p,
861 struct wkssvc_NetrUnjoinDomain2 *r)
863 struct libnet_UnjoinCtx *u = NULL;
864 char *cleartext_pwd = NULL;
865 char *admin_domain = NULL;
866 char *admin_account = NULL;
867 WERROR werr;
868 struct nt_user_token *token = p->server_info->ptok;
870 if (!r->in.account || !r->in.encrypted_password) {
871 return WERR_INVALID_PARAM;
874 if (!user_has_privileges(token, &se_machine_account) &&
875 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
876 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
877 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
878 "sufficient privileges\n"));
879 return WERR_ACCESS_DENIED;
882 werr = decode_wkssvc_join_password_buffer(
883 p->mem_ctx, r->in.encrypted_password,
884 &p->server_info->user_session_key, &cleartext_pwd);
885 if (!W_ERROR_IS_OK(werr)) {
886 return werr;
889 split_domain_user(p->mem_ctx,
890 r->in.account,
891 &admin_domain,
892 &admin_account);
894 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
895 if (!W_ERROR_IS_OK(werr)) {
896 return werr;
899 u->in.domain_name = lp_realm();
900 u->in.unjoin_flags = r->in.unjoin_flags |
901 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
902 u->in.admin_account = admin_account;
903 u->in.admin_password = cleartext_pwd;
904 u->in.debug = true;
905 u->in.modify_config = lp_config_backend_is_registry();
906 u->in.msg_ctx = smbd_messaging_context();
908 become_root();
909 werr = libnet_Unjoin(p->mem_ctx, u);
910 unbecome_root();
912 if (!W_ERROR_IS_OK(werr)) {
913 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
914 u->out.error_string ? u->out.error_string :
915 win_errstr(werr)));
918 TALLOC_FREE(u);
919 return werr;
922 /********************************************************************
923 ********************************************************************/
925 WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r)
927 /* for now just return not supported */
928 return WERR_NOT_SUPPORTED;
931 /********************************************************************
932 ********************************************************************/
934 WERROR _wkssvc_NetrValidateName2(pipes_struct *p, struct wkssvc_NetrValidateName2 *r)
936 /* FIXME: Add implementation code here */
937 p->rng_fault_state = True;
938 return WERR_NOT_SUPPORTED;
941 /********************************************************************
942 ********************************************************************/
944 WERROR _wkssvc_NetrGetJoinableOus2(pipes_struct *p, struct wkssvc_NetrGetJoinableOus2 *r)
946 /* FIXME: Add implementation code here */
947 p->rng_fault_state = True;
948 return WERR_NOT_SUPPORTED;
951 /********************************************************************
952 ********************************************************************/
954 WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r)
956 /* FIXME: Add implementation code here */
957 p->rng_fault_state = True;
958 return WERR_NOT_SUPPORTED;
961 /********************************************************************
962 ********************************************************************/
964 WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *r)
966 /* FIXME: Add implementation code here */
967 p->rng_fault_state = True;
968 return WERR_NOT_SUPPORTED;
971 /********************************************************************
972 ********************************************************************/
974 WERROR _wkssvc_NetrSetPrimaryComputername(pipes_struct *p, struct wkssvc_NetrSetPrimaryComputername *r)
976 /* FIXME: Add implementation code here */
977 p->rng_fault_state = True;
978 return WERR_NOT_SUPPORTED;
981 /********************************************************************
982 ********************************************************************/
984 WERROR _wkssvc_NetrEnumerateComputerNames(pipes_struct *p, struct wkssvc_NetrEnumerateComputerNames *r)
986 /* FIXME: Add implementation code here */
987 p->rng_fault_state = True;
988 return WERR_NOT_SUPPORTED;