d7f3f82298e2b6e986b068412128af54dfecd1ce
[ira/wip.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 "libnet/libnet.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../librpc/gen_ndr/srv_wkssvc.h"
29
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
32
33 struct dom_usr {
34         char *name;
35         char *domain;
36         time_t login_time;
37 };
38
39 #ifdef HAVE_GETUTXENT
40
41 #include <utmpx.h>
42
43 struct usrinfo {
44         char *name;
45         struct timeval login_time;
46 };
47
48 static int usr_info_cmp(const void *p1, const void *p2)
49 {
50         const struct usrinfo *usr1 = (const struct usrinfo *)p1;
51         const struct usrinfo *usr2 = (const struct usrinfo *)p2;
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         qsort(usr_infos, num_users, sizeof(struct usrinfo), 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 void *p1, const void *p2)
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         const struct dom_usr *usr1 = (const struct dom_usr *)p1;
136         const struct dom_usr *usr2 = (const struct dom_usr *)p2;
137
138         return (usr1->login_time - usr2->login_time);
139 }
140
141 /*******************************************************************
142  Get a list of the names of all users of this machine who are
143  logged into the domain.
144
145  This should return a list of the users on this machine who are
146  logged into the domain (i.e. have been authenticated by the domain's
147  password server) but that doesn't fit well with the normal Samba
148  scenario where accesses out to the domain are made through smbclient
149  with each such session individually authenticated. So about the best
150  we can do currently is to list sessions of local users connected to
151  this server, which means that to get themself included in the list a
152  local user must create a session to the local samba server by running:
153      smbclient \\\\localhost\\share
154
155  FIXME: find a better way to get local users logged into the domain
156  in this list.
157  ********************************************************************/
158
159 static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
160 {
161         struct sessionid *session_list = NULL;
162         char *machine_name, *p, *nm;
163         const char *sep;
164         struct dom_usr *users, *tmp;
165         int i, num_users, num_sessions;
166
167         sep = lp_winbind_separator();
168         if (!sep) {
169                 sep = "\\";
170         }
171
172         num_sessions = list_sessions(mem_ctx, &session_list);
173         if (num_sessions == 0) {
174                 errno = 0;
175                 return NULL;
176         }
177
178         users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
179         if (users == NULL) {
180                 TALLOC_FREE(session_list);
181                 return NULL;
182         }
183
184         for (i=num_users=0; i<num_sessions; i++) {
185                 if (!session_list[i].username
186                     || !session_list[i].remote_machine) {
187                         continue;
188                 }
189                 p = strpbrk(session_list[i].remote_machine, "./");
190                 if (p) {
191                         *p = '\0';
192                 }
193                 machine_name = talloc_asprintf_strupper_m(
194                         users, "%s", session_list[i].remote_machine);
195                 if (machine_name == NULL) {
196                         DEBUG(10, ("talloc_asprintf failed\n"));
197                         continue;
198                 }
199                 if (strcmp(machine_name, global_myname()) == 0) {
200                         p = session_list[i].username;
201                         nm = strstr(p, sep);
202                         if (nm) {
203                                 /*
204                                  * "domain+name" format so split domain and
205                                  * name components
206                                  */
207                                 *nm = '\0';
208                                 nm += strlen(sep);
209                                 users[num_users].domain =
210                                         talloc_asprintf_strupper_m(users,
211                                                                    "%s", p);
212                                 users[num_users].name = talloc_strdup(users,
213                                                                       nm);
214                         } else {
215                                 /*
216                                  * Simple user name so get domain from smb.conf
217                                  */
218                                 users[num_users].domain =
219                                         talloc_strdup(users, lp_workgroup());
220                                 users[num_users].name = talloc_strdup(users,
221                                                                       p);
222                         }
223                         users[num_users].login_time =
224                                 session_list[i].connect_start;
225                         num_users++;
226                 }
227                 TALLOC_FREE(machine_name);
228         }
229         TALLOC_FREE(session_list);
230
231         tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
232         if (tmp == NULL) {
233                 return NULL;
234         }
235         users = tmp;
236
237         /* Sort the user list by time, oldest first */
238         qsort(users, num_users, sizeof(struct dom_usr), dom_user_cmp);
239
240         errno = 0;
241         return users;
242 }
243
244 /*******************************************************************
245  RPC Workstation Service request NetWkstaGetInfo with level 100.
246  Returns to the requester:
247   - The machine name.
248   - The smb version number
249   - The domain name.
250  Returns a filled in wkssvc_NetWkstaInfo100 struct.
251  ********************************************************************/
252
253 static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
254 {
255         struct wkssvc_NetWkstaInfo100 *info100;
256
257         info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
258         if (info100 == NULL) {
259                 return NULL;
260         }
261
262         info100->platform_id     = PLATFORM_ID_NT;      /* unknown */
263         info100->version_major   = lp_major_announce_version();
264         info100->version_minor   = lp_minor_announce_version();
265
266         info100->server_name = talloc_asprintf_strupper_m(
267                 info100, "%s", global_myname());
268         info100->domain_name = talloc_asprintf_strupper_m(
269                 info100, "%s", lp_workgroup());
270
271         return info100;
272 }
273
274 /*******************************************************************
275  RPC Workstation Service request NetWkstaGetInfo with level 101.
276  Returns to the requester:
277   - As per NetWkstaGetInfo with level 100, plus:
278   - The LANMAN directory path (not currently supported).
279  Returns a filled in wkssvc_NetWkstaInfo101 struct.
280  ********************************************************************/
281
282 static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
283 {
284         struct wkssvc_NetWkstaInfo101 *info101;
285
286         info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
287         if (info101 == NULL) {
288                 return NULL;
289         }
290
291         info101->platform_id     = PLATFORM_ID_NT;      /* unknown */
292         info101->version_major   = lp_major_announce_version();
293         info101->version_minor   = lp_minor_announce_version();
294
295         info101->server_name = talloc_asprintf_strupper_m(
296                 info101, "%s", global_myname());
297         info101->domain_name = talloc_asprintf_strupper_m(
298                 info101, "%s", lp_workgroup());
299         info101->lan_root = "";
300
301         return info101;
302 }
303
304 /*******************************************************************
305  RPC Workstation Service request NetWkstaGetInfo with level 102.
306  Returns to the requester:
307   - As per NetWkstaGetInfo with level 101, plus:
308   - The number of logged in users.
309  Returns a filled in wkssvc_NetWkstaInfo102 struct.
310  ********************************************************************/
311
312 static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
313 {
314         struct wkssvc_NetWkstaInfo102 *info102;
315         char **users;
316
317         info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
318         if (info102 == NULL) {
319                 return NULL;
320         }
321
322         info102->platform_id     = PLATFORM_ID_NT;      /* unknown */
323         info102->version_major   = lp_major_announce_version();
324         info102->version_minor   = lp_minor_announce_version();
325
326         info102->server_name = talloc_asprintf_strupper_m(
327                 info102, "%s", global_myname());
328         info102->domain_name = talloc_asprintf_strupper_m(
329                 info102, "%s", lp_workgroup());
330         info102->lan_root = "";
331
332         users = get_logged_on_userlist(talloc_tos());
333         info102->logged_on_users = talloc_array_length(users);
334
335         TALLOC_FREE(users);
336
337         return info102;
338 }
339
340 /********************************************************************
341  Handling for RPC Workstation Service request NetWkstaGetInfo
342  ********************************************************************/
343
344 WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
345 {
346         switch (r->in.level) {
347         case 100:
348                 /* Level 100 can be allowed from anyone including anonymous
349                  * so no access checks are needed for this case */
350                 r->out.info->info100 = create_wks_info_100(p->mem_ctx);
351                 if (r->out.info->info100 == NULL) {
352                         return WERR_NOMEM;
353                 }
354                 break;
355         case 101:
356                 /* Level 101 can be allowed from any logged in user */
357                 if (!nt_token_check_sid(&global_sid_Authenticated_Users,
358                                         p->server_info->ptok)) {
359                         DEBUG(1,("User not allowed for NetWkstaGetInfo level "
360                                  "101\n"));
361                         DEBUGADD(3,(" - does not have sid for Authenticated "
362                                     "Users %s:\n",
363                                     sid_string_dbg(
364                                             &global_sid_Authenticated_Users)));
365                         debug_nt_user_token(DBGC_CLASS, 3,
366                                             p->server_info->ptok);
367                         return WERR_ACCESS_DENIED;
368                 }
369                 r->out.info->info101 = create_wks_info_101(p->mem_ctx);
370                 if (r->out.info->info101 == NULL) {
371                         return WERR_NOMEM;
372                 }
373                 break;
374         case 102:
375                 /* Level 102 Should only be allowed from a domain administrator */
376                 if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
377                                         p->server_info->ptok)) {
378                         DEBUG(1,("User not allowed for NetWkstaGetInfo level "
379                                  "102\n"));
380                         DEBUGADD(3,(" - does not have sid for Administrators "
381                                     "group %s, sids are:\n",
382                                     sid_string_dbg(&global_sid_Builtin_Administrators)));
383                         debug_nt_user_token(DBGC_CLASS, 3,
384                                             p->server_info->ptok);
385                         return WERR_ACCESS_DENIED;
386                 }
387                 r->out.info->info102 = create_wks_info_102(p->mem_ctx);
388                 if (r->out.info->info102 == NULL) {
389                         return WERR_NOMEM;
390                 }
391                 break;
392         default:
393                 return WERR_UNKNOWN_LEVEL;
394         }
395
396         return WERR_OK;
397 }
398
399 /********************************************************************
400  ********************************************************************/
401
402 WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, 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(pipes_struct *p, 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->server_info->ptok)) {
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                 debug_nt_user_token(DBGC_CLASS, 3, p->server_info->ptok);
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(pipes_struct *p, struct wkssvc_NetrWkstaUserGetInfo *r)
600 {
601         /* FIXME: Add implementation code here */
602         p->rng_fault_state = True;
603         return WERR_NOT_SUPPORTED;
604 }
605
606 /********************************************************************
607  ********************************************************************/
608
609 WERROR _wkssvc_NetrWkstaUserSetInfo(pipes_struct *p, 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(pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r)
620 {
621         /* FIXME: Add implementation code here */
622         p->rng_fault_state = True;
623         return WERR_NOT_SUPPORTED;
624 }
625
626 /********************************************************************
627  ********************************************************************/
628
629 WERROR _wkssvc_NetrWkstaTransportAdd(pipes_struct *p, struct wkssvc_NetrWkstaTransportAdd *r)
630 {
631         /* FIXME: Add implementation code here */
632         p->rng_fault_state = True;
633         return WERR_NOT_SUPPORTED;
634 }
635
636 /********************************************************************
637  ********************************************************************/
638
639 WERROR _wkssvc_NetrWkstaTransportDel(pipes_struct *p, struct wkssvc_NetrWkstaTransportDel *r)
640 {
641         /* FIXME: Add implementation code here */
642         p->rng_fault_state = True;
643         return WERR_NOT_SUPPORTED;
644 }
645
646 /********************************************************************
647  ********************************************************************/
648
649 WERROR _wkssvc_NetrUseAdd(pipes_struct *p, struct wkssvc_NetrUseAdd *r)
650 {
651         /* FIXME: Add implementation code here */
652         p->rng_fault_state = True;
653         return WERR_NOT_SUPPORTED;
654 }
655
656 /********************************************************************
657  ********************************************************************/
658
659 WERROR _wkssvc_NetrUseGetInfo(pipes_struct *p, struct wkssvc_NetrUseGetInfo *r)
660 {
661         /* FIXME: Add implementation code here */
662         p->rng_fault_state = True;
663         return WERR_NOT_SUPPORTED;
664 }
665
666 /********************************************************************
667  ********************************************************************/
668
669 WERROR _wkssvc_NetrUseDel(pipes_struct *p, struct wkssvc_NetrUseDel *r)
670 {
671         /* FIXME: Add implementation code here */
672         p->rng_fault_state = True;
673         return WERR_NOT_SUPPORTED;
674 }
675
676 /********************************************************************
677  ********************************************************************/
678
679 WERROR _wkssvc_NetrUseEnum(pipes_struct *p, struct wkssvc_NetrUseEnum *r)
680 {
681         /* FIXME: Add implementation code here */
682         p->rng_fault_state = True;
683         return WERR_NOT_SUPPORTED;
684 }
685
686 /********************************************************************
687  ********************************************************************/
688
689 WERROR _wkssvc_NetrMessageBufferSend(pipes_struct *p, struct wkssvc_NetrMessageBufferSend *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_NetrWorkstationStatisticsGet(pipes_struct *p, struct wkssvc_NetrWorkstationStatisticsGet *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_NetrLogonDomainNameAdd(pipes_struct *p, struct wkssvc_NetrLogonDomainNameAdd *r)
710 {
711         /* FIXME: Add implementation code here */
712         p->rng_fault_state = True;
713         return WERR_NOT_SUPPORTED;
714 }
715
716 /********************************************************************
717  ********************************************************************/
718
719 WERROR _wkssvc_NetrLogonDomainNameDel(pipes_struct *p, struct wkssvc_NetrLogonDomainNameDel *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_NetrJoinDomain(pipes_struct *p, struct wkssvc_NetrJoinDomain *r)
730 {
731         /* FIXME: Add implementation code here */
732         p->rng_fault_state = True;
733         return WERR_NOT_SUPPORTED;
734 }
735
736 /********************************************************************
737  ********************************************************************/
738
739 WERROR _wkssvc_NetrUnjoinDomain(pipes_struct *p, struct wkssvc_NetrUnjoinDomain *r)
740 {
741         /* FIXME: Add implementation code here */
742         p->rng_fault_state = True;
743         return WERR_NOT_SUPPORTED;
744 }
745
746 /********************************************************************
747  ********************************************************************/
748
749 WERROR _wkssvc_NetrRenameMachineInDomain(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain *r)
750 {
751         /* FIXME: Add implementation code here */
752         p->rng_fault_state = True;
753         return WERR_NOT_SUPPORTED;
754 }
755
756 /********************************************************************
757  ********************************************************************/
758
759 WERROR _wkssvc_NetrValidateName(pipes_struct *p, struct wkssvc_NetrValidateName *r)
760 {
761         /* FIXME: Add implementation code here */
762         p->rng_fault_state = True;
763         return WERR_NOT_SUPPORTED;
764 }
765
766 /********************************************************************
767  ********************************************************************/
768
769 WERROR _wkssvc_NetrGetJoinInformation(pipes_struct *p, struct wkssvc_NetrGetJoinInformation *r)
770 {
771         /* FIXME: Add implementation code here */
772         p->rng_fault_state = True;
773         return WERR_NOT_SUPPORTED;
774 }
775
776 /********************************************************************
777  ********************************************************************/
778
779 WERROR _wkssvc_NetrGetJoinableOus(pipes_struct *p, struct wkssvc_NetrGetJoinableOus *r)
780 {
781         /* FIXME: Add implementation code here */
782         p->rng_fault_state = True;
783         return WERR_NOT_SUPPORTED;
784 }
785
786 /********************************************************************
787  _wkssvc_NetrJoinDomain2
788  ********************************************************************/
789
790 WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p,
791                                struct wkssvc_NetrJoinDomain2 *r)
792 {
793         struct libnet_JoinCtx *j = NULL;
794         char *cleartext_pwd = NULL;
795         char *admin_domain = NULL;
796         char *admin_account = NULL;
797         WERROR werr;
798         struct nt_user_token *token = p->server_info->ptok;
799
800         if (!r->in.domain_name) {
801                 return WERR_INVALID_PARAM;
802         }
803
804         if (!r->in.admin_account || !r->in.encrypted_password) {
805                 return WERR_INVALID_PARAM;
806         }
807
808         if (!user_has_privileges(token, &se_machine_account) &&
809             !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) &&
810             !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
811                 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have "
812                         "sufficient privileges\n"));
813                 return WERR_ACCESS_DENIED;
814         }
815
816         if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) ||
817             (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
818                 return WERR_NOT_SUPPORTED;
819         }
820
821         werr = decode_wkssvc_join_password_buffer(
822                 p->mem_ctx, r->in.encrypted_password,
823                 &p->server_info->user_session_key, &cleartext_pwd);
824         if (!W_ERROR_IS_OK(werr)) {
825                 return werr;
826         }
827
828         split_domain_user(p->mem_ctx,
829                           r->in.admin_account,
830                           &admin_domain,
831                           &admin_account);
832
833         werr = libnet_init_JoinCtx(p->mem_ctx, &j);
834         if (!W_ERROR_IS_OK(werr)) {
835                 return werr;
836         }
837
838         j->in.domain_name       = r->in.domain_name;
839         j->in.account_ou        = r->in.account_ou;
840         j->in.join_flags        = r->in.join_flags;
841         j->in.admin_account     = admin_account;
842         j->in.admin_password    = cleartext_pwd;
843         j->in.debug             = true;
844         j->in.modify_config     = lp_config_backend_is_registry();
845         j->in.msg_ctx           = smbd_messaging_context();
846
847         become_root();
848         werr = libnet_Join(p->mem_ctx, j);
849         unbecome_root();
850
851         if (!W_ERROR_IS_OK(werr)) {
852                 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n",
853                         j->out.error_string ? j->out.error_string :
854                         win_errstr(werr)));
855         }
856
857         TALLOC_FREE(j);
858         return werr;
859 }
860
861 /********************************************************************
862  _wkssvc_NetrUnjoinDomain2
863  ********************************************************************/
864
865 WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p,
866                                  struct wkssvc_NetrUnjoinDomain2 *r)
867 {
868         struct libnet_UnjoinCtx *u = NULL;
869         char *cleartext_pwd = NULL;
870         char *admin_domain = NULL;
871         char *admin_account = NULL;
872         WERROR werr;
873         struct nt_user_token *token = p->server_info->ptok;
874
875         if (!r->in.account || !r->in.encrypted_password) {
876                 return WERR_INVALID_PARAM;
877         }
878
879         if (!user_has_privileges(token, &se_machine_account) &&
880             !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) &&
881             !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
882                 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
883                         "sufficient privileges\n"));
884                 return WERR_ACCESS_DENIED;
885         }
886
887         werr = decode_wkssvc_join_password_buffer(
888                 p->mem_ctx, r->in.encrypted_password,
889                 &p->server_info->user_session_key, &cleartext_pwd);
890         if (!W_ERROR_IS_OK(werr)) {
891                 return werr;
892         }
893
894         split_domain_user(p->mem_ctx,
895                           r->in.account,
896                           &admin_domain,
897                           &admin_account);
898
899         werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
900         if (!W_ERROR_IS_OK(werr)) {
901                 return werr;
902         }
903
904         u->in.domain_name       = lp_realm();
905         u->in.unjoin_flags      = r->in.unjoin_flags |
906                                   WKSSVC_JOIN_FLAGS_JOIN_TYPE;
907         u->in.admin_account     = admin_account;
908         u->in.admin_password    = cleartext_pwd;
909         u->in.debug             = true;
910         u->in.modify_config     = lp_config_backend_is_registry();
911         u->in.msg_ctx           = smbd_messaging_context();
912
913         become_root();
914         werr = libnet_Unjoin(p->mem_ctx, u);
915         unbecome_root();
916
917         if (!W_ERROR_IS_OK(werr)) {
918                 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
919                         u->out.error_string ? u->out.error_string :
920                         win_errstr(werr)));
921         }
922
923         TALLOC_FREE(u);
924         return werr;
925 }
926
927 /********************************************************************
928  ********************************************************************/
929
930 WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r)
931 {
932         /* for now just return not supported */
933         return WERR_NOT_SUPPORTED;
934 }
935
936 /********************************************************************
937  ********************************************************************/
938
939 WERROR _wkssvc_NetrValidateName2(pipes_struct *p, struct wkssvc_NetrValidateName2 *r)
940 {
941         /* FIXME: Add implementation code here */
942         p->rng_fault_state = True;
943         return WERR_NOT_SUPPORTED;
944 }
945
946 /********************************************************************
947  ********************************************************************/
948
949 WERROR _wkssvc_NetrGetJoinableOus2(pipes_struct *p, struct wkssvc_NetrGetJoinableOus2 *r)
950 {
951         /* FIXME: Add implementation code here */
952         p->rng_fault_state = True;
953         return WERR_NOT_SUPPORTED;
954 }
955
956 /********************************************************************
957  ********************************************************************/
958
959 WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r)
960 {
961         /* FIXME: Add implementation code here */
962         p->rng_fault_state = True;
963         return WERR_NOT_SUPPORTED;
964 }
965
966 /********************************************************************
967  ********************************************************************/
968
969 WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *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_NetrSetPrimaryComputername(pipes_struct *p, struct wkssvc_NetrSetPrimaryComputername *r)
980 {
981         /* FIXME: Add implementation code here */
982         p->rng_fault_state = True;
983         return WERR_NOT_SUPPORTED;
984 }
985
986 /********************************************************************
987  ********************************************************************/
988
989 WERROR _wkssvc_NetrEnumerateComputerNames(pipes_struct *p, struct wkssvc_NetrEnumerateComputerNames *r)
990 {
991         /* FIXME: Add implementation code here */
992         p->rng_fault_state = True;
993         return WERR_NOT_SUPPORTED;
994 }
995