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