Remove more uses of "extern struct current_user current_user;".
[ira/wip.git] / source3 / smbd / lanman.c
index 1d6369c18b57cc29761db9a0b36856ae87af0d11..4c15f133aec0cab39fe34ffa384c98eacfa30398 100644 (file)
@@ -6,17 +6,17 @@
 
    SMB Version handling
    Copyright (C) John H Terpstra 1995-1998
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */
    */
 
 #include "includes.h"
-
-extern struct current_user current_user;
-extern userdom_struct current_user_info;
+#include "smbd/globals.h"
+#include "../librpc/gen_ndr/cli_samr.h"
+#include "../librpc/gen_ndr/srv_samr.h"
+#include "../lib/util/binsearch.h"
 
 #ifdef CHECK_TYPES
 #undef CHECK_TYPES
@@ -50,39 +51,73 @@ extern userdom_struct current_user_info;
 
 #define SHPWLEN 8              /* share password length */
 
-static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
+/* Limit size of ipc replies */
+
+static char *smb_realloc_limit(void *ptr, size_t size)
+{
+       char *val;
+
+       size = MAX((size),4*1024);
+       val = (char *)SMB_REALLOC(ptr,size);
+       if (val) {
+               memset(val,'\0',size);
+       }
+       return val;
+}
+
+static bool api_Unsupported(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt, int mprcnt,
                                char **rdata, char **rparam,
                                int *rdata_len, int *rparam_len);
 
-static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
+static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
                         int mdrcnt, int mprcnt,
                         char **rdata, char **rparam,
                         int *rdata_len, int *rparam_len);
 
 
-static int CopyExpanded(connection_struct *conn, 
-                       int snum, char **dst, char *src, int *n)
+static int CopyExpanded(connection_struct *conn,
+                       int snum, char **dst, char *src, int *p_space_remaining)
 {
-       pstring buf;
+       TALLOC_CTX *ctx = talloc_tos();
+       char *buf = NULL;
        int l;
 
-       if (!src || !dst || !n || !(*dst)) {
+       if (!src || !dst || !p_space_remaining || !(*dst) ||
+                       *p_space_remaining <= 0) {
                return 0;
        }
 
-       StrnCpy(buf,src,sizeof(buf)/2);
-       pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
-                             conn->connectpath, conn->gid,
-                             get_current_username(),
-                             current_user_info.domain,
-                             buf, sizeof(buf));
-       l = push_ascii(*dst,buf,*n, STR_TERMINATE);
+       buf = talloc_strdup(ctx, src);
+       if (!buf) {
+               *p_space_remaining = 0;
+               return 0;
+       }
+       buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
+       if (!buf) {
+               *p_space_remaining = 0;
+               return 0;
+       }
+       buf = talloc_sub_advanced(ctx,
+                               lp_servicename(SNUM(conn)),
+                               conn->server_info->unix_name,
+                               conn->connectpath,
+                               conn->server_info->utok.gid,
+                               conn->server_info->sanitized_username,
+                               pdb_get_domain(conn->server_info->sam_account),
+                               buf);
+       if (!buf) {
+               *p_space_remaining = 0;
+               return 0;
+       }
+       l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
+       if (l == -1) {
+               return 0;
+       }
        (*dst) += l;
-       (*n) -= l;
+       (*p_space_remaining) -= l;
        return l;
 }
 
@@ -93,6 +128,9 @@ static int CopyAndAdvance(char **dst, char *src, int *n)
                return 0;
        }
        l = push_ascii(*dst,src,*n, STR_TERMINATE);
+       if (l == -1) {
+               return 0;
+       }
        (*dst) += l;
        (*n) -= l;
        return l;
@@ -100,41 +138,64 @@ static int CopyAndAdvance(char **dst, char *src, int *n)
 
 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
 {
-       pstring buf;
+       TALLOC_CTX *ctx = talloc_tos();
+       char *buf = NULL;
        if (!s) {
                return 0;
        }
-       StrnCpy(buf,s,sizeof(buf)/2);
-       pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
-                             conn->connectpath, conn->gid,
-                             get_current_username(),
-                             current_user_info.domain,
-                             buf, sizeof(buf));
+       buf = talloc_strdup(ctx,s);
+       if (!buf) {
+               return 0;
+       }
+       buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
+       if (!buf) {
+               return 0;
+       }
+       buf = talloc_sub_advanced(ctx,
+                               lp_servicename(SNUM(conn)),
+                               conn->server_info->unix_name,
+                               conn->connectpath,
+                               conn->server_info->utok.gid,
+                               conn->server_info->sanitized_username,
+                               pdb_get_domain(conn->server_info->sam_account),
+                               buf);
+       if (!buf) {
+               return 0;
+       }
        return strlen(buf) + 1;
 }
 
 static char *Expand(connection_struct *conn, int snum, char *s)
 {
-       static pstring buf;
+       TALLOC_CTX *ctx = talloc_tos();
+       char *buf = NULL;
+
        if (!s) {
                return NULL;
        }
-       StrnCpy(buf,s,sizeof(buf)/2);
-       pstring_sub(buf,"%S",lp_servicename(snum));
-       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
-                             conn->connectpath, conn->gid,
-                             get_current_username(),
-                             current_user_info.domain,
-                             buf, sizeof(buf));
-       return &buf[0];
+       buf = talloc_strdup(ctx,s);
+       if (!buf) {
+               return 0;
+       }
+       buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
+       if (!buf) {
+               return 0;
+       }
+       return talloc_sub_advanced(ctx,
+                               lp_servicename(SNUM(conn)),
+                               conn->server_info->unix_name,
+                               conn->connectpath,
+                               conn->server_info->utok.gid,
+                               conn->server_info->sanitized_username,
+                               pdb_get_domain(conn->server_info->sam_account),
+                               buf);
 }
 
 /*******************************************************************
  Check a API string for validity when we only need to check the prefix.
 ******************************************************************/
 
-static BOOL prefix_ok(const char *str, const char *prefix)
+static bool prefix_ok(const char *str, const char *prefix)
 {
        return(strncmp(str,prefix,strlen(prefix)) == 0);
 }
@@ -209,7 +270,7 @@ static int getlen(const char *p)
        return n;
 }
 
-static BOOL init_package(struct pack_desc *p, int count, int subcount)
+static bool init_package(struct pack_desc *p, int count, int subcount)
 {
        int n = p->buflen;
        int i;
@@ -403,7 +464,7 @@ static void PackDriverData(struct pack_desc* desc)
        SIVAL(drivdata,0,sizeof drivdata); /* cb */
        SIVAL(drivdata,4,1000); /* lVersion */
        memset(drivdata+8,0,32);        /* szDeviceName */
-       push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
+       push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
        PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
 }
 
@@ -560,16 +621,20 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
  Returns True if from tdb, False otherwise.
  ********************************************************************/
 
-static BOOL get_driver_name(int snum, pstring drivername)
+static bool get_driver_name(int snum, char **pp_drivername)
 {
        NT_PRINTER_INFO_LEVEL *info = NULL;
-       BOOL in_tdb = False;
+       bool in_tdb = false;
 
        get_a_printer (NULL, &info, 2, lp_servicename(snum));
        if (info != NULL) {
-               pstrcpy( drivername, info->info_2->drivername);
-               in_tdb = True;
+               *pp_drivername = talloc_strdup(talloc_tos(),
+                                       info->info_2->drivername);
+               in_tdb = true;
                free_a_printer(&info, 2);
+               if (!*pp_drivername) {
+                       return false;
+               }
        }
 
        return in_tdb;
@@ -584,18 +649,16 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
 {
        int                             i;
        fstring                         location;
-       NT_PRINTER_DRIVER_INFO_LEVEL    driver;
+       struct spoolss_DriverInfo8 *driver = NULL;
        NT_PRINTER_INFO_LEVEL           *printer = NULL;
 
-       ZERO_STRUCT(driver);
-
        if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
                DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", 
                        lp_servicename(snum)));
                goto err;
        }
 
-       if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
+       if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
                "Windows 4.0", 0)) )
        {
                DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n", 
@@ -603,38 +666,38 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
                goto err;
        }
 
-       trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
-       trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
-       trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
+       trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
+       trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
+       trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
 
        PACKI(desc, "W", 0x0400);                     /* don't know */
