s3-lib: Do not set an empty string in split_domain_user()
[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         switch (r->in.level) {
349         case 100:
350                 /* Level 100 can be allowed from anyone including anonymous
351                  * so no access checks are needed for this case */
352                 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
353                 if (r->out.info->info100 == NULL) {
354                         return WERR_NOMEM;
355                 }
356                 break;
357         case 101:
358                 /* Level 101 can be allowed from any logged in user */
359                 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
360                                         p->session_info->security_token)) {
361                         DEBUG(1,("User not allowed for NetWkstaGetInfo level "
362                                  "101\n"));
363                         DEBUGADD(3,(" - does not have sid for Authenticated "
364                                     "Users %s:\n",
365                                     sid_string_dbg(
366                                             &global_sid_Authenticated_Users)));
367                         security_token_debug(DBGC_CLASS, 3,
368                                             p->session_info->security_token);
369                         return WERR_ACCESS_DENIED;
370                 }
371                 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
372                 if (r->out.info->info101 == NULL) {
373                         return WERR_NOMEM;
374                 }
375                 break;
376         case 102:
377                 /* Level 102 Should only be allowed from a domain administrator */
378                 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
379                                         p->session_info->security_token)) {
380                         DEBUG(1,("User not allowed for NetWkstaGetInfo level "
381                                  "102\n"));
382                         DEBUGADD(3,(" - does not have sid for Administrators "
383                                     "group %s, sids are:\n",
384                                     sid_string_dbg(&global_sid_Builtin_Administrators)));
385                         security_token_debug(DBGC_CLASS, 3,
386                                             p->session_info->security_token);
387                         return WERR_ACCESS_DENIED;
388                 }
389                 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
390                 if (r->out.info->info102 == NULL) {
391                         return WERR_NOMEM;
392                 }
393                 break;
394         default:
395                 return WERR_UNKNOWN_LEVEL;
396         }
397
398         return WERR_OK;
399 }
400
401 /********************************************************************
402  ********************************************************************/
403
404 WERROR _wkssvc_NetWkstaSetInfo(struct pipes_struct *p,
405                                struct wkssvc_NetWkstaSetInfo *r)
406 {
407         /* FIXME: Add implementation code here */
408         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
409         return WERR_NOT_SUPPORTED;
410 }
411
412 /********************************************************************
413  RPC Workstation Service request NetWkstaEnumUsers with level 0:
414  Returns to the requester:
415   - the user names of the logged in users.
416  Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
417  ********************************************************************/
418
419 static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
420         TALLOC_CTX *mem_ctx)
421 {
422         struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
423         char **users;
424         int i, num_users;
425
426         ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
427         if (ctr0 == NULL) {
428                 return NULL;
429         }
430
431         users = get_logged_on_userlist(talloc_tos());
432         if (users == NULL && errno != 0) {
433                 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
434                         errno, strerror(errno)));
435                 TALLOC_FREE(ctr0);
436                 return NULL;
437         }
438
439         num_users = talloc_array_length(users);
440         ctr0->entries_read = num_users;
441         ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
442                                    num_users);
443         if (ctr0->user0 == NULL) {
444                 TALLOC_FREE(ctr0);
445                 TALLOC_FREE(users);
446                 return NULL;
447         }
448
449         for (i=0; i<num_users; i++) {
450                 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
451         }
452         TALLOC_FREE(users);
453         return ctr0;
454 }
455
456 /********************************************************************
457  RPC Workstation Service request NetWkstaEnumUsers with level 1.
458  Returns to the requester:
459   - the user names of the logged in users,
460   - the domain or machine each is logged into,
461   - the password server that was used to authenticate each,
462   - other domains each user is logged into (not currently supported).
463  Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
464  ********************************************************************/
465
466 static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
467         TALLOC_CTX *mem_ctx)
468 {
469         struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
470         char **users;
471         struct dom_usr *dom_users;
472         const char *pwd_server;
473         char *pwd_tmp;
474         int i, j, num_users, num_dom_users;
475
476         ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
477         if (ctr1 == NULL) {
478                 return NULL;
479         }
480
481         users = get_logged_on_userlist(talloc_tos());
482         if (users == NULL && errno != 0) {
483                 DEBUG(1,("get_logged_on_userlist error %d: %s\n",
484                         errno, strerror(errno)));
485                 TALLOC_FREE(ctr1);
486                 return NULL;
487         }
488         num_users = talloc_array_length(users);
489
490         dom_users = get_domain_userlist(talloc_tos());
491         if (dom_users == NULL && errno != 0) {
492                 TALLOC_FREE(ctr1);
493                 TALLOC_FREE(users);
494                 return NULL;
495         }
496         num_dom_users = talloc_array_length(dom_users);
497
498         ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
499                                    num_users+num_dom_users);
500         if (ctr1->user1 == NULL) {
501                 TALLOC_FREE(ctr1);
502                 TALLOC_FREE(users);
503                 TALLOC_FREE(dom_users);
504                 return NULL;
505         }
506
507         pwd_server = "";
508
509         if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_password_server()))) {
510                 /* The configured password server is a full DNS name but
511                  * for the logon server we need to return just the first
512                  * component (machine name) of it in upper-case */
513                 char *p = strchr(pwd_tmp, '.');
514                 if (p) {
515                         *p = '\0';
516                 } else {
517                         p = pwd_tmp + strlen(pwd_tmp);
518                 }
519                 while (--p >= pwd_tmp) {
520                         *p = toupper(*p);
521                 }
522                 pwd_server = pwd_tmp;
523         }
524
525         /* Put in local users first */
526         for (i=0; i<num_users; i++) {
527                 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]);
528
529                 /* For a local user the domain name and logon server are
530                  * both returned as the local machine's NetBIOS name */
531                 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server =
532                         talloc_asprintf_strupper_m(ctr1->user1, "%s", lp_netbios_name());
533
534                 ctr1->user1[i].other_domains = NULL;    /* Maybe in future? */
535         }
536
537         /* Now domain users */
538         for (j=0; j<num_dom_users; j++) {
539                 ctr1->user1[i].user_name =
540                                 talloc_strdup(ctr1->user1, dom_users[j].name);
541                 ctr1->user1[i].logon_domain =
542                                 talloc_strdup(ctr1->user1, dom_users[j].domain);
543                 ctr1->user1[i].logon_server = pwd_server;
544
545                 ctr1->user1[i++].other_domains = NULL;  /* Maybe in future? */
546         }
547
548         ctr1->entries_read = i;
549
550         TALLOC_FREE(users);
551         TALLOC_FREE(dom_users);
552         return ctr1;
553 }
554
555 /********************************************************************
556  Handling for RPC Workstation Service request NetWkstaEnumUsers
557  (a.k.a Windows NetWkstaUserEnum)
558  ********************************************************************/
559
560 WERROR _wkssvc_NetWkstaEnumUsers(struct pipes_struct *p,
561                                  struct wkssvc_NetWkstaEnumUsers *r)
562 {
563         /* This with any level should only be allowed from a domain administrator */
564         if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
565                                 p->session_info->security_token)) {
566                 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n"));
567                 DEBUGADD(3,(" - does not have sid for Administrators group "
568                             "%s\n", sid_string_dbg(
569                                     &global_sid_Builtin_Administrators)));
570                 security_token_debug(DBGC_CLASS, 3, p->session_info->security_token);
571                 return WERR_ACCESS_DENIED;
572         }
573
574         switch (r->in.info->level) {
575         case 0:
576                 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx);
577                 if (r->out.info->ctr.user0 == NULL) {
578                         return WERR_NOMEM;
579                 }
580                 r->out.info->level = r->in.info->level;
581                 *r->out.entries_read = r->out.info->ctr.user0->entries_read;
582                 if (r->out.resume_handle != NULL) {
583                         *r->out.resume_handle = 0;
584                 }
585                 break;
586         case 1:
587                 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx);
588                 if (r->out.info->ctr.user1 == NULL) {
589                         return WERR_NOMEM;
590                 }
591                 r->out.info->level = r->in.info->level;
592                 *r->out.entries_read = r->out.info->ctr.user1->entries_read;
593                 if (r->out.resume_handle != NULL) {
594                         *r->out.resume_handle = 0;
595                 }
596                 break;
597         default:
598                 return WERR_UNKNOWN_LEVEL;
599         }
600
601         return WERR_OK;
602 }
603
604 /********************************************************************
605  ********************************************************************/
606
607 WERROR _wkssvc_NetrWkstaUserGetInfo(struct pipes_struct *p,
608                                     struct wkssvc_NetrWkstaUserGetInfo *r)
609 {
610         /* FIXME: Add implementation code here */
611         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
612         return WERR_NOT_SUPPORTED;
613 }
614
615 /********************************************************************
616  ********************************************************************/
617
618 WERROR _wkssvc_NetrWkstaUserSetInfo(struct pipes_struct *p,
619                                     struct wkssvc_NetrWkstaUserSetInfo *r)
620 {
621         /* FIXME: Add implementation code here */
622         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
623         return WERR_NOT_SUPPORTED;
624 }
625
626 /********************************************************************
627  ********************************************************************/
628
629 WERROR _wkssvc_NetWkstaTransportEnum(struct pipes_struct *p,
630                                      struct wkssvc_NetWkstaTransportEnum *r)
631 {
632         /* FIXME: Add implementation code here */
633         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
634         return WERR_NOT_SUPPORTED;
635 }
636
637 /********************************************************************
638  ********************************************************************/
639
640 WERROR _wkssvc_NetrWkstaTransportAdd(struct pipes_struct *p,
641                                      struct wkssvc_NetrWkstaTransportAdd *r)
642 {
643         /* FIXME: Add implementation code here */
644         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
645         return WERR_NOT_SUPPORTED;
646 }
647
648 /********************************************************************
649  ********************************************************************/
650
651 WERROR _wkssvc_NetrWkstaTransportDel(struct pipes_struct *p,
652                                      struct wkssvc_NetrWkstaTransportDel *r)
653 {
654         /* FIXME: Add implementation code here */
655         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
656         return WERR_NOT_SUPPORTED;
657 }
658
659 /********************************************************************
660  ********************************************************************/
661
662 WERROR _wkssvc_NetrUseAdd(struct pipes_struct *p,
663                           struct wkssvc_NetrUseAdd *r)
664 {
665         /* FIXME: Add implementation code here */
666         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
667         return WERR_NOT_SUPPORTED;
668 }
669
670 /********************************************************************
671  ********************************************************************/
672
673 WERROR _wkssvc_NetrUseGetInfo(struct pipes_struct *p,
674                               struct wkssvc_NetrUseGetInfo *r)
675 {
676         /* FIXME: Add implementation code here */
677         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
678         return WERR_NOT_SUPPORTED;
679 }
680
681 /********************************************************************
682  ********************************************************************/
683
684 WERROR _wkssvc_NetrUseDel(struct pipes_struct *p,
685                           struct wkssvc_NetrUseDel *r)
686 {
687         /* FIXME: Add implementation code here */
688         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
689         return WERR_NOT_SUPPORTED;
690 }
691
692 /********************************************************************
693  ********************************************************************/
694
695 WERROR _wkssvc_NetrUseEnum(struct pipes_struct *p,
696                            struct wkssvc_NetrUseEnum *r)
697 {
698         /* FIXME: Add implementation code here */
699         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
700         return WERR_NOT_SUPPORTED;
701 }
702
703 /********************************************************************
704  ********************************************************************/
705
706 WERROR _wkssvc_NetrMessageBufferSend(struct pipes_struct *p,
707                                      struct wkssvc_NetrMessageBufferSend *r)
708 {
709         /* FIXME: Add implementation code here */
710         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
711         return WERR_NOT_SUPPORTED;
712 }
713
714 /********************************************************************
715  ********************************************************************/
716
717 WERROR _wkssvc_NetrWorkstationStatisticsGet(struct pipes_struct *p,
718                                             struct wkssvc_NetrWorkstationStatisticsGet *r)
719 {
720         /* FIXME: Add implementation code here */
721         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
722         return WERR_NOT_SUPPORTED;
723 }
724
725 /********************************************************************
726  ********************************************************************/
727
728 WERROR _wkssvc_NetrLogonDomainNameAdd(struct pipes_struct *p,
729                                       struct wkssvc_NetrLogonDomainNameAdd *r)
730 {
731         /* FIXME: Add implementation code here */
732         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
733         return WERR_NOT_SUPPORTED;
734 }
735
736 /********************************************************************
737  ********************************************************************/
738
739 WERROR _wkssvc_NetrLogonDomainNameDel(struct pipes_struct *p,
740                                       struct wkssvc_NetrLogonDomainNameDel *r)
741 {
742         /* FIXME: Add implementation code here */
743         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
744         return WERR_NOT_SUPPORTED;
745 }
746
747 /********************************************************************
748  ********************************************************************/
749
750 WERROR _wkssvc_NetrJoinDomain(struct pipes_struct *p,
751                               struct wkssvc_NetrJoinDomain *r)
752 {
753         /* FIXME: Add implementation code here */
754         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
755         return WERR_NOT_SUPPORTED;
756 }
757
758 /********************************************************************
759  ********************************************************************/
760
761 WERROR _wkssvc_NetrUnjoinDomain(struct pipes_struct *p,
762                                 struct wkssvc_NetrUnjoinDomain *r)
763 {
764         /* FIXME: Add implementation code here */
765         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
766         return WERR_NOT_SUPPORTED;
767 }
768
769 /********************************************************************
770  ********************************************************************/
771
772 WERROR _wkssvc_NetrRenameMachineInDomain(struct pipes_struct *p,
773                                          struct wkssvc_NetrRenameMachineInDomain *r)
774 {
775         /* FIXME: Add implementation code here */
776         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
777         return WERR_NOT_SUPPORTED;
778 }
779
780 /********************************************************************
781  ********************************************************************/
782
783 WERROR _wkssvc_NetrValidateName(struct pipes_struct *p,
784                                 struct wkssvc_NetrValidateName *r)
785 {
786         /* FIXME: Add implementation code here */
787         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
788         return WERR_NOT_SUPPORTED;
789 }
790
791 /********************************************************************
792  ********************************************************************/
793
794 WERROR _wkssvc_NetrGetJoinInformation(struct pipes_struct *p,
795                                       struct wkssvc_NetrGetJoinInformation *r)
796 {
797         /* FIXME: Add implementation code here */
798         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
799         return WERR_NOT_SUPPORTED;
800 }
801
802 /********************************************************************
803  ********************************************************************/
804
805 WERROR _wkssvc_NetrGetJoinableOus(struct pipes_struct *p,
806                                   struct wkssvc_NetrGetJoinableOus *r)
807 {
808         /* FIXME: Add implementation code here */
809         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
810         return WERR_NOT_SUPPORTED;
811 }
812
813 /********************************************************************
814  _wkssvc_NetrJoinDomain2
815  ********************************************************************/
816
817 WERROR _wkssvc_NetrJoinDomain2(struct pipes_struct *p,
818                                struct wkssvc_NetrJoinDomain2 *r)
819 {
820         struct libnet_JoinCtx *j = NULL;
821         char *cleartext_pwd = NULL;
822         char *admin_domain = NULL;
823         char *admin_account = NULL;
824         WERROR werr;
825         struct security_token *token = p->session_info->security_token;
826         NTSTATUS status;
827         DATA_BLOB session_key;
828         bool ok;
829
830         if (!r->in.domain_name) {
831                 return WERR_INVALID_PARAM;
832         }
833
834         if (!r->in.admin_account || !r->in.encrypted_password) {
835                 return WERR_INVALID_PARAM;
836         }
837
838         if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
839             !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
840             !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
841                 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
842                         "sufficient privileges\n"));
843                 return WERR_ACCESS_DENIED;
844         }
845
846         if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
847             (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
848                 return WERR_NOT_SUPPORTED;
849         }
850
851         status = session_extract_session_key(p->session_info,
852                                              &session_key,
853                                              KEY_USE_16BYTES);
854         if(!NT_STATUS_IS_OK(status)) {
855                 DEBUG(5,("_wkssvc_NetrJoinDomain2: no session key %s\n",
856                         nt_errstr(status)));
857                 return WERR_NO_USER_SESSION_KEY;
858         }
859
860         werr = decode_wkssvc_join_password_buffer(
861                 p->mem_ctx, r->in.encrypted_password,
862                 &session_key, &cleartext_pwd);
863         if (!W_ERROR_IS_OK(werr)) {
864                 return werr;
865         }
866
867         ok = split_domain_user(p->mem_ctx,
868                                r->in.admin_account,
869                                &admin_domain,
870                                &admin_account);
871         if (!ok) {
872                 return WERR_NOMEM;
873         }
874
875         werr = libnet_init_JoinCtx(p->mem_ctx, &j);
876         if (!W_ERROR_IS_OK(werr)) {
877                 return werr;
878         }
879
880         j->in.domain_name       = r->in.domain_name;
881         j->in.account_ou        = r->in.account_ou;
882         j->in.join_flags        = r->in.join_flags;
883         j->in.admin_account     = admin_account;
884         j->in.admin_password    = cleartext_pwd;
885         j->in.debug             = true;
886         j->in.modify_config     = lp_config_backend_is_registry();
887         j->in.msg_ctx           = p->msg_ctx;
888
889         become_root();
890         setenv(KRB5_ENV_CCNAME, "MEMORY:_wkssvc_NetrJoinDomain2", 1);
891         werr = libnet_Join(p->mem_ctx, j);
892         unsetenv(KRB5_ENV_CCNAME);
893         unbecome_root();
894
895         if (!W_ERROR_IS_OK(werr)) {
896                 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
897                         j->out.error_string ? j->out.error_string :
898                         win_errstr(werr)));
899         }
900
901         TALLOC_FREE(j);
902         return werr;
903 }
904
905 /********************************************************************
906  _wkssvc_NetrUnjoinDomain2
907  ********************************************************************/
908
909 WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p,
910                                  struct wkssvc_NetrUnjoinDomain2 *r)
911 {
912         struct libnet_UnjoinCtx *u = NULL;
913         char *cleartext_pwd = NULL;
914         char *admin_domain = NULL;
915         char *admin_account = NULL;
916         WERROR werr;
917         struct security_token *token = p->session_info->security_token;
918         NTSTATUS status;
919         DATA_BLOB session_key;
920         bool ok;
921
922         if (!r->in.account || !r->in.encrypted_password) {
923                 return WERR_INVALID_PARAM;
924         }
925
926         if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
927             !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
928             !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
929                 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
930                         "sufficient privileges\n"));
931                 return WERR_ACCESS_DENIED;
932         }
933
934         status = session_extract_session_key(p->session_info,
935                                              &session_key,
936                                              KEY_USE_16BYTES);
937         if (!NT_STATUS_IS_OK(status)) {
938                 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: no session key %s\n",
939                         nt_errstr(status)));
940                 return WERR_NO_USER_SESSION_KEY;
941         }
942
943         werr = decode_wkssvc_join_password_buffer(
944                 p->mem_ctx, r->in.encrypted_password,
945                 &session_key, &cleartext_pwd);
946         if (!W_ERROR_IS_OK(werr)) {
947                 return werr;
948         }
949
950         ok = split_domain_user(p->mem_ctx,
951                                r->in.account,
952                                &admin_domain,
953                                &admin_account);
954         if (!ok) {
955                 return WERR_NOMEM;
956         }
957
958         werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
959         if (!W_ERROR_IS_OK(werr)) {
960                 return werr;
961         }
962
963         u->in.domain_name       = lp_realm();
964         u->in.unjoin_flags      = r->in.unjoin_flags |
965                                   WKSSVC_JOIN_FLAGS_JOIN_TYPE;
966         u->in.admin_account     = admin_account;
967         u->in.admin_password    = cleartext_pwd;
968         u->in.debug             = true;
969         u->in.modify_config     = lp_config_backend_is_registry();
970         u->in.msg_ctx           = p->msg_ctx;
971
972         become_root();
973         setenv(KRB5_ENV_CCNAME, "MEMORY:_wkssvc_NetrUnjoinDomain2", 1);
974         werr = libnet_Unjoin(p->mem_ctx, u);
975         unsetenv(KRB5_ENV_CCNAME);
976         unbecome_root();
977
978         if (!W_ERROR_IS_OK(werr)) {
979                 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
980                         u->out.error_string ? u->out.error_string :
981                         win_errstr(werr)));
982         }
983
984         TALLOC_FREE(u);
985         return werr;
986 }
987
988 /********************************************************************
989  ********************************************************************/
990
991 WERROR _wkssvc_NetrRenameMachineInDomain2(struct pipes_struct *p,
992                                           struct wkssvc_NetrRenameMachineInDomain2 *r)
993 {
994         /* for now just return not supported */
995         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
996         return WERR_NOT_SUPPORTED;
997 }
998
999 /********************************************************************
1000  ********************************************************************/
1001
1002 WERROR _wkssvc_NetrValidateName2(struct pipes_struct *p,
1003                                  struct wkssvc_NetrValidateName2 *r)
1004 {
1005         /* FIXME: Add implementation code here */
1006         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1007         return WERR_NOT_SUPPORTED;
1008 }
1009
1010 /********************************************************************
1011  ********************************************************************/
1012
1013 WERROR _wkssvc_NetrGetJoinableOus2(struct pipes_struct *p,
1014                                    struct wkssvc_NetrGetJoinableOus2 *r)
1015 {
1016         /* FIXME: Add implementation code here */
1017         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1018         return WERR_NOT_SUPPORTED;
1019 }
1020
1021 /********************************************************************
1022  ********************************************************************/
1023
1024 WERROR _wkssvc_NetrAddAlternateComputerName(struct pipes_struct *p,
1025                                             struct wkssvc_NetrAddAlternateComputerName *r)
1026 {
1027         /* FIXME: Add implementation code here */
1028         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1029         return WERR_NOT_SUPPORTED;
1030 }
1031
1032 /********************************************************************
1033  ********************************************************************/
1034
1035 WERROR _wkssvc_NetrRemoveAlternateComputerName(struct pipes_struct *p,
1036                                                struct wkssvc_NetrRemoveAlternateComputerName *r)
1037 {
1038         /* FIXME: Add implementation code here */
1039         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1040         return WERR_NOT_SUPPORTED;
1041 }
1042
1043 /********************************************************************
1044  ********************************************************************/
1045
1046 WERROR _wkssvc_NetrSetPrimaryComputername(struct pipes_struct *p,
1047                                           struct wkssvc_NetrSetPrimaryComputername *r)
1048 {
1049         /* FIXME: Add implementation code here */
1050         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1051         return WERR_NOT_SUPPORTED;
1052 }
1053
1054 /********************************************************************
1055  ********************************************************************/
1056
1057 WERROR _wkssvc_NetrEnumerateComputerNames(struct pipes_struct *p,
1058                                           struct wkssvc_NetrEnumerateComputerNames *r)
1059 {
1060         /* FIXME: Add implementation code here */
1061         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1062         return WERR_NOT_SUPPORTED;
1063 }