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"
+#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
{
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",
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 */
if ( printer )
free_a_printer( &printer, 2 );
- if ( driver.info_3 )
- free_a_printer_driver( driver, 3 );
+ free_a_printer_driver(driver);
}
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);
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",
}
/* 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;
}
/* 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;
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));
}
*rdata_len = desc.usedlen;
-
+
/*
* We must set the return code to ERRbuftoosmall
* in order to support lanman style printing with Win NT/2k
*/
if (!mdrcnt && lp_disable_spoolss())
desc.errcode = ERRbuftoosmall;
-
+
*rdata_len = desc.usedlen;
*rparam_len = 6;
*rparam = smb_realloc_limit(*rparam,*rparam_len);
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);
print_status_struct *status = NULL;
int *subcntarr = NULL;
int queuecnt = 0, subcnt = 0, succnt = 0;
-
+
if (!param_format || !output_format1 || !p) {
return False;
}
memset((char *)&desc,'\0',sizeof(desc));
DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
-
+
if (!prefix_ok(param_format,"WrLeh")) {
return False;
}
}
SAFE_FREE(subcntarr);
-
+
*rdata_len = desc.usedlen;
*rparam_len = 8;
*rparam = smb_realloc_limit(*rparam,*rparam_len);
SSVAL(*rparam,2,0);
SSVAL(*rparam,4,succnt);
SSVAL(*rparam,6,queuecnt);
-
+
for (i = 0; i < queuecnt; i++) {
if (queue) {
SAFE_FREE(queue[i]);
SAFE_FREE(queue);
SAFE_FREE(status);
-
+
return True;
err:
bool local_list_only;
int i;
- lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0, NULL);
+ 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;
}
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)) {
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;
s->name, s->type, s->comment, s->domain));
}
}
-
+
TALLOC_FREE(lines);
return count;
}
char* p2;
int l2;
int len;
-
+
switch (uLevel) {
case 0:
struct_len = 16;
default:
return -1;
}
-
+
if (!buf) {
len = 0;
switch (uLevel) {
*stringspace = len;
return struct_len + len;
}
-
+
len = struct_len;
p = *buf;
if (*buflen < struct_len) {
if (!baseaddr) {
baseaddr = p;
}
-
+
switch (uLevel) {
case 0:
push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
}
-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);
}
/****************************************************************************
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,
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)));
fstrcpy(domain, lp_workgroup());
}
+ DEBUG(4, ("domain [%s]\n", domain));
+
if (lp_browse_list()) {
total = get_server_info(servertype,&servers,domain);
}
}
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;
if (!*rdata) {
return False;
}
-
+
p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
p = *rdata;
f_len = fixed_len;
}
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) {
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;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
****************************************************************************/
if (!prefix_ok(str1,"zWrLeh")) {
return False;
}
-
+
*rdata_len = 0;
-
+
*rparam_len = 8;
*rparam = smb_realloc_limit(*rparam,*rparam_len);
if (!*rparam) {
}
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;
char* p2;
int l2;
int len;
-
+
switch( uLevel ) {
case 0:
struct_len = 13;
default:
return -1;
}
-
-
+
if (!buf) {
len = 0;
}
return struct_len + len;
}
-
+
len = struct_len;
p = *buf;
if ((*buflen) < struct_len) {
if (!baseaddr) {
baseaddr = p;
}
-
+
push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
-
+
if (uLevel > 0) {
int type;
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 */
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);
SSVAL(p,64,0);
SSVAL(p,66,0);
}
-
+
if (stringbuf) {
(*buf) = p + struct_len;
(*buflen) -= struct_len;
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;
}
if (snum < 0) {
return False;
}
-
+
/* check it's a supported varient */
if (!prefix_ok(str1,"zWrLh")) {
return False;
if (!check_share_info(uLevel,str2)) {
return False;
}
-
+
*rdata = smb_realloc_limit(*rdata,mdrcnt);
if (!*rdata) {
return False;
if (*rdata_len < 0) {
return False;
}
-
+
*rparam_len = 6;
*rparam = smb_realloc_limit(*rparam,*rparam_len);
if (!*rparam) {
SSVAL(*rparam,0,NERR_Success);
SSVAL(*rparam,2,0); /* converter word */
SSVAL(*rparam,4,*rdata_len);
-
+
return True;
}
int i;
int data_len, fixed_len, string_len;
int f_len = 0, s_len = 0;
-
+
if (!str1 || !str2 || !p) {
return False;
}
if (!check_share_info(uLevel,str2)) {
return False;
}
-
+
/* Ensure all the usershares are loaded. */
become_root();
load_registry_shares();
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;
if (!*rdata) {
return False;
}
-
+
p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
p = *rdata;
f_len = fixed_len;
}
}
}
-
+
*rparam_len = 8;
*rparam = smb_realloc_limit(*rparam,*rparam_len);
if (!*rparam) {
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));
SSVAL(*rparam,2,0); /* converter word */
SSVAL(*rparam,4,*rdata_len);
*rdata_len = 0;
-
+
return True;
error_exit:
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;
}
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);
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) {
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);
}
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);
}
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;
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; i<num_groups; i++) {
- const char *grp_name;
+ for (i=0; i<rids->count; 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++;
}
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;
}
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);
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;
+ resume_handle = 0;
- 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;
+ 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);
memset((char *)pass1,'\0',sizeof(fstring));
memset((char *)pass2,'\0',sizeof(fstring));
-
+
return(True);
}
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;
* 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);
}
errcode = NERR_notsupported;
-
+
switch (function) {
case 81: /* delete */
if (print_job_delete(conn->server_info, snum, jobid, &werr))
if (!W_ERROR_IS_OK(werr))
errcode = W_ERROR_V(werr);
-
+
out:
SSVAL(*rparam,0,errcode);
SSVAL(*rparam,2,0); /* converter word */
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);
sharename));
return False;
}
-
+
*rdata_len = 0;
-
+
/* check it's a supported varient */
if ((strcmp(str1,"WWsTP")) ||
(!check_printjob_info(&desc,uLevel,str2)))
out:
SSVALS(*rparam,0,errcode);
SSVAL(*rparam,2,0); /* converter word */
-
+
return(True);
}
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);
/* 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,
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);
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;
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 */
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;
}
{"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},
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;
/* 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);