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 "ntdomain.h"
27 #include "librpc/gen_ndr/libnet_join.h"
28 #include "libnet/libnet_join.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/srv_wkssvc.h"
31 #include "../libcli/security/security.h"
32 #include "session.h"
33 #include "smbd/smbd.h"
34 #include "auth.h"
35 #include "krb5_env.h"
36 
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_RPC_SRV
39 
40 struct dom_usr {
41 	char *name;
42 	char *domain;
43 	time_t login_time;
44 };
45 
46 #ifdef HAVE_GETUTXENT
47 
48 #include <utmpx.h>
49 
50 struct usrinfo {
51 	char *name;
52 	struct timeval login_time;
53 };
54 
usr_info_cmp(const struct usrinfo * usr1,const struct usrinfo * usr2)55 static int usr_info_cmp(const struct usrinfo *usr1, const struct usrinfo *usr2)
56 {
57 	/* Called from qsort to compare two users in a usrinfo_t array for
58 	 * sorting by login time. Return >0 if usr1 login time was later than
59 	 * usr2 login time, <0 if it was earlier */
60 	return timeval_compare(&usr1->login_time, &usr2->login_time);
61 }
62 
63 /*******************************************************************
64  Get a list of the names of all users logged into this machine
65  ********************************************************************/
66 
get_logged_on_userlist(TALLOC_CTX * mem_ctx)67 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
68 {
69 	char **users;
70 	int i, num_users = 0;
71 	struct usrinfo *usr_infos = NULL;
72 	struct utmpx *u;
73 
74 	while ((u = getutxent()) != NULL) {
75 		struct usrinfo *tmp;
76 		if (u->ut_type != USER_PROCESS) {
77 			continue;
78 		}
79 		for (i = 0; i < num_users; i++) {
80 			/* getutxent can return multiple user entries for the
81 			 * same user, so ignore any dups */
82 			int cmp = strncmp(u->ut_user, usr_infos[i].name, sizeof(u->ut_user));
83 			if (cmp == 0) {
84 				break;
85 			}
86 		}
87 		if (i < num_users) {
88 			continue;
89 		}
90 
91 		tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
92 				     num_users+1);
93 		if (tmp == NULL) {
94 			TALLOC_FREE(tmp);
95 			endutxent();
96 			return NULL;
97 		}
98 		usr_infos = tmp;
99 		usr_infos[num_users].name = talloc_strdup(usr_infos,
100 							  u->ut_user);
101 		if (usr_infos[num_users].name == NULL) {
102 			TALLOC_FREE(usr_infos);
103 			endutxent();
104 			return NULL;
105 		}
106 		usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
107 		usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
108 		num_users += 1;
109 	}
110 
111 	/* Sort the user list by time, oldest first */
112 	TYPESAFE_QSORT(usr_infos, num_users, usr_info_cmp);
113 
114 	users = (char**)talloc_array(mem_ctx, char*, num_users);
115 	if (users) {
116 		for (i = 0; i < num_users; i++) {
117 			users[i] = talloc_move(users, &usr_infos[i].name);
118 		}
119 	}
120 	TALLOC_FREE(usr_infos);
121 	endutxent();
122 	errno = 0;
123 	return users;
124 }
125 
126 #else
127 
get_logged_on_userlist(TALLOC_CTX * mem_ctx)128 static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
129 {
130 	return NULL;
131 }
132 
133 #endif
134 
dom_user_cmp(const struct dom_usr * usr1,const struct dom_usr * usr2)135 static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
136 {
137 	/* Called from qsort to compare two domain users in a dom_usr_t array
138 	 * for sorting by login time. Return >0 if usr1 login time was later
139 	 * than usr2 login time, <0 if it was earlier */
140 	return (usr1->login_time - usr2->login_time);
141 }
142 
143 /*******************************************************************
144  Get a list of the names of all users of this machine who are
145  logged into the domain.
146 
147  This should return a list of the users on this machine who are
148  logged into the domain (i.e. have been authenticated by the domain's
149  password server) but that doesn't fit well with the normal Samba
150  scenario where accesses out to the domain are made through smbclient
151  with each such session individually authenticated. So about the best
152  we can do currently is to list sessions of local users connected to
153  this server, which means that to get themself included in the list a
154  local user must create a session to the local samba server by running:
155      smbclient \\\\localhost\\share
156 
157  FIXME: find a better way to get local users logged into the domain
158  in this list.
159  ********************************************************************/
160 
get_domain_userlist(TALLOC_CTX * mem_ctx)161 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
162 {
163 	struct sessionid *session_list = NULL;
164 	char *machine_name, *p, *nm;
165 	const char *sep;
166 	struct dom_usr *users, *tmp;
167 	int i, num_users, num_sessions;
168 
169 	sep = lp_winbind_separator();
170 	if (!sep) {
171 		sep = "\\";
172 	}
173 
174 	num_sessions = list_sessions(mem_ctx, &session_list);
175 	if (num_sessions == 0) {
176 		errno = 0;
177 		return NULL;
178 	}
179 
180 	users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
181 	if (users == NULL) {
182 		TALLOC_FREE(session_list);
183 		return NULL;
184 	}
185 
186 	for (i=num_users=0; i<num_sessions; i++) {
187 		if (session_list[i].username[0] == '\0' ||
188 		    session_list[i].remote_machine[0] == '\0') {
189 			continue;
190 		}
191 		p = strpbrk(session_list[i].remote_machine, "./");
192 		if (p) {
193 			*p = '\0';
194 		}
195 		machine_name = talloc_asprintf_strupper_m(
196 			users, "%s", session_list[i].remote_machine);
197 		if (machine_name == NULL) {
198 			DEBUG(10, ("talloc_asprintf failed\n"));
199 			continue;
200 		}
201 		if (strcmp(machine_name, lp_netbios_name()) == 0) {
202 			p = session_list[i].username;
203 			nm = strstr(p, sep);
204 			if (nm) {
205 				/*
206 				 * "domain+name" format so split domain and
207 				 * name components
208 				 */
209 				*nm = '\0';
210 				nm += strlen(sep);
211 				users[num_users].domain =
212 					talloc_asprintf_strupper_m(users,
213 								   "%s", p);
214 				users[num_users].name = talloc_strdup(users,
215 								      nm);
216 			} else {
217 				/*
218 				 * Simple user name so get domain from smb.conf
219 				 */
220 				users[num_users].domain =
221 					talloc_strdup(users, lp_workgroup());
222 				users[num_users].name = talloc_strdup(users,
223 								      p);
224 			}
225 			users[num_users].login_time =
226 				session_list[i].connect_start;
227 			num_users++;
228 		}
229 		TALLOC_FREE(machine_name);
230 	}
231 	TALLOC_FREE(session_list);
232 
233 	tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
234 	if (tmp == NULL) {
235 		return NULL;
236 	}
237 	users = tmp;
238 
239 	/* Sort the user list by time, oldest first */
240 	TYPESAFE_QSORT(users, num_users, dom_user_cmp);
241 
242 	errno = 0;
243 	return users;
244 }
245 
246 /*******************************************************************
247  RPC Workstation Service request NetWkstaGetInfo with level 100.
248  Returns to the requester:
249   - The machine name.
250   - The smb version number
251   - The domain name.
252  Returns a filled in wkssvc_NetWkstaInfo100 struct.
253  ********************************************************************/
254 
create_wks_info_100(TALLOC_CTX * mem_ctx)255 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
256 {
257 	struct wkssvc_NetWkstaInfo100 *info100;
258 
259 	info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
260 	if (info100 == NULL) {
261 		return NULL;
262 	}
263 
264 	info100->platform_id	 = PLATFORM_ID_NT;	/* unknown */
265 	info100->version_major	 = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
266 	info100->version_minor	 = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
267 
268 	info100->server_name = talloc_asprintf_strupper_m(
269 		info100, "%s", lp_netbios_name());
270 	info100->domain_name = talloc_asprintf_strupper_m(
271 		info100, "%s", lp_workgroup());
272 
273 	return info100;
274 }
275 
276 /*******************************************************************
277  RPC Workstation Service request NetWkstaGetInfo with level 101.
278  Returns to the requester:
279   - As per NetWkstaGetInfo with level 100, plus:
280   - The LANMAN directory path (not currently supported).
281  Returns a filled in wkssvc_NetWkstaInfo101 struct.
282  ********************************************************************/
283 
create_wks_info_101(TALLOC_CTX * mem_ctx)284 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
285 {
286 	struct wkssvc_NetWkstaInfo101 *info101;
287 
288 	info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
289 	if (info101 == NULL) {
290 		return NULL;
291 	}
292 
293 	info101->platform_id	 = PLATFORM_ID_NT;	/* unknown */
294 	info101->version_major	 = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
295 	info101->version_minor	 = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
296 
297 	info101->server_name = talloc_asprintf_strupper_m(
298 		info101, "%s", lp_netbios_name());
299 	info101->domain_name = talloc_asprintf_strupper_m(
300 		info101, "%s", lp_workgroup());
301 	info101->lan_root = "";
302 
303 	return info101;
304 }
305 
306 /*******************************************************************
307  RPC Workstation Service request NetWkstaGetInfo with level 102.
308  Returns to the requester:
309   - As per NetWkstaGetInfo with level 101, plus:
310   - The number of logged in users.
311  Returns a filled in wkssvc_NetWkstaInfo102 struct.
312  ********************************************************************/
313 
create_wks_info_102(TALLOC_CTX * mem_ctx)314 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
315 {
316 	struct wkssvc_NetWkstaInfo102 *info102;
317 	char **users;
318 
319 	info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
320 	if (info102 == NULL) {
321 		return NULL;
322 	}
323 
324 	info102->platform_id	 = PLATFORM_ID_NT;	/* unknown */
325 	info102->version_major	 = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
326 	info102->version_minor	 = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
327 
328 	info102->server_name = talloc_asprintf_strupper_m(
329 		info102, "%s", lp_netbios_name());
330 	info102->domain_name = talloc_asprintf_strupper_m(
331 		info102, "%s", lp_workgroup());
332 	info102->lan_root = "";
333 
334 	users = get_logged_on_userlist(talloc_tos());
335 	info102->logged_on_users = talloc_array_length(users);
336 
337 	TALLOC_FREE(users);
338 
339 	return info102;
340 }
341 
342 /********************************************************************
343  Handling for RPC Workstation Service request NetWkstaGetInfo
344  ********************************************************************/
345 
_wkssvc_NetWkstaGetInfo(struct pipes_struct * p,struct wkssvc_NetWkstaGetInfo * r)346 WERROR _wkssvc_NetWkstaGetInfo(struct pipes_struct *p,
347 			       struct wkssvc_NetWkstaGetInfo *r)
348 {
349 	struct dom_sid_buf buf;
350 
351 	switch (r->in.level) {
352 	case 100:
353 		/* Level 100 can be allowed from anyone including anonymous
354 		 * so no access checks are needed for this case */
355 		r->out.info->info100 = create_wks_info_100(p->mem_ctx);
356 		if (r->out.info->info100 == NULL) {
357 			return WERR_NOT_ENOUGH_MEMORY;
358 		}
359 		break;
360 	case 101:
361 		/* Level 101 can be allowed from any logged in user */
362 		if (!nt_token_check_sid(&global_sid_Authenticated_Users,
363 					p->session_info->security_token)) {
364 			DEBUG(1,("User not allowed for NetWkstaGetInfo level "
365 				 "101\n"));
366 			DEBUGADD(3,(" - does not have sid for Authenticated "
367 				    "Users %s:\n",
368 				    dom_sid_str_buf(
369 					    &global_sid_Authenticated_Users,
370 					    &buf)));
371 			security_token_debug(DBGC_CLASS, 3,
372 					    p->session_info->security_token);
373 			return WERR_ACCESS_DENIED;
374 		}
375 		r->out.info->info101 = create_wks_info_101(p->mem_ctx);
376 		if (r->out.info->info101 == NULL) {
377 			return WERR_NOT_ENOUGH_MEMORY;
378 		}
379 		break;
380 	case 102:
381 		/* Level 102 Should only be allowed from a domain administrator */
382 		if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
383 					p->session_info->security_token)) {
384 			DEBUG(1,("User not allowed for NetWkstaGetInfo level "
385 				 "102\n"));
386 			DEBUGADD(3,(" - does not have sid for Administrators "
387 				    "group %s, sids are:\n",
388 				    dom_sid_str_buf(
389 					    &global_sid_Builtin_Administrators,
390 					    &buf)));
391 			security_token_debug(DBGC_CLASS, 3,
392 					    p->session_info->security_token);
393 			return WERR_ACCESS_DENIED;
394 		}
395 		r->out.info->info102 = create_wks_info_102(p->mem_ctx);
396 		if (r->out.info->info102 == NULL) {
397 			return WERR_NOT_ENOUGH_MEMORY;
398 		}
399 		break;
400 	default:
401 		return WERR_INVALID_LEVEL;
402 	}
403 
404 	return WERR_OK;
405 }
406 
407 /********************************************************************
408  ********************************************************************/
409 
_wkssvc_NetWkstaSetInfo(struct pipes_struct * p,struct wkssvc_NetWkstaSetInfo * r)410 WERROR _wkssvc_NetWkstaSetInfo(struct pipes_struct *p,
411 			       struct wkssvc_NetWkstaSetInfo *r)
412 {
413 	/* FIXME: Add implementation code here */
414 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
415 	return WERR_NOT_SUPPORTED;
416 }
417 
418 /********************************************************************
419  RPC Workstation Service request NetWkstaEnumUsers with level 0:
420  Returns to the requester:
421   - the user names of the logged in users.
422  Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
423  ********************************************************************/
424 
create_enum_users0(TALLOC_CTX * mem_ctx)425 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
426 	TALLOC_CTX *mem_ctx)
427 {
428 	struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
429 	char **users;
430 	int i, num_users;
431 
432 	ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
433 	if (ctr0 == NULL) {
434 		return NULL;
435 	}
436 
437 	users = get_logged_on_userlist(talloc_tos());
438 	if (users == NULL && errno != 0) {
439 		DEBUG(1,("get_logged_on_userlist error %d: %s\n",
440 			errno, strerror(errno)));
441 		TALLOC_FREE(ctr0);
442 		return NULL;
443 	}
444 
445 	num_users = talloc_array_length(users);
446 	ctr0->entries_read = num_users;
447 	ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
448 				   num_users);
449 	if (ctr0->user0 == NULL) {
450 		TALLOC_FREE(ctr0);
451 		TALLOC_FREE(users);
452 		return NULL;
453 	}
454 
455 	for (i=0; i<num_users; i++) {
456 		ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
457 	}
458 	TALLOC_FREE(users);
459 	return ctr0;
460 }
461 
462 /********************************************************************
463  RPC Workstation Service request NetWkstaEnumUsers with level 1.
464  Returns to the requester:
465   - the user names of the logged in users,
466   - the domain or machine each is logged into,
467   - the password server that was used to authenticate each,
468   - other domains each user is logged into (not currently supported).
469  Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
470  ********************************************************************/
471 
create_enum_users1(TALLOC_CTX * mem_ctx)472 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
473 	TALLOC_CTX *mem_ctx)
474 {
475 	struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
476 	char **users;
477 	struct dom_usr *dom_users;
478 	const char *pwd_server;
479 	char *pwd_tmp;
480 	int i, j, num_users, num_dom_users;
481 
482 	ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
483 	if (ctr1 == NULL) {
484 		return NULL;
485 	}
486 
487 	users = get_logged_on_userlist(talloc_tos());
488 	if (users == NULL && errno != 0) {
489 		DEBUG(1,("get_logged_on_userlist error %d: %s\n",
490 			errno, strerror(errno)));
491 		TALLOC_FREE(ctr1);
492 		return NULL;
493 	}
494 	num_users = talloc_array_length(users);
495 
496 	dom_users = get_domain_userlist(talloc_tos());
497 	if (dom_users == NULL && errno != 0) {
498 		TALLOC_FREE(ctr1);
499 		TALLOC_FREE(users);
500 		return NULL;
501 	}
502 	num_dom_users = talloc_array_length(dom_users);
503 
504 	ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
505 				   num_users+num_dom_users);
506 	if (ctr1->user1 == NULL) {
507 		TALLOC_FREE(ctr1);
508 		TALLOC_FREE(users);
509 		TALLOC_FREE(dom_users);
510 		return NULL;
511 	}
512 
513 	pwd_server = "";
514 
515 	if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_password_server()))) {
516 		/* The configured password server is a full DNS name but
517 		 * for the logon server we need to return just the first
518 		 * component (machine name) of it in upper-case */
519 		char *p = strchr(pwd_tmp, '.');
520 		if (p) {
521 			*p = '\0';
522 		} else {
523 			p = pwd_tmp + strlen(pwd_tmp);
524 		}
525 		while (--p >= pwd_tmp) {
526 			*p = toupper(*p);
527 		}
528 		pwd_server = pwd_tmp;
529 	}
530 
531 	/* Put in local users first */
532 	for (i=0; i<num_users; i++) {
533 		ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
534 
535 		/* For a local user the domain name and logon server are
536 		 * both returned as the local machine's NetBIOS name */
537 		ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
538 			talloc_asprintf_strupper_m(ctr1->user1, "%s", lp_netbios_name());
539 
540 		ctr1->user1[i].other_domains = NULL;	/* Maybe in future? */
541 	}
542 
543 	/* Now domain users */
544 	for (j=0; j<num_dom_users; j++) {
545 		ctr1->user1[i].user_name =
546 				talloc_strdup(ctr1->user1, dom_users[j].name);
547 		ctr1->user1[i].logon_domain =
548 				talloc_strdup(ctr1->user1, dom_users[j].domain);
549 		ctr1->user1[i].logon_server = pwd_server;
550 
551 		ctr1->user1[i++].other_domains = NULL;	/* Maybe in future? */
552 	}
553 
554 	ctr1->entries_read = i;
555 
556 	TALLOC_FREE(users);
557 	TALLOC_FREE(dom_users);
558 	return ctr1;
559 }
560 
561 /********************************************************************
562  Handling for RPC Workstation Service request NetWkstaEnumUsers
563  (a.k.a Windows NetWkstaUserEnum)
564  ********************************************************************/
565 
_wkssvc_NetWkstaEnumUsers(struct pipes_struct * p,struct wkssvc_NetWkstaEnumUsers * r)566 WERROR _wkssvc_NetWkstaEnumUsers(struct pipes_struct *p,
567 				 struct wkssvc_NetWkstaEnumUsers *r)
568 {
569 	/* This with any level should only be allowed from a domain administrator */
570 	if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
571 				p->session_info->security_token)) {
572 		struct dom_sid_buf buf;
573 		DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
574 		DEBUGADD(3,(" - does not have sid for Administrators group "
575 			    "%s\n",
576 			    dom_sid_str_buf(
577 				    &global_sid_Builtin_Administrators,
578 				    &buf)));
579 		security_token_debug(DBGC_CLASS, 3, p->session_info->security_token);
580 		return WERR_ACCESS_DENIED;
581 	}
582 
583 	switch (r->in.info->level) {
584 	case 0:
585 		r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
586 		if (r->out.info->ctr.user0 == NULL) {
587 			return WERR_NOT_ENOUGH_MEMORY;
588 		}
589 		r->out.info->level = r->in.info->level;
590 		*r->out.entries_read = r->out.info->ctr.user0->entries_read;
591 		if (r->out.resume_handle != NULL) {
592 			*r->out.resume_handle = 0;
593 		}
594 		break;
595 	case 1:
596 		r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
597 		if (r->out.info->ctr.user1 == NULL) {
598 			return WERR_NOT_ENOUGH_MEMORY;
599 		}
600 		r->out.info->level = r->in.info->level;
601 		*r->out.entries_read = r->out.info->ctr.user1->entries_read;
602 		if (r->out.resume_handle != NULL) {
603 			*r->out.resume_handle = 0;
604 		}
605 		break;
606 	default:
607 		return WERR_INVALID_LEVEL;
608 	}
609 
610 	return WERR_OK;
611 }
612 
613 /********************************************************************
614  ********************************************************************/
615 
_wkssvc_NetrWkstaUserGetInfo(struct pipes_struct * p,struct wkssvc_NetrWkstaUserGetInfo * r)616 WERROR _wkssvc_NetrWkstaUserGetInfo(struct pipes_struct *p,
617 				    struct wkssvc_NetrWkstaUserGetInfo *r)
618 {
619 	/* FIXME: Add implementation code here */
620 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
621 	return WERR_NOT_SUPPORTED;
622 }
623 
624 /********************************************************************
625  ********************************************************************/
626 
_wkssvc_NetrWkstaUserSetInfo(struct pipes_struct * p,struct wkssvc_NetrWkstaUserSetInfo * r)627 WERROR _wkssvc_NetrWkstaUserSetInfo(struct pipes_struct *p,
628 				    struct wkssvc_NetrWkstaUserSetInfo *r)
629 {
630 	/* FIXME: Add implementation code here */
631 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
632 	return WERR_NOT_SUPPORTED;
633 }
634 
635 /********************************************************************
636  ********************************************************************/
637 
_wkssvc_NetWkstaTransportEnum(struct pipes_struct * p,struct wkssvc_NetWkstaTransportEnum * r)638 WERROR _wkssvc_NetWkstaTransportEnum(struct pipes_struct *p,
639 				     struct wkssvc_NetWkstaTransportEnum *r)
640 {
641 	/* FIXME: Add implementation code here */
642 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
643 	return WERR_NOT_SUPPORTED;
644 }
645 
646 /********************************************************************
647  ********************************************************************/
648 
_wkssvc_NetrWkstaTransportAdd(struct pipes_struct * p,struct wkssvc_NetrWkstaTransportAdd * r)649 WERROR _wkssvc_NetrWkstaTransportAdd(struct pipes_struct *p,
650 				     struct wkssvc_NetrWkstaTransportAdd *r)
651 {
652 	/* FIXME: Add implementation code here */
653 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
654 	return WERR_NOT_SUPPORTED;
655 }
656 
657 /********************************************************************
658  ********************************************************************/
659 
_wkssvc_NetrWkstaTransportDel(struct pipes_struct * p,struct wkssvc_NetrWkstaTransportDel * r)660 WERROR _wkssvc_NetrWkstaTransportDel(struct pipes_struct *p,
661 				     struct wkssvc_NetrWkstaTransportDel *r)
662 {
663 	/* FIXME: Add implementation code here */
664 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
665 	return WERR_NOT_SUPPORTED;
666 }
667 
668 /********************************************************************
669  ********************************************************************/
670 
_wkssvc_NetrUseAdd(struct pipes_struct * p,struct wkssvc_NetrUseAdd * r)671 WERROR _wkssvc_NetrUseAdd(struct pipes_struct *p,
672 			  struct wkssvc_NetrUseAdd *r)
673 {
674 	/* FIXME: Add implementation code here */
675 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
676 	return WERR_NOT_SUPPORTED;
677 }
678 
679 /********************************************************************
680  ********************************************************************/
681 
_wkssvc_NetrUseGetInfo(struct pipes_struct * p,struct wkssvc_NetrUseGetInfo * r)682 WERROR _wkssvc_NetrUseGetInfo(struct pipes_struct *p,
683 			      struct wkssvc_NetrUseGetInfo *r)
684 {
685 	/* FIXME: Add implementation code here */
686 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
687 	return WERR_NOT_SUPPORTED;
688 }
689 
690 /********************************************************************
691  ********************************************************************/
692 
_wkssvc_NetrUseDel(struct pipes_struct * p,struct wkssvc_NetrUseDel * r)693 WERROR _wkssvc_NetrUseDel(struct pipes_struct *p,
694 			  struct wkssvc_NetrUseDel *r)
695 {
696 	/* FIXME: Add implementation code here */
697 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
698 	return WERR_NOT_SUPPORTED;
699 }
700 
701 /********************************************************************
702  ********************************************************************/
703 
_wkssvc_NetrUseEnum(struct pipes_struct * p,struct wkssvc_NetrUseEnum * r)704 WERROR _wkssvc_NetrUseEnum(struct pipes_struct *p,
705 			   struct wkssvc_NetrUseEnum *r)
706 {
707 	/* FIXME: Add implementation code here */
708 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
709 	return WERR_NOT_SUPPORTED;
710 }
711 
712 /********************************************************************
713  ********************************************************************/
714 
_wkssvc_NetrMessageBufferSend(struct pipes_struct * p,struct wkssvc_NetrMessageBufferSend * r)715 WERROR _wkssvc_NetrMessageBufferSend(struct pipes_struct *p,
716 				     struct wkssvc_NetrMessageBufferSend *r)
717 {
718 	/* FIXME: Add implementation code here */
719 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
720 	return WERR_NOT_SUPPORTED;
721 }
722 
723 /********************************************************************
724  ********************************************************************/
725 
_wkssvc_NetrWorkstationStatisticsGet(struct pipes_struct * p,struct wkssvc_NetrWorkstationStatisticsGet * r)726 WERROR _wkssvc_NetrWorkstationStatisticsGet(struct pipes_struct *p,
727 					    struct wkssvc_NetrWorkstationStatisticsGet *r)
728 {
729 	/* FIXME: Add implementation code here */
730 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
731 	return WERR_NOT_SUPPORTED;
732 }
733 
734 /********************************************************************
735  ********************************************************************/
736 
_wkssvc_NetrLogonDomainNameAdd(struct pipes_struct * p,struct wkssvc_NetrLogonDomainNameAdd * r)737 WERROR _wkssvc_NetrLogonDomainNameAdd(struct pipes_struct *p,
738 				      struct wkssvc_NetrLogonDomainNameAdd *r)
739 {
740 	/* FIXME: Add implementation code here */
741 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
742 	return WERR_NOT_SUPPORTED;
743 }
744 
745 /********************************************************************
746  ********************************************************************/
747 
_wkssvc_NetrLogonDomainNameDel(struct pipes_struct * p,struct wkssvc_NetrLogonDomainNameDel * r)748 WERROR _wkssvc_NetrLogonDomainNameDel(struct pipes_struct *p,
749 				      struct wkssvc_NetrLogonDomainNameDel *r)
750 {
751 	/* FIXME: Add implementation code here */
752 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
753 	return WERR_NOT_SUPPORTED;
754 }
755 
756 /********************************************************************
757  ********************************************************************/
758 
_wkssvc_NetrJoinDomain(struct pipes_struct * p,struct wkssvc_NetrJoinDomain * r)759 WERROR _wkssvc_NetrJoinDomain(struct pipes_struct *p,
760 			      struct wkssvc_NetrJoinDomain *r)
761 {
762 	/* FIXME: Add implementation code here */
763 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
764 	return WERR_NOT_SUPPORTED;
765 }
766 
767 /********************************************************************
768  ********************************************************************/
769 
_wkssvc_NetrUnjoinDomain(struct pipes_struct * p,struct wkssvc_NetrUnjoinDomain * r)770 WERROR _wkssvc_NetrUnjoinDomain(struct pipes_struct *p,
771 				struct wkssvc_NetrUnjoinDomain *r)
772 {
773 	/* FIXME: Add implementation code here */
774 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
775 	return WERR_NOT_SUPPORTED;
776 }
777 
778 /********************************************************************
779  ********************************************************************/
780 
_wkssvc_NetrRenameMachineInDomain(struct pipes_struct * p,struct wkssvc_NetrRenameMachineInDomain * r)781 WERROR _wkssvc_NetrRenameMachineInDomain(struct pipes_struct *p,
782 					 struct wkssvc_NetrRenameMachineInDomain *r)
783 {
784 	/* FIXME: Add implementation code here */
785 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
786 	return WERR_NOT_SUPPORTED;
787 }
788 
789 /********************************************************************
790  ********************************************************************/
791 
_wkssvc_NetrValidateName(struct pipes_struct * p,struct wkssvc_NetrValidateName * r)792 WERROR _wkssvc_NetrValidateName(struct pipes_struct *p,
793 				struct wkssvc_NetrValidateName *r)
794 {
795 	/* FIXME: Add implementation code here */
796 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
797 	return WERR_NOT_SUPPORTED;
798 }
799 
800 /********************************************************************
801  ********************************************************************/
802 
_wkssvc_NetrGetJoinInformation(struct pipes_struct * p,struct wkssvc_NetrGetJoinInformation * r)803 WERROR _wkssvc_NetrGetJoinInformation(struct pipes_struct *p,
804 				      struct wkssvc_NetrGetJoinInformation *r)
805 {
806 	/* FIXME: Add implementation code here */
807 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
808 	return WERR_NOT_SUPPORTED;
809 }
810 
811 /********************************************************************
812  ********************************************************************/
813 
_wkssvc_NetrGetJoinableOus(struct pipes_struct * p,struct wkssvc_NetrGetJoinableOus * r)814 WERROR _wkssvc_NetrGetJoinableOus(struct pipes_struct *p,
815 				  struct wkssvc_NetrGetJoinableOus *r)
816 {
817 	/* FIXME: Add implementation code here */
818 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
819 	return WERR_NOT_SUPPORTED;
820 }
821 
822 /********************************************************************
823  _wkssvc_NetrJoinDomain2
824  ********************************************************************/
825 
_wkssvc_NetrJoinDomain2(struct pipes_struct * p,struct wkssvc_NetrJoinDomain2 * r)826 WERROR _wkssvc_NetrJoinDomain2(struct pipes_struct *p,
827 			       struct wkssvc_NetrJoinDomain2 *r)
828 {
829 	struct libnet_JoinCtx *j = NULL;
830 	char *cleartext_pwd = NULL;
831 	char *admin_domain = NULL;
832 	char *admin_account = NULL;
833 	WERROR werr;
834 	struct security_token *token = p->session_info->security_token;
835 	NTSTATUS status;
836 	DATA_BLOB session_key;
837 	bool ok;
838 
839 	if (!r->in.domain_name) {
840 		return WERR_INVALID_PARAMETER;
841 	}
842 
843 	if (!r->in.admin_account || !r->in.encrypted_password) {
844 		return WERR_INVALID_PARAMETER;
845 	}
846 
847 	if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
848 	    !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
849 	    !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
850 		DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
851 			"sufficient privileges\n"));
852 		return WERR_ACCESS_DENIED;
853 	}
854 
855 	if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
856 	    (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
857 		return WERR_NOT_SUPPORTED;
858 	}
859 
860 	status = session_extract_session_key(p->session_info,
861 					     &session_key,
862 					     KEY_USE_16BYTES);
863 	if(!NT_STATUS_IS_OK(status)) {
864 		DEBUG(5,("_wkssvc_NetrJoinDomain2: no session key %s\n",
865 			nt_errstr(status)));
866 		return WERR_NO_USER_SESSION_KEY;
867 	}
868 
869 	werr = decode_wkssvc_join_password_buffer(
870 		p->mem_ctx, r->in.encrypted_password,
871 		&session_key, &cleartext_pwd);
872 	if (!W_ERROR_IS_OK(werr)) {
873 		return werr;
874 	}
875 
876 	ok = split_domain_user(p->mem_ctx,
877 			       r->in.admin_account,
878 			       &admin_domain,
879 			       &admin_account);
880 	if (!ok) {
881 		return WERR_NOT_ENOUGH_MEMORY;
882 	}
883 
884 	werr = libnet_init_JoinCtx(p->mem_ctx, &j);
885 	if (!W_ERROR_IS_OK(werr)) {
886 		return werr;
887 	}
888 
889 	j->in.domain_name	= r->in.domain_name;
890 	j->in.account_ou	= r->in.account_ou;
891 	j->in.join_flags	= r->in.join_flags;
892 	j->in.admin_account	= admin_account;
893 	j->in.admin_password	= cleartext_pwd;
894 	j->in.debug		= true;
895 	j->in.modify_config     = lp_config_backend_is_registry();
896 	j->in.msg_ctx		= p->msg_ctx;
897 
898 	become_root();
899 	setenv(KRB5_ENV_CCNAME, "MEMORY:_wkssvc_NetrJoinDomain2", 1);
900 	werr = libnet_Join(p->mem_ctx, j);
901 	unsetenv(KRB5_ENV_CCNAME);
902 	unbecome_root();
903 
904 	if (!W_ERROR_IS_OK(werr)) {
905 		DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
906 			j->out.error_string ? j->out.error_string :
907 			win_errstr(werr)));
908 	}
909 
910 	TALLOC_FREE(j);
911 	return werr;
912 }
913 
914 /********************************************************************
915  _wkssvc_NetrUnjoinDomain2
916  ********************************************************************/
917 
_wkssvc_NetrUnjoinDomain2(struct pipes_struct * p,struct wkssvc_NetrUnjoinDomain2 * r)918 WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p,
919 				 struct wkssvc_NetrUnjoinDomain2 *r)
920 {
921 	struct libnet_UnjoinCtx *u = NULL;
922 	char *cleartext_pwd = NULL;
923 	char *admin_domain = NULL;
924 	char *admin_account = NULL;
925 	WERROR werr;
926 	struct security_token *token = p->session_info->security_token;
927 	NTSTATUS status;
928 	DATA_BLOB session_key;
929 	bool ok;
930 
931 	if (!r->in.account || !r->in.encrypted_password) {
932 		return WERR_INVALID_PARAMETER;
933 	}
934 
935 	if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
936 	    !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
937 	    !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
938 		DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
939 			"sufficient privileges\n"));
940 		return WERR_ACCESS_DENIED;
941 	}
942 
943 	status = session_extract_session_key(p->session_info,
944 					     &session_key,
945 					     KEY_USE_16BYTES);
946 	if (!NT_STATUS_IS_OK(status)) {
947 		DEBUG(5,("_wkssvc_NetrUnjoinDomain2: no session key %s\n",
948 			nt_errstr(status)));
949 		return WERR_NO_USER_SESSION_KEY;
950 	}
951 
952 	werr = decode_wkssvc_join_password_buffer(
953 		p->mem_ctx, r->in.encrypted_password,
954 		&session_key, &cleartext_pwd);
955 	if (!W_ERROR_IS_OK(werr)) {
956 		return werr;
957 	}
958 
959 	ok = split_domain_user(p->mem_ctx,
960 			       r->in.account,
961 			       &admin_domain,
962 			       &admin_account);
963 	if (!ok) {
964 		return WERR_NOT_ENOUGH_MEMORY;
965 	}
966 
967 	werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
968 	if (!W_ERROR_IS_OK(werr)) {
969 		return werr;
970 	}
971 
972 	u->in.domain_name	= lp_realm();
973 	u->in.unjoin_flags	= r->in.unjoin_flags |
974 				  WKSSVC_JOIN_FLAGS_JOIN_TYPE;
975 	u->in.admin_account	= admin_account;
976 	u->in.admin_password	= cleartext_pwd;
977 	u->in.debug		= true;
978 	u->in.modify_config     = lp_config_backend_is_registry();
979 	u->in.msg_ctx		= p->msg_ctx;
980 
981 	become_root();
982 	setenv(KRB5_ENV_CCNAME, "MEMORY:_wkssvc_NetrUnjoinDomain2", 1);
983 	werr = libnet_Unjoin(p->mem_ctx, u);
984 	unsetenv(KRB5_ENV_CCNAME);
985 	unbecome_root();
986 
987 	if (!W_ERROR_IS_OK(werr)) {
988 		DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
989 			u->out.error_string ? u->out.error_string :
990 			win_errstr(werr)));
991 	}
992 
993 	TALLOC_FREE(u);
994 	return werr;
995 }
996 
997 /********************************************************************
998  ********************************************************************/
999 
_wkssvc_NetrRenameMachineInDomain2(struct pipes_struct * p,struct wkssvc_NetrRenameMachineInDomain2 * r)1000 WERROR _wkssvc_NetrRenameMachineInDomain2(struct pipes_struct *p,
1001 					  struct wkssvc_NetrRenameMachineInDomain2 *r)
1002 {
1003 	/* for now just return not supported */
1004 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1005 	return WERR_NOT_SUPPORTED;
1006 }
1007 
1008 /********************************************************************
1009  ********************************************************************/
1010 
_wkssvc_NetrValidateName2(struct pipes_struct * p,struct wkssvc_NetrValidateName2 * r)1011 WERROR _wkssvc_NetrValidateName2(struct pipes_struct *p,
1012 				 struct wkssvc_NetrValidateName2 *r)
1013 {
1014 	/* FIXME: Add implementation code here */
1015 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1016 	return WERR_NOT_SUPPORTED;
1017 }
1018 
1019 /********************************************************************
1020  ********************************************************************/
1021 
_wkssvc_NetrGetJoinableOus2(struct pipes_struct * p,struct wkssvc_NetrGetJoinableOus2 * r)1022 WERROR _wkssvc_NetrGetJoinableOus2(struct pipes_struct *p,
1023 				   struct wkssvc_NetrGetJoinableOus2 *r)
1024 {
1025 	/* FIXME: Add implementation code here */
1026 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1027 	return WERR_NOT_SUPPORTED;
1028 }
1029 
1030 /********************************************************************
1031  ********************************************************************/
1032 
_wkssvc_NetrAddAlternateComputerName(struct pipes_struct * p,struct wkssvc_NetrAddAlternateComputerName * r)1033 WERROR _wkssvc_NetrAddAlternateComputerName(struct pipes_struct *p,
1034 					    struct wkssvc_NetrAddAlternateComputerName *r)
1035 {
1036 	/* FIXME: Add implementation code here */
1037 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1038 	return WERR_NOT_SUPPORTED;
1039 }
1040 
1041 /********************************************************************
1042  ********************************************************************/
1043 
_wkssvc_NetrRemoveAlternateComputerName(struct pipes_struct * p,struct wkssvc_NetrRemoveAlternateComputerName * r)1044 WERROR _wkssvc_NetrRemoveAlternateComputerName(struct pipes_struct *p,
1045 					       struct wkssvc_NetrRemoveAlternateComputerName *r)
1046 {
1047 	/* FIXME: Add implementation code here */
1048 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1049 	return WERR_NOT_SUPPORTED;
1050 }
1051 
1052 /********************************************************************
1053  ********************************************************************/
1054 
_wkssvc_NetrSetPrimaryComputername(struct pipes_struct * p,struct wkssvc_NetrSetPrimaryComputername * r)1055 WERROR _wkssvc_NetrSetPrimaryComputername(struct pipes_struct *p,
1056 					  struct wkssvc_NetrSetPrimaryComputername *r)
1057 {
1058 	/* FIXME: Add implementation code here */
1059 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1060 	return WERR_NOT_SUPPORTED;
1061 }
1062 
1063 /********************************************************************
1064  ********************************************************************/
1065 
_wkssvc_NetrEnumerateComputerNames(struct pipes_struct * p,struct wkssvc_NetrEnumerateComputerNames * r)1066 WERROR _wkssvc_NetrEnumerateComputerNames(struct pipes_struct *p,
1067 					  struct wkssvc_NetrEnumerateComputerNames *r)
1068 {
1069 	/* FIXME: Add implementation code here */
1070 	p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1071 	return WERR_NOT_SUPPORTED;
1072 }
1073