X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fsmbd%2Flanman.c;h=7b01968a1f04146b874af76e4b06cfc54611f300;hb=3985669176ad4989133f9a7a8995ce6c69504bf2;hp=03a48f5e6187b1c0e4a17491463be28a489320b1;hpb=e2585b73e975e8a434533019fbab1b8bd045ca70;p=samba.git diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 03a48f5e618..7b01968a1f0 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -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 . */ @@ -26,6 +26,10 @@ */ #include "includes.h" +#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 @@ -645,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", @@ -664,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; idependentfiles && *driver.info_3->dependentfiles[i]; i++) + for ( i=0; idependent_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 */ @@ -716,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); } @@ -806,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); @@ -817,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", @@ -826,15 +827,13 @@ 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; } @@ -876,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; @@ -899,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)); @@ -934,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 @@ -942,7 +941,7 @@ 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); @@ -954,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); @@ -986,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; } @@ -994,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; } @@ -1071,7 +1070,7 @@ 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); @@ -1082,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]); @@ -1091,7 +1090,7 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid, SAFE_FREE(queue); SAFE_FREE(status); - + return True; err: @@ -1154,9 +1153,9 @@ static int get_server_info(uint32 servertype, 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; } @@ -1186,7 +1185,7 @@ static int get_server_info(uint32 servertype, *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)); @@ -1214,6 +1213,7 @@ static int get_server_info(uint32 servertype, continue; } fstrcpy(s->comment, p); + string_truncate(s->comment, MAX_SERVER_STRING_LENGTH); s->domain[0] = '\0'; if (!next_token_talloc(frame,&ptr,&p, NULL)) { @@ -1248,11 +1248,11 @@ static int get_server_info(uint32 servertype, 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; @@ -1266,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; } @@ -1284,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; @@ -1295,7 +1295,7 @@ static int fill_srv_info(struct srv_info_struct *service, default: return -1; } - + if (!buf) { len = 0; switch (uLevel) { @@ -1308,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) { @@ -1324,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); @@ -1351,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); } /**************************************************************************** @@ -1361,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, @@ -1416,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))); @@ -1430,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); } @@ -1452,10 +1454,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; @@ -1470,7 +1472,7 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid, if (!*rdata) { return False; } - + p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ p = *rdata; f_len = fixed_len; @@ -1488,12 +1490,12 @@ 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); if (!*rparam) { @@ -1506,12 +1508,220 @@ 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; + + if (total > 0) { + qsort(servers,total,sizeof(servers[0]),QSORT_CAST 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;iname)) { + 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 ****************************************************************************/ @@ -1540,9 +1750,9 @@ 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); if (!*rparam) { @@ -1570,7 +1780,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; @@ -1599,7 +1811,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; @@ -1616,8 +1828,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, default: return -1; } - - + if (!buf) { len = 0; @@ -1635,7 +1846,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) { @@ -1653,9 +1864,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; @@ -1671,7 +1882,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 */ @@ -1680,7 +1891,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); @@ -1691,7 +1902,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; @@ -1718,7 +1929,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; } @@ -1727,7 +1938,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; @@ -1735,7 +1946,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, if (!check_share_info(uLevel,str2)) { return False; } - + *rdata = smb_realloc_limit(*rdata,mdrcnt); if (!*rdata) { return False; @@ -1745,7 +1956,7 @@ 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); if (!*rparam) { @@ -1754,7 +1965,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ SSVAL(*rparam,4,*rdata_len); - + return True; } @@ -1790,7 +2001,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, int i; int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; - + if (!str1 || !str2 || !p) { return False; } @@ -1801,7 +2012,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(); @@ -1819,7 +2030,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; @@ -1834,7 +2045,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, if (!*rdata) { return False; } - + p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */ p = *rdata; f_len = fixed_len; @@ -1853,7 +2064,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid, } } } - + *rparam_len = 8; *rparam = smb_realloc_limit(*rparam,*rparam_len); if (!*rparam) { @@ -1863,7 +2074,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)); @@ -2004,7 +2215,7 @@ 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: @@ -2038,11 +2249,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; } @@ -2063,14 +2275,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); @@ -2078,11 +2307,6 @@ 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); if (!*rdata) { @@ -2091,25 +2315,63 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid, p = *rdata; - for(i=0; ientries[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); @@ -2120,8 +2382,8 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid, } 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); } @@ -2144,17 +2406,17 @@ 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; + uint32_t i; char *endp = NULL; - TALLOC_CTX *mem_ctx; + + 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; @@ -2194,59 +2456,75 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid, 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_dbg(&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; icount; i++) { - if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) { - strlcpy(p, grp_name, PTR_DIFF(endp,p)); + 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++; } @@ -2259,10 +2537,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; } @@ -2282,8 +2562,11 @@ 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); @@ -2328,40 +2611,89 @@ static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid, 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; ientries[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); @@ -2538,7 +2870,7 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid, memset((char *)pass1,'\0',sizeof(fstring)); memset((char *)pass2,'\0',sizeof(fstring)); - + return(True); } @@ -2553,6 +2885,7 @@ static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, 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; @@ -2610,7 +2943,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); @@ -2677,7 +3010,7 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, } errcode = NERR_notsupported; - + switch (function) { case 81: /* delete */ if (print_job_delete(conn->server_info, snum, jobid, &werr)) @@ -2695,7 +3028,7 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr); - + out: SSVAL(*rparam,0,errcode); SSVAL(*rparam,2,0); /* converter word */ @@ -2749,23 +3082,20 @@ static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, switch (function) { case 74: /* Pause queue */ - if (print_queue_pause(conn->server_info, snum, &werr)) { - errcode = NERR_Success; - } + werr = print_queue_pause(conn->server_info, snum); break; case 75: /* Resume queue */ - if (print_queue_resume(conn->server_info, snum, &werr)) { - errcode = NERR_Success; - } + werr = print_queue_resume(conn->server_info, snum); break; case 103: /* Purge */ - if (print_queue_purge(conn->server_info, 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); @@ -2845,9 +3175,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))) @@ -2884,7 +3214,7 @@ static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid, out: SSVALS(*rparam,0,errcode); SSVAL(*rparam,2,0); /* converter word */ - + return(True); } @@ -3335,6 +3665,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, 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); @@ -3347,7 +3678,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, /* 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->server_info->utok.uid, @@ -3590,6 +3921,7 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, 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); @@ -3598,7 +3930,7 @@ 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; @@ -3638,7 +3970,7 @@ 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 */ @@ -3870,11 +4202,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; } @@ -4510,7 +4842,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}, @@ -4537,6 +4870,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; @@ -4585,7 +4919,7 @@ 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->server_info->guest) { reply_nterror(req, NT_STATUS_ACCESS_DENIED);