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