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