s4:"dns_update_list" file: install it properly into the private directory
[Samba/cd1.git] / source3 / rpc_server / srv_wkssvc_nt.c
bloba8cbfba368a68402645d8a1d1cab8bd12471d36a
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 "libnet/libnet.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../librpc/gen_ndr/srv_wkssvc.h"
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
33 struct dom_usr {
34 char *name;
35 char *domain;
36 time_t login_time;
39 #ifdef HAVE_GETUTXENT
41 #include <utmpx.h>
43 struct usrinfo {
44 char *name;
45 struct timeval login_time;
48 static int usr_info_cmp(const struct usrinfo *usr1, const struct usrinfo *usr2)
50 /* Called from qsort to compare two users in a usrinfo_t array for
51 * sorting by login time. Return >0 if usr1 login time was later than
52 * usr2 login time, <0 if it was earlier */
53 return timeval_compare(&usr1->login_time, &usr2->login_time);
56 /*******************************************************************
57 Get a list of the names of all users logged into this machine
58 ********************************************************************/
60 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
62 char **users;
63 int i, num_users = 0;
64 struct usrinfo *usr_infos = NULL;
65 struct utmpx *u;
67 while ((u = getutxent()) != NULL) {
68 struct usrinfo *tmp;
69 if (u->ut_type != USER_PROCESS) {
70 continue;
72 for (i = 0; i < num_users; i++) {
73 /* getutxent can return multiple user entries for the
74 * same user, so ignore any dups */
75 if (strcmp(u->ut_user, usr_infos[i].name) == 0) {
76 break;
79 if (i < num_users) {
80 continue;
83 tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
84 num_users+1);
85 if (tmp == NULL) {
86 TALLOC_FREE(tmp);
87 endutxent();
88 return NULL;
90 usr_infos = tmp;
91 usr_infos[num_users].name = talloc_strdup(usr_infos,
92 u->ut_user);
93 if (usr_infos[num_users].name == NULL) {
94 TALLOC_FREE(usr_infos);
95 endutxent();
96 return NULL;
98 usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
99 usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
100 num_users += 1;
103 /* Sort the user list by time, oldest first */
104 TYPESAFE_QSORT(usr_infos, num_users, usr_info_cmp);
106 users = (char**)talloc_array(mem_ctx, char*, num_users);
107 if (users) {
108 for (i = 0; i < num_users; i++) {
109 users[i] = talloc_move(users, &usr_infos[i].name);
112 TALLOC_FREE(usr_infos);
113 endutxent();
114 errno = 0;
115 return users;
118 #else
120 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
122 return NULL;
125 #endif
127 static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
129 /* Called from qsort to compare two domain users in a dom_usr_t array
130 * for sorting by login time. Return >0 if usr1 login time was later
131 * than usr2 login time, <0 if it was earlier */
132 return (usr1->login_time - usr2->login_time);
135 /*******************************************************************
136 Get a list of the names of all users of this machine who are
137 logged into the domain.
139 This should return a list of the users on this machine who are
140 logged into the domain (i.e. have been authenticated by the domain's
141 password server) but that doesn't fit well with the normal Samba
142 scenario where accesses out to the domain are made through smbclient
143 with each such session individually authenticated. So about the best
144 we can do currently is to list sessions of local users connected to
145 this server, which means that to get themself included in the list a
146 local user must create a session to the local samba server by running:
147 smbclient \\\\localhost\\share
149 FIXME: find a better way to get local users logged into the domain
150 in this list.
151 ********************************************************************/
153 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
155 struct sessionid *session_list = NULL;
156 char *machine_name, *p, *nm;
157 const char *sep;
158 struct dom_usr *users, *tmp;
159 int i, num_users, num_sessions;
161 sep = lp_winbind_separator();
162 if (!sep) {
163 sep = "\\";
166 num_sessions = list_sessions(mem_ctx, &session_list);
167 if (num_sessions == 0) {
168 errno = 0;
169 return NULL;
172 users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
173 if (users == NULL) {
174 TALLOC_FREE(session_list);
175 return NULL;
178 for (i=num_users=0; i<num_sessions; i++) {
179 if (!session_list[i].username
180 || !session_list[i].remote_machine) {
181 continue;
183 p = strpbrk(session_list[i].remote_machine, "./");
184 if (p) {
185 *p = '\0';
187 machine_name = talloc_asprintf_strupper_m(
188 users, "%s", session_list[i].remote_machine);
189 if (machine_name == NULL) {
190 DEBUG(10, ("talloc_asprintf failed\n"));
191 continue;
193 if (strcmp(machine_name, global_myname()) == 0) {
194 p = session_list[i].username;
195 nm = strstr(p, sep);
196 if (nm) {
198 * "domain+name" format so split domain and
199 * name components
201 *nm = '\0';
202 nm += strlen(sep);
203 users[num_users].domain =
204 talloc_asprintf_strupper_m(users,
205 "%s", p);
206 users[num_users].name = talloc_strdup(users,
207 nm);
208 } else {
210 * Simple user name so get domain from smb.conf
212 users[num_users].domain =
213 talloc_strdup(users, lp_workgroup());
214 users[num_users].name = talloc_strdup(users,
217 users[num_users].login_time =
218 session_list[i].connect_start;
219 num_users++;
221 TALLOC_FREE(machine_name);
223 TALLOC_FREE(session_list);
225 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
226 if (tmp == NULL) {
227 return NULL;
229 users = tmp;
231 /* Sort the user list by time, oldest first */
232 TYPESAFE_QSORT(users, num_users, dom_user_cmp);
234 errno = 0;
235 return users;
238 /*******************************************************************
239 RPC Workstation Service request NetWkstaGetInfo with level 100.
240 Returns to the requester:
241 - The machine name.
242 - The smb version number
243 - The domain name.
244 Returns a filled in wkssvc_NetWkstaInfo100 struct.
245 ********************************************************************/
247 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
249 struct wkssvc_NetWkstaInfo100 *info100;
251 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
252 if (info100 == NULL) {
253 return NULL;
256 info100->platform_id = PLATFORM_ID_NT; /* unknown */
257 info100->version_major = lp_major_announce_version();
258 info100->version_minor = lp_minor_announce_version();
260 info100->server_name = talloc_asprintf_strupper_m(
261 info100, "%s", global_myname());
262 info100->domain_name = talloc_asprintf_strupper_m(
263 info100, "%s", lp_workgroup());
265 return info100;
268 /*******************************************************************
269 RPC Workstation Service request NetWkstaGetInfo with level 101.
270 Returns to the requester:
271 - As per NetWkstaGetInfo with level 100, plus:
272 - The LANMAN directory path (not currently supported).
273 Returns a filled in wkssvc_NetWkstaInfo101 struct.
274 ********************************************************************/
276 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
278 struct wkssvc_NetWkstaInfo101 *info101;
280 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
281 if (info101 == NULL) {
282 return NULL;
285 info101->platform_id = PLATFORM_ID_NT; /* unknown */
286 info101->version_major = lp_major_announce_version();
287 info101->version_minor = lp_minor_announce_version();
289 info101->server_name = talloc_asprintf_strupper_m(
290 info101, "%s", global_myname());
291 info101->domain_name = talloc_asprintf_strupper_m(
292 info101, "%s", lp_workgroup());
293 info101->lan_root = "";
295 return info101;
298 /*******************************************************************
299 RPC Workstation Service request NetWkstaGetInfo with level 102.
300 Returns to the requester:
301 - As per NetWkstaGetInfo with level 101, plus:
302 - The number of logged in users.
303 Returns a filled in wkssvc_NetWkstaInfo102 struct.
304 ********************************************************************/
306 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
308 struct wkssvc_NetWkstaInfo102 *info102;
309 char **users;
311 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
312 if (info102 == NULL) {
313 return NULL;
316 info102->platform_id = PLATFORM_ID_NT; /* unknown */
317 info102->version_major = lp_major_announce_version();
318 info102->version_minor = lp_minor_announce_version();
320 info102->server_name = talloc_asprintf_strupper_m(
321 info102, "%s", global_myname());
322 info102->domain_name = talloc_asprintf_strupper_m(
323 info102, "%s", lp_workgroup());
324 info102->lan_root = "";
326 users = get_logged_on_userlist(talloc_tos());
327 info102->logged_on_users = talloc_array_length(users);
329 TALLOC_FREE(users);
331 return info102;
334 /********************************************************************
335 Handling for RPC Workstation Service request NetWkstaGetInfo
336 ********************************************************************/
338 WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
340 switch (r->in.level) {
341 case 100:
342 /* Level 100 can be allowed from anyone including anonymous
343 * so no access checks are needed for this case */
344 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
345 if (r->out.info->info100 == NULL) {
346 return WERR_NOMEM;
348 break;
349 case 101:
350 /* Level 101 can be allowed from any logged in user */
351 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
352 p->server_info->ptok)) {
353 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
354 "101\n"));
355 DEBUGADD(3,(" - does not have sid for Authenticated "
356 "Users %s:\n",
357 sid_string_dbg(
358 &global_sid_Authenticated_Users)));
359 debug_nt_user_token(DBGC_CLASS, 3,
360 p->server_info->ptok);
361 return WERR_ACCESS_DENIED;
363 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
364 if (r->out.info->info101 == NULL) {
365 return WERR_NOMEM;
367 break;
368 case 102:
369 /* Level 102 Should only be allowed from a domain administrator */
370 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
371 p->server_info->ptok)) {
372 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
373 "102\n"));
374 DEBUGADD(3,(" - does not have sid for Administrators "
375 "group %s, sids are:\n",
376 sid_string_dbg(&global_sid_Builtin_Administrators)));
377 debug_nt_user_token(DBGC_CLASS, 3,
378 p->server_info->ptok);
379 return WERR_ACCESS_DENIED;
381 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
382 if (r->out.info->info102 == NULL) {
383 return WERR_NOMEM;
385 break;
386 default:
387 return WERR_UNKNOWN_LEVEL;
390 return WERR_OK;
393 /********************************************************************
394 ********************************************************************/
396 WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r)
398 /* FIXME: Add implementation code here */
399 p->rng_fault_state = True;
400 return WERR_NOT_SUPPORTED;
403 /********************************************************************
404 RPC Workstation Service request NetWkstaEnumUsers with level 0:
405 Returns to the requester:
406 - the user names of the logged in users.
407 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
408 ********************************************************************/
410 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
411 TALLOC_CTX *mem_ctx)
413 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
414 char **users;
415 int i, num_users;
417 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
418 if (ctr0 == NULL) {
419 return NULL;
422 users = get_logged_on_userlist(talloc_tos());
423 if (users == NULL && errno != 0) {
424 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
425 errno, strerror(errno)));
426 TALLOC_FREE(ctr0);
427 return NULL;
430 num_users = talloc_array_length(users);
431 ctr0->entries_read = num_users;
432 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
433 num_users);
434 if (ctr0->user0 == NULL) {
435 TALLOC_FREE(ctr0);
436 TALLOC_FREE(users);
437 return NULL;
440 for (i=0; i<num_users; i++) {
441 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
443 TALLOC_FREE(users);
444 return ctr0;
447 /********************************************************************
448 RPC Workstation Service request NetWkstaEnumUsers with level 1.
449 Returns to the requester:
450 - the user names of the logged in users,
451 - the domain or machine each is logged into,
452 - the password server that was used to authenticate each,
453 - other domains each user is logged into (not currently supported).
454 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
455 ********************************************************************/
457 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
458 TALLOC_CTX *mem_ctx)
460 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
461 char **users;
462 struct dom_usr *dom_users;
463 const char *pwd_server;
464 char *pwd_tmp;
465 int i, j, num_users, num_dom_users;
467 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
468 if (ctr1 == NULL) {
469 return NULL;
472 users = get_logged_on_userlist(talloc_tos());
473 if (users == NULL && errno != 0) {
474 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
475 errno, strerror(errno)));
476 TALLOC_FREE(ctr1);
477 return NULL;
479 num_users = talloc_array_length(users);
481 dom_users = get_domain_userlist(talloc_tos());
482 if (dom_users == NULL && errno != 0) {
483 TALLOC_FREE(ctr1);
484 TALLOC_FREE(users);
485 return NULL;
487 num_dom_users = talloc_array_length(dom_users);
489 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
490 num_users+num_dom_users);
491 if (ctr1->user1 == NULL) {
492 TALLOC_FREE(ctr1);
493 TALLOC_FREE(users);
494 TALLOC_FREE(dom_users);
495 return NULL;
498 pwd_server = "";
500 if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) {
501 /* The configured password server is a full DNS name but
502 * for the logon server we need to return just the first
503 * component (machine name) of it in upper-case */
504 char *p = strchr(pwd_tmp, '.');
505 if (p) {
506 *p = '\0';
507 } else {
508 p = pwd_tmp + strlen(pwd_tmp);
510 while (--p >= pwd_tmp) {
511 *p = toupper(*p);
513 pwd_server = pwd_tmp;
516 /* Put in local users first */
517 for (i=0; i<num_users; i++) {
518 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
520 /* For a local user the domain name and logon server are
521 * both returned as the local machine's NetBIOS name */
522 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
523 talloc_asprintf_strupper_m(ctr1->user1, "%s", global_myname());
525 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */
528 /* Now domain users */
529 for (j=0; j<num_dom_users; j++) {
530 ctr1->user1[i].user_name =
531 talloc_strdup(ctr1->user1, dom_users[j].name);
532 ctr1->user1[i].logon_domain =
533 talloc_strdup(ctr1->user1, dom_users[j].domain);
534 ctr1->user1[i].logon_server = pwd_server;
536 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
539 ctr1->entries_read = i;
541 TALLOC_FREE(users);
542 TALLOC_FREE(dom_users);
543 return ctr1;
546 /********************************************************************
547 Handling for RPC Workstation Service request NetWkstaEnumUsers
548 (a.k.a Windows NetWkstaUserEnum)
549 ********************************************************************/
551 WERROR _wkssvc_NetWkstaEnumUsers(pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r)
553 /* This with any level should only be allowed from a domain administrator */
554 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
555 p->server_info->ptok)) {
556 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
557 DEBUGADD(3,(" - does not have sid for Administrators group "
558 "%s\n", sid_string_dbg(
559 &global_sid_Builtin_Administrators)));
560 debug_nt_user_token(DBGC_CLASS, 3, p->server_info->ptok);
561 return WERR_ACCESS_DENIED;
564 switch (r->in.info->level) {
565 case 0:
566 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
567 if (r->out.info->ctr.user0 == NULL) {
568 return WERR_NOMEM;
570 r->out.info->level = r->in.info->level;
571 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
572 *r->out.resume_handle = 0;
573 break;
574 case 1:
575 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
576 if (r->out.info->ctr.user1 == NULL) {
577 return WERR_NOMEM;
579 r->out.info->level = r->in.info->level;
580 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
581 *r->out.resume_handle = 0;
582 break;
583 default:
584 return WERR_UNKNOWN_LEVEL;
587 return WERR_OK;
590 /********************************************************************
591 ********************************************************************/
593 WERROR _wkssvc_NetrWkstaUserGetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserGetInfo *r)
595 /* FIXME: Add implementation code here */
596 p->rng_fault_state = True;
597 return WERR_NOT_SUPPORTED;
600 /********************************************************************
601 ********************************************************************/
603 WERROR _wkssvc_NetrWkstaUserSetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserSetInfo *r)
605 /* FIXME: Add implementation code here */
606 p->rng_fault_state = True;
607 return WERR_NOT_SUPPORTED;
610 /********************************************************************
611 ********************************************************************/
613 WERROR _wkssvc_NetWkstaTransportEnum(pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r)
615 /* FIXME: Add implementation code here */
616 p->rng_fault_state = True;
617 return WERR_NOT_SUPPORTED;
620 /********************************************************************
621 ********************************************************************/
623 WERROR _wkssvc_NetrWkstaTransportAdd(pipes_struct *p, struct wkssvc_NetrWkstaTransportAdd *r)
625 /* FIXME: Add implementation code here */
626 p->rng_fault_state = True;
627 return WERR_NOT_SUPPORTED;
630 /********************************************************************
631 ********************************************************************/
633 WERROR _wkssvc_NetrWkstaTransportDel(pipes_struct *p, struct wkssvc_NetrWkstaTransportDel *r)
635 /* FIXME: Add implementation code here */
636 p->rng_fault_state = True;
637 return WERR_NOT_SUPPORTED;
640 /********************************************************************
641 ********************************************************************/
643 WERROR _wkssvc_NetrUseAdd(pipes_struct *p, struct wkssvc_NetrUseAdd *r)
645 /* FIXME: Add implementation code here */
646 p->rng_fault_state = True;
647 return WERR_NOT_SUPPORTED;
650 /********************************************************************
651 ********************************************************************/
653 WERROR _wkssvc_NetrUseGetInfo(pipes_struct *p, struct wkssvc_NetrUseGetInfo *r)
655 /* FIXME: Add implementation code here */
656 p->rng_fault_state = True;
657 return WERR_NOT_SUPPORTED;
660 /********************************************************************
661 ********************************************************************/
663 WERROR _wkssvc_NetrUseDel(pipes_struct *p, struct wkssvc_NetrUseDel *r)
665 /* FIXME: Add implementation code here */
666 p->rng_fault_state = True;
667 return WERR_NOT_SUPPORTED;
670 /********************************************************************
671 ********************************************************************/
673 WERROR _wkssvc_NetrUseEnum(pipes_struct *p, struct wkssvc_NetrUseEnum *r)
675 /* FIXME: Add implementation code here */
676 p->rng_fault_state = True;
677 return WERR_NOT_SUPPORTED;
680 /********************************************************************
681 ********************************************************************/
683 WERROR _wkssvc_NetrMessageBufferSend(pipes_struct *p, struct wkssvc_NetrMessageBufferSend *r)
685 /* FIXME: Add implementation code here */
686 p->rng_fault_state = True;
687 return WERR_NOT_SUPPORTED;
690 /********************************************************************
691 ********************************************************************/
693 WERROR _wkssvc_NetrWorkstationStatisticsGet(pipes_struct *p, struct wkssvc_NetrWorkstationStatisticsGet *r)
695 /* FIXME: Add implementation code here */
696 p->rng_fault_state = True;
697 return WERR_NOT_SUPPORTED;
700 /********************************************************************
701 ********************************************************************/
703 WERROR _wkssvc_NetrLogonDomainNameAdd(pipes_struct *p, struct wkssvc_NetrLogonDomainNameAdd *r)
705 /* FIXME: Add implementation code here */
706 p->rng_fault_state = True;
707 return WERR_NOT_SUPPORTED;
710 /********************************************************************
711 ********************************************************************/
713 WERROR _wkssvc_NetrLogonDomainNameDel(pipes_struct *p, struct wkssvc_NetrLogonDomainNameDel *r)
715 /* FIXME: Add implementation code here */
716 p->rng_fault_state = True;
717 return WERR_NOT_SUPPORTED;
720 /********************************************************************
721 ********************************************************************/
723 WERROR _wkssvc_NetrJoinDomain(pipes_struct *p, struct wkssvc_NetrJoinDomain *r)
725 /* FIXME: Add implementation code here */
726 p->rng_fault_state = True;
727 return WERR_NOT_SUPPORTED;
730 /********************************************************************
731 ********************************************************************/
733 WERROR _wkssvc_NetrUnjoinDomain(pipes_struct *p, struct wkssvc_NetrUnjoinDomain *r)
735 /* FIXME: Add implementation code here */
736 p->rng_fault_state = True;
737 return WERR_NOT_SUPPORTED;
740 /********************************************************************
741 ********************************************************************/
743 WERROR _wkssvc_NetrRenameMachineInDomain(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain *r)
745 /* FIXME: Add implementation code here */
746 p->rng_fault_state = True;
747 return WERR_NOT_SUPPORTED;
750 /********************************************************************
751 ********************************************************************/
753 WERROR _wkssvc_NetrValidateName(pipes_struct *p, struct wkssvc_NetrValidateName *r)
755 /* FIXME: Add implementation code here */
756 p->rng_fault_state = True;
757 return WERR_NOT_SUPPORTED;
760 /********************************************************************
761 ********************************************************************/
763 WERROR _wkssvc_NetrGetJoinInformation(pipes_struct *p, struct wkssvc_NetrGetJoinInformation *r)
765 /* FIXME: Add implementation code here */
766 p->rng_fault_state = True;
767 return WERR_NOT_SUPPORTED;
770 /********************************************************************
771 ********************************************************************/
773 WERROR _wkssvc_NetrGetJoinableOus(pipes_struct *p, struct wkssvc_NetrGetJoinableOus *r)
775 /* FIXME: Add implementation code here */
776 p->rng_fault_state = True;
777 return WERR_NOT_SUPPORTED;
780 /********************************************************************
781 _wkssvc_NetrJoinDomain2
782 ********************************************************************/
784 WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p,
785 struct wkssvc_NetrJoinDomain2 *r)
787 struct libnet_JoinCtx *j = NULL;
788 char *cleartext_pwd = NULL;
789 char *admin_domain = NULL;
790 char *admin_account = NULL;
791 WERROR werr;
792 struct nt_user_token *token = p->server_info->ptok;
794 if (!r->in.domain_name) {
795 return WERR_INVALID_PARAM;
798 if (!r->in.admin_account || !r->in.encrypted_password) {
799 return WERR_INVALID_PARAM;
802 if (!user_has_privileges(token, &se_machine_account) &&
803 !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) &&
804 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
805 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
806 "sufficient privileges\n"));
807 return WERR_ACCESS_DENIED;
810 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
811 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
812 return WERR_NOT_SUPPORTED;
815 werr = decode_wkssvc_join_password_buffer(
816 p->mem_ctx, r->in.encrypted_password,
817 &p->server_info->user_session_key, &cleartext_pwd);
818 if (!W_ERROR_IS_OK(werr)) {
819 return werr;
822 split_domain_user(p->mem_ctx,
823 r->in.admin_account,
824 &admin_domain,
825 &admin_account);
827 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
828 if (!W_ERROR_IS_OK(werr)) {
829 return werr;
832 j->in.domain_name = r->in.domain_name;
833 j->in.account_ou = r->in.account_ou;
834 j->in.join_flags = r->in.join_flags;
835 j->in.admin_account = admin_account;
836 j->in.admin_password = cleartext_pwd;
837 j->in.debug = true;
838 j->in.modify_config = lp_config_backend_is_registry();
839 j->in.msg_ctx = smbd_messaging_context();
841 become_root();
842 werr = libnet_Join(p->mem_ctx, j);
843 unbecome_root();
845 if (!W_ERROR_IS_OK(werr)) {
846 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
847 j->out.error_string ? j->out.error_string :
848 win_errstr(werr)));
851 TALLOC_FREE(j);
852 return werr;
855 /********************************************************************
856 _wkssvc_NetrUnjoinDomain2
857 ********************************************************************/
859 WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p,
860 struct wkssvc_NetrUnjoinDomain2 *r)
862 struct libnet_UnjoinCtx *u = NULL;
863 char *cleartext_pwd = NULL;
864 char *admin_domain = NULL;
865 char *admin_account = NULL;
866 WERROR werr;
867 struct nt_user_token *token = p->server_info->ptok;
869 if (!r->in.account || !r->in.encrypted_password) {
870 return WERR_INVALID_PARAM;
873 if (!user_has_privileges(token, &se_machine_account) &&
874 !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) &&
875 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
876 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
877 "sufficient privileges\n"));
878 return WERR_ACCESS_DENIED;
881 werr = decode_wkssvc_join_password_buffer(
882 p->mem_ctx, r->in.encrypted_password,
883 &p->server_info->user_session_key, &cleartext_pwd);
884 if (!W_ERROR_IS_OK(werr)) {
885 return werr;
888 split_domain_user(p->mem_ctx,
889 r->in.account,
890 &admin_domain,
891 &admin_account);
893 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
894 if (!W_ERROR_IS_OK(werr)) {
895 return werr;
898 u->in.domain_name = lp_realm();
899 u->in.unjoin_flags = r->in.unjoin_flags |
900 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
901 u->in.admin_account = admin_account;
902 u->in.admin_password = cleartext_pwd;
903 u->in.debug = true;
904 u->in.modify_config = lp_config_backend_is_registry();
905 u->in.msg_ctx = smbd_messaging_context();
907 become_root();
908 werr = libnet_Unjoin(p->mem_ctx, u);
909 unbecome_root();
911 if (!W_ERROR_IS_OK(werr)) {
912 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
913 u->out.error_string ? u->out.error_string :
914 win_errstr(werr)));
917 TALLOC_FREE(u);
918 return werr;
921 /********************************************************************
922 ********************************************************************/
924 WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r)
926 /* for now just return not supported */
927 return WERR_NOT_SUPPORTED;
930 /********************************************************************
931 ********************************************************************/
933 WERROR _wkssvc_NetrValidateName2(pipes_struct *p, struct wkssvc_NetrValidateName2 *r)
935 /* FIXME: Add implementation code here */
936 p->rng_fault_state = True;
937 return WERR_NOT_SUPPORTED;
940 /********************************************************************
941 ********************************************************************/
943 WERROR _wkssvc_NetrGetJoinableOus2(pipes_struct *p, struct wkssvc_NetrGetJoinableOus2 *r)
945 /* FIXME: Add implementation code here */
946 p->rng_fault_state = True;
947 return WERR_NOT_SUPPORTED;
950 /********************************************************************
951 ********************************************************************/
953 WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r)
955 /* FIXME: Add implementation code here */
956 p->rng_fault_state = True;
957 return WERR_NOT_SUPPORTED;
960 /********************************************************************
961 ********************************************************************/
963 WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *r)
965 /* FIXME: Add implementation code here */
966 p->rng_fault_state = True;
967 return WERR_NOT_SUPPORTED;
970 /********************************************************************
971 ********************************************************************/
973 WERROR _wkssvc_NetrSetPrimaryComputername(pipes_struct *p, struct wkssvc_NetrSetPrimaryComputername *r)
975 /* FIXME: Add implementation code here */
976 p->rng_fault_state = True;
977 return WERR_NOT_SUPPORTED;
980 /********************************************************************
981 ********************************************************************/
983 WERROR _wkssvc_NetrEnumerateComputerNames(pipes_struct *p, struct wkssvc_NetrEnumerateComputerNames *r)
985 /* FIXME: Add implementation code here */
986 p->rng_fault_state = True;
987 return WERR_NOT_SUPPORTED;