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