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