-       PACKS(desc, "z", driver.info_3->name);        /* long printer name */
-       PACKS(desc, "z", driver.info_3->driverpath);  /* Driverfile Name */
-       PACKS(desc, "z", driver.info_3->datafile);    /* Datafile name */
-       PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
+       PACKS(desc, "z", driver->driver_name);        /* long printer name */
+       PACKS(desc, "z", driver->driver_path);  /* Driverfile Name */
+       PACKS(desc, "z", driver->data_file);    /* Datafile name */
+       PACKS(desc, "z", driver->monitor_name); /* language monitor */
 
        fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
        standard_sub_basic( "", "", location, sizeof(location)-1 );
        PACKS(desc,"z", location);                          /* share to retrieve files */
 
-       PACKS(desc,"z", driver.info_3->defaultdatatype);    /* default data type */
-       PACKS(desc,"z", driver.info_3->helpfile);           /* helpfile name */
-       PACKS(desc,"z", driver.info_3->driverpath);               /* driver name */
+       PACKS(desc,"z", driver->default_datatype);    /* default data type */
+       PACKS(desc,"z", driver->help_file);           /* helpfile name */
+       PACKS(desc,"z", driver->driver_path);               /* driver name */
 
-       DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
-       DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
-       DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
-       DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
+       DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
+       DEBUG(3,("Driver: %s:\n",driver->driver_path));
+       DEBUG(3,("Data File: %s:\n",driver->data_file));
+       DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
        DEBUG(3,("Driver Location: %s:\n",location));
-       DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
-       DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
+       DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
+       DEBUG(3,("Help File: %s:\n",driver->help_file));
        PACKI(desc,"N",count);                     /* number of files to copy */
 
-       for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++) 
+       for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
        {
-               trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
-               PACKS(desc,"z",driver.info_3->dependentfiles[i]);         /* driver files to copy */
-               DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
+               trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
+               PACKS(desc,"z",driver->dependent_files[i]);         /* driver files to copy */
+               DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
        }
 
        /* sanity check */
@@ -655,8 +718,7 @@ done:
        if ( printer )
                free_a_printer( &printer, 2 );
 
-       if ( driver.info_3 )
-               free_a_printer_driver( driver, 3 );
+       free_a_printer_driver(driver);
 }
 
 
@@ -704,7 +766,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
        }
 
        if (uLevel == 3 || uLevel == 4) {
-               pstring drivername;
+               char *drivername = NULL;
 
                PACKI(desc,"W",5);              /* uPriority */
                PACKI(desc,"W",0);              /* uStarttime */
@@ -714,7 +776,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
                PACKS(desc,"z","WinPrint");     /* pszPrProc */
                PACKS(desc,"z",NULL);           /* pszParms */
                PACKS(desc,"z",NULL);           /* pszComment - don't ask.... JRA */
-               /* "don't ask" that it's done this way to fix corrupted 
+               /* "don't ask" that it's done this way to fix corrupted
                   Win9X/ME printer comments. */
                if (!status) {
                        PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
@@ -723,7 +785,10 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
                }
                PACKI(desc,(uLevel == 3 ? "W" : "N"),count);    /* cJobs */
                PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
-               get_driver_name(snum,drivername);
+               get_driver_name(snum,&drivername);
+               if (!drivername) {
+                       return;
+               }
                PACKS(desc,"z",drivername);             /* pszDriverName */
                PackDriverData(desc);   /* pDriverData */
        }
@@ -742,7 +807,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
 static int get_printerdrivernumber(int snum)
 {
        int                             result = 0;
-       NT_PRINTER_DRIVER_INFO_LEVEL    driver;
+       struct spoolss_DriverInfo8 *driver;
        NT_PRINTER_INFO_LEVEL           *printer = NULL;
 
        ZERO_STRUCT(driver);
@@ -753,7 +818,7 @@ static int get_printerdrivernumber(int snum)
                goto done;
        }
 
-       if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
+       if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
                "Windows 4.0", 0)) )
        {
                DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n", 
@@ -762,20 +827,18 @@ static int get_printerdrivernumber(int snum)
        }
 
        /* count the number of files */
-       while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
-                       result++;
-                       \
+       while (driver->dependent_files && *driver->dependent_files[result])
+               result++;
  done:
        if ( printer )
                free_a_printer( &printer, 2 );
 
-       if ( driver.info_3 )
-               free_a_printer_driver( driver, 3 );
+       free_a_printer_driver(driver);
 
        return result;
 }
 
-static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
+static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -812,9 +875,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
        /* remove any trailing username */
        if ((p = strchr_m(QueueName,'%')))
                *p = 0;
+
        DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
+
        /* check it's a supported varient */
        if (!prefix_ok(str1,"zWrLh"))
                return False;
@@ -826,7 +889,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
                 */
                *rdata_len = 0;
                *rparam_len = 6;
-               *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+               *rparam = smb_realloc_limit(*rparam,*rparam_len);
                if (!*rparam) {
                        return False;
                }
@@ -835,11 +898,11 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
                SSVAL(*rparam,4,0);
                return(True);
        }
+
        snum = find_service(QueueName);
        if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
                return False;
-               
+
        if (uLevel==52) {
                count = get_printerdrivernumber(snum);
                DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
@@ -848,7 +911,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        SAFE_FREE(queue);
                        return False;
@@ -870,7 +933,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        *rdata_len = desc.usedlen;
-  
+
        /*
         * We must set the return code to ERRbuftoosmall
         * in order to support lanman style printing with Win NT/2k
@@ -878,10 +941,10 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
         */
        if (!mdrcnt && lp_disable_spoolss())
                desc.errcode = ERRbuftoosmall;
+
        *rdata_len = desc.usedlen;
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                SAFE_FREE(queue);
                SAFE_FREE(tmpdata);
@@ -890,7 +953,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,desc.neededlen);
-  
+
        DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
 
        SAFE_FREE(queue);
@@ -903,7 +966,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
  View list of all print jobs on all queues.
 ****************************************************************************/
 
-static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
+static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt, int mprcnt,
@@ -922,7 +985,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        print_status_struct *status = NULL;
        int *subcntarr = NULL;
        int queuecnt = 0, subcnt = 0, succnt = 0;
+
        if (!param_format || !output_format1 || !p) {
                return False;
        }
@@ -930,7 +993,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        memset((char *)&desc,'\0',sizeof(desc));
 
        DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
+
        if (!prefix_ok(param_format,"WrLeh")) {
                return False;
        }
@@ -942,7 +1005,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
                 */
                *rdata_len = 0;
                *rparam_len = 6;
-               *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+               *rparam = smb_realloc_limit(*rparam,*rparam_len);
                if (!*rparam) {
                        return False;
                }
@@ -984,7 +1047,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        }
 
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        goto err;
                }
@@ -1007,10 +1070,10 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        }
 
        SAFE_FREE(subcntarr);
+
        *rdata_len = desc.usedlen;
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                goto err;
        }
@@ -1018,7 +1081,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,succnt);
        SSVAL(*rparam,6,queuecnt);
