• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source3/rpc_server/
1/*
2 *  Unix SMB/CIFS implementation.
3 *  RPC Pipe client / server routines
4 *
5 *  Copyright (C) Andrew Tridgell		1992-1997,
6 *  Copyright (C) Gerald (Jerry) Carter		2006.
7 *  Copyright (C) Guenther Deschner		2007-2008.
8 *
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.
13 *
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.
18 *
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/>.
21 */
22
23/* This is the implementation of the wks interface. */
24
25#include "includes.h"
26#include "libnet/libnet.h"
27#include "../libcli/auth/libcli_auth.h"
28#include "../librpc/gen_ndr/srv_wkssvc.h"
29
30#undef DBGC_CLASS
31#define DBGC_CLASS DBGC_RPC_SRV
32
33struct dom_usr {
34	char *name;
35	char *domain;
36	time_t login_time;
37};
38
39#ifdef HAVE_GETUTXENT
40
41#include <utmpx.h>
42
43struct usrinfo {
44	char *name;
45	struct timeval login_time;
46};
47
48static int usr_info_cmp(const void *p1, const void *p2)
49{
50	const struct usrinfo *usr1 = (const struct usrinfo *)p1;
51	const struct usrinfo *usr2 = (const struct usrinfo *)p2;
52
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);
57}
58
59/*******************************************************************
60 Get a list of the names of all users logged into this machine
61 ********************************************************************/
62
63static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
64{
65	char **users;
66	int i, num_users = 0;
67	struct usrinfo *usr_infos = NULL;
68	struct utmpx *u;
69
70	while ((u = getutxent()) != NULL) {
71		struct usrinfo *tmp;
72		if (u->ut_type != USER_PROCESS) {
73			continue;
74		}
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;
80			}
81		}
82		if (i < num_users) {
83			continue;
84		}
85
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;
92		}
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;
100		}
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;
104	}
105
106	/* Sort the user list by time, oldest first */
107	qsort(usr_infos, num_users, sizeof(struct usrinfo), usr_info_cmp);
108
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);
113		}
114	}
115	TALLOC_FREE(usr_infos);
116	endutxent();
117	errno = 0;
118	return users;
119}
120
121#else
122
123static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
124{
125	return NULL;
126}
127
128#endif
129
130static int dom_user_cmp(const void *p1, const void *p2)
131{
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;
137
138	return (usr1->login_time - usr2->login_time);
139}
140
141/*******************************************************************
142 Get a list of the names of all users of this machine who are
143 logged into the domain.
144
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
154
155 FIXME: find a better way to get local users logged into the domain
156 in this list.
157 ********************************************************************/
158
159static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
160{
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;
166
167	sep = lp_winbind_separator();
168	if (!sep) {
169		sep = "\\";
170	}
171
172	num_sessions = list_sessions(mem_ctx, &session_list);
173	if (num_sessions == 0) {
174		errno = 0;
175		return NULL;
176	}
177
178	users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
179	if (users == NULL) {
180		TALLOC_FREE(session_list);
181		return NULL;
182	}
183
184	for (i=num_users=0; i<num_sessions; i++) {
185		if (!session_list[i].username
186		    || !session_list[i].remote_machine) {
187			continue;
188		}
189		p = strpbrk(session_list[i].remote_machine, "./");
190		if (p) {
191			*p = '\0';
192		}
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;
198		}
199		if (strcmp(machine_name, global_myname()) == 0) {
200			p = session_list[i].username;
201			nm = strstr(p, sep);
202			if (nm) {
203				/*
204				 * "domain+name" format so split domain and
205				 * name components
206				 */
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 {
215				/*
216				 * Simple user name so get domain from smb.conf
217				 */
218				users[num_users].domain =
219					talloc_strdup(users, lp_workgroup());
220				users[num_users].name = talloc_strdup(users,
221								      p);
222			}
223			users[num_users].login_time =
224				session_list[i].connect_start;
225			num_users++;
226		}
227		TALLOC_FREE(machine_name);
228	}
229	TALLOC_FREE(session_list);
230
231	tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
232	if (tmp == NULL) {
233		return NULL;
234	}
235	users = tmp;
236
237	/* Sort the user list by time, oldest first */
238	qsort(users, num_users, sizeof(struct dom_usr), dom_user_cmp);
239
240	errno = 0;
241	return users;
242}
243
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 ********************************************************************/
252
253static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
254{
255	struct wkssvc_NetWkstaInfo100 *info100;
256
257	info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
258	if (info100 == NULL) {
259		return NULL;
260	}
261
262	info100->platform_id	 = PLATFORM_ID_NT;	/* unknown */
263	info100->version_major	 = lp_major_announce_version();
264	info100->version_minor	 = lp_minor_announce_version();
265
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());
270
271	return info100;
272}
273
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 ********************************************************************/
281
282static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
283{
284	struct wkssvc_NetWkstaInfo101 *info101;
285
286	info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
287	if (info101 == NULL) {
288		return NULL;
289	}
290
291	info101->platform_id	 = PLATFORM_ID_NT;	/* unknown */
292	info101->version_major	 = lp_major_announce_version();
293	info101->version_minor	 = lp_minor_announce_version();
294
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 = "";
300
301	return info101;
302}
303
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 ********************************************************************/
311
312static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
313{
314	struct wkssvc_NetWkstaInfo102 *info102;
315	char **users;
316
317	info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
318	if (info102 == NULL) {
319		return NULL;
320	}
321
322	info102->platform_id	 = PLATFORM_ID_NT;	/* unknown */
323	info102->version_major	 = lp_major_announce_version();
324	info102->version_minor	 = lp_minor_announce_version();
325
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 = "";
331
332	users = get_logged_on_userlist(talloc_tos());
333	info102->logged_on_users = talloc_array_length(users);
334
335	TALLOC_FREE(users);
336
337	return info102;
338}
339
340/********************************************************************
341 Handling for RPC Workstation Service request NetWkstaGetInfo
342 ********************************************************************/
343
344WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
345{
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;
353		}
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;
368		}
369		r->out.info->info101 = create_wks_info_101(p->mem_ctx);
370		if (r->out.info->info101 == NULL) {
371			return WERR_NOMEM;
372		}
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;
386		}
387		r->out.info->info102 = create_wks_info_102(p->mem_ctx);
388		if (r->out.info->info102 == NULL) {
389			return WERR_NOMEM;
390		}
391		break;
392	default:
393		return WERR_UNKNOWN_LEVEL;
394	}
395
396	return WERR_OK;
397}
398
399/********************************************************************
400 ********************************************************************/
401
402WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r)
403{
404	/* FIXME: Add implementation code here */
405	p->rng_fault_state = True;
406	return WERR_NOT_SUPPORTED;
407}
408
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 ********************************************************************/
415
416static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
417	TALLOC_CTX *mem_ctx)
418{
419	struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
420	char **users;
421	int i, num_users;
422
423	ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
424	if (ctr0 == NULL) {
425		return NULL;
426	}
427
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;
434	}
435
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;
444	}
445
446	for (i=0; i<num_users; i++) {
447		ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
448	}
449	TALLOC_FREE(users);
450	return ctr0;
451}
452
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 ********************************************************************/
462
463static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
464	TALLOC_CTX *mem_ctx)
465{
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;
472
473	ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
474	if (ctr1 == NULL) {
475		return NULL;
476	}
477
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;
484	}
485	num_users = talloc_array_length(users);
486
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;
492	}
493	num_dom_users = talloc_array_length(dom_users);
494
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;
502	}
503
504	pwd_server = "";
505
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);
515		}
516		while (--p >= pwd_tmp) {
517			*p = toupper(*p);
518		}
519		pwd_server = pwd_tmp;
520	}
521
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]);
525
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());
530
531		ctr1->user1[i].other_domains = NULL;	/* Maybe in future? */
532	}
533
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;
541
542		ctr1->user1[i++].other_domains = NULL;	/* Maybe in future? */
543	}
544
545	ctr1->entries_read = i;
546
547	TALLOC_FREE(users);
548	TALLOC_FREE(dom_users);
549	return ctr1;
550}
551
552/********************************************************************
553 Handling for RPC Workstation Service request NetWkstaEnumUsers
554 (a.k.a Windows NetWkstaUserEnum)
555 ********************************************************************/
556
557WERROR _wkssvc_NetWkstaEnumUsers(pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r)
558{
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;
568	}
569
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;
575		}
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;
584		}
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;
591	}
592
593	return WERR_OK;
594}
595
596/********************************************************************
597 ********************************************************************/
598
599WERROR _wkssvc_NetrWkstaUserGetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserGetInfo *r)
600{
601	/* FIXME: Add implementation code here */
602	p->rng_fault_state = True;
603	return WERR_NOT_SUPPORTED;
604}
605
606/********************************************************************
607 ********************************************************************/
608
609WERROR _wkssvc_NetrWkstaUserSetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserSetInfo *r)
610{
611	/* FIXME: Add implementation code here */
612	p->rng_fault_state = True;
613	return WERR_NOT_SUPPORTED;
614}
615
616/********************************************************************
617 ********************************************************************/
618
619WERROR _wkssvc_NetWkstaTransportEnum(pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r)
620{
621	/* FIXME: Add implementation code here */
622	p->rng_fault_state = True;
623	return WERR_NOT_SUPPORTED;
624}
625
626/********************************************************************
627 ********************************************************************/
628
629WERROR _wkssvc_NetrWkstaTransportAdd(pipes_struct *p, struct wkssvc_NetrWkstaTransportAdd *r)
630{
631	/* FIXME: Add implementation code here */
632	p->rng_fault_state = True;
633	return WERR_NOT_SUPPORTED;
634}
635
636/********************************************************************
637 ********************************************************************/
638
639WERROR _wkssvc_NetrWkstaTransportDel(pipes_struct *p, struct wkssvc_NetrWkstaTransportDel *r)
640{
641	/* FIXME: Add implementation code here */
642	p->rng_fault_state = True;
643	return WERR_NOT_SUPPORTED;
644}
645
646/********************************************************************
647 ********************************************************************/
648
649WERROR _wkssvc_NetrUseAdd(pipes_struct *p, struct wkssvc_NetrUseAdd *r)
650{
651	/* FIXME: Add implementation code here */
652	p->rng_fault_state = True;
653	return WERR_NOT_SUPPORTED;
654}
655
656/********************************************************************
657 ********************************************************************/
658
659WERROR _wkssvc_NetrUseGetInfo(pipes_struct *p, struct wkssvc_NetrUseGetInfo *r)
660{
661	/* FIXME: Add implementation code here */
662	p->rng_fault_state = True;
663	return WERR_NOT_SUPPORTED;
664}
665
666/********************************************************************
667 ********************************************************************/
668
669WERROR _wkssvc_NetrUseDel(pipes_struct *p, struct wkssvc_NetrUseDel *r)
670{
671	/* FIXME: Add implementation code here */
672	p->rng_fault_state = True;
673	return WERR_NOT_SUPPORTED;
674}
675
676/********************************************************************
677 ********************************************************************/
678
679WERROR _wkssvc_NetrUseEnum(pipes_struct *p, struct wkssvc_NetrUseEnum *r)
680{
681	/* FIXME: Add implementation code here */
682	p->rng_fault_state = True;
683	return WERR_NOT_SUPPORTED;
684}
685
686/********************************************************************
687 ********************************************************************/
688
689WERROR _wkssvc_NetrMessageBufferSend(pipes_struct *p, struct wkssvc_NetrMessageBufferSend *r)
690{
691	/* FIXME: Add implementation code here */
692	p->rng_fault_state = True;
693	return WERR_NOT_SUPPORTED;
694}
695
696/********************************************************************
697 ********************************************************************/
698
699WERROR _wkssvc_NetrWorkstationStatisticsGet(pipes_struct *p, struct wkssvc_NetrWorkstationStatisticsGet *r)
700{
701	/* FIXME: Add implementation code here */
702	p->rng_fault_state = True;
703	return WERR_NOT_SUPPORTED;
704}
705
706/********************************************************************
707 ********************************************************************/
708
709WERROR _wkssvc_NetrLogonDomainNameAdd(pipes_struct *p, struct wkssvc_NetrLogonDomainNameAdd *r)
710{
711	/* FIXME: Add implementation code here */
712	p->rng_fault_state = True;
713	return WERR_NOT_SUPPORTED;
714}
715
716/********************************************************************
717 ********************************************************************/
718
719WERROR _wkssvc_NetrLogonDomainNameDel(pipes_struct *p, struct wkssvc_NetrLogonDomainNameDel *r)
720{
721	/* FIXME: Add implementation code here */
722	p->rng_fault_state = True;
723	return WERR_NOT_SUPPORTED;
724}
725
726/********************************************************************
727 ********************************************************************/
728
729WERROR _wkssvc_NetrJoinDomain(pipes_struct *p, struct wkssvc_NetrJoinDomain *r)
730{
731	/* FIXME: Add implementation code here */
732	p->rng_fault_state = True;
733	return WERR_NOT_SUPPORTED;
734}
735
736/********************************************************************
737 ********************************************************************/
738
739WERROR _wkssvc_NetrUnjoinDomain(pipes_struct *p, struct wkssvc_NetrUnjoinDomain *r)
740{
741	/* FIXME: Add implementation code here */
742	p->rng_fault_state = True;
743	return WERR_NOT_SUPPORTED;
744}
745
746/********************************************************************
747 ********************************************************************/
748
749WERROR _wkssvc_NetrRenameMachineInDomain(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain *r)
750{
751	/* FIXME: Add implementation code here */
752	p->rng_fault_state = True;
753	return WERR_NOT_SUPPORTED;
754}
755
756/********************************************************************
757 ********************************************************************/
758
759WERROR _wkssvc_NetrValidateName(pipes_struct *p, struct wkssvc_NetrValidateName *r)
760{
761	/* FIXME: Add implementation code here */
762	p->rng_fault_state = True;
763	return WERR_NOT_SUPPORTED;
764}
765
766/********************************************************************
767 ********************************************************************/
768
769WERROR _wkssvc_NetrGetJoinInformation(pipes_struct *p, struct wkssvc_NetrGetJoinInformation *r)
770{
771	/* FIXME: Add implementation code here */
772	p->rng_fault_state = True;
773	return WERR_NOT_SUPPORTED;
774}
775
776/********************************************************************
777 ********************************************************************/
778
779WERROR _wkssvc_NetrGetJoinableOus(pipes_struct *p, struct wkssvc_NetrGetJoinableOus *r)
780{
781	/* FIXME: Add implementation code here */
782	p->rng_fault_state = True;
783	return WERR_NOT_SUPPORTED;
784}
785
786/********************************************************************
787 _wkssvc_NetrJoinDomain2
788 ********************************************************************/
789
790WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p,
791			       struct wkssvc_NetrJoinDomain2 *r)
792{
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;
799
800	if (!r->in.domain_name) {
801		return WERR_INVALID_PARAM;
802	}
803
804	if (!r->in.admin_account || !r->in.encrypted_password) {
805		return WERR_INVALID_PARAM;
806	}
807
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;
814	}
815
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;
819	}
820
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;
826	}
827
828	split_domain_user(p->mem_ctx,
829			  r->in.admin_account,
830			  &admin_domain,
831			  &admin_account);
832
833	werr = libnet_init_JoinCtx(p->mem_ctx, &j);
834	if (!W_ERROR_IS_OK(werr)) {
835		return werr;
836	}
837
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();
846
847	become_root();
848	werr = libnet_Join(p->mem_ctx, j);
849	unbecome_root();
850
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)));
855	}
856
857	TALLOC_FREE(j);
858	return werr;
859}
860
861/********************************************************************
862 _wkssvc_NetrUnjoinDomain2
863 ********************************************************************/
864
865WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p,
866				 struct wkssvc_NetrUnjoinDomain2 *r)
867{
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;
874
875	if (!r->in.account || !r->in.encrypted_password) {
876		return WERR_INVALID_PARAM;
877	}
878
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;
885	}
886
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;
892	}
893
894	split_domain_user(p->mem_ctx,
895			  r->in.account,
896			  &admin_domain,
897			  &admin_account);
898
899	werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
900	if (!W_ERROR_IS_OK(werr)) {
901		return werr;
902	}
903
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();
912
913	become_root();
914	werr = libnet_Unjoin(p->mem_ctx, u);
915	unbecome_root();
916
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)));
921	}
922
923	TALLOC_FREE(u);
924	return werr;
925}
926
927/********************************************************************
928 ********************************************************************/
929
930WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r)
931{
932	/* for now just return not supported */
933	return WERR_NOT_SUPPORTED;
934}
935
936/********************************************************************
937 ********************************************************************/
938
939WERROR _wkssvc_NetrValidateName2(pipes_struct *p, struct wkssvc_NetrValidateName2 *r)
940{
941	/* FIXME: Add implementation code here */
942	p->rng_fault_state = True;
943	return WERR_NOT_SUPPORTED;
944}
945
946/********************************************************************
947 ********************************************************************/
948
949WERROR _wkssvc_NetrGetJoinableOus2(pipes_struct *p, struct wkssvc_NetrGetJoinableOus2 *r)
950{
951	/* FIXME: Add implementation code here */
952	p->rng_fault_state = True;
953	return WERR_NOT_SUPPORTED;
954}
955
956/********************************************************************
957 ********************************************************************/
958
959WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r)
960{
961	/* FIXME: Add implementation code here */
962	p->rng_fault_state = True;
963	return WERR_NOT_SUPPORTED;
964}
965
966/********************************************************************
967 ********************************************************************/
968
969WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *r)
970{
971	/* FIXME: Add implementation code here */
972	p->rng_fault_state = True;
973	return WERR_NOT_SUPPORTED;
974}
975
976/********************************************************************
977 ********************************************************************/
978
979WERROR _wkssvc_NetrSetPrimaryComputername(pipes_struct *p, struct wkssvc_NetrSetPrimaryComputername *r)
980{
981	/* FIXME: Add implementation code here */
982	p->rng_fault_state = True;
983	return WERR_NOT_SUPPORTED;
984}
985
986/********************************************************************
987 ********************************************************************/
988
989WERROR _wkssvc_NetrEnumerateComputerNames(pipes_struct *p, struct wkssvc_NetrEnumerateComputerNames *r)
990{
991	/* FIXME: Add implementation code here */
992	p->rng_fault_state = True;
993	return WERR_NOT_SUPPORTED;
994}
995
996