LCOV - code coverage report
Current view: top level - source3/rpc_server/wkssvc - srv_wkssvc_nt.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 217 451 48.1 %
Date: 2024-06-13 04:01:37 Functions: 30 40 75.0 %

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

Generated by: LCOV version 1.13