-  
+
        for (i = 0; i < queuecnt; i++) {
                if (queue) {
                        SAFE_FREE(queue[i]);
@@ -1027,7 +1090,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
 
        SAFE_FREE(queue);
        SAFE_FREE(status);
-  
+
        return True;
 
   err:
@@ -1048,7 +1111,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
  Get info level for a server list query.
 ****************************************************************************/
 
-static BOOL check_server_info(int uLevel, char* id)
+static bool check_server_info(int uLevel, char* id)
 {
        switch( uLevel ) {
                case 0:
@@ -1072,7 +1135,7 @@ struct srv_info_struct {
        uint32 type;
        fstring comment;
        fstring domain;
-       BOOL server_added;
+       bool server_added;
 };
 
 /*******************************************************************
@@ -1087,12 +1150,12 @@ static int get_server_info(uint32 servertype,
        int count=0;
        int alloced=0;
        char **lines;
-       BOOL local_list_only;
+       bool local_list_only;
        int i;
 
-       lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
+       lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
        if (!lines) {
-               DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
+               DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
                return 0;
        }
 
@@ -1109,43 +1172,63 @@ static int get_server_info(uint32 servertype,
                fstring stype;
                struct srv_info_struct *s;
                const char *ptr = lines[i];
-               BOOL ok = True;
+               bool ok = True;
+               TALLOC_CTX *frame = NULL;
+               char *p;
 
                if (!*ptr) {
                        continue;
                }
-    
+
                if (count == alloced) {
                        alloced += 10;
                        *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
                        if (!*servers) {
                                DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
-                               file_lines_free(lines);
+                               TALLOC_FREE(lines);
                                return 0;
                        }
                        memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
                }
                s = &(*servers)[count];
-    
-               if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
+
+               frame = talloc_stackframe();
+               s->name[0] = '\0';
+               if (!next_token_talloc(frame,&ptr,&p, NULL)) {
+                       TALLOC_FREE(frame);
                        continue;
                }
-               if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
+               fstrcpy(s->name, p);
+
+               stype[0] = '\0';
+               if (!next_token_talloc(frame,&ptr, &p, NULL)) {
+                       TALLOC_FREE(frame);
                        continue;
                }
-               if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
+               fstrcpy(stype, p);
+
+               s->comment[0] = '\0';
+               if (!next_token_talloc(frame,&ptr, &p, NULL)) {
+                       TALLOC_FREE(frame);
                        continue;
                }
-               if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
+               fstrcpy(s->comment, p);
+               string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
+
+               s->domain[0] = '\0';
+               if (!next_token_talloc(frame,&ptr,&p, NULL)) {
                        /* this allows us to cope with an old nmbd */
-                       fstrcpy(s->domain,lp_workgroup()); 
+                       fstrcpy(s->domain,lp_workgroup());
+               } else {
+                       fstrcpy(s->domain, p);
                }
-    
-               if (sscanf(stype,"%X",&s->type) != 1) { 
-                       DEBUG(4,("r:host file ")); 
-                       ok = False; 
+               TALLOC_FREE(frame);
+
+               if (sscanf(stype,"%X",&s->type) != 1) {
+                       DEBUG(4,("r:host file "));
+                       ok = False;
                }
-    
+
                /* Filter the servers/domains we return based on what was asked for. */
 
                /* Check to see if we are being asked for a local list only. */
@@ -1155,21 +1238,21 @@ static int get_server_info(uint32 servertype,
                }
 
                /* doesn't match up: don't want it */
-               if (!(servertype & s->type)) { 
-                       DEBUG(4,("r:serv type ")); 
-                       ok = False; 
+               if (!(servertype & s->type)) {
+                       DEBUG(4,("r:serv type "));
+                       ok = False;
                }
-    
+
                if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
                                (s->type & SV_TYPE_DOMAIN_ENUM)) {
                        DEBUG(4,("s: dom mismatch "));
                        ok = False;
                }
-    
+
                if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
                        ok = False;
                }
-    
+
                /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
                s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
 
@@ -1183,8 +1266,8 @@ static int get_server_info(uint32 servertype,
                                s->name, s->type, s->comment, s->domain));
                }
        }
-  
-       file_lines_free(lines);
+
+       TALLOC_FREE(lines);
        return count;
 }
 
@@ -1201,7 +1284,7 @@ static int fill_srv_info(struct srv_info_struct *service,
        char* p2;
        int l2;
        int len;
+
        switch (uLevel) {
                case 0:
                        struct_len = 16;
@@ -1212,7 +1295,7 @@ static int fill_srv_info(struct srv_info_struct *service,
                default:
                        return -1;
        }
+
        if (!buf) {
                len = 0;
                switch (uLevel) {
@@ -1225,7 +1308,7 @@ static int fill_srv_info(struct srv_info_struct *service,
                *stringspace = len;
                return struct_len + len;
        }
-  
+
        len = struct_len;
        p = *buf;
        if (*buflen < struct_len) {
@@ -1241,7 +1324,7 @@ static int fill_srv_info(struct srv_info_struct *service,
        if (!baseaddr) {
                baseaddr = p;
        }
-  
+
        switch (uLevel) {
                case 0:
                        push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
@@ -1268,9 +1351,9 @@ static int fill_srv_info(struct srv_info_struct *service,
 }
 
 
-static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
+static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
 {
-       return(strcmp(s1->name,s2->name));
+       return StrCaseCmp(s1->name,s2->name);
 }
 
 /****************************************************************************
@@ -1278,7 +1361,7 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
  extracted from lists saved by nmbd on the local host.
 ****************************************************************************/
 
-static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
+static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt, int mprcnt, char **rdata, 
@@ -1297,8 +1380,8 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
        int counted=0,total=0;
        int i,missed;
        fstring domain;
-       BOOL domain_request;
-       BOOL local_request;
+       bool domain_request;
+       bool local_request;
 
        if (!str1 || !str2 || !p) {
                return False;
@@ -1313,7 +1396,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
        }
 
        /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
-          any other bit (they may just set this bit on it's own) they 
+          any other bit (they may just set this bit on its own) they 
           want all the locally seen servers. However this bit can be 
           set on its own so set the requested servers to be 
           ALL - DOMAIN_ENUM. */
@@ -1333,7 +1416,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
        if (!check_server_info(uLevel,str2)) {
                return False;
        }
-  
+
        DEBUG(4, ("server request level: %s %8x ", str2, servertype));
        DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
        DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
@@ -1347,6 +1430,8 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
                fstrcpy(domain, lp_workgroup());
        }
 
+       DEBUG(4, ("domain [%s]\n", domain));
+
        if (lp_browse_list()) {
                total = get_server_info(servertype,&servers,domain);
        }
@@ -1354,9 +1439,7 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
        data_len = fixed_len = string_len = 0;
        missed = 0;
 
-       if (total > 0) {
-               qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
-       }
+       TYPESAFE_QSORT(servers, total, srv_comp);
 
        {
                char *lastname=NULL;
@@ -1369,10 +1452,10 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
                        }
                        lastname = s->name;
                        data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
-                       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
-                               s->name, s->type, s->comment, s->domain));
-      
-                       if (data_len <= buf_len) {
+                       DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
+                               i, s->name, s->type, s->comment, s->domain));
+
+                       if (data_len < buf_len) {
                                counted++;
                                fixed_len += f_len;
                                string_len += s_len;
@@ -1383,12 +1466,11 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
        }
 
        *rdata_len = fixed_len + string_len;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
-       memset(*rdata,'\0',*rdata_len);
-  
+
        p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
        p = *rdata;
        f_len = fixed_len;
@@ -1406,14 +1488,14 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
                        }
                        lastname = s->name;
                        fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
-                       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
-                               s->name, s->type, s->comment, s->domain));
+                       DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
+                               i, s->name, s->type, s->comment, s->domain));
                        count2--;
                }
        }
-  
+
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -1424,17 +1506,223 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
 
        SAFE_FREE(servers);
 
-       DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
+       DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
                domain,uLevel,counted,counted+missed));
 
        return True;
 }
 
