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