Revert "Fix bug #7067 - Linux asynchronous IO (aio) can cause smbd to fail to respond...
[Samba.git] / source3 / rpc_server / srv_wkssvc_nt.c
blobd7f3f82298e2b6e986b068412128af54dfecd1ce
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 void *p1, const void *p2)
50 const struct usrinfo *usr1 = (const struct usrinfo *)p1;
51 const struct usrinfo *usr2 = (const struct usrinfo *)p2;
53 /* Called from qsort to compare two users in a usrinfo_t array for
54 * sorting by login time. Return >0 if usr1 login time was later than
55 * usr2 login time, <0 if it was earlier */
56 return timeval_compare(&usr1->login_time, &usr2->login_time);
59 /*******************************************************************
60 Get a list of the names of all users logged into this machine
61 ********************************************************************/
63 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
65 char **users;
66 int i, num_users = 0;
67 struct usrinfo *usr_infos = NULL;
68 struct utmpx *u;
70 while ((u = getutxent()) != NULL) {
71 struct usrinfo *tmp;
72 if (u->ut_type != USER_PROCESS) {
73 continue;
75 for (i = 0; i < num_users; i++) {
76 /* getutxent can return multiple user entries for the
77 * same user, so ignore any dups */
78 if (strcmp(u->ut_user, usr_infos[i].name) == 0) {
79 break;
82 if (i < num_users) {
83 continue;
86 tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
87 num_users+1);
88 if (tmp == NULL) {
89 TALLOC_FREE(tmp);
90 endutxent();
91 return NULL;
93 usr_infos = tmp;
94 usr_infos[num_users].name = talloc_strdup(usr_infos,
95 u->ut_user);
96 if (usr_infos[num_users].name == NULL) {
97 TALLOC_FREE(usr_infos);
98 endutxent();
99 return NULL;
101 usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
102 usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
103 num_users += 1;
106 /* Sort the user list by time, oldest first */
107 qsort(usr_infos, num_users, sizeof(struct usrinfo), usr_info_cmp);
109 users = (char**)talloc_array(mem_ctx, char*, num_users);
110 if (users) {
111 for (i = 0; i < num_users; i++) {
112 users[i] = talloc_move(users, &usr_infos[i].name);
115 TALLOC_FREE(usr_infos);
116 endutxent();
117 errno = 0;
118 return users;
121 #else
123 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
125 return NULL;
128 #endif
130 static int dom_user_cmp(const void *p1, const void *p2)
132 /* Called from qsort to compare two domain users in a dom_usr_t array
133 * for sorting by login time. Return >0 if usr1 login time was later
134 * than usr2 login time, <0 if it was earlier */
135 const struct dom_usr *usr1 = (const struct dom_usr *)p1;
136 const struct dom_usr *usr2 = (const struct dom_usr *)p2;
138 return (usr1->login_time - usr2->login_time);
141 /*******************************************************************
142 Get a list of the names of all users of this machine who are
143 logged into the domain.
145 This should return a list of the users on this machine who are
146 logged into the domain (i.e. have been authenticated by the domain's
147 password server) but that doesn't fit well with the normal Samba
148 scenario where accesses out to the domain are made through smbclient
149 with each such session individually authenticated. So about the best
150 we can do currently is to list sessions of local users connected to
151 this server, which means that to get themself included in the list a
152 local user must create a session to the local samba server by running:
153 smbclient \\\\localhost\\share
155 FIXME: find a better way to get local users logged into the domain
156 in this list.
157 ********************************************************************/
159 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
161 struct sessionid *session_list = NULL;
162 char *machine_name, *p, *nm;
163 const char *sep;
164 struct dom_usr *users, *tmp;
165 int i, num_users, num_sessions;
167 sep = lp_winbind_separator();
168 if (!sep) {
169 sep = "\\";
172 num_sessions = list_sessions(mem_ctx, &session_list);
173 if (num_sessions == 0) {
174 errno = 0;
175 return NULL;
178 users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
179 if (users == NULL) {
180 TALLOC_FREE(session_list);
181 return NULL;
184 for (i=num_users=0; i<num_sessions; i++) {
185 if (!session_list[i].username
186 || !session_list[i].remote_machine) {
187 continue;
189 p = strpbrk(session_list[i].remote_machine, "./");
190 if (p) {
191 *p = '\0';
193 machine_name = talloc_asprintf_strupper_m(
194 users, "%s", session_list[i].remote_machine);
195 if (machine_name == NULL) {
196 DEBUG(10, ("talloc_asprintf failed\n"));
197 continue;
199 if (strcmp(machine_name, global_myname()) == 0) {
200 p = session_list[i].username;
201 nm = strstr(p, sep);
202 if (nm) {
204 * "domain+name" format so split domain and
205 * name components
207 *nm = '\0';
208 nm += strlen(sep);
209 users[num_users].domain =
210 talloc_asprintf_strupper_m(users,
211 "%s", p);
212 users[num_users].name = talloc_strdup(users,
213 nm);
214 } else {
216 * Simple user name so get domain from smb.conf
218 users[num_users].domain =
219 talloc_strdup(users, lp_workgroup());
220 users[num_users].name = talloc_strdup(users,
223 users[num_users].login_time =
224 session_list[i].connect_start;
225 num_users++;
227 TALLOC_FREE(machine_name);
229 TALLOC_FREE(session_list);
231 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
232 if (tmp == NULL) {
233 return NULL;
235 users = tmp;
237 /* Sort the user list by time, oldest first */
238 qsort(users, num_users, sizeof(struct dom_usr), dom_user_cmp);
240 errno = 0;
241 return users;
244 /*******************************************************************
245 RPC Workstation Service request NetWkstaGetInfo with level 100.
246 Returns to the requester:
247 - The machine name.
248 - The smb version number
249 - The domain name.
250 Returns a filled in wkssvc_NetWkstaInfo100 struct.
251 ********************************************************************/
253 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
255 struct wkssvc_NetWkstaInfo100 *info100;
257 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
258 if (info100 == NULL) {
259 return NULL;
262 info100->platform_id = PLATFORM_ID_NT; /* unknown */
263 info100->version_major = lp_major_announce_version();
264 info100->version_minor = lp_minor_announce_version();
266 info100->server_name = talloc_asprintf_strupper_m(
267 info100, "%s", global_myname());
268 info100->domain_name = talloc_asprintf_strupper_m(
269 info100, "%s", lp_workgroup());
271 return info100;
274 /*******************************************************************
275 RPC Workstation Service request NetWkstaGetInfo with level 101.
276 Returns to the requester:
277 - As per NetWkstaGetInfo with level 100, plus:
278 - The LANMAN directory path (not currently supported).
279 Returns a filled in wkssvc_NetWkstaInfo101 struct.
280 ********************************************************************/
282 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
284 struct wkssvc_NetWkstaInfo101 *info101;
286 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
287 if (info101 == NULL) {
288 return NULL;
291 info101->platform_id = PLATFORM_ID_NT; /* unknown */
292 info101->version_major = lp_major_announce_version();
293 info101->version_minor = lp_minor_announce_version();
295 info101->server_name = talloc_asprintf_strupper_m(
296 info101, "%s", global_myname());
297 info101->domain_name = talloc_asprintf_strupper_m(
298 info101, "%s", lp_workgroup());
299 info101->lan_root = "";
301 return info101;
304 /*******************************************************************
305 RPC Workstation Service request NetWkstaGetInfo with level 102.
306 Returns to the requester:
307 - As per NetWkstaGetInfo with level 101, plus:
308 - The number of logged in users.
309 Returns a filled in wkssvc_NetWkstaInfo102 struct.
310 ********************************************************************/
312 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
314 struct wkssvc_NetWkstaInfo102 *info102;
315 char **users;
317 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
318 if (info102 == NULL) {
319 return NULL;
322 info102->platform_id = PLATFORM_ID_NT; /* unknown */
323 info102->version_major = lp_major_announce_version();
324 info102->version_minor = lp_minor_announce_version();
326 info102->server_name = talloc_asprintf_strupper_m(
327 info102, "%s", global_myname());
328 info102->domain_name = talloc_asprintf_strupper_m(
329 info102, "%s", lp_workgroup());
330 info102->lan_root = "";
332 users = get_logged_on_userlist(talloc_tos());
333 info102->logged_on_users = talloc_array_length(users);
335 TALLOC_FREE(users);
337 return info102;
340 /********************************************************************
341 Handling for RPC Workstation Service request NetWkstaGetInfo
342 ********************************************************************/
344 WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
346 switch (r->in.level) {
347 case 100:
348 /* Level 100 can be allowed from anyone including anonymous
349 * so no access checks are needed for this case */
350 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
351 if (r->out.info->info100 == NULL) {
352 return WERR_NOMEM;
354 break;
355 case 101:
356 /* Level 101 can be allowed from any logged in user */
357 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
358 p->server_info->ptok)) {
359 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
360 "101\n"));
361 DEBUGADD(3,(" - does not have sid for Authenticated "
362 "Users %s:\n",
363 sid_string_dbg(
364 &global_sid_Authenticated_Users)));
365 debug_nt_user_token(DBGC_CLASS, 3,
366 p->server_info->ptok);
367 return WERR_ACCESS_DENIED;
369 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
370 if (r->out.info->info101 == NULL) {
371 return WERR_NOMEM;
373 break;
374 case 102:
375 /* Level 102 Should only be allowed from a domain administrator */
376 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
377 p->server_info->ptok)) {
378 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
379 "102\n"));
380 DEBUGADD(3,(" - does not have sid for Administrators "
381 "group %s, sids are:\n",
382 sid_string_dbg(&global_sid_Builtin_Administrators)));
383 debug_nt_user_token(DBGC_CLASS, 3,
384 p->server_info->ptok);
385 return WERR_ACCESS_DENIED;
387 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
388 if (r->out.info->info102 == NULL) {
389 return WERR_NOMEM;
391 break;
392 default:
393 return WERR_UNKNOWN_LEVEL;
396 return WERR_OK;
399 /********************************************************************
400 ********************************************************************/
402 WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r)
404 /* FIXME: Add implementation code here */
405 p->rng_fault_state = True;
406 return WERR_NOT_SUPPORTED;
409 /********************************************************************
410 RPC Workstation Service request NetWkstaEnumUsers with level 0:
411 Returns to the requester:
412 - the user names of the logged in users.
413 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
414 ********************************************************************/
416 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
417 TALLOC_CTX *mem_ctx)
419 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
420 char **users;
421 int i, num_users;
423 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
424 if (ctr0 == NULL) {
425 return NULL;
428 users = get_logged_on_userlist(talloc_tos());
429 if (users == NULL && errno != 0) {
430 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
431 errno, strerror(errno)));
432 TALLOC_FREE(ctr0);
433 return NULL;
436 num_users = talloc_array_length(users);
437 ctr0->entries_read = num_users;
438 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
439 num_users);
440 if (ctr0->user0 == NULL) {
441 TALLOC_FREE(ctr0);
442 TALLOC_FREE(users);
443 return NULL;
446 for (i=0; i<num_users; i++) {
447 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
449 TALLOC_FREE(users);
450 return ctr0;
453 /********************************************************************
454 RPC Workstation Service request NetWkstaEnumUsers with level 1.
455 Returns to the requester:
456 - the user names of the logged in users,
457 - the domain or machine each is logged into,
458 - the password server that was used to authenticate each,
459 - other domains each user is logged into (not currently supported).
460 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
461 ********************************************************************/
463 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
464 TALLOC_CTX *mem_ctx)
466 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
467 char **users;
468 struct dom_usr *dom_users;
469 const char *pwd_server;
470 char *pwd_tmp;
471 int i, j, num_users, num_dom_users;
473 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
474 if (ctr1 == NULL) {
475 return NULL;
478 users = get_logged_on_userlist(talloc_tos());
479 if (users == NULL && errno != 0) {
480 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
481 errno, strerror(errno)));
482 TALLOC_FREE(ctr1);
483 return NULL;
485 num_users = talloc_array_length(users);
487 dom_users = get_domain_userlist(talloc_tos());
488 if (dom_users == NULL && errno != 0) {
489 TALLOC_FREE(ctr1);
490 TALLOC_FREE(users);
491 return NULL;
493 num_dom_users = talloc_array_length(dom_users);
495 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
496 num_users+num_dom_users);
497 if (ctr1->user1 == NULL) {
498 TALLOC_FREE(ctr1);
499 TALLOC_FREE(users);
500 TALLOC_FREE(dom_users);
501 return NULL;
504 pwd_server = "";
506 if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) {
507 /* The configured password server is a full DNS name but
508 * for the logon server we need to return just the first
509 * component (machine name) of it in upper-case */
510 char *p = strchr(pwd_tmp, '.');
511 if (p) {
512 *p = '\0';
513 } else {
514 p = pwd_tmp + strlen(pwd_tmp);
516 while (--p >= pwd_tmp) {
517 *p = toupper(*p);
519 pwd_server = pwd_tmp;
522 /* Put in local users first */
523 for (i=0; i<num_users; i++) {
524 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
526 /* For a local user the domain name and logon server are
527 * both returned as the local machine's NetBIOS name */
528 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
529 talloc_asprintf_strupper_m(ctr1->user1, "%s", global_myname());
531 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */
534 /* Now domain users */
535 for (j=0; j<num_dom_users; j++) {
536 ctr1->user1[i].user_name =
537 talloc_strdup(ctr1->user1, dom_users[j].name);
538 ctr1->user1[i].logon_domain =
539 talloc_strdup(ctr1->user1, dom_users[j].domain);
540 ctr1->user1[i].logon_server = pwd_server;
542 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
545 ctr1->entries_read = i;
547 TALLOC_FREE(users);
548 TALLOC_FREE(dom_users);
549 return ctr1;
552 /********************************************************************
553 Handling for RPC Workstation Service request NetWkstaEnumUsers
554 (a.k.a Windows NetWkstaUserEnum)
555 ********************************************************************/
557 WERROR _wkssvc_NetWkstaEnumUsers(pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r)
559 /* This with any level should only be allowed from a domain administrator */
560 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
561 p->server_info->ptok)) {
562 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
563 DEBUGADD(3,(" - does not have sid for Administrators group "
564 "%s\n", sid_string_dbg(
565 &global_sid_Builtin_Administrators)));
566 debug_nt_user_token(DBGC_CLASS, 3, p->server_info->ptok);
567 return WERR_ACCESS_DENIED;
570 switch (r->in.info->level) {
571 case 0:
572 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
573 if (r->out.info->ctr.user0 == NULL) {
574 return WERR_NOMEM;
576 r->out.info->level = r->in.info->level;
577 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
578 *r->out.resume_handle = 0;
579 break;
580 case 1:
581 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
582 if (r->out.info->ctr.user1 == NULL) {
583 return WERR_NOMEM;
585 r->out.info->level = r->in.info->level;
586 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
587 *r->out.resume_handle = 0;
588 break;
589 default:
590 return WERR_UNKNOWN_LEVEL;
593 return WERR_OK;
596 /********************************************************************
597 ********************************************************************/
599 WERROR _wkssvc_NetrWkstaUserGetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserGetInfo *r)
601 /* FIXME: Add implementation code here */
602 p->rng_fault_state = True;
603 return WERR_NOT_SUPPORTED;
606 /********************************************************************
607 ********************************************************************/
609 WERROR _wkssvc_NetrWkstaUserSetInfo(pipes_struct *p, 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(pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r)
621 /* FIXME: Add implementation code here */
622 p->rng_fault_state = True;
623 return WERR_NOT_SUPPORTED;
626 /********************************************************************
627 ********************************************************************/
629 WERROR _wkssvc_NetrWkstaTransportAdd(pipes_struct *p, struct wkssvc_NetrWkstaTransportAdd *r)
631 /* FIXME: Add implementation code here */
632 p->rng_fault_state = True;
633 return WERR_NOT_SUPPORTED;
636 /********************************************************************
637 ********************************************************************/
639 WERROR _wkssvc_NetrWkstaTransportDel(pipes_struct *p, struct wkssvc_NetrWkstaTransportDel *r)
641 /* FIXME: Add implementation code here */
642 p->rng_fault_state = True;
643 return WERR_NOT_SUPPORTED;
646 /********************************************************************
647 ********************************************************************/
649 WERROR _wkssvc_NetrUseAdd(pipes_struct *p, struct wkssvc_NetrUseAdd *r)
651 /* FIXME: Add implementation code here */
652 p->rng_fault_state = True;
653 return WERR_NOT_SUPPORTED;
656 /********************************************************************
657 ********************************************************************/
659 WERROR _wkssvc_NetrUseGetInfo(pipes_struct *p, struct wkssvc_NetrUseGetInfo *r)
661 /* FIXME: Add implementation code here */
662 p->rng_fault_state = True;
663 return WERR_NOT_SUPPORTED;
666 /********************************************************************
667 ********************************************************************/
669 WERROR _wkssvc_NetrUseDel(pipes_struct *p, struct wkssvc_NetrUseDel *r)
671 /* FIXME: Add implementation code here */
672 p->rng_fault_state = True;
673 return WERR_NOT_SUPPORTED;
676 /********************************************************************
677 ********************************************************************/
679 WERROR _wkssvc_NetrUseEnum(pipes_struct *p, struct wkssvc_NetrUseEnum *r)
681 /* FIXME: Add implementation code here */
682 p->rng_fault_state = True;
683 return WERR_NOT_SUPPORTED;
686 /********************************************************************
687 ********************************************************************/
689 WERROR _wkssvc_NetrMessageBufferSend(pipes_struct *p, struct wkssvc_NetrMessageBufferSend *r)
691 /* FIXME: Add implementation code here */
692 p->rng_fault_state = True;
693 return WERR_NOT_SUPPORTED;
696 /********************************************************************
697 ********************************************************************/
699 WERROR _wkssvc_NetrWorkstationStatisticsGet(pipes_struct *p, struct wkssvc_NetrWorkstationStatisticsGet *r)
701 /* FIXME: Add implementation code here */
702 p->rng_fault_state = True;
703 return WERR_NOT_SUPPORTED;
706 /********************************************************************
707 ********************************************************************/
709 WERROR _wkssvc_NetrLogonDomainNameAdd(pipes_struct *p, struct wkssvc_NetrLogonDomainNameAdd *r)
711 /* FIXME: Add implementation code here */
712 p->rng_fault_state = True;
713 return WERR_NOT_SUPPORTED;
716 /********************************************************************
717 ********************************************************************/
719 WERROR _wkssvc_NetrLogonDomainNameDel(pipes_struct *p, struct wkssvc_NetrLogonDomainNameDel *r)
721 /* FIXME: Add implementation code here */
722 p->rng_fault_state = True;
723 return WERR_NOT_SUPPORTED;
726 /********************************************************************
727 ********************************************************************/
729 WERROR _wkssvc_NetrJoinDomain(pipes_struct *p, struct wkssvc_NetrJoinDomain *r)
731 /* FIXME: Add implementation code here */
732 p->rng_fault_state = True;
733 return WERR_NOT_SUPPORTED;
736 /********************************************************************
737 ********************************************************************/
739 WERROR _wkssvc_NetrUnjoinDomain(pipes_struct *p, struct wkssvc_NetrUnjoinDomain *r)
741 /* FIXME: Add implementation code here */
742 p->rng_fault_state = True;
743 return WERR_NOT_SUPPORTED;
746 /********************************************************************
747 ********************************************************************/
749 WERROR _wkssvc_NetrRenameMachineInDomain(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain *r)
751 /* FIXME: Add implementation code here */
752 p->rng_fault_state = True;
753 return WERR_NOT_SUPPORTED;
756 /********************************************************************
757 ********************************************************************/
759 WERROR _wkssvc_NetrValidateName(pipes_struct *p, struct wkssvc_NetrValidateName *r)
761 /* FIXME: Add implementation code here */
762 p->rng_fault_state = True;
763 return WERR_NOT_SUPPORTED;
766 /********************************************************************
767 ********************************************************************/
769 WERROR _wkssvc_NetrGetJoinInformation(pipes_struct *p, struct wkssvc_NetrGetJoinInformation *r)
771 /* FIXME: Add implementation code here */
772 p->rng_fault_state = True;
773 return WERR_NOT_SUPPORTED;
776 /********************************************************************
777 ********************************************************************/
779 WERROR _wkssvc_NetrGetJoinableOus(pipes_struct *p, struct wkssvc_NetrGetJoinableOus *r)
781 /* FIXME: Add implementation code here */
782 p->rng_fault_state = True;
783 return WERR_NOT_SUPPORTED;
786 /********************************************************************
787 _wkssvc_NetrJoinDomain2
788 ********************************************************************/
790 WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p,
791 struct wkssvc_NetrJoinDomain2 *r)
793 struct libnet_JoinCtx *j = NULL;
794 char *cleartext_pwd = NULL;
795 char *admin_domain = NULL;
796 char *admin_account = NULL;
797 WERROR werr;
798 struct nt_user_token *token = p->server_info->ptok;
800 if (!r->in.domain_name) {
801 return WERR_INVALID_PARAM;
804 if (!r->in.admin_account || !r->in.encrypted_password) {
805 return WERR_INVALID_PARAM;
808 if (!user_has_privileges(token, &se_machine_account) &&
809 !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) &&
810 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
811 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
812 "sufficient privileges\n"));
813 return WERR_ACCESS_DENIED;
816 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
817 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
818 return WERR_NOT_SUPPORTED;
821 werr = decode_wkssvc_join_password_buffer(
822 p->mem_ctx, r->in.encrypted_password,
823 &p->server_info->user_session_key, &cleartext_pwd);
824 if (!W_ERROR_IS_OK(werr)) {
825 return werr;
828 split_domain_user(p->mem_ctx,
829 r->in.admin_account,
830 &admin_domain,
831 &admin_account);
833 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
834 if (!W_ERROR_IS_OK(werr)) {
835 return werr;
838 j->in.domain_name = r->in.domain_name;
839 j->in.account_ou = r->in.account_ou;
840 j->in.join_flags = r->in.join_flags;
841 j->in.admin_account = admin_account;
842 j->in.admin_password = cleartext_pwd;
843 j->in.debug = true;
844 j->in.modify_config = lp_config_backend_is_registry();
845 j->in.msg_ctx = smbd_messaging_context();
847 become_root();
848 werr = libnet_Join(p->mem_ctx, j);
849 unbecome_root();
851 if (!W_ERROR_IS_OK(werr)) {
852 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
853 j->out.error_string ? j->out.error_string :
854 win_errstr(werr)));
857 TALLOC_FREE(j);
858 return werr;
861 /********************************************************************
862 _wkssvc_NetrUnjoinDomain2
863 ********************************************************************/
865 WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p,
866 struct wkssvc_NetrUnjoinDomain2 *r)
868 struct libnet_UnjoinCtx *u = NULL;
869 char *cleartext_pwd = NULL;
870 char *admin_domain = NULL;
871 char *admin_account = NULL;
872 WERROR werr;
873 struct nt_user_token *token = p->server_info->ptok;
875 if (!r->in.account || !r->in.encrypted_password) {
876 return WERR_INVALID_PARAM;
879 if (!user_has_privileges(token, &se_machine_account) &&
880 !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) &&
881 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
882 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
883 "sufficient privileges\n"));
884 return WERR_ACCESS_DENIED;
887 werr = decode_wkssvc_join_password_buffer(
888 p->mem_ctx, r->in.encrypted_password,
889 &p->server_info->user_session_key, &cleartext_pwd);
890 if (!W_ERROR_IS_OK(werr)) {
891 return werr;
894 split_domain_user(p->mem_ctx,
895 r->in.account,
896 &admin_domain,
897 &admin_account);
899 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
900 if (!W_ERROR_IS_OK(werr)) {
901 return werr;
904 u->in.domain_name = lp_realm();
905 u->in.unjoin_flags = r->in.unjoin_flags |
906 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
907 u->in.admin_account = admin_account;
908 u->in.admin_password = cleartext_pwd;
909 u->in.debug = true;
910 u->in.modify_config = lp_config_backend_is_registry();
911 u->in.msg_ctx = smbd_messaging_context();
913 become_root();
914 werr = libnet_Unjoin(p->mem_ctx, u);
915 unbecome_root();
917 if (!W_ERROR_IS_OK(werr)) {
918 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
919 u->out.error_string ? u->out.error_string :
920 win_errstr(werr)));
923 TALLOC_FREE(u);
924 return werr;
927 /********************************************************************
928 ********************************************************************/
930 WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r)
932 /* for now just return not supported */
933 return WERR_NOT_SUPPORTED;
936 /********************************************************************
937 ********************************************************************/
939 WERROR _wkssvc_NetrValidateName2(pipes_struct *p, struct wkssvc_NetrValidateName2 *r)
941 /* FIXME: Add implementation code here */
942 p->rng_fault_state = True;
943 return WERR_NOT_SUPPORTED;
946 /********************************************************************
947 ********************************************************************/
949 WERROR _wkssvc_NetrGetJoinableOus2(pipes_struct *p, struct wkssvc_NetrGetJoinableOus2 *r)
951 /* FIXME: Add implementation code here */
952 p->rng_fault_state = True;
953 return WERR_NOT_SUPPORTED;
956 /********************************************************************
957 ********************************************************************/
959 WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r)
961 /* FIXME: Add implementation code here */
962 p->rng_fault_state = True;
963 return WERR_NOT_SUPPORTED;
966 /********************************************************************
967 ********************************************************************/
969 WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *r)
971 /* FIXME: Add implementation code here */
972 p->rng_fault_state = True;
973 return WERR_NOT_SUPPORTED;
976 /********************************************************************
977 ********************************************************************/
979 WERROR _wkssvc_NetrSetPrimaryComputername(pipes_struct *p, struct wkssvc_NetrSetPrimaryComputername *r)
981 /* FIXME: Add implementation code here */
982 p->rng_fault_state = True;
983 return WERR_NOT_SUPPORTED;
986 /********************************************************************
987 ********************************************************************/
989 WERROR _wkssvc_NetrEnumerateComputerNames(pipes_struct *p, struct wkssvc_NetrEnumerateComputerNames *r)
991 /* FIXME: Add implementation code here */
992 p->rng_fault_state = True;
993 return WERR_NOT_SUPPORTED;