+static int srv_name_match(const char *n1, const char *n2)
+{
+       /*
+        * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
+        *
+        *  In Windows, FirstNameToReturn need not be an exact match:
+        *  the server will return a list of servers that exist on
+        *  the network greater than or equal to the FirstNameToReturn.
+        */
+       int ret = StrCaseCmp(n1, n2);
+
+       if (ret <= 0) {
+               return 0;
+       }
+
+       return ret;
+}
+
+static bool api_RNetServerEnum3(connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               int mdrcnt, int mprcnt, char **rdata,
+                               char **rparam, int *rdata_len, int *rparam_len)
+{
+       char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+       int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
+       int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
+       uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
+       char *p2;
+       int data_len, fixed_len, string_len;
+       int f_len = 0, s_len = 0;
+       struct srv_info_struct *servers=NULL;
+       int counted=0,first=0,total=0;
+       int i,missed;
+       fstring domain;
+       fstring first_name;
+       bool domain_request;
+       bool local_request;
+
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
+       /* If someone sets all the bits they don't really mean to set
+          DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
+          known servers. */
+
+       if (servertype == SV_TYPE_ALL) {
+               servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+       }
+
+       /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
+          any other bit (they may just set this bit on its own) they
+          want all the locally seen servers. However this bit can be
+          set on its own so set the requested servers to be
+          ALL - DOMAIN_ENUM. */
+
+       if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
+               servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
+       }
+
+       domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
+       local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
+
+       p += 8;
+
+       if (strcmp(str1, "WrLehDzz") != 0) {
+               return false;
+       }
+       if (!check_server_info(uLevel,str2)) {
+               return False;
+       }
+
+       DEBUG(4, ("server request level: %s %8x ", str2, servertype));
+       DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
+       DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
+
+       if (skip_string(param,tpscnt,p) == NULL) {
+               return False;
+       }
+       pull_ascii_fstring(domain, p);
+       if (domain[0] == '\0') {
+               fstrcpy(domain, lp_workgroup());
+       }
+       p = skip_string(param,tpscnt,p);
+       if (skip_string(param,tpscnt,p) == NULL) {
+               return False;
+       }
+       pull_ascii_fstring(first_name, p);
+
+       DEBUG(4, ("domain: '%s' first_name: '%s'\n",
+                 domain, first_name));
+
+       if (lp_browse_list()) {
+               total = get_server_info(servertype,&servers,domain);
+       }
+
+       data_len = fixed_len = string_len = 0;
+       missed = 0;
+
+       TYPESAFE_QSORT(servers, total, srv_comp);
+
+       if (first_name[0] != '\0') {
+               struct srv_info_struct *first_server = NULL;
+
+               BINARY_ARRAY_SEARCH(servers, total, name, first_name,
+                                   srv_name_match, first_server);
+               if (first_server) {
+                       first = PTR_DIFF(first_server, servers) / sizeof(*servers);
+                       /*
+                        * The binary search may not find the exact match
+                        * so we need to search backward to find the first match
+                        *
+                        * This implements the strange matching windows
+                        * implements. (see the comment in srv_name_match().
+                        */
+                       for (;first > 0;) {
+                               int ret;
+                               ret = StrCaseCmp(first_name,
+                                                servers[first-1].name);
+                               if (ret > 0) {
+                                       break;
+                               }
+                               first--;
+                       }
+               } else {
+                       /* we should return no entries */
+                       first = total;
+               }
+       }
+
+       {
+               char *lastname=NULL;
+
+               for (i=first;i<total;i++) {
+                       struct srv_info_struct *s = &servers[i];
+
+                       if (lastname && strequal(lastname,s->name)) {
+                               continue;
+                       }
+                       lastname = s->name;
+                       data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
+                       DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
+                               i, s->name, s->type, s->comment, s->domain));
+
+                       if (data_len < buf_len) {
+                               counted++;
+                               fixed_len += f_len;
+                               string_len += s_len;
+                       } else {
+                               missed++;
+                       }
+               }
+       }
+
+       *rdata_len = fixed_len + string_len;
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
+
+       p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
+       p = *rdata;
+       f_len = fixed_len;
+       s_len = string_len;
+
+       {
+               char *lastname=NULL;
+               int count2 = counted;
+
+               for (i = first; i < total && count2;i++) {
+                       struct srv_info_struct *s = &servers[i];
+
+                       if (lastname && strequal(lastname,s->name)) {
+                               continue;
+                       }
+                       lastname = s->name;
+                       fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
+                       DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
+                               i, s->name, s->type, s->comment, s->domain));
+                       count2--;
+               }
+       }
+
+       *rparam_len = 8;
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
+       SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,counted);
+       SSVAL(*rparam,6,counted+missed);
+
+       DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
+               domain,uLevel,first,first_name,
+               first < total ? servers[first].name : "",
+               counted,counted+missed));
+
+       SAFE_FREE(servers);
+
+       return True;
+}
+
 /****************************************************************************
   command 0x34 - suspected of being a "Lookup Names" stub api
   ****************************************************************************/
 
-static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
+static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt, int mprcnt, char **rdata, 
@@ -1458,11 +1746,11 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
        if (!prefix_ok(str1,"zWrLeh")) {
                return False;
        }
-  
+
        *rdata_len = 0;
-  
+
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -1479,7 +1767,7 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
   get info about a share
   ****************************************************************************/
 
-static BOOL check_share_info(int uLevel, char* id)
+static bool check_share_info(int uLevel, char* id)
 {
        switch( uLevel ) {
                case 0:
@@ -1488,7 +1776,9 @@ static BOOL check_share_info(int uLevel, char* id)
                        }
                        break;
                case 1:
-                       if (strcmp(id,"B13BWz") != 0) {
+                       /* Level-2 descriptor is allowed (and ignored) */
+                       if (strcmp(id,"B13BWz") != 0 &&
+                           strcmp(id,"B13BWzWWWzB9B") != 0) {
                                return False;
                        }
                        break;
@@ -1517,7 +1807,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
        char* p2;
        int l2;
        int len;
+
        switch( uLevel ) {
                case 0:
                        struct_len = 13;
@@ -1534,8 +1824,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                default:
                        return -1;
        }
-  
+
        if (!buf) {
                len = 0;
 
@@ -1553,7 +1842,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                }
                return struct_len + len;
        }
-  
+
        len = struct_len;
        p = *buf;
        if ((*buflen) < struct_len) {
@@ -1571,9 +1860,9 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
        if (!baseaddr) {
                baseaddr = p;
        }
-  
+
        push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
-  
+
        if (uLevel > 0) {
                int type;
 
@@ -1589,7 +1878,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                SIVAL(p,16,PTR_DIFF(p2,baseaddr));
                len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
        }
-  
+
        if (uLevel > 1) {
                SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
                SSVALS(p,22,-1);                /* max uses */
@@ -1598,7 +1887,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
                memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
        }
-  
+
        if (uLevel > 2) {
                memset(p+40,0,SHPWLEN+2);
                SSVAL(p,50,0);
@@ -1609,7 +1898,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                SSVAL(p,64,0);
                SSVAL(p,66,0);
        }
-       
+
        if (stringbuf) {
                (*buf) = p + struct_len;
                (*buflen) -= struct_len;
@@ -1623,7 +1912,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
        return len;
 }
 
-static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
+static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -1636,7 +1925,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
        char *p = skip_string(param,tpscnt,netname);
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        int snum;
-  
+
        if (!str1 || !str2 || !netname || !p) {
                return False;
        }
@@ -1645,7 +1934,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
        if (snum < 0) {
                return False;
        }
-  
+
        /* check it's a supported varient */
        if (!prefix_ok(str1,"zWrLh")) {
                return False;
@@ -1653,8 +1942,8 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
        if (!check_share_info(uLevel,str2)) {
                return False;
        }
-       *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+
+       *rdata = smb_realloc_limit(*rdata,mdrcnt);
        if (!*rdata) {
                return False;
        }
@@ -1663,16 +1952,16 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
        if (*rdata_len < 0) {
                return False;
        }
+
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);
+
        return True;
 }
 
@@ -1686,7 +1975,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
   Share names longer than 12 bytes must be skipped.
  ****************************************************************************/
 
-static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
+static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int                mdrcnt,
@@ -1704,11 +1993,11 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
        char *p2;
        int count = 0;
        int total=0,counted=0;
-       BOOL missed = False;
+       bool missed = False;
        int i;
        int data_len, fixed_len, string_len;
        int f_len = 0, s_len = 0;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -1719,7 +2008,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
        if (!check_share_info(uLevel,str2)) {
                return False;
        }
-  
+
        /* Ensure all the usershares are loaded. */
        become_root();
        load_registry_shares();
@@ -1737,7 +2026,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
                if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
                        total++;
                        data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
-                       if (data_len <= buf_len) {
+                       if (data_len < buf_len) {
                                counted++;
                                fixed_len += f_len;
                                string_len += s_len;
@@ -1748,12 +2037,11 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
        }
 
        *rdata_len = fixed_len + string_len;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
-       memset(*rdata,0,*rdata_len);
-  
+
        p2 = (*rdata) + fixed_len;      /* auxiliary data (strings) will go here */
        p = *rdata;
        f_len = fixed_len;
@@ -1772,9 +2060,9 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
                        }
                }
        }
-  
+
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -1782,7 +2070,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,counted);
        SSVAL(*rparam,6,total);
-  
+
        DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
                counted,total,uLevel,
                buf_len,*rdata_len,mdrcnt));
@@ -1794,7 +2082,7 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
   Add a share
   ****************************************************************************/
 
-static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
+static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -1807,12 +2095,13 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        fstring sharename;
        fstring comment;
-       pstring pathname;
+       char *pathname = NULL;
        char *command, *cmdname;
        unsigned int offset;
        int snum;
        int res = ERRunsup;
-  
+       size_t converted_size;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -1871,7 +2160,17 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
        if (skip_string(data,mdrcnt,data+offset) == NULL) {
                return False;
        }
-       pull_ascii_pstring(pathname, offset? (data+offset) : "");
+
+       if (!pull_ascii_talloc(talloc_tos(), &pathname,
+                              offset ? (data+offset) : "", &converted_size))
+       {
+               DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
+                        strerror(errno)));
+       }
+
+       if (!pathname) {
+               return false;
+       }
 
        string_replace(sharename, '"', ' ');
        string_replace(pathname, '"', ' ');
@@ -1883,28 +2182,28 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
                return False;
        }
 
-       asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
-               lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
+       if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
+                    lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
+                    pathname, comment) == -1) {
+               return false;
+       }
 
-       if (command) {
-               DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
+       DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
 
-               if ((res = smbrun(command, NULL)) != 0) {
-                       DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
-                       SAFE_FREE(command);
-                       res = ERRnoaccess;
-                       goto error_exit;
-               } else {
-                       SAFE_FREE(command);
-                       message_send_all(smbd_messaging_context(),
-                                        MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
-               }
+       if ((res = smbrun(command, NULL)) != 0) {
+               DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
+                        command, res ));
+               SAFE_FREE(command);
+               res = ERRnoaccess;
+               goto error_exit;
        } else {
-               return False;
+               SAFE_FREE(command);
+               message_send_all(smbd_messaging_context(),
+                                MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
        }
 
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -1912,13 +2211,13 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);
        *rdata_len = 0;
