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