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