-  
+
        return True;
 
   error_exit:
 
        *rparam_len = 4;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -1932,7 +2231,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
   view list of groups available
   ****************************************************************************/
 
-static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
+static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -1946,11 +2245,12 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
 
-       struct pdb_search *search;
-       struct samr_displayentry *entries;
+       uint32_t num_groups;
+       uint32_t resume_handle;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle samr_handle, domain_handle;
+       NTSTATUS status;
 
-       int num_entries;
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -1971,14 +2271,31 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
                return False;
        }
 
-       /* get list of domain groups SID_DOMAIN_GRP=2 */
-       become_root();
-       search = pdb_search_groups();
-       unbecome_root();
+       status = rpc_pipe_open_internal(
+               talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
+               conn->server_info, &samr_pipe);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               return false;
+       }
 
-       if (search == NULL) {
-               DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
-               return False;
+       status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
+                                     SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(status)));
+               return false;
+       }
+
+       status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
+                                       SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
+                                       get_global_sam_sid(), &domain_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(status)));
+               rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
+               return false;
        }
 
        resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
@@ -1986,50 +2303,83 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
        DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
                  "%d\n", resume_context, cli_buf_size));
 
-       become_root();
-       num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
-                                        &entries);
-       unbecome_root();
-
        *rdata_len = cli_buf_size;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
 
        p = *rdata;
 
-       for(i=0; i<num_entries; i++) {
-               fstring name;
-               fstrcpy(name, entries[i].account_name);
-               if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
+       errflags = NERR_Success;
+       num_groups = 0;
+       resume_handle = 0;
+
+       while (true) {
+               struct samr_SamArray *sam_entries;
+               uint32_t num_entries;
+
+               status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
+                                                     &domain_handle,
+                                                     &resume_handle,
+                                                     &sam_entries, 1,
+                                                     &num_entries);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
+                                  "%s\n", nt_errstr(status)));
+                       break;
+               }
+
+               if (num_entries == 0) {
+                       DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
+                                  "no entries -- done\n"));
+                       break;
+               }
+
+               for(i=0; i<num_entries; i++) {
+                       const char *name;
+
+                       name = sam_entries->entries[i].name.string;
+
+                       if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
+                               /* set overflow error */
+                               DEBUG(3,("overflow on entry %d group %s\n", i,
+                                        name));
+                               errflags=234;
+                               break;
+                       }
+
                        /* truncate the name at 21 chars. */
-                       memcpy(p, name, 21); 
+                       memset(p, 0, 21);
+                       strlcpy(p, name, 21);
                        DEBUG(10,("adding entry %d group %s\n", i, p));
                        p += 21;
-                       p += 5; /* Both NT4 and W2k3SP1 do padding here.
-                                  No idea why... */
-               } else {
-                       /* set overflow error */
-                       DEBUG(3,("overflow on entry %d group %s\n", i, name));
-                       errflags=234;
+                       p += 5; /* Both NT4 and W2k3SP1 do padding here.  No
+                                * idea why... */
+                       num_groups += 1;
+               }
+
+               if (errflags != NERR_Success) {
                        break;
                }
+
+               TALLOC_FREE(sam_entries);
        }
 
-       pdb_search_destroy(search);
+       rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
+       rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
 
        *rdata_len = PTR_DIFF(p,*rdata);
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
        SSVAL(*rparam, 0, errflags);
        SSVAL(*rparam, 2, 0);           /* converter word */
-       SSVAL(*rparam, 4, i);   /* is this right?? */
-       SSVAL(*rparam, 6, resume_context+num_entries);  /* is this right?? */
+       SSVAL(*rparam, 4, num_groups);  /* is this right?? */
+       SSVAL(*rparam, 6, resume_context+num_groups);   /* is this right?? */
 
        return(True);
 }
@@ -2038,7 +2388,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
  Get groups that a user is a member of.
 ******************************************************************/
 
-static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
+static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2052,32 +2402,33 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        const char *level_string;
        int count=0;
-       struct samu *sampw = NULL;
-       BOOL ret = False;
-       DOM_SID *sids;
-       gid_t *gids;
-       size_t num_groups;
-       size_t i;
-       NTSTATUS result;
-       DOM_SID user_sid;
-       enum lsa_SidType type;
-       TALLOC_CTX *mem_ctx;
+       bool ret = False;
+       uint32_t i;
+       char *endp = NULL;
+
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle samr_handle, domain_handle, user_handle;
+       struct lsa_String name;
+       struct lsa_Strings names;
+       struct samr_Ids type, rid;
+       struct samr_RidWithAttributeArray *rids;
+       NTSTATUS status;
 
        if (!str1 || !str2 || !UserName || !p) {
                return False;
        }
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
-  
+
        /* check it's a supported varient */
-       
+
        if ( strcmp(str1,"zWrLeh") != 0 )
                return False;
-               
+
        switch( uLevel ) {
                case 0:
                        level_string = "B21";
@@ -2090,70 +2441,87 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
                return False;
 
        *rdata_len = mdrcnt + 1024;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
+
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
 
        p = *rdata;
+       endp = *rdata + *rdata_len;
 
-       mem_ctx = talloc_new(NULL);
-       if (mem_ctx == NULL) {
-               DEBUG(0, ("talloc_new failed\n"));
-               return False;
+       status = rpc_pipe_open_internal(
+               talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
+               conn->server_info, &samr_pipe);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               return false;
        }
 
-       if ( !(sampw = samu_new(mem_ctx)) ) {
-               DEBUG(0, ("samu_new() failed!\n"));
-               TALLOC_FREE(mem_ctx);
-               return False;
+       status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
+                                     SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(status)));
+               return false;
        }
 
-       /* Lookup the user information; This should only be one of 
-          our accounts (not remote domains) */
+       status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
+                                       SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+                                       get_global_sam_sid(), &domain_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(status)));
+               goto close_sam;
+       }
 
-       become_root();                                  /* ROOT BLOCK */
+       name.string = UserName;
 
-       if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
-                        NULL, NULL, &user_sid, &type)) {
-               DEBUG(10, ("lookup_name(%s) failed\n", UserName));
-               goto done;
+       status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
+                                        &domain_handle, 1, &name,
+                                        &rid, &type);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(status)));
+               goto close_domain;
        }
 
-       if (type != SID_NAME_USER) {
+       if (type.ids[0] != SID_NAME_USER) {
                DEBUG(10, ("%s is a %s, not a user\n", UserName,
-                          sid_type_lookup(type)));
-               goto done;
+                          sid_type_lookup(type.ids[0])));
+               goto close_domain;
        }
 
-       if ( !pdb_getsampwsid(sampw, &user_sid) ) {
-               DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
-                          sid_string_static(&user_sid), UserName));
-               goto done;
+       status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
+                                     &domain_handle,
+                                     SAMR_USER_ACCESS_GET_GROUPS,
+                                     rid.ids[0], &user_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(status)));
+               goto close_domain;
        }
 
-       gids = NULL;
-       sids = NULL;
-       num_groups = 0;
-
-       result = pdb_enum_group_memberships(mem_ctx, sampw,
-                                           &sids, &gids, &num_groups);
-
-       if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
-                          UserName));
-               goto done;
+       status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
+                                             &user_handle, &rids);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(status)));
+               goto close_user;
        }
 
-       for (i=0; i<num_groups; i++) {
+       for (i=0; i<rids->count; i++) {
 
-               const char *grp_name;
-       
-               if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
-                       pstrcpy(p, grp_name);
-                       p += 21; 
+               status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
+                                               &domain_handle,
+                                               1, &rids->rids[i].rid,
+                                               &names, &type);
+               if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
+                       strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
+                       p += 21;
                        count++;
                }
        }
@@ -2165,10 +2533,12 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
 
        ret = True;
 
-done:
-       unbecome_root();                                /* END ROOT BLOCK */
-
-       TALLOC_FREE(mem_ctx);
+ close_user:
+       rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
+ close_domain:
+       rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
+ close_sam:
+       rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
 
        return ret;
 }
@@ -2177,7 +2547,7 @@ done:
  Get all users.
 ******************************************************************/
 
-static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
+static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2188,12 +2558,16 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
        int num_users=0;
        int errflags=0;
        int i, resume_context, cli_buf_size;
