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