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