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