-       struct pdb_search *search;
-       struct samr_displayentry *users;
+       uint32_t resume_handle;
+
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle samr_handle, domain_handle;
+       NTSTATUS status;
 
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
+       char *endp = NULL;
 
        if (!str1 || !str2 || !p) {
                return False;
@@ -2208,14 +2582,14 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
          * e -> return parameter number of entries
          * h -> return parameter total number of users
          */
-  
+
        resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
        cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
        DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
                        resume_context, cli_buf_size));
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -2225,47 +2599,97 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
                return False;
 
        *rdata_len = cli_buf_size;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
 
        p = *rdata;
+       endp = *rdata + *rdata_len;
 
-       become_root();
-       search = pdb_search_users(ACB_NORMAL);
-       unbecome_root();
-       if (search == NULL) {
-               DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
-               return False;
+       status = rpc_pipe_open_internal(
+               talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
+               conn->server_info, &samr_pipe);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               return false;
        }
 
-       become_root();
-       num_users = pdb_search_entries(search, resume_context, 0xffffffff,
-                                      &users);
-       unbecome_root();
+       status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
+                                     SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(status)));
+               return false;
+       }
+
+       status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
+                                       SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
+                                       get_global_sam_sid(), &domain_handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(status)));
+               rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
+               return false;
+       }
 
        errflags=NERR_Success;
 
-       for (i=0; i<num_users; i++) {
-               const char *name = users[i].account_name;
-               
-               if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
-                       pstrcpy(p,name); 
-                       DEBUG(10,("api_RNetUserEnum:adding entry %d username "
-                                 "%s\n",count_sent,p));
-                       p += 21; 
-                       count_sent++; 
-               } else {
-                       /* set overflow error */
-                       DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
-                                 "username %s\n",count_sent,name));
-                       errflags=234;
+       resume_handle = 0;
+
+       while (true) {
+               struct samr_SamArray *sam_entries;
+               uint32_t num_entries;
+
+               status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
+                                                    &domain_handle,
+                                                    &resume_handle,
+                                                    0, &sam_entries, 1,
+                                                    &num_entries);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
+                                  "%s\n", nt_errstr(status)));
+                       break;
+               }
+
+               if (num_entries == 0) {
+                       DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
+                                  "no entries -- done\n"));
                        break;
                }
+
+               for (i=0; i<num_entries; i++) {
+                       const char *name;
+
+                       name = sam_entries->entries[i].name.string;
+
+                       if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
+                          &&(strlen(name)<=21)) {
+                               strlcpy(p,name,PTR_DIFF(endp,p));
+                               DEBUG(10,("api_RNetUserEnum:adding entry %d "
+                                         "username %s\n",count_sent,p));
+                               p += 21;
+                               count_sent++;
+                       } else {
+                               /* set overflow error */
+                               DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
+                                         "username %s\n",count_sent,name));
+                               errflags=234;
+                               break;
+                       }
+               }
+
+               if (errflags != NERR_Success) {
+                       break;
+               }
+
+               TALLOC_FREE(sam_entries);
        }
 
-       pdb_search_destroy(search);
+       rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
+       rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
 
        *rdata_len = PTR_DIFF(p,*rdata);
 
@@ -2281,7 +2705,7 @@ static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
  Get the time of day info.
 ****************************************************************************/
 
-static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
+static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2293,13 +2717,13 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
        char *p;
 
        *rparam_len = 4;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
 
        *rdata_len = 21;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
@@ -2339,7 +2763,7 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
  Set the user password.
 *****************************************************************************/
 
-static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
+static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2383,7 +2807,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
        memcpy(pass2,p+16,16);
 
        *rparam_len = 4;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -2401,7 +2825,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
         */
 
        {
-               auth_serversupplied_info *server_info = NULL;
+               struct auth_serversupplied_info *server_info = NULL;
                DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
 
                if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
@@ -2442,7 +2866,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
 
        memset((char *)pass1,'\0',sizeof(fstring));
        memset((char *)pass2,'\0',sizeof(fstring));      
-        
+
        return(True);
 }
 
@@ -2450,17 +2874,18 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
   Set the user password (SamOEM version - gets plaintext).
 ****************************************************************************/
 
-static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
+static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
+       struct smbd_server_connection *sconn = smbd_server_conn;
        fstring user;
        char *p = get_safe_str_ptr(param,tpscnt,param,2);
        *rparam_len = 2;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -2514,7 +2939,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
         * function.
         */
 
-       (void)map_username(user);
+       (void)map_username(sconn, user);
 
        if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
                SSVAL(*rparam,0,NERR_Success);
@@ -2528,7 +2953,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
   Form: <W> <> 
   ****************************************************************************/
 
-static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
+static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2563,7 +2988,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
                return(False);
 
        *rparam_len = 4;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);       
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -2581,25 +3006,25 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
        }
 
        errcode = NERR_notsupported;
-       
+
        switch (function) {
        case 81:                /* delete */ 
-               if (print_job_delete(&current_user, snum, jobid, &werr)) 
+               if (print_job_delete(conn->server_info, snum, jobid, &werr))
                        errcode = NERR_Success;
                break;
        case 82:                /* pause */
-               if (print_job_pause(&current_user, snum, jobid, &werr)) 
+               if (print_job_pause(conn->server_info, snum, jobid, &werr))
                        errcode = NERR_Success;
                break;
        case 83:                /* resume */
-               if (print_job_resume(&current_user, snum, jobid, &werr)) 
+               if (print_job_resume(conn->server_info, snum, jobid, &werr))
                        errcode = NERR_Success;
                break;
        }
 
        if (!W_ERROR_IS_OK(werr))
                errcode = W_ERROR_V(werr);
-       
+
  out:
        SSVAL(*rparam,0,errcode);       
        SSVAL(*rparam,2,0);             /* converter word */
@@ -2611,7 +3036,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
   Purge a print queue - or pause or resume it.
   ****************************************************************************/
 
-static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
+static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2635,7 +3060,7 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
                return(False);
 
        *rparam_len = 4;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -2653,17 +3078,20 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
 
        switch (function) {
        case 74: /* Pause queue */
-               if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
+               werr = print_queue_pause(conn->server_info, snum);
                break;
        case 75: /* Resume queue */
-               if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
+               werr = print_queue_resume(conn->server_info, snum);
                break;
        case 103: /* Purge */
-               if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
+               werr = print_queue_purge(conn->server_info, snum);
+               break;
+       default:
+               werr = WERR_NOT_SUPPORTED;
                break;
        }
 
-       if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
+       errcode = W_ERROR_V(werr);
 
  out:
        SSVAL(*rparam,0,errcode);
@@ -2703,7 +3131,7 @@ static int check_printjob_info(struct pack_desc* desc,
        return True;
 }
 
-static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
+static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2733,7 +3161,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
        if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
                return False;
        *rparam_len = 4;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -2743,9 +3171,9 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
                         sharename));
                return False;
        }
-  
+
        *rdata_len = 0;
-       
+
        /* check it's a supported varient */
        if ((strcmp(str1,"WWsTP")) || 
            (!check_printjob_info(&desc,uLevel,str2)))
@@ -2782,7 +3210,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
  out:
        SSVALS(*rparam,0,errcode);
        SSVAL(*rparam,2,0);             /* converter word */
-       
+
        return(True);
 }
 
@@ -2791,7 +3219,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
  Get info about the server.
 ****************************************************************************/
 
-static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
+static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2858,7 +3286,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
        }
 
        *rdata_len = mdrcnt;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
@@ -2873,16 +3301,25 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
        if (uLevel > 0) {
                struct srv_info_struct *servers=NULL;
                int i,count;
-               pstring comment;
+               char *comment = NULL;
+               TALLOC_CTX *ctx = talloc_tos();
                uint32 servertype= lp_default_server_announce();
 
-               push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
+               comment = talloc_strdup(ctx,lp_serverstring());
+               if (!comment) {
+                       return false;
+               }
 
                if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
                        for (i=0;i<count;i++) {
                                if (strequal(servers[i].name,global_myname())) {
                                        servertype = servers[i].type;
-                                       push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
+                                       TALLOC_FREE(comment);
+                                       comment = talloc_strdup(ctx,
+                                                       servers[i].comment);
+                                       if (comment) {
+                                               return false;
+                                       }
                                }
                        }
                }
