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