ctdb-server: Remove duplicate logic
[samba4-gss.git] / source3 / rpc_server / wkssvc / srv_wkssvc_nt.c
blobc75b0d19e2bb04d523eec0167ead5baa11355cec
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-1997,
6 * Copyright (C) Gerald (Jerry) Carter 2006.
7 * Copyright (C) Guenther Deschner 2007-2008.
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.
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.
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/>.
23 /* This is the implementation of the wks interface. */
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 "ads.h"
39 #undef DBGC_CLASS
40 #define DBGC_CLASS DBGC_RPC_SRV
42 struct dom_usr {
43 char *name;
44 char *domain;
45 time_t login_time;
48 static int dom_user_cmp(const struct dom_usr *usr1, const struct dom_usr *usr2)
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 return NUMERIC_CMP(usr1->login_time, usr2->login_time);
56 /*******************************************************************
57 Get a list of the names of all users of this machine who are
58 logged into the domain.
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
70 FIXME: find a better way to get local users logged into the domain
71 in this list.
72 ********************************************************************/
74 static int get_domain_userlist(TALLOC_CTX *mem_ctx, struct dom_usr **pusers)
76 struct sessionid *session_list = NULL;
77 char *machine_name, *p, *nm;
78 const char *sep;
79 struct dom_usr *users, *tmp;
80 int i, num_users, num_sessions;
82 sep = lp_winbind_separator();
83 if (!sep) {
84 sep = "\\";
87 num_sessions = list_sessions(mem_ctx, &session_list);
88 if (num_sessions == 0) {
89 *pusers = NULL;
90 return 0;
93 users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
94 if (users == NULL) {
95 TALLOC_FREE(session_list);
96 return ENOMEM;
99 for (i=num_users=0; i<num_sessions; i++) {
100 if (session_list[i].username[0] == '\0' ||
101 session_list[i].remote_machine[0] == '\0') {
102 continue;
104 p = strpbrk(session_list[i].remote_machine, "./");
105 if (p) {
106 *p = '\0';
108 machine_name = talloc_asprintf_strupper_m(
109 users, "%s", session_list[i].remote_machine);
110 if (machine_name == NULL) {
111 DEBUG(10, ("talloc_asprintf failed\n"));
112 continue;
114 if (strcmp(machine_name, lp_netbios_name()) == 0) {
115 p = session_list[i].username;
116 nm = strstr(p, sep);
117 if (nm) {
119 * "domain+name" format so split domain and
120 * name components
122 *nm = '\0';
123 nm += strlen(sep);
124 users[num_users].domain =
125 talloc_asprintf_strupper_m(users,
126 "%s", p);
127 users[num_users].name = talloc_strdup(users,
128 nm);
129 } else {
131 * Simple user name so get domain from smb.conf
133 users[num_users].domain =
134 talloc_strdup(users, lp_workgroup());
135 users[num_users].name = talloc_strdup(users,
138 users[num_users].login_time =
139 session_list[i].connect_start;
140 num_users++;
142 TALLOC_FREE(machine_name);
144 TALLOC_FREE(session_list);
146 if (num_users == 0) {
147 TALLOC_FREE(users);
148 *pusers = NULL;
149 return 0;
152 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
153 if (tmp == NULL) {
154 TALLOC_FREE(users);
155 return ENOMEM;
157 users = tmp;
159 /* Sort the user list by time, oldest first */
160 TYPESAFE_QSORT(users, num_users, dom_user_cmp);
162 *pusers = users;
163 return 0;
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 ********************************************************************/
175 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
177 struct wkssvc_NetWkstaInfo100 *info100;
179 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
180 if (info100 == NULL) {
181 return NULL;
184 info100->platform_id = PLATFORM_ID_NT; /* unknown */
185 info100->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
186 info100->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
188 info100->server_name = talloc_asprintf_strupper_m(
189 info100, "%s", lp_netbios_name());
190 info100->domain_name = talloc_asprintf_strupper_m(
191 info100, "%s", lp_workgroup());
193 return info100;
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 ********************************************************************/
204 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
206 struct wkssvc_NetWkstaInfo101 *info101;
208 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
209 if (info101 == NULL) {
210 return NULL;
213 info101->platform_id = PLATFORM_ID_NT; /* unknown */
214 info101->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
215 info101->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
217 info101->server_name = talloc_asprintf_strupper_m(
218 info101, "%s", lp_netbios_name());
219 info101->domain_name = talloc_asprintf_strupper_m(
220 info101, "%s", lp_workgroup());
221 info101->lan_root = "";
223 return info101;
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 ********************************************************************/
234 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
236 struct wkssvc_NetWkstaInfo102 *info102;
238 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
239 if (info102 == NULL) {
240 return NULL;
243 info102->platform_id = PLATFORM_ID_NT; /* unknown */
244 info102->version_major = SAMBA_MAJOR_NBT_ANNOUNCE_VERSION;
245 info102->version_minor = SAMBA_MINOR_NBT_ANNOUNCE_VERSION;
247 info102->server_name = talloc_asprintf_strupper_m(
248 info102, "%s", lp_netbios_name());
249 info102->domain_name = talloc_asprintf_strupper_m(
250 info102, "%s", lp_workgroup());
251 info102->lan_root = "";
252 info102->logged_on_users = 0;
254 return info102;
257 /********************************************************************
258 Handling for RPC Workstation Service request NetWkstaGetInfo
259 ********************************************************************/
261 WERROR _wkssvc_NetWkstaGetInfo(struct pipes_struct *p,
262 struct wkssvc_NetWkstaGetInfo *r)
264 struct dcesrv_call_state *dce_call = p->dce_call;
265 struct auth_session_info *session_info =
266 dcesrv_call_session_info(dce_call);
267 struct dom_sid_buf buf;
269 switch (r->in.level) {
270 case 100:
271 /* Level 100 can be allowed from anyone including anonymous
272 * so no access checks are needed for this case */
273 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
274 if (r->out.info->info100 == NULL) {
275 return WERR_NOT_ENOUGH_MEMORY;
277 break;
278 case 101:
279 /* Level 101 can be allowed from any logged in user */
280 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
281 session_info->security_token)) {
282 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
283 "101\n"));
284 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 security_token_debug(DBGC_CLASS, 3,
290 session_info->security_token);
291 return WERR_ACCESS_DENIED;
293 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
294 if (r->out.info->info101 == NULL) {
295 return WERR_NOT_ENOUGH_MEMORY;
297 break;
298 case 102:
299 /* Level 102 Should only be allowed from a domain administrator */
300 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
301 session_info->security_token)) {
302 DEBUG(1,("User not allowed for NetWkstaGetInfo level "
303 "102\n"));
304 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 security_token_debug(DBGC_CLASS, 3,
310 session_info->security_token);
311 return WERR_ACCESS_DENIED;
313 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
314 if (r->out.info->info102 == NULL) {
315 return WERR_NOT_ENOUGH_MEMORY;
317 break;
318 default:
319 return WERR_INVALID_LEVEL;
322 return WERR_OK;
325 /********************************************************************
326 ********************************************************************/
328 WERROR _wkssvc_NetWkstaSetInfo(struct pipes_struct *p,
329 struct wkssvc_NetWkstaSetInfo *r)
331 /* FIXME: Add implementation code here */
332 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
333 return WERR_NOT_SUPPORTED;
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 ********************************************************************/
343 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
344 TALLOC_CTX *mem_ctx)
346 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
348 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
349 if (ctr0 == NULL) {
350 return NULL;
353 ctr0->entries_read = 0;
354 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0, 0);
355 if (ctr0->user0 == NULL) {
356 TALLOC_FREE(ctr0);
357 return NULL;
360 return ctr0;
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 ********************************************************************/
373 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
374 TALLOC_CTX *mem_ctx)
376 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
377 struct dom_usr *dom_users;
378 const char *pwd_server;
379 char *pwd_tmp;
380 int i, num_dom_users, ret;
382 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
383 if (ctr1 == NULL) {
384 return NULL;
387 ret = get_domain_userlist(talloc_tos(), &dom_users);
388 if (ret != 0) {
389 TALLOC_FREE(ctr1);
390 errno = ret;
391 return NULL;
393 num_dom_users = talloc_array_length(dom_users);
395 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
396 num_dom_users);
397 if (ctr1->user1 == NULL) {
398 TALLOC_FREE(ctr1);
399 TALLOC_FREE(dom_users);
400 errno = ENOMEM;
401 return NULL;
404 pwd_server = "";
406 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 char *p = strchr(pwd_tmp, '.');
411 if (p) {
412 *p = '\0';
413 } else {
414 p = pwd_tmp + strlen(pwd_tmp);
416 while (--p >= pwd_tmp) {
417 *p = toupper(*p);
419 pwd_server = pwd_tmp;
422 /* Now domain users */
423 for (i=0; i<num_dom_users; i++) {
424 ctr1->user1[i].user_name =
425 talloc_strdup(ctr1->user1, dom_users[i].name);
426 ctr1->user1[i].logon_domain =
427 talloc_strdup(ctr1->user1, dom_users[i].domain);
428 ctr1->user1[i].logon_server = pwd_server;
430 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */
433 ctr1->entries_read = i;
435 TALLOC_FREE(dom_users);
436 return ctr1;
439 /********************************************************************
440 Handling for RPC Workstation Service request NetWkstaEnumUsers
441 (a.k.a Windows NetWkstaUserEnum)
442 ********************************************************************/
444 WERROR _wkssvc_NetWkstaEnumUsers(struct pipes_struct *p,
445 struct wkssvc_NetWkstaEnumUsers *r)
447 struct dcesrv_call_state *dce_call = p->dce_call;
448 struct auth_session_info *session_info =
449 dcesrv_call_session_info(dce_call);
451 /* This with any level should only be allowed from a domain administrator */
452 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
453 session_info->security_token)) {
454 struct dom_sid_buf buf;
455 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
456 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 security_token_debug(
462 DBGC_CLASS, 3, session_info->security_token);
463 return WERR_ACCESS_DENIED;
466 switch (r->in.info->level) {
467 case 0:
468 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
469 if (r->out.info->ctr.user0 == NULL) {
470 return WERR_NOT_ENOUGH_MEMORY;
472 r->out.info->level = r->in.info->level;
473 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
474 if (r->out.resume_handle != NULL) {
475 *r->out.resume_handle = 0;
477 break;
478 case 1:
479 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
480 if (r->out.info->ctr.user1 == NULL) {
481 return WERR_NOT_ENOUGH_MEMORY;
483 r->out.info->level = r->in.info->level;
484 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
485 if (r->out.resume_handle != NULL) {
486 *r->out.resume_handle = 0;
488 break;
489 default:
490 return WERR_INVALID_LEVEL;
493 return WERR_OK;
496 /********************************************************************
497 ********************************************************************/
499 WERROR _wkssvc_NetrWkstaUserGetInfo(struct pipes_struct *p,
500 struct wkssvc_NetrWkstaUserGetInfo *r)
502 /* FIXME: Add implementation code here */
503 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
504 return WERR_NOT_SUPPORTED;
507 /********************************************************************
508 ********************************************************************/
510 WERROR _wkssvc_NetrWkstaUserSetInfo(struct pipes_struct *p,
511 struct wkssvc_NetrWkstaUserSetInfo *r)
513 /* FIXME: Add implementation code here */
514 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
515 return WERR_NOT_SUPPORTED;
518 /********************************************************************
519 ********************************************************************/
521 WERROR _wkssvc_NetWkstaTransportEnum(struct pipes_struct *p,
522 struct wkssvc_NetWkstaTransportEnum *r)
524 /* FIXME: Add implementation code here */
525 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
526 return WERR_NOT_SUPPORTED;
529 /********************************************************************
530 ********************************************************************/
532 WERROR _wkssvc_NetrWkstaTransportAdd(struct pipes_struct *p,
533 struct wkssvc_NetrWkstaTransportAdd *r)
535 /* FIXME: Add implementation code here */
536 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
537 return WERR_NOT_SUPPORTED;
540 /********************************************************************
541 ********************************************************************/
543 WERROR _wkssvc_NetrWkstaTransportDel(struct pipes_struct *p,
544 struct wkssvc_NetrWkstaTransportDel *r)
546 /* FIXME: Add implementation code here */
547 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
548 return WERR_NOT_SUPPORTED;
551 /********************************************************************
552 ********************************************************************/
554 WERROR _wkssvc_NetrUseAdd(struct pipes_struct *p,
555 struct wkssvc_NetrUseAdd *r)
557 /* FIXME: Add implementation code here */
558 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
559 return WERR_NOT_SUPPORTED;
562 /********************************************************************
563 ********************************************************************/
565 WERROR _wkssvc_NetrUseGetInfo(struct pipes_struct *p,
566 struct wkssvc_NetrUseGetInfo *r)
568 /* FIXME: Add implementation code here */
569 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
570 return WERR_NOT_SUPPORTED;
573 /********************************************************************
574 ********************************************************************/
576 WERROR _wkssvc_NetrUseDel(struct pipes_struct *p,
577 struct wkssvc_NetrUseDel *r)
579 /* FIXME: Add implementation code here */
580 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
581 return WERR_NOT_SUPPORTED;
584 /********************************************************************
585 ********************************************************************/
587 WERROR _wkssvc_NetrUseEnum(struct pipes_struct *p,
588 struct wkssvc_NetrUseEnum *r)
590 /* FIXME: Add implementation code here */
591 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
592 return WERR_NOT_SUPPORTED;
595 /********************************************************************
596 ********************************************************************/
598 WERROR _wkssvc_NetrMessageBufferSend(struct pipes_struct *p,
599 struct wkssvc_NetrMessageBufferSend *r)
601 /* FIXME: Add implementation code here */
602 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
603 return WERR_NOT_SUPPORTED;
606 /********************************************************************
607 ********************************************************************/
609 WERROR _wkssvc_NetrWorkstationStatisticsGet(struct pipes_struct *p,
610 struct wkssvc_NetrWorkstationStatisticsGet *r)
612 /* FIXME: Add implementation code here */
613 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
614 return WERR_NOT_SUPPORTED;
617 /********************************************************************
618 ********************************************************************/
620 WERROR _wkssvc_NetrLogonDomainNameAdd(struct pipes_struct *p,
621 struct wkssvc_NetrLogonDomainNameAdd *r)
623 /* FIXME: Add implementation code here */
624 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
625 return WERR_NOT_SUPPORTED;
628 /********************************************************************
629 ********************************************************************/
631 WERROR _wkssvc_NetrLogonDomainNameDel(struct pipes_struct *p,
632 struct wkssvc_NetrLogonDomainNameDel *r)
634 /* FIXME: Add implementation code here */
635 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
636 return WERR_NOT_SUPPORTED;
639 /********************************************************************
640 ********************************************************************/
642 WERROR _wkssvc_NetrJoinDomain(struct pipes_struct *p,
643 struct wkssvc_NetrJoinDomain *r)
645 /* FIXME: Add implementation code here */
646 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
647 return WERR_NOT_SUPPORTED;
650 /********************************************************************
651 ********************************************************************/
653 WERROR _wkssvc_NetrUnjoinDomain(struct pipes_struct *p,
654 struct wkssvc_NetrUnjoinDomain *r)
656 /* FIXME: Add implementation code here */
657 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
658 return WERR_NOT_SUPPORTED;
661 /********************************************************************
662 ********************************************************************/
664 WERROR _wkssvc_NetrRenameMachineInDomain(struct pipes_struct *p,
665 struct wkssvc_NetrRenameMachineInDomain *r)
667 /* FIXME: Add implementation code here */
668 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
669 return WERR_NOT_SUPPORTED;
672 /********************************************************************
673 ********************************************************************/
675 WERROR _wkssvc_NetrValidateName(struct pipes_struct *p,
676 struct wkssvc_NetrValidateName *r)
678 /* FIXME: Add implementation code here */
679 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
680 return WERR_NOT_SUPPORTED;
683 /********************************************************************
684 ********************************************************************/
686 WERROR _wkssvc_NetrGetJoinInformation(struct pipes_struct *p,
687 struct wkssvc_NetrGetJoinInformation *r)
689 /* FIXME: Add implementation code here */
690 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
691 return WERR_NOT_SUPPORTED;
694 /********************************************************************
695 ********************************************************************/
697 WERROR _wkssvc_NetrGetJoinableOus(struct pipes_struct *p,
698 struct wkssvc_NetrGetJoinableOus *r)
700 /* FIXME: Add implementation code here */
701 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
702 return WERR_NOT_SUPPORTED;
705 /********************************************************************
706 _wkssvc_NetrJoinDomain2
707 ********************************************************************/
709 WERROR _wkssvc_NetrJoinDomain2(struct pipes_struct *p,
710 struct wkssvc_NetrJoinDomain2 *r)
712 struct dcesrv_call_state *dce_call = p->dce_call;
713 struct auth_session_info *session_info =
714 dcesrv_call_session_info(dce_call);
715 struct libnet_JoinCtx *j = NULL;
716 char *cleartext_pwd = NULL;
717 char *admin_domain = NULL;
718 char *admin_account = NULL;
719 WERROR werr;
720 struct security_token *token = session_info->security_token;
721 NTSTATUS status;
722 DATA_BLOB session_key;
723 bool ok;
725 if (!r->in.domain_name) {
726 return WERR_INVALID_PARAMETER;
729 if (!r->in.admin_account || !r->in.encrypted_password) {
730 return WERR_INVALID_PARAMETER;
733 if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
734 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
735 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
736 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
737 "sufficient privileges\n"));
738 return WERR_ACCESS_DENIED;
741 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
742 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
743 return WERR_NOT_SUPPORTED;
746 status = session_extract_session_key(session_info,
747 &session_key,
748 KEY_USE_16BYTES);
749 if(!NT_STATUS_IS_OK(status)) {
750 DEBUG(5,("_wkssvc_NetrJoinDomain2: no session key %s\n",
751 nt_errstr(status)));
752 return WERR_NO_USER_SESSION_KEY;
755 werr = decode_wkssvc_join_password_buffer(
756 p->mem_ctx, r->in.encrypted_password,
757 &session_key, &cleartext_pwd);
758 if (!W_ERROR_IS_OK(werr)) {
759 return werr;
762 ok = split_domain_user(p->mem_ctx,
763 r->in.admin_account,
764 &admin_domain,
765 &admin_account);
766 if (!ok) {
767 return WERR_NOT_ENOUGH_MEMORY;
770 werr = libnet_init_JoinCtx(p->mem_ctx, &j);
771 if (!W_ERROR_IS_OK(werr)) {
772 return werr;
775 status = ads_simple_creds(j,
776 admin_domain,
777 admin_account,
778 cleartext_pwd,
779 &j->in.admin_credentials);
780 if (!NT_STATUS_IS_OK(status)) {
781 return WERR_NERR_BADUSERNAME;
784 j->in.domain_name = r->in.domain_name;
785 j->in.account_ou = r->in.account_ou;
786 j->in.join_flags = r->in.join_flags;
787 j->in.debug = true;
788 j->in.modify_config = lp_config_backend_is_registry();
789 j->in.msg_ctx = p->msg_ctx;
791 become_root();
792 werr = libnet_Join(p->mem_ctx, j);
793 unbecome_root();
795 if (!W_ERROR_IS_OK(werr)) {
796 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
797 j->out.error_string ? j->out.error_string :
798 win_errstr(werr)));
801 TALLOC_FREE(j);
802 return werr;
805 /********************************************************************
806 _wkssvc_NetrUnjoinDomain2
807 ********************************************************************/
809 WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p,
810 struct wkssvc_NetrUnjoinDomain2 *r)
812 struct dcesrv_call_state *dce_call = p->dce_call;
813 struct auth_session_info *session_info =
814 dcesrv_call_session_info(dce_call);
815 struct libnet_UnjoinCtx *u = NULL;
816 char *cleartext_pwd = NULL;
817 char *admin_domain = NULL;
818 char *admin_account = NULL;
819 WERROR werr;
820 struct security_token *token = session_info->security_token;
821 NTSTATUS status;
822 DATA_BLOB session_key;
823 bool ok;
825 if (!r->in.account || !r->in.encrypted_password) {
826 return WERR_INVALID_PARAMETER;
829 if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
830 !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
831 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
832 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
833 "sufficient privileges\n"));
834 return WERR_ACCESS_DENIED;
837 status = session_extract_session_key(session_info,
838 &session_key,
839 KEY_USE_16BYTES);
840 if (!NT_STATUS_IS_OK(status)) {
841 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: no session key %s\n",
842 nt_errstr(status)));
843 return WERR_NO_USER_SESSION_KEY;
846 werr = decode_wkssvc_join_password_buffer(
847 p->mem_ctx, r->in.encrypted_password,
848 &session_key, &cleartext_pwd);
849 if (!W_ERROR_IS_OK(werr)) {
850 return werr;
853 ok = split_domain_user(p->mem_ctx,
854 r->in.account,
855 &admin_domain,
856 &admin_account);
857 if (!ok) {
858 return WERR_NOT_ENOUGH_MEMORY;
861 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
862 if (!W_ERROR_IS_OK(werr)) {
863 return werr;
866 status = ads_simple_creds(u,
867 admin_domain,
868 admin_account,
869 cleartext_pwd,
870 &u->in.admin_credentials);
871 if (!NT_STATUS_IS_OK(status)) {
872 return WERR_NERR_BADUSERNAME;
875 u->in.domain_name = lp_realm();
876 u->in.unjoin_flags = r->in.unjoin_flags |
877 WKSSVC_JOIN_FLAGS_JOIN_TYPE;
878 u->in.debug = true;
879 u->in.modify_config = lp_config_backend_is_registry();
880 u->in.msg_ctx = p->msg_ctx;
882 become_root();
883 werr = libnet_Unjoin(p->mem_ctx, u);
884 unbecome_root();
886 if (!W_ERROR_IS_OK(werr)) {
887 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
888 u->out.error_string ? u->out.error_string :
889 win_errstr(werr)));
892 TALLOC_FREE(u);
893 return werr;
896 /********************************************************************
897 ********************************************************************/
899 WERROR _wkssvc_NetrRenameMachineInDomain2(struct pipes_struct *p,
900 struct wkssvc_NetrRenameMachineInDomain2 *r)
902 /* for now just return not supported */
903 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
904 return WERR_NOT_SUPPORTED;
907 /********************************************************************
908 ********************************************************************/
910 WERROR _wkssvc_NetrValidateName2(struct pipes_struct *p,
911 struct wkssvc_NetrValidateName2 *r)
913 /* FIXME: Add implementation code here */
914 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
915 return WERR_NOT_SUPPORTED;
918 /********************************************************************
919 ********************************************************************/
921 WERROR _wkssvc_NetrGetJoinableOus2(struct pipes_struct *p,
922 struct wkssvc_NetrGetJoinableOus2 *r)
924 /* FIXME: Add implementation code here */
925 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
926 return WERR_NOT_SUPPORTED;
929 /********************************************************************
930 ********************************************************************/
932 WERROR _wkssvc_NetrAddAlternateComputerName(struct pipes_struct *p,
933 struct wkssvc_NetrAddAlternateComputerName *r)
935 /* FIXME: Add implementation code here */
936 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
937 return WERR_NOT_SUPPORTED;
940 /********************************************************************
941 ********************************************************************/
943 WERROR _wkssvc_NetrRemoveAlternateComputerName(struct pipes_struct *p,
944 struct wkssvc_NetrRemoveAlternateComputerName *r)
946 /* FIXME: Add implementation code here */
947 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
948 return WERR_NOT_SUPPORTED;
951 /********************************************************************
952 ********************************************************************/
954 WERROR _wkssvc_NetrSetPrimaryComputername(struct pipes_struct *p,
955 struct wkssvc_NetrSetPrimaryComputername *r)
957 /* FIXME: Add implementation code here */
958 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
959 return WERR_NOT_SUPPORTED;
962 /********************************************************************
963 ********************************************************************/
965 WERROR _wkssvc_NetrEnumerateComputerNames(struct pipes_struct *p,
966 struct wkssvc_NetrEnumerateComputerNames *r)
968 /* FIXME: Add implementation code here */
969 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
970 return WERR_NOT_SUPPORTED;
973 /* include the generated boilerplate */
974 #include "librpc/gen_ndr/ndr_wkssvc_scompat.c"