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