@@ -2897,12 +3334,26 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
                        SIVAL(p,6,0);
                } else {
                        SIVAL(p,6,PTR_DIFF(p2,*rdata));
-                       standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
-                                             conn->connectpath, conn->gid,
-                                             get_current_username(),
-                                             current_user_info.domain,
-                                             comment, sizeof(comment));
-                       StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
+                       comment = talloc_sub_advanced(
+                               ctx,
+                               lp_servicename(SNUM(conn)),
+                               conn->server_info->unix_name,
+                               conn->connectpath,
+                               conn->server_info->utok.gid,
+                               conn->server_info->sanitized_username,
+                               pdb_get_domain(conn->server_info->sam_account),
+                               comment);
+                       if (comment) {
+                               return false;
+                       }
+                       if (mdrcnt - struct_len <= 0) {
+                               return false;
+                       }
+                       push_ascii(p2,
+                               comment,
+                               MIN(mdrcnt - struct_len,
+                                       MAX_SERVER_STRING_LENGTH),
+                               STR_TERMINATE);
                        p2 = skip_string(*rdata,*rdata_len,p2);
                        if (!p2) {
                                return False;
@@ -2917,7 +3368,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
        *rdata_len = PTR_DIFF(p2,*rdata);
 
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -2932,7 +3383,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
  Get info about the server.
 ****************************************************************************/
 
-static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
+static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2943,6 +3394,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
        char *p2;
+       char *endp;
        int level = get_safe_SVAL(param,tpscnt,p,0,-1);
 
        if (!str1 || !str2 || !p) {
@@ -2952,7 +3404,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        DEBUG(4,("NetWkstaGetInfo level %d\n",level));
 
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -2963,7 +3415,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        }
 
        *rdata_len = mdrcnt + 1024;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
@@ -2972,13 +3424,15 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        SSVAL(*rparam,2,0);             /* converter word */
 
        p = *rdata;
+       endp = *rdata + *rdata_len;
+
        p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
        if (!p2) {
                return False;
        }
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
-       pstrcpy(p2,get_local_machine_name());
+       strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
        strupper_m(p2);
        p2 = skip_string(*rdata,*rdata_len,p2);
        if (!p2) {
@@ -2987,7 +3441,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        p += 4;
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata));
-       pstrcpy(p2,current_user_info.smb_name);
+       strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
        p2 = skip_string(*rdata,*rdata_len,p2);
        if (!p2) {
                return False;
@@ -2995,7 +3449,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        p += 4;
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
-       pstrcpy(p2,lp_workgroup());
+       strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
        strupper_m(p2);
        p2 = skip_string(*rdata,*rdata_len,p2);
        if (!p2) {
@@ -3008,7 +3462,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        p += 2;
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata));
-       pstrcpy(p2,lp_workgroup());     /* don't know.  login domain?? */
+       strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));   /* don't know.  login domain?? */
        p2 = skip_string(*rdata,*rdata_len,p2);
        if (!p2) {
                return False;
@@ -3016,7 +3470,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        p += 4;
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
-       pstrcpy(p2,"");
+       strlcpy(p2,"",PTR_DIFF(endp,p2));
        p2 = skip_string(*rdata,*rdata_len,p2);
        if (!p2) {
                return False;
@@ -3058,7 +3512,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
 
 where:
 
-  usri11_name specifies the user name for which information is retireved
+  usri11_name specifies the user name for which information is retrieved
 
   usri11_pad aligns the next data structure element to a word boundary
 
@@ -3200,28 +3654,31 @@ There is no auxiliary data in the response.
 #define AF_OP_ACCOUNTS  3
 
 
-static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
+static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
+       struct smbd_server_connection *sconn = smbd_server_conn;
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
        char *str2 = skip_string(param,tpscnt,str1);
        char *UserName = skip_string(param,tpscnt,str2);
        char *p = skip_string(param,tpscnt,UserName);
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        char *p2;
+       char *endp;
        const char *level_string;
 
        /* get NIS home of a previously validated user - simeon */
        /* With share level security vuid will always be zero.
           Don't depend on vuser being non-null !!. JRA */
-       user_struct *vuser = get_valid_user_struct(vuid);
+       user_struct *vuser = get_valid_user_struct(sconn, vuid);
        if(vuser != NULL) {
-               DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, 
-                       vuser->user.unix_name));
+               DEBUG(3,("  Username of UID %d is %s\n",
+                        (int)vuser->server_info->utok.uid,
+                        vuser->server_info->unix_name));
        }
 
        if (!str1 || !str2 || !UserName || !p) {
@@ -3229,13 +3686,13 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
 
        DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
-  
+
        /* check it's a supported variant */
        if (strcmp(str1,"zWrLh") != 0) {
                return False;
@@ -3254,7 +3711,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        *rdata_len = mdrcnt + 1024;
-       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
                return False;
        }
@@ -3263,12 +3720,13 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
        SSVAL(*rparam,2,0);             /* converter word */
 
        p = *rdata;
+       endp = *rdata + *rdata_len;
        p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
        if (!p2) {
                return False;
        }
 
-       memset(p,0,21); 
+       memset(p,0,21);
        fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
 
        if (uLevel > 0) {
@@ -3278,14 +3736,14 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
 
        if (uLevel >= 10) {
                SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
-               pstrcpy(p2,"Comment");
+               strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
                }
 
                SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
-               pstrcpy(p2,"UserComment");
+               strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
@@ -3293,7 +3751,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
 
                /* EEK! the cifsrap.txt doesn't have this in!!!! */
                SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
-               pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
+               strlcpy(p2,((vuser != NULL)
+                           ? pdb_get_fullname(vuser->server_info->sam_account)
+                           : UserName),PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
@@ -3301,18 +3761,25 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        if (uLevel == 11) {
+               const char *homedir = "";
+               if (vuser != NULL) {
+                       homedir = pdb_get_homedir(
+                               vuser->server_info->sam_account);
+               }
                /* modelled after NTAS 3.51 reply */
-               SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
+               SSVAL(p,usri11_priv,
+                       (get_current_uid(conn) == (uid_t)0)?
+                       USER_PRIV_ADMIN:USER_PRIV_USER);
                SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
                SIVALS(p,usri11_password_age,-1);               /* password age */
                SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
-               pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
+               strlcpy(p2, homedir, PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
                }
                SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
-               pstrcpy(p2,"");
+               strlcpy(p2,"",PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
@@ -3322,7 +3789,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                SSVALS(p,usri11_bad_pw_count,-1);       /* bad pw counts */
                SSVALS(p,usri11_num_logons,-1);         /* num logons */
                SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
-               pstrcpy(p2,"\\\\*");
+               strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
@@ -3330,7 +3797,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                SSVAL(p,usri11_country_code,0);         /* country code */
 
                SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
-               pstrcpy(p2,"");
+               strlcpy(p2,"",PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
@@ -3355,9 +3822,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                memset(p+22,' ',16);    /* password */
                SIVALS(p,38,-1);                /* password age */
                SSVAL(p,42,
-               conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+                       (get_current_uid(conn) == (uid_t)0)?
+                       USER_PRIV_ADMIN:USER_PRIV_USER);
                SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
-               pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
+               strlcpy(p2, vuser ? pdb_get_homedir(
+                               vuser->server_info->sam_account) : "",
+                       PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
@@ -3366,7 +3836,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                *p2++ = 0;
                SSVAL(p,52,0);          /* flags */
                SIVAL(p,54,PTR_DIFF(p2,*rdata));                /* script_path */
-               pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
+               strlcpy(p2, vuser ? pdb_get_logon_script(
+                               vuser->server_info->sam_account) : "",
+                       PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
@@ -3374,14 +3846,16 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                if (uLevel == 2) {
                        SIVAL(p,60,0);          /* auth_flags */
                        SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
-                       pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
+                       strlcpy(p2,((vuser != NULL)
+                                   ? pdb_get_fullname(vuser->server_info->sam_account)
+                                   : UserName),PTR_DIFF(endp,p2));
                        p2 = skip_string(*rdata,*rdata_len,p2);
                        if (!p2) {
                                return False;
                        }
                        SIVAL(p,68,0);          /* urs_comment */
                        SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
-                       pstrcpy(p2,"");
+                       strlcpy(p2,"",PTR_DIFF(endp,p2));
                        p2 = skip_string(*rdata,*rdata_len,p2);
                        if (!p2) {
                                return False;
@@ -3399,10 +3873,29 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                        SSVALS(p,104,-1);       /* num_logons */
                        SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
                        {
-                               pstring tmp;
-                               pstrcpy(tmp, "\\\\%L");
-                               standard_sub_basic("", "", tmp, sizeof(tmp));
-                               pstrcpy(p2, tmp);
+                               TALLOC_CTX *ctx = talloc_tos();
+                               int space_rem = *rdata_len - (p2 - *rdata);
+                               char *tmp;
+
+                               if (space_rem <= 0) {
+                                       return false;
+                               }
+                               tmp = talloc_strdup(ctx, "\\\\%L");
+                               if (!tmp) {
+                                       return false;
+                               }
+                               tmp = talloc_sub_basic(ctx,
+                                               "",
+                                               "",
+                                               tmp);
+                               if (!tmp) {
+                                       return false;
+                               }
+
+                               push_ascii(p2,
+                                       tmp,
+                                       space_rem,
+                                       STR_TERMINATE);
                        }
                        p2 = skip_string(*rdata,*rdata_len,p2);
                        if (!p2) {
@@ -3420,13 +3913,14 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
        return(True);
 }
 
-static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
+static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
+       struct smbd_server_connection *sconn = smbd_server_conn;
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
@@ -3435,15 +3929,16 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
        char* name;
                /* With share level security vuid will always be zero.
                   Don't depend on vuser being non-null !!. JRA */
-       user_struct *vuser = get_valid_user_struct(vuid);
+       user_struct *vuser = get_valid_user_struct(sconn, vuid);
 
        if (!str1 || !str2 || !p) {
                return False;
        }
 
        if(vuser != NULL) {
-               DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, 
-                       vuser->user.unix_name));
+               DEBUG(3,("  Username of UID %d is %s\n",
+                        (int)vuser->server_info->utok.uid,
+                        vuser->server_info->unix_name));
        }
 
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
@@ -3464,7 +3959,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
                return False;
        }
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
@@ -3474,12 +3969,14 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
        desc.buflen = mdrcnt;
        desc.subformat = NULL;
        desc.format = str2;
-  
+
        if (init_package(&desc,1,0)) {
                PACKI(&desc,"W",0);             /* code */
                PACKS(&desc,"B21",name);        /* eff. name */
                PACKS(&desc,"B","");            /* pad */
-               PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+               PACKI(&desc,"W",
+                       (get_current_uid(conn) == (uid_t)0)?
+                       USER_PRIV_ADMIN:USER_PRIV_USER);
                PACKI(&desc,"D",0);             /* auth flags XXX */
                PACKI(&desc,"W",0);             /* num logons */
                PACKI(&desc,"W",0);             /* bad pw count */
@@ -3500,13 +3997,14 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
                }
 
                PACKS(&desc,"z",lp_workgroup());/* domain */
-               PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
+               PACKS(&desc,"z", vuser ? pdb_get_logon_script(
+                             vuser->server_info->sam_account) : ""); /* script path */
                PACKI(&desc,"D",0x00000000);            /* reserved */
        }
 
        *rdata_len = desc.usedlen;
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -3523,7 +4021,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
  api_WAccessGetUserPerms
 ****************************************************************************/
 
-static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
+static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3553,7 +4051,7 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
        }
 
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -3568,7 +4066,7 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
   api_WPrintJobEnumerate
   ****************************************************************************/
 
-static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
+static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3625,7 +4123,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
@@ -3651,7 +4149,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -3667,7 +4165,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
+static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3705,11 +4203,11 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
        if (strcmp(str1,"zWrLeh") != 0) {
                return False;
        }
-    
+
        if (uLevel > 2) {
                return False;   /* defined only for uLevel 0,1,2 */
        }
-    
+
        if (!check_printjob_info(&desc,uLevel,str2)) { 
                return False;
        }
@@ -3721,7 +4219,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
 
        count = print_queue_status(snum,&queue,&status);
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
@@ -3742,7 +4240,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
        *rdata_len = desc.usedlen;
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -3824,7 +4322,7 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
        }
 }
 
-static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
+static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3869,7 +4367,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
                desc.neededlen = 0;
        } else {
                if (mdrcnt > 0) {
-                       *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+                       *rdata = smb_realloc_limit(*rdata,mdrcnt);
                        if (!*rdata) {
                                return False;
                        }
@@ -3890,7 +4388,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        *rparam_len = 6;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -3904,7 +4402,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
+static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3946,7 +4444,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
        }
 
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
@@ -3971,7 +4469,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
        *rdata_len = desc.usedlen;
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -3985,7 +4483,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
+static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4018,7 +4516,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
        }
 
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
@@ -4034,7 +4532,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
        *rdata_len = desc.usedlen;
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -4048,7 +4546,7 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
+static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4080,7 +4578,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
        }
 
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
@@ -4097,7 +4595,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
        *rdata_len = desc.usedlen;
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -4111,7 +4609,7 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
+static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4144,7 +4642,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
        }
 
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
@@ -4162,7 +4660,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
        *rdata_len = desc.usedlen;
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -4180,7 +4678,7 @@ static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
  List open sessions
  ****************************************************************************/
 
-static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
+static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4216,10 +4714,10 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
                return False;
        }
 
-       num_sessions = list_sessions(tmp_talloc_ctx(), &session_list);
+       num_sessions = list_sessions(talloc_tos(), &session_list);
 
        if (mdrcnt > 0) {
-               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
@@ -4247,7 +4745,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
        *rdata_len = desc.usedlen;
 
        *rparam_len = 8;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -4265,13 +4763,13 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
  The buffer was too small.
  ****************************************************************************/
 
-static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
+static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
                         int mdrcnt, int mprcnt,
                         char **rdata, char **rparam,
                         int *rdata_len, int *rparam_len)
 {
        *rparam_len = MIN(*rparam_len,mprcnt);
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -4289,7 +4787,7 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char
  The request is not supported.
  ****************************************************************************/
 
-static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
+static bool api_Unsupported(connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt, int mprcnt,
@@ -4297,7 +4795,7 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
                                int *rdata_len, int *rparam_len)
 {
        *rparam_len = 4;
-       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
        }
@@ -4315,11 +4813,11 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
 static const struct {
        const char *name;
        int id;
-       BOOL (*fn)(connection_struct *, uint16,
+       bool (*fn)(connection_struct *, uint16,
                        char *, int,
                        char *, int,
                        int,int,char **,char **,int *,int *);
-       BOOL auth_user;         /* Deny anonymous access? */
+       bool auth_user;         /* Deny anonymous access? */
 } api_commands[] = {
        {"RNetShareEnum",       RAP_WshareEnum,         api_RNetShareEnum, True},
        {"RNetShareGetInfo",    RAP_WshareGetInfo,      api_RNetShareGetInfo},
@@ -4345,7 +4843,8 @@ static const struct {
        {"WPrintDestGetInfo",   RAP_WPrintDestGetInfo,  api_WPrintDestGetInfo},
        {"NetRemoteTOD",        RAP_NetRemoteTOD,       api_NetRemoteTOD},
        {"WPrintQueuePurge",    RAP_WPrintQPurge,       api_WPrintQueueCtrl},
-       {"NetServerEnum",       RAP_NetServerEnum2,     api_RNetServerEnum}, /* anon OK */
+       {"NetServerEnum2",      RAP_NetServerEnum2,     api_RNetServerEnum2}, /* anon OK */
+       {"NetServerEnum3",      RAP_NetServerEnum3,     api_RNetServerEnum3}, /* anon OK */
        {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
        {"SetUserPassword",     RAP_WUserPasswordSet2,  api_SetUserPassword},
        {"WWkstaUserLogon",     RAP_WWkstaUserLogon,    api_WWkstaUserLogon},
@@ -4372,6 +4871,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
               int tdscnt, int tpscnt,
               int mdrcnt, int mprcnt)
 {
+       struct smbd_server_connection *sconn = smbd_server_conn;
        int api_command;
        char *rdata = NULL;
        char *rparam = NULL;
@@ -4379,7 +4879,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
        const char *name2 = NULL;
        int rdata_len = 0;
        int rparam_len = 0;
-       BOOL reply=False;
+       bool reply=False;
        int i;
 
        if (!params) {
@@ -4420,9 +4920,9 @@ void api_reply(connection_struct *conn, uint16 vuid,
        /* Check whether this api call can be done anonymously */
 
        if (api_commands[i].auth_user && lp_restrict_anonymous()) {
-               user_struct *user = get_valid_user_struct(vuid);
+               user_struct *user = get_valid_user_struct(sconn, vuid);
 
-               if (!user || user->guest) {
+               if (!user || user->server_info->guest) {
                        reply_nterror(req, NT_STATUS_ACCESS_DENIED);
                        return;
                }
@@ -4467,7 +4967,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
 
        /* If api_Unsupported returns false we can't return anything. */
        if (reply) {
-               send_trans_reply(req, rparam, rparam_len,
+               send_trans_reply(conn, req, rparam, rparam_len,
                                 rdata, rdata_len, False);
        }