Unix SMB/Netbios implementation.
Version 1.9.
Inter-process communication and named pipe handling
- Copyright (C) Andrew Tridgell 1992-1995
+ Copyright (C) Andrew Tridgell 1992-1998
+
+ 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
*/
#include "includes.h"
+#include "nterr.h"
#ifdef CHECK_TYPES
#undef CHECK_TYPES
#define CHECK_TYPES 0
extern int DEBUGLEVEL;
-extern int maxxmit;
+extern int max_send;
extern files_struct Files[];
extern connection_struct Connections[];
extern fstring local_machine;
+extern fstring myworkgroup;
#define NERR_Success 0
#define NERR_badpass 86
#define ERROR_INVALID_LEVEL 124
#define ERROR_MORE_DATA 234
-#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
-
#define ACCESS_READ 0x01
#define ACCESS_WRITE 0x02
#define ACCESS_CREATE 0x04
#define QNLEN 12 /* queue name maximum length */
extern int Client;
+extern int oplock_sock;
+extern int smb_read_error;
+
+static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len);
+static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len);
+
static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
{
return(strncmp(str,prefix,strlen(prefix)) == 0);
}
+/*******************************************************************
+ copies parameters and data, as needed, into the smb buffer
+
+ *both* the data and params sections should be aligned. this
+ is fudged in the rpc pipes by
+ at present, only the data section is. this may be a possible
+ cause of some of the ipc problems being experienced. lkcl26dec97
+
+ ******************************************************************/
+static void copy_trans_params_and_data(char *outbuf, int align,
+ struct mem_buf *rparam, struct mem_buf *rdata,
+ int param_offset, int data_offset,
+ int param_len, int data_len)
+{
+ char *copy_into = smb_buf(outbuf);
+
+ DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
+ param_offset, param_offset + param_len,
+ data_offset , data_offset + data_len));
+
+ if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
+ copy_into += param_len + align;
+ if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
+}
/****************************************************************************
send a trans reply
****************************************************************************/
-static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
- int ldata,int lparam,int lsetup)
+static void send_trans_reply(char *outbuf,
+ struct mem_buf *rdata,
+ struct mem_buf *rparam,
+ uint16 *setup, int lsetup, int max_data_ret)
{
- int i;
- int this_ldata,this_lparam;
- int tot_data=0,tot_param=0;
- int align;
-
- this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
- this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
-
- align = (this_lparam%4);
-
- set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
- if (this_lparam)
- memcpy(smb_buf(outbuf),param,this_lparam);
- if (this_ldata)
- memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
-
- SSVAL(outbuf,smb_vwv0,lparam);
- SSVAL(outbuf,smb_vwv1,ldata);
- SSVAL(outbuf,smb_vwv3,this_lparam);
- SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
- SSVAL(outbuf,smb_vwv5,0);
- SSVAL(outbuf,smb_vwv6,this_ldata);
- SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
- SSVAL(outbuf,smb_vwv8,0);
- SSVAL(outbuf,smb_vwv9,lsetup);
- for (i=0;i<lsetup;i++)
- SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
-
- show_msg(outbuf);
- send_smb(Client,outbuf);
-
- tot_data = this_ldata;
- tot_param = this_lparam;
-
- while (tot_data < ldata || tot_param < lparam)
- {
- this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
- this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
+ int i;
+ int this_ldata,this_lparam;
+ int tot_data=0,tot_param=0;
+ int align;
- align = (this_lparam%4);
+ int ldata = rdata ? mem_buf_len(rdata ) : 0;
+ int lparam = rparam ? mem_buf_len(rparam) : 0;
- set_message(outbuf,10,this_ldata+this_lparam+align,False);
- if (this_lparam)
- memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
- if (this_ldata)
- memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
+ BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
- SSVAL(outbuf,smb_vwv3,this_lparam);
- SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
- SSVAL(outbuf,smb_vwv5,tot_param);
- SSVAL(outbuf,smb_vwv6,this_ldata);
- SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
- SSVAL(outbuf,smb_vwv8,tot_data);
- SSVAL(outbuf,smb_vwv9,0);
+ if (buffer_too_large)
+ {
+ DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
+ ldata = max_data_ret;
+ }
- show_msg(outbuf);
- send_smb(Client,outbuf);
+ this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
+ this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
- tot_data += this_ldata;
- tot_param += this_lparam;
- }
-}
+#ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
+ /* if you don't want Net Monitor to decode your packets, do this!!! */
+ align = ((this_lparam+1)%4);
+#else
+ align = (this_lparam%4);
+#endif
+ set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
+ if (buffer_too_large)
+ {
+ /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
+ SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+ SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
+ }
-/****************************************************************************
- get a print queue
- ****************************************************************************/
+ copy_trans_params_and_data(outbuf, align,
+ rparam , rdata,
+ tot_param , tot_data,
+ this_lparam, this_ldata);
+
+ SSVAL(outbuf,smb_vwv0,lparam);
+ SSVAL(outbuf,smb_vwv1,ldata);
+ SSVAL(outbuf,smb_vwv3,this_lparam);
+ SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
+ SSVAL(outbuf,smb_vwv5,0);
+ SSVAL(outbuf,smb_vwv6,this_ldata);
+ SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
+ SSVAL(outbuf,smb_vwv8,0);
+ SSVAL(outbuf,smb_vwv9,lsetup);
+
+ for (i=0;i<lsetup;i++)
+ {
+ SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
+ }
+
+ show_msg(outbuf);
+ send_smb(Client,outbuf);
+
+ tot_data = this_ldata;
+ tot_param = this_lparam;
+
+ while (tot_data < ldata || tot_param < lparam)
+ {
+ this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
+ this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
+
+ align = (this_lparam%4);
+
+ set_message(outbuf,10,this_ldata+this_lparam+align,False);
+
+ copy_trans_params_and_data(outbuf, align,
+ rparam , rdata,
+ tot_param , tot_data,
+ this_lparam, this_ldata);
+
+ SSVAL(outbuf,smb_vwv3,this_lparam);
+ SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
+ SSVAL(outbuf,smb_vwv5,tot_param);
+ SSVAL(outbuf,smb_vwv6,this_ldata);
+ SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
+ SSVAL(outbuf,smb_vwv8,tot_data);
+ SSVAL(outbuf,smb_vwv9,0);
+
+ show_msg(outbuf);
+ send_smb(Client,outbuf);
+
+ tot_data += this_ldata;
+ tot_param += this_lparam;
+ }
+}
struct pack_desc {
char* format; /* formatstring for structure */
p->subcount = 0;
p->curpos = p->format;
if (i > n) {
+ p->neededlen = i;
i = n = 0;
- p->errcode = NERR_BufTooSmall;
+ p->errcode = ERROR_MORE_DATA;
}
-
- p->errcode = NERR_Success;
+ else
+ p->errcode = NERR_Success;
p->buflen = i;
n -= i;
p->stringbuf = p->base + i;
p->usedlen += needed;
}
else {
- if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
+ if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
}
return 1;
}
PACK(desc,t,v);
}
+
+/****************************************************************************
+ get a print queue
+ ****************************************************************************/
+
static void PackDriverData(struct pack_desc* desc)
{
char drivdata[4+4+32];
}
static int check_printq_info(struct pack_desc* desc,
- int uLevel, const char* id1, const char* id2)
+ int uLevel, char *id1, char *id2)
{
desc->subformat = NULL;
switch( uLevel ) {
case 5:
desc->format = "z";
break;
+ case 52:
+ desc->format = "WzzzzzzzzN";
+ desc->subformat = "z";
+ break;
default: return False;
}
if (strcmp(desc->format,id1) != 0) return False;
/* the client expects localtime */
t -= TimeDiff(t);
- PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
+ PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
if (uLevel == 1) {
PACKS(desc,"B21",queue->user); /* szUserName */
PACKS(desc,"B",""); /* pad */
int count, print_queue_struct* queue,
print_status_struct* status)
{
- if (uLevel < 3) {
- PACKS(desc,"B13",SERVICE(snum));
- } else {
- PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
+ switch (uLevel) {
+ case 1:
+ case 2:
+ PACKS(desc,"B13",SERVICE(snum));
+ break;
+ case 3:
+ case 4:
+ case 5:
+ PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
+ break;
}
+
if (uLevel == 1 || uLevel == 2) {
PACKS(desc,"B",""); /* alignment */
PACKI(desc,"W",5); /* priority */
PACKI(desc,"W",0); /* uUntiltime */
PACKI(desc,"W",5); /* pad1 */
PACKS(desc,"z",""); /* pszSepFile */
- PACKS(desc,"z","lpd"); /* pszPrProc */
+ PACKS(desc,"z","WinPrint"); /* pszPrProc */
PACKS(desc,"z",""); /* pszParms */
if (!status || !status->message[0]) {
PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
}
PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
- PACKS(desc,"z","NULL"); /* pszDriverName */
+ PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
PackDriverData(desc); /* pDriverData */
}
if (uLevel == 2 || uLevel == 4) {
for (i=0;i<count;i++)
fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
}
-
- DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
+
+ if (uLevel==52) {
+ int i,ok=0;
+ pstring tok,driver,datafile,langmon,helpfile,datatype;
+ char *p,*q;
+ FILE *f;
+ pstring fname;
+
+ strcpy(fname,lp_driverfile());
+ f=fopen(fname,"r");
+ if (!f) {
+ DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
+ desc->errcode=NERR_notsupported;
+ return;
+ }
+
+ p=(char *)malloc(8192*sizeof(char));
+ bzero(p, 8192*sizeof(char));
+ q=p;
+
+ /* lookup the long printer driver name in the file description */
+ while (f && !feof(f) && !ok)
+ {
+ p = q; /* reset string pointer */
+ fgets(p,8191,f);
+ p[strlen(p)-1]='\0';
+ if (next_token(&p,tok,":") &&
+ (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
+ ok=1;
+ }
+ fclose(f);
+
+ /* driver file name */
+ if (ok && !next_token(&p,driver,":")) ok = 0;
+ /* data file name */
+ if (ok && !next_token(&p,datafile,":")) ok = 0;
+ /*
+ * for the next tokens - which may be empty - I have to check for empty
+ * tokens first because the next_token function will skip all empty
+ * token fields
+ */
+ if (ok) {
+ /* help file */
+ if (*p == ':') {
+ *helpfile = '\0';
+ p++;
+ } else if (!next_token(&p,helpfile,":")) ok = 0;
+ }
+
+ if (ok) {
+ /* language monitor */
+ if (*p == ':') {
+ *langmon = '\0';
+ p++;
+ } else if (!next_token(&p,langmon,":")) ok = 0;
+ }
+
+ /* default data type */
+ if (ok && !next_token(&p,datatype,":")) ok = 0;
+
+ if (ok) {
+ PACKI(desc,"W",0x0400); /* don't know */
+ PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
+ PACKS(desc,"z",driver); /* Driverfile Name */
+ PACKS(desc,"z",datafile); /* Datafile name */
+ PACKS(desc,"z",langmon); /* language monitor */
+ PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
+ PACKS(desc,"z",datatype); /* default data type */
+ PACKS(desc,"z",helpfile); /* helpfile name */
+ PACKS(desc,"z",driver); /* driver name */
+ DEBUG(3,("Driver:%s:\n",driver));
+ DEBUG(3,("Data File:%s:\n",datafile));
+ DEBUG(3,("Language Monitor:%s:\n",langmon));
+ DEBUG(3,("Data Type:%s:\n",datatype));
+ DEBUG(3,("Help File:%s:\n",helpfile));
+ PACKI(desc,"N",count); /* number of files to copy */
+ for (i=0;i<count;i++)
+ {
+ /* no need to check return value here - it was already tested in
+ * get_printerdrivernumber
+ */
+ next_token(&p,tok,",");
+ PACKS(desc,"z",tok); /* driver files to copy */
+ DEBUG(3,("file:%s:\n",tok));
+ }
+
+ DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
+ SERVICE(snum),count));
+ } else {
+ DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
+ desc->errcode=NERR_notsupported;
+ }
+ free(q);
+ }
}
-static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
+/* This function returns the number of files for a given driver */
+int get_printerdrivernumber(int snum)
+{
+ int i=0,ok=0;
+ pstring tok;
+ char *p,*q;
+ FILE *f;
+ pstring fname;
+
+ strcpy(fname,lp_driverfile());
+
+ DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
+ f=fopen(fname,"r");
+ if (!f) {
+ DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
+ return(0);
+ }
+
+ p=(char *)malloc(8192*sizeof(char));
+ q=p; /* need it to free memory because p change ! */
+
+ /* lookup the long printer driver name in the file description */
+ while (!feof(f) && !ok)
+ {
+ p = q; /* reset string pointer */
+ fgets(p,8191,f);
+ if (next_token(&p,tok,":") &&
+ (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
+ ok=1;
+ }
+ fclose(f);
+
+ if (ok) {
+ /* skip 5 fields */
+ i = 5;
+ while (*p && i) {
+ if (*p++ == ':') i--;
+ }
+ if (!*p || i)
+ return(0);
+
+ /* count the number of files */
+ while (next_token(&p,tok,","))
+ i++;
+ }
+ free(q);
+
+ return(i);
+}
+
+static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
cbBuf = SVAL(p,2);
str3 = p + 4;
+ /* remove any trailing username */
if ((p = strchr(QueueName,'%'))) *p = 0;
DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
if (snum < 0 || !VALID_SNUM(snum)) return(False);
- count = get_printqueue(snum,cnum,&queue,&status);
+ if (uLevel==52)
+ {
+ count = get_printerdrivernumber(snum);
+ DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
+ }
+ else
+ count = get_printqueue(snum,cnum,&queue,&status);
+
if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
desc.base = *rdata;
desc.buflen = mdrcnt;
/****************************************************************************
view list of all print jobs on all queues
****************************************************************************/
-static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
+static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
int mdrcnt, int mprcnt,
char **rdata, char** rparam,
int *rdata_len, int *rparam_len)
DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
- if (prefix_ok(param_format,"WrLeh")) return False;
+ if (!prefix_ok(param_format,"WrLeh")) return False;
if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
return False;
queuecnt = 0;
return True;
}
-/* used for server information: client, nameserv and ipc */
struct srv_info_struct
{
fstring name;
uint32 type;
fstring comment;
- fstring domain; /* used ONLY in ipc.c NOT namework.c */
- BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
+ fstring domain;
+ BOOL server_added;
};
-/*******************************************************************
- filter out unwanted server info
- ******************************************************************/
-static BOOL filter_server_info(struct srv_info_struct *server,
- BOOL domains,
- char *domain, uint32 request)
-{
- if (*domain == 0)
- {
- if (strequal(lp_workgroup(), server->domain)) {
- return True;
- }
- else if (domains)
- {
- DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
- return False;
- }
- else if ((request & SV_TYPE_DOMAIN_ENUM) &&
- (server->type & SV_TYPE_DOMAIN_ENUM))
- {
- DEBUG(4,("rej:DOM %8x: %s %s\n",server->type,server->name,server->domain));
- return False;
- }
-
- return True;
- }
- else
- {
- if (strequal(domain, server->domain))
- {
- /*
- if (request == SV_TYPE_LOCAL_LIST_ONLY &&
- !(server->type & SV_TYPE_LOCAL_LIST_ONLY))
- {
- DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
- return False;
- }
- */
- if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
- !(server->type&SV_TYPE_DOMAIN_ENUM))
- {
- DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
- return False;
- }
-
- return True;
- }
- else if (!domains)
- {
- DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
- return False;
- }
- return True;
- }
-}
/*******************************************************************
get server info lists from the files saved by nmbd. Return the
number of entries
******************************************************************/
static int get_server_info(uint32 servertype,
- struct srv_info_struct **servers, BOOL domains,
+ struct srv_info_struct **servers,
char *domain)
{
FILE *f;
int count=0;
int alloced=0;
pstring line;
+ BOOL local_list_only;
- strcpy(fname,lp_lockdir());
+ pstrcpy(fname,lp_lockdir());
trim_string(fname,NULL,"/");
strcat(fname,"/");
strcat(fname,SERVER_LIST);
}
/* request for everything is code for request all servers */
- if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+ if (servertype == SV_TYPE_ALL)
+ servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+
+ local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
- DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains)));
+ DEBUG(4,("Servertype search: %8x\n",servertype));
while (!feof(f))
{
if (!next_token(&ptr,s->comment, NULL)) continue;
if (!next_token(&ptr,s->domain , NULL)) {
/* this allows us to cope with an old nmbd */
- strcpy(s->domain,my_workgroup());
+ strcpy(s->domain,myworkgroup);
}
if (sscanf(stype,"%X",&s->type) != 1) {
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. */
+ if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
+ DEBUG(4,("r: local list only"));
+ ok = False;
+ }
+
/* doesn't match up: don't want it */
if (!(servertype & s->type)) {
DEBUG(4,("r:serv type "));
ok = False;
}
- if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
+ if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
(s->type & SV_TYPE_DOMAIN_ENUM))
{
- DEBUG(4,("s:all x dom "));
+ DEBUG(4,("s: dom mismatch "));
ok = False;
}
- if (domains && !(domain && *domain && strequal(domain, s->domain)))
+ if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
{
- if (!(s->type & SV_TYPE_DOMAIN_ENUM))
- {
- DEBUG(4,("r:dom enum "));
- ok = False;
- }
+ ok = False;
}
+ /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
+ s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
+
if (ok)
{
DEBUG(4,("**SV** %20s %8x %25s %15s\n",
s->name, s->type, s->comment, s->domain));
- s->type |= SV_TYPE_LOCAL_LIST_ONLY;
s->server_added = True;
count++;
}
view list of servers available (or possibly domains). The info is
extracted from lists saved by nmbd on the local host
****************************************************************************/
-static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
+static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
int mdrcnt, int mprcnt, char **rdata,
char **rparam, int *rdata_len, int *rparam_len)
{
uint32 servertype = IVAL(p,4);
char *p2;
int data_len, fixed_len, string_len;
- int f_len, s_len;
+ int f_len = 0, s_len = 0;
struct srv_info_struct *servers=NULL;
int counted=0,total=0;
- int i;
+ int i,missed;
fstring domain;
- BOOL domains;
BOOL domain_request;
- BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
+ BOOL local_request;
+
+ /* 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 (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+ if (servertype == SV_TYPE_ALL)
+ servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
- domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
+ /* 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
+ 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);
- domain[0] = 0;
p += 8;
if (!prefix_ok(str1,"WrLehD")) return False;
DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
- if (strcmp(str1, "WrLehDO") == 0)
- {
- domains = False;
- }
- else if (strcmp(str1, "WrLehDz") == 0)
- {
- domains = True;
+ if (strcmp(str1, "WrLehDz") == 0) {
StrnCpy(domain, p, sizeof(fstring)-1);
+ } else {
+ StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
}
if (lp_browse_list())
- {
- total = get_server_info(servertype,&servers,domains,domain);
- }
+ total = get_server_info(servertype,&servers,domain);
data_len = fixed_len = string_len = 0;
+ missed = 0;
qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
for (i=0;i<total;i++)
{
struct srv_info_struct *s = &servers[i];
- if (filter_server_info(s,domains,domain,
- local_request|domain_request))
- {
- 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 %20s %8x %25s %15s\n",
- s->name, s->type, s->comment, s->domain));
-
- if (data_len <= buf_len)
- {
- counted++;
- fixed_len += f_len;
- string_len += s_len;
- }
- }
+ 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 %20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
+
+ if (data_len <= buf_len) {
+ counted++;
+ fixed_len += f_len;
+ string_len += s_len;
+ } else {
+ missed++;
+ }
}
}
for (i = 0; i < total && count2;i++)
{
struct srv_info_struct *s = &servers[i];
- if (filter_server_info(s,domains,domain,local_request|domain_request))
- {
- 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 %20s %8x %25s %15s\n",
- s->name, s->type, s->comment, s->domain));
- count2--;
- }
+ 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 %20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
+ count2--;
}
}
*rparam_len = 8;
*rparam = REALLOC(*rparam,*rparam_len);
- SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
SSVAL(*rparam,2,0);
SSVAL(*rparam,4,counted);
- SSVAL(*rparam,6,total);
+ SSVAL(*rparam,6,counted+missed);
if (servers) free(servers);
DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
- domain,uLevel,counted,total));
+ domain,uLevel,counted,counted+missed));
return(True);
}
+/****************************************************************************
+ command 0x34 - suspected of being a "Lookup Names" stub api
+ ****************************************************************************/
+static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data,
+ int mdrcnt, int mprcnt, char **rdata,
+ char **rparam, int *rdata_len, int *rparam_len)
+{
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel = SVAL(p,0);
+ int buf_len = SVAL(p,2);
+ int counted=0;
+ int missed=0;
+
+ DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
+ str1, str2, p, uLevel, buf_len));
+
+ if (!prefix_ok(str1,"zWrLeh")) return False;
+
+ *rdata_len = 0;
+ *rdata = NULL;
+
+ *rparam_len = 8;
+ *rparam = REALLOC(*rparam,*rparam_len);
+
+ SSVAL(*rparam,0,0x08AC); /* informational warning message */
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,counted);
+ SSVAL(*rparam,6,counted+missed);
+
+ return(True);
+}
/****************************************************************************
get info about a share
return len;
}
-static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
/****************************************************************************
view list of shares available
****************************************************************************/
-static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
int total=0,counted=0;
int i;
int data_len, fixed_len, string_len;
- int f_len, s_len;
+ int f_len = 0, s_len = 0;
if (!prefix_ok(str1,"WrLeh")) return False;
if (!check_share_info(uLevel,str2)) return False;
/****************************************************************************
get the time of day info
****************************************************************************/
-static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
+static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
/****************************************************************************
set the user password
****************************************************************************/
-static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
+static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
fstring user;
fstring pass1,pass2;
- strcpy(user,p);
+ fstrcpy(user,p);
p = skip_string(p,1);
- StrnCpy(pass1,p,16);
- StrnCpy(pass2,p+16,16);
+ memcpy(pass1,p,16);
+ memcpy(pass2,p+16,16);
*rparam_len = 4;
*rparam = REALLOC(*rparam,*rparam_len);
*rdata_len = 0;
- SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,0,NERR_badpass);
SSVAL(*rparam,2,0); /* converter word */
DEBUG(3,("Set password for <%s>\n",user));
- if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
- !chgpasswd(user,pass1,pass2))
- SSVAL(*rparam,0,NERR_badpass);
+ /*
+ * Attempt the plaintext password change first.
+ * Older versions of Windows seem to do this.
+ */
+
+ if (password_ok(user,pass1,strlen(pass1),NULL) &&
+ chgpasswd(user,pass1,pass2,False))
+ {
+ SSVAL(*rparam,0,NERR_Success);
+ }
+
+ /*
+ * If the plaintext change failed, attempt
+ * the encrypted. NT will generate this
+ * after trying the samr method.
+ */
+
+ if(SVAL(*rparam,0) != NERR_Success)
+ {
+ struct smb_passwd *smbpw = NULL;
+
+ if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &smbpw) &&
+ change_lanman_password(smbpw,(unsigned char *)pass1,(unsigned char *)pass2))
+ {
+ SSVAL(*rparam,0,NERR_Success);
+ }
+ }
bzero(pass1,sizeof(fstring));
bzero(pass2,sizeof(fstring));
return(True);
}
+/****************************************************************************
+ Set the user password (SamOEM version - gets plaintext).
+****************************************************************************/
+
+static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
+{
+ fstring user;
+ fstring new_passwd;
+ struct smb_passwd *smbpw = NULL;
+ char *p = param + 2;
+
+ *rparam_len = 2;
+ *rparam = REALLOC(*rparam,*rparam_len);
+
+ *rdata_len = 0;
+
+ SSVAL(*rparam,0,NERR_badpass);
+
+ /*
+ * Check the parameter definition is correct.
+ */
+ if(!strequal(param + 2, "zsT")) {
+ DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
+ return False;
+ }
+ p = skip_string(p, 1);
+
+ if(!strequal(p, "B516B16")) {
+ DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
+ return False;
+ }
+ p = skip_string(p,1);
+
+ fstrcpy(user,p);
+ p = skip_string(p,1);
+
+ if(check_oem_password( user, (unsigned char *)data, &smbpw,
+ new_passwd, (int)sizeof(new_passwd)) == False) {
+ return True;
+ }
+
+ /*
+ * At this point we have the new case-sensitive plaintext
+ * password in the fstring new_passwd. If we wanted to synchronise
+ * with UNIX passwords we would call a UNIX password changing
+ * function here. However it would have to be done as root
+ * as the plaintext of the old users password is not
+ * available. JRA.
+ */
+
+ if(lp_unix_password_sync())
+ chgpasswd(user,"", new_passwd, True);
+
+ if(change_oem_password( smbpw, new_passwd)) {
+ SSVAL(*rparam,0,NERR_Success);
+ }
+
+ return(True);
+}
+
/****************************************************************************
delete a print job
Form: <W> <>
****************************************************************************/
-static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
+static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
char *str1 = param+2;
char *str2 = skip_string(str1,1);
char *p = skip_string(str2,1);
- int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
- by the print queue api */
- int snum = (SVAL(p,0)>>8);
+ int jobid, snum;
int i, count;
+ printjob_decode(SVAL(p,0), &snum, &jobid);
/* check it's a supported varient */
if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
count = get_printqueue(snum,cnum,&queue,NULL);
for (i=0;i<count;i++)
- if ((queue[i].job%0xFF) == jobid)
+ if ((queue[i].job&0xFF) == jobid)
{
switch (function) {
case 81: /* delete */
return(True);
}
-static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
return True;
}
-static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
+static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
char *str1 = param+2;
char *str2 = skip_string(str1,1);
char *p = skip_string(str2,1);
- int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
- by the print queue api */
- int snum = (SVAL(p,0)>>8);
+ int jobid, snum;
int uLevel = SVAL(p,2);
int function = SVAL(p,4); /* what is this ?? */
int i;
char *s = data;
+
+ printjob_decode(SVAL(p,0), &snum, &jobid);
*rparam_len = 4;
*rparam = REALLOC(*rparam,*rparam_len);
lpq_reset(snum);
count = get_printqueue(snum,cnum,&queue,NULL);
for (i=0;i<count;i++) /* find job */
- if ((queue[i].job%0xFF) == jobid) break;
+ if ((queue[i].job&0xFF) == jobid) break;
if (i==count) {
desc.errcode=NERR_JobNotFound;
DEBUG(3,("Setting print name to %s\n",name));
+ become_root(True);
+
for (i=0;i<MAX_OPEN_FILES;i++)
if (Files[i].open && Files[i].print_file)
{
pstring wd;
+ int fcnum = Files[i].cnum;
GetWd(wd);
unbecome_user();
- if (!become_user(Files[i].cnum,uid) ||
- !become_service(Files[i].cnum,True))
+ if (!become_user(&Connections[fcnum], fcnum,vuid) ||
+ !become_service(fcnum,True))
break;
if (sys_rename(Files[i].name,name) == 0)
string_set(&Files[i].name,name);
break;
}
+
+ unbecome_root(True);
}
desc.errcode=NERR_Success;
/****************************************************************************
get info about the server
****************************************************************************/
-static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
struct srv_info_struct *servers=NULL;
int i,count;
pstring comment;
- uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
- SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
+ uint32 servertype= lp_default_server_announce();
- strcpy(comment,lp_serverstring());
+ pstrcpy(comment,lp_serverstring());
- if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
+ if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
for (i=0;i<count;i++)
- if (strequal(servers[i].name,local_machine)) {
+ if (strequal(servers[i].name,local_machine))
+ {
servertype = servers[i].type;
- strcpy(comment,servers[i].comment);
+ pstrcpy(comment,servers[i].comment);
}
}
if (servers) free(servers);
- SCVAL(p,0,2); /* version_major */
- SCVAL(p,1,0); /* version_minor */
+ SCVAL(p,0,lp_major_announce_version());
+ SCVAL(p,1,lp_minor_announce_version());
SIVAL(p,2,servertype);
+
if (mdrcnt == struct_len) {
SIVAL(p,6,0);
} else {
/****************************************************************************
get info about the server
****************************************************************************/
-static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
p = *rdata;
p2 = p + 22;
- SIVAL(p,0,PTR_DIFF(p2,*rdata));
+
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
strcpy(p2,local_machine);
+ strupper(p2);
p2 = skip_string(p2,1);
p += 4;
p2 = skip_string(p2,1);
p += 4;
- SIVAL(p,0,PTR_DIFF(p2,*rdata));
- strcpy(p2,my_workgroup());
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
+ strcpy(p2,myworkgroup);
+ strupper(p2);
p2 = skip_string(p2,1);
p += 4;
- SCVAL(p,0,2); /* major version?? */
- SCVAL(p,1,1); /* minor version?? */
+ SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
+ SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
p += 2;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
- strcpy(p2,my_workgroup()); /* login domain?? */
+ strcpy(p2,myworkgroup); /* don't know. login domain?? */
p2 = skip_string(p2,1);
p += 4;
- SIVAL(p,0,PTR_DIFF(p2,*rdata));
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
strcpy(p2,"");
p2 = skip_string(p2,1);
p += 4;
return(True);
}
-
/****************************************************************************
get info about a user
+
+ struct user_info_11 {
+ char usri11_name[21]; 0-20
+ char usri11_pad; 21
+ char *usri11_comment; 22-25
+ char *usri11_usr_comment; 26-29
+ unsigned short usri11_priv; 30-31
+ unsigned long usri11_auth_flags; 32-35
+ long usri11_password_age; 36-39
+ char *usri11_homedir; 40-43
+ char *usri11_parms; 44-47
+ long usri11_last_logon; 48-51
+ long usri11_last_logoff; 52-55
+ unsigned short usri11_bad_pw_count; 56-57
+ unsigned short usri11_num_logons; 58-59
+ char *usri11_logon_server; 60-63
+ unsigned short usri11_country_code; 64-65
+ char *usri11_workstations; 66-69
+ unsigned long usri11_max_storage; 70-73
+ unsigned short usri11_units_per_week; 74-75
+ unsigned char *usri11_logon_hours; 76-79
+ unsigned short usri11_code_page; 80-81
+ };
+
+where:
+
+ usri11_name specifies the user name for which information is retireved
+
+ usri11_pad aligns the next data structure element to a word boundary
+
+ usri11_comment is a null terminated ASCII comment
+
+ usri11_user_comment is a null terminated ASCII comment about the user
+
+ usri11_priv specifies the level of the privilege assigned to the user.
+ The possible values are:
+
+Name Value Description
+USER_PRIV_GUEST 0 Guest privilege
+USER_PRIV_USER 1 User privilege
+USER_PRV_ADMIN 2 Administrator privilege
+
+ usri11_auth_flags specifies the account operator privileges. The
+ possible values are:
+
+Name Value Description
+AF_OP_PRINT 0 Print operator
+
+
+Leach, Naik [Page 28]\r\f
+
+
+INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
+
+
+AF_OP_COMM 1 Communications operator
+AF_OP_SERVER 2 Server operator
+AF_OP_ACCOUNTS 3 Accounts operator
+
+
+ usri11_password_age specifies how many seconds have elapsed since the
+ password was last changed.
+
+ usri11_home_dir points to a null terminated ASCII string that contains
+ the path name of the user's home directory.
+
+ usri11_parms points to a null terminated ASCII string that is set
+ aside for use by applications.
+
+ usri11_last_logon specifies the time when the user last logged on.
+ This value is stored as the number of seconds elapsed since
+ 00:00:00, January 1, 1970.
+
+ usri11_last_logoff specifies the time when the user last logged off.
+ This value is stored as the number of seconds elapsed since
+ 00:00:00, January 1, 1970. A value of 0 means the last logoff
+ time is unknown.
+
+ usri11_bad_pw_count specifies the number of incorrect passwords
+ entered since the last successful logon.
+
+ usri11_log1_num_logons specifies the number of times this user has
+ logged on. A value of -1 means the number of logons is unknown.
+
+ usri11_logon_server points to a null terminated ASCII string that
+ contains the name of the server to which logon requests are sent.
+ A null string indicates logon requests should be sent to the
+ domain controller.
+
+ usri11_country_code specifies the country code for the user's language
+ of choice.
+
+ usri11_workstations points to a null terminated ASCII string that
+ contains the names of workstations the user may log on from.
+ There may be up to 8 workstations, with the names separated by
+ commas. A null strings indicates there are no restrictions.
+
+ usri11_max_storage specifies the maximum amount of disk space the user
+ can occupy. A value of 0xffffffff indicates there are no
+ restrictions.
+
+ usri11_units_per_week specifies the equal number of time units into
+ which a week is divided. This value must be equal to 168.
+
+ usri11_logon_hours points to a 21 byte (168 bits) string that
+ specifies the time during which the user can log on. Each bit
+ represents one unique hour in a week. The first bit (bit 0, word
+ 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
+
+
+
+Leach, Naik [Page 29]\r\f
+
+
+INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
+
+
+ Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
+ are no restrictions.
+
+ usri11_code_page specifies the code page for the user's language of
+ choice
+
+All of the pointers in this data structure need to be treated
+specially. The pointer is a 32 bit pointer. The higher 16 bits need
+to be ignored. The converter word returned in the parameters section
+needs to be subtracted from the lower 16 bits to calculate an offset
+into the return buffer where this ASCII string resides.
+
+There is no auxiliary data in the response.
+
****************************************************************************/
+#define usri11_name 0
+#define usri11_pad 21
+#define usri11_comment 22
+#define usri11_usr_comment 26
+#define usri11_full_name 30
+#define usri11_priv 34
+#define usri11_auth_flags 36
+#define usri11_password_age 40
+#define usri11_homedir 44
+#define usri11_parms 48
+#define usri11_last_logon 52
+#define usri11_last_logoff 56
+#define usri11_bad_pw_count 60
+#define usri11_num_logons 62
+#define usri11_logon_server 64
+#define usri11_country_code 68
+#define usri11_workstations 70
+#define usri11_max_storage 74
+#define usri11_units_per_week 78
+#define usri11_logon_hours 80
+#define usri11_code_page 84
+#define usri11_end 86
+
#define USER_PRIV_GUEST 0
#define USER_PRIV_USER 1
#define USER_PRIV_ADMIN 2
-static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
+#define AF_OP_PRINT 0
+#define AF_OP_COMM 1
+#define AF_OP_SERVER 2
+#define AF_OP_ACCOUNTS 3
+
+
+static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *UserName = skip_string(str2,1);
- char *p = skip_string(UserName,1);
- int uLevel = SVAL(p,0);
- char *p2;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *UserName = skip_string(str2,1);
+ char *p = skip_string(UserName,1);
+ int uLevel = SVAL(p,0);
+ char *p2;
+
+ /* 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);
+ if(vuser != NULL)
+ DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
+
+ *rparam_len = 6;
+ *rparam = REALLOC(*rparam,*rparam_len);
+
+ DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
+
+ /* check it's a supported variant */
+ if (strcmp(str1,"zWrLh") != 0) return False;
+ switch( uLevel )
+ {
+ case 0: p2 = "B21"; break;
+ case 1: p2 = "B21BB16DWzzWz"; break;
+ case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
+ case 10: p2 = "B21Bzzz"; break;
+ case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
+ default: return False;
+ }
- *rparam_len = 6;
- *rparam = REALLOC(*rparam,*rparam_len);
+ if (strcmp(p2,str2) != 0) return False;
- /* check it's a supported varient */
- if (strcmp(str1,"zWrLh") != 0) return False;
- switch( uLevel ) {
- case 0: p2 = "B21"; break;
- case 1: p2 = "B21BB16DWzzWz"; break;
- case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
- case 10: p2 = "B21Bzzz"; break;
- case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
- default: return False;
- }
- if (strcmp(p2,str2) != 0) return False;
+ *rdata_len = mdrcnt + 1024;
+ *rdata = REALLOC(*rdata,*rdata_len);
- *rdata_len = mdrcnt + 1024;
- *rdata = REALLOC(*rdata,*rdata_len);
+ SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
+ p = *rdata;
+ p2 = p + usri11_end;
- p = *rdata;
- p2 = p + 86;
+ memset(p,0,21);
+ fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
- memset(p,0,21);
- strcpy(p,UserName);
- if (uLevel > 0) {
- SCVAL(p,21,0);
- *p2 = 0;
- if (uLevel >= 10) {
- SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
- strcpy(p2,"<Comment>");
- p2 = skip_string(p2,1);
- SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
- strcpy(p2,"<UserComment>");
- p2 = skip_string(p2,1);
- SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
- strcpy(p2,"<FullName>");
- p2 = skip_string(p2,1);
- }
- if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
- SSVAL(p,34,USER_PRIV_USER); /* user privilege */
- SIVAL(p,36,0); /* auth flags */
- SIVALS(p,40,-1); /* password age */
- SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
- strcpy(p2,"\\\\%L\\HOMES");
- standard_sub_basic(p2);
- p2 = skip_string(p2,1);
- SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
- strcpy(p2,"");
- p2 = skip_string(p2,1);
- SIVAL(p,52,0); /* last logon */
- SIVAL(p,56,0); /* last logoff */
- SSVALS(p,60,-1); /* bad pw counts */
- SSVALS(p,62,-1); /* num logons */
- SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
- strcpy(p2,"\\\\*");
- p2 = skip_string(p2,1);
- SSVAL(p,68,0); /* country code */
-
- SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
- strcpy(p2,"");
- p2 = skip_string(p2,1);
-
- SIVALS(p,74,-1); /* max storage */
- SSVAL(p,78,168); /* units per week */
- SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
- memset(p2,-1,21);
- SCVAL(p2,21,0); /* fix zero termination */
- p2 = skip_string(p2,1);
-
- SSVAL(p,84,0); /* code page */
- }
- if (uLevel == 1 || uLevel == 2) {
- memset(p+22,' ',16); /* password */
- SIVALS(p,38,-1); /* password age */
- SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
- SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
- strcpy(p2,"\\\\%L\\HOMES");
- standard_sub_basic(p2);
- p2 = skip_string(p2,1);
- SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
- *p2++ = 0;
- SSVAL(p,52,0); /* flags */
- SIVAL(p,54,0); /* script_path */
- if (uLevel == 2) {
- SIVAL(p,60,0); /* auth_flags */
- SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
- strcpy(p2,"<Full Name>");
- p2 = skip_string(p2,1);
- SIVAL(p,68,0); /* urs_comment */
- SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
- strcpy(p2,"");
- p2 = skip_string(p2,1);
- SIVAL(p,76,0); /* workstations */
- SIVAL(p,80,0); /* last_logon */
- SIVAL(p,84,0); /* last_logoff */
- SIVALS(p,88,-1); /* acct_expires */
- SIVALS(p,92,-1); /* max_storage */
- SSVAL(p,96,168); /* units_per_week */
- SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
- memset(p2,-1,21);
- p2 += 21;
- SSVALS(p,102,-1); /* bad_pw_count */
- SSVALS(p,104,-1); /* num_logons */
- SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
- strcpy(p2,"\\\\%L");
- standard_sub_basic(p2);
- p2 = skip_string(p2,1);
- SSVAL(p,110,49); /* country_code */
- SSVAL(p,112,860); /* code page */
- }
- }
- }
+ if (uLevel > 0)
+ {
+ SCVAL(p,usri11_pad,0); /* padding - 1 byte */
+ *p2 = 0;
+ }
+ if (uLevel >= 10)
+ {
+ SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
+ strcpy(p2,"Comment");
+ p2 = skip_string(p2,1);
+
+ SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
+ strcpy(p2,"UserComment");
+ p2 = skip_string(p2,1);
+
+ /* EEK! the cifsrap.txt doesn't have this in!!!! */
+ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
+ strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
+ p2 = skip_string(p2,1);
+ }
- *rdata_len = PTR_DIFF(p2,*rdata);
+ if (uLevel == 11) /* modelled after NTAS 3.51 reply */
+ {
+ SSVAL(p,usri11_priv,Connections[cnum].admin_user?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 */
+ strcpy(p2, lp_logon_path());
+ p2 = skip_string(p2,1);
+ SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
+ strcpy(p2,"");
+ p2 = skip_string(p2,1);
+ SIVAL(p,usri11_last_logon,0); /* last logon */
+ SIVAL(p,usri11_last_logoff,0); /* last logoff */
+ 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 */
+ strcpy(p2,"\\\\*");
+ p2 = skip_string(p2,1);
+ SSVAL(p,usri11_country_code,0); /* country code */
+
+ SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
+ strcpy(p2,"");
+ p2 = skip_string(p2,1);
+
+ SIVALS(p,usri11_max_storage,-1); /* max storage */
+ SSVAL(p,usri11_units_per_week,168); /* units per week */
+ SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
+
+ /* a simple way to get logon hours at all times. */
+ memset(p2,0xff,21);
+ SCVAL(p2,21,0); /* fix zero termination */
+ p2 = skip_string(p2,1);
+
+ SSVAL(p,usri11_code_page,0); /* code page */
+ }
+ if (uLevel == 1 || uLevel == 2)
+ {
+ memset(p+22,' ',16); /* password */
+ SIVALS(p,38,-1); /* password age */
+ SSVAL(p,42,
+ Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+ SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
+ strcpy(p2,lp_logon_path());
+ p2 = skip_string(p2,1);
+ SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
+ *p2++ = 0;
+ SSVAL(p,52,0); /* flags */
+ SIVAL(p,54,0); /* script_path */
+ if (uLevel == 2)
+ {
+ SIVAL(p,60,0); /* auth_flags */
+ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
+ strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
+ p2 = skip_string(p2,1);
+ SIVAL(p,68,0); /* urs_comment */
+ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
+ strcpy(p2,"");
+ p2 = skip_string(p2,1);
+ SIVAL(p,76,0); /* workstations */
+ SIVAL(p,80,0); /* last_logon */
+ SIVAL(p,84,0); /* last_logoff */
+ SIVALS(p,88,-1); /* acct_expires */
+ SIVALS(p,92,-1); /* max_storage */
+ SSVAL(p,96,168); /* units_per_week */
+ SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
+ memset(p2,-1,21);
+ p2 += 21;
+ SSVALS(p,102,-1); /* bad_pw_count */
+ SSVALS(p,104,-1); /* num_logons */
+ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
+ strcpy(p2,"\\\\%L");
+ standard_sub_basic(p2);
+ p2 = skip_string(p2,1);
+ SSVAL(p,110,49); /* country_code */
+ SSVAL(p,112,860); /* code page */
+ }
+ }
- SSVAL(*rparam,4,*rdata_len); /* is this right?? */
+ *rdata_len = PTR_DIFF(p2,*rdata);
- return(True);
-}
+ SSVAL(*rparam,4,*rdata_len); /* is this right?? */
+ return(True);
+}
/*******************************************************************
get groups that a user is a member of
******************************************************************/
-static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
+static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
}
-static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
+static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
int uLevel;
struct pack_desc desc;
char* name;
+ char* logon_script;
uLevel = SVAL(p,0);
name = p + 2;
desc.subformat = NULL;
desc.format = str2;
-
-
- if (init_package(&desc,1,0)) {
+ if (init_package(&desc,1,0))
+ {
PACKI(&desc,"W",0); /* code */
PACKS(&desc,"B21",name); /* eff. name */
PACKS(&desc,"B",""); /* pad */
PACKI(&desc,"D",0); /* auth flags XXX */
PACKI(&desc,"W",0); /* num logons */
PACKI(&desc,"W",0); /* bad pw count */
- PACKI(&desc,"D",-1); /* last logon */
+ PACKI(&desc,"D",0); /* last logon */
PACKI(&desc,"D",-1); /* last logoff */
PACKI(&desc,"D",-1); /* logoff time */
PACKI(&desc,"D",-1); /* kickoff time */
strupper(mypath);
PACKS(&desc,"z",mypath); /* computer */
}
- PACKS(&desc,"z",my_workgroup());/* domain */
- PACKS(&desc,"z",lp_logon_script()); /* script path */
- PACKI(&desc,"D",0); /* reserved */
+ PACKS(&desc,"z",myworkgroup);/* domain */
+
+/* JHT - By calling lp_logon_script() and standard_sub() we have */
+/* made sure all macros are fully substituted and available */
+ logon_script = lp_logon_script();
+ standard_sub( cnum, logon_script );
+ PACKS(&desc,"z", logon_script); /* script path */
+/* End of JHT mods */
+
+ PACKI(&desc,"D",0x00000000); /* reserved */
}
*rdata_len = desc.usedlen;
/****************************************************************************
api_WAccessGetUserPerms
****************************************************************************/
-static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
+static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
/****************************************************************************
api_WPrintJobEnumerate
****************************************************************************/
-static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
char *str1 = param+2;
char *str2 = skip_string(str1,1);
char *p = skip_string(str2,1);
- int uJobId = SVAL(p,0);
int uLevel,cbBuf;
int count;
int i;
bzero(&desc,sizeof(desc));
bzero(&status,sizeof(status));
- DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
+ DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
/* check it's a supported varient */
if (strcmp(str1,"WWrLh") != 0) return False;
if (!check_printjob_info(&desc,uLevel,str2)) return False;
- snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
- job = uJobId & 0xFF;
+ printjob_decode(SVAL(p,0), &snum, &job);
if (snum < 0 || !VALID_SNUM(snum)) return(False);
count = get_printqueue(snum,cnum,&queue,&status);
for (i = 0; i < count; i++) {
- if ((queue[i].job % 0xFF) == job) break;
+ if ((queue[i].job & 0xFF) == job) break;
}
if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
desc.base = *rdata;
return(True);
}
-static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
struct pack_desc* desc)
{
char buf[100];
- strcpy(buf,SERVICE(snum));
+ strncpy(buf,SERVICE(snum),sizeof(buf)-1);
+ buf[sizeof(buf)-1] = 0;
strupper(buf);
if (uLevel <= 1) {
PACKS(desc,"B9",buf); /* szName */
}
}
-static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
return(True);
}
-static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
return(True);
}
-static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
return(True);
}
-static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
return(True);
}
-static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
+static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
return(True);
}
+struct api_cmd
+{
+ char * pipe_clnt_name;
+ char * pipe_srv_name;
+ BOOL (*fn) (pipes_struct *, prs_struct *);
+};
+
+static struct api_cmd api_fd_commands[] =
+{
+ { "lsarpc", "lsass", api_ntlsa_rpc },
+ { "samr", "lsass", api_samr_rpc },
+ { "srvsvc", "ntsvcs", api_srvsvc_rpc },
+ { "wkssvc", "ntsvcs", api_wkssvc_rpc },
+ { "NETLOGON", "lsass", api_netlog_rpc },
+ { "winreg", "winreg", api_reg_rpc },
+ { NULL, NULL, NULL }
+};
+
+static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
+{
+ BOOL ntlmssp_auth = False;
+ fstring ack_pipe_name;
+ int i = 0;
+
+ DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
+
+ for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
+ {
+ if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
+ api_fd_commands[i].fn != NULL)
+ {
+ DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
+ api_fd_commands[i].pipe_clnt_name,
+ api_fd_commands[i].pipe_srv_name));
+ fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
+ break;
+ }
+ }
+
+ if (api_fd_commands[i].fn == NULL) return False;
+
+ /* decode the bind request */
+ smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
+
+ if (pd->offset == 0) return False;
+
+ if (p->hdr.auth_len != 0)
+ {
+ /* decode the authentication verifier */
+ smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
+
+ if (pd->offset == 0) return False;
+
+ /* ignore the version number for now */
+ ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
+ }
+
+ /* name has to be \PIPE\xxxxx */
+ strcpy(ack_pipe_name, "\\PIPE\\");
+ strcat(ack_pipe_name, p->pipe_srv_name);
+
+ DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
+
+ prs_init(&(p->rdata), 1024, 4, 0, False);
+ prs_init(&(p->rhdr ), 0x10, 4, 0, False);
+ prs_init(&(p->rauth), 1024, 4, 0, False);
+
+ /***/
+ /*** do the bind ack first ***/
+ /***/
+
+ make_rpc_hdr_ba(&p->hdr_ba,
+ p->hdr_rb.bba.max_tsize,
+ p->hdr_rb.bba.max_rsize,
+ p->hdr_rb.bba.assoc_gid,
+ ack_pipe_name,
+ 0x1, 0x0, 0x0,
+ &(p->hdr_rb.transfer));
+
+ smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
+ mem_realloc_data(p->rdata.data, p->rdata.offset);
+
+ /***/
+ /*** now the authentication ***/
+ /***/
+
+ if (ntlmssp_auth)
+ {
+ uint8 data[16];
+ bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
+
+ make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
+ 0x0a, 0x06, 0,
+ "NTLMSSP", 2,
+ 0x00000000, 0x0000b2b3, 0x000082b1,
+ data);
+ smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
+ mem_realloc_data(p->rauth.data, p->rauth.offset);
+ }
+
+ /***/
+ /*** then do the header, now we know the length ***/
+ /***/
+
+ make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
+ p->hdr.call_id,
+ p->rdata.offset + p->rauth.offset,
+ p->rauth.offset);
+
+ smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
+ mem_realloc_data(p->rhdr.data, p->rdata.offset);
+
+ /***/
+ /*** link rpc header, bind acknowledgment and authentication responses ***/
+ /***/
+
+ p->rhdr.data->offset.start = 0;
+ p->rhdr.data->offset.end = p->rhdr.offset;
+ p->rhdr.data->next = p->rdata.data;
+
+ if (ntlmssp_auth)
+ {
+ p->rdata.data->offset.start = p->rhdr.offset;
+ p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
+ p->rdata.data->next = p->rauth.data;
+
+ p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
+ p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
+ p->rauth.data->next = NULL;
+ }
+ else
+ {
+ p->rdata.data->offset.start = p->rhdr.offset;
+ p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
+ p->rdata.data->next = NULL;
+ }
+
+ return True;
+}
+
+static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
+{
+ int i = 0;
+
+ for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
+ {
+ if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
+ api_fd_commands[i].fn != NULL)
+ {
+ DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
+ return api_fd_commands[i].fn(p, pd);
+ }
+ }
+ return False;
+}
+
+static BOOL api_dce_rpc_command(char *outbuf,
+ pipes_struct *p,
+ prs_struct *pd)
+{
+ BOOL reply = False;
+ if (pd->data == NULL) return False;
+
+ /* process the rpc header */
+ smb_io_rpc_hdr("", &p->hdr, pd, 0);
+
+ if (pd->offset == 0) return False;
+
+ switch (p->hdr.pkt_type)
+ {
+ case RPC_BIND :
+ {
+ reply = api_pipe_bind_req(p, pd);
+ break;
+ }
+ case RPC_REQUEST:
+ {
+ reply = api_pipe_request (p, pd);
+ break;
+ }
+ }
+
+ if (reply)
+ {
+ /* now send the reply */
+ send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
+
+ if (mem_buf_len(p->rhdr.data) <= p->file_offset)
+ {
+ /* all of data was sent: no need to wait for SMBreadX calls */
+ mem_free_data(p->rhdr .data);
+ mem_free_data(p->rdata.data);
+ }
+ }
+
+ return reply;
+}
+
+/****************************************************************************
+ SetNamedPipeHandleState
+****************************************************************************/
+static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
+{
+ uint16 id;
+
+ if (!param) return False;
+
+ id = param[0] + (param[1] << 8);
+ DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
+
+ if (set_rpc_pipe_hnd_state(p, id))
+ {
+ /* now send the reply */
+ send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
+
+ return True;
+ }
+ return False;
+}
+
+
+/****************************************************************************
+ when no reply is generated, indicate unsupported.
+ ****************************************************************************/
+static BOOL api_no_reply(char *outbuf, int max_rdata_len)
+{
+ struct mem_buf rparam;
+
+ mem_init(&rparam, 0);
+ mem_alloc_data(&rparam, 4);
+
+ rparam.offset.start = 0;
+ rparam.offset.end = 4;
+
+ /* unsupported */
+ SSVAL(rparam.data,0,NERR_notsupported);
+ SSVAL(rparam.data,2,0); /* converter word */
+
+ DEBUG(3,("Unsupported API fd command\n"));
+
+ /* now send the reply */
+ send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
+
+ mem_free_data(&rparam);
+
+ return(-1);
+}
+
+/****************************************************************************
+ handle remote api calls delivered to a named pipe already opened.
+ ****************************************************************************/
+static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
+ uint16 *setup,char *data,char *params,
+ int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
+{
+ BOOL reply = False;
+
+ int pnum;
+ int subcommand;
+ pipes_struct *p = NULL;
+ prs_struct pd;
+ struct mem_buf data_buf;
+
+ DEBUG(5,("api_fd_reply\n"));
+
+ /* fake up a data buffer from the api_fd_reply data parameters */
+ mem_create(&data_buf, data, tdscnt, 0, False);
+ data_buf.offset.start = 0;
+ data_buf.offset.end = tdscnt;
+
+ /* fake up a parsing structure */
+ pd.data = &data_buf;
+ pd.align = 4;
+ pd.io = True;
+ pd.offset = 0;
+
+ /* First find out the name of this file. */
+ if (suwcnt != 2)
+ {
+ DEBUG(0,("Unexpected named pipe transaction.\n"));
+ return(-1);
+ }
+
+ /* Get the file handle and hence the file name. */
+ pnum = setup[1];
+ subcommand = setup[0];
+ get_rpc_pipe(pnum, &p);
+
+ if (p != NULL)
+ {
+ DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
+ subcommand, p->name, pnum));
+ DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
+ tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
+
+ /* record maximum data length that can be transmitted in an SMBtrans */
+ p->file_offset = mdrcnt;
+
+ DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
+ p, p->file_offset));
+
+ switch (subcommand)
+ {
+ case 0x26:
+ {
+ /* dce/rpc command */
+ reply = api_dce_rpc_command(outbuf, p, &pd);
+ break;
+ }
+ case 0x01:
+ {
+ /* Set Named Pipe Handle state */
+ reply = api_SNPHS(outbuf, p, params);
+ break;
+ }
+ }
+ }
+ else
+ {
+ DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
+ }
+
+ if (!reply)
+ {
+ return api_no_reply(outbuf, mdrcnt);
+ }
+ return -1;
+}
+
/****************************************************************************
the buffer was too small
****************************************************************************/
-static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
+static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
/****************************************************************************
the request is not supported
****************************************************************************/
-static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
+static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
char *name;
int id;
- BOOL (*fn)();
+ BOOL (*fn)(int,uint16,char *,char *,int,int,char **,char **,int *,int *);
int flags;
} api_commands[] = {
{"RNetShareEnum", 0, api_RNetShareEnum,0},
{"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
{"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
+ {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
{"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
{"NetUserGetGroups", 59, api_NetUserGetGroups,0},
{"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
{"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
{"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
{"WPrintPortEnum", 207, api_WPrintPortEnum,0},
+ {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
{NULL, -1, api_Unsupported,0}};
/****************************************************************************
handle remote api calls
****************************************************************************/
-static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
+static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
{
int api_command = SVAL(params,0);
+ struct mem_buf rdata_buf;
+ struct mem_buf rparam_buf;
char *rdata = NULL;
char *rparam = NULL;
int rdata_len = 0;
rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
- reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
+ reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
if (rdata_len > mdrcnt ||
rparam_len > mprcnt)
{
- reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
+ reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
}
/* if we get False back then it's actually unsupported */
if (!reply)
- api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
+ api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
+ mem_create(&rdata_buf , rdata , rdata_len , 0, False);
+ mem_create(&rparam_buf, rparam, rparam_len, 0, False);
+
+ rdata_buf.offset.start = 0;
+ rdata_buf.offset.end = rdata_len;
+
+ rparam_buf.offset.start = 0;
+ rparam_buf.offset.end = rparam_len;
/* now send the reply */
- send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
+ send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
- if (rdata)
- free(rdata);
- if (rparam)
- free(rparam);
+ if (rdata ) free(rdata);
+ if (rparam) free(rparam);
return(-1);
}
/****************************************************************************
handle named pipe commands
****************************************************************************/
-static int named_pipe(int cnum,int uid, char *outbuf,char *name,
+static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
uint16 *setup,char *data,char *params,
int suwcnt,int tdscnt,int tpscnt,
int msrcnt,int mdrcnt,int mprcnt)
{
+ DEBUG(3,("named pipe command on <%s> name\n", name));
+
+ if (strequal(name,"LANMAN"))
+ {
+ return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
+ }
- if (strequal(name,"LANMAN"))
- return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
+ if (strlen(name) < 1)
+ {
+ return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
+ }
- DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
- name,(int)setup[0],(int)setup[1]));
-
- return(0);
+ if (setup)
+ {
+ DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
+ }
+
+ return 0;
}
/****************************************************************************
reply to a SMBtrans
****************************************************************************/
-int reply_trans(char *inbuf,char *outbuf)
+int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
{
fstring name;
int outsize = 0;
int cnum = SVAL(inbuf,smb_tid);
- int uid = SVAL(inbuf,smb_uid);
+ uint16 vuid = SVAL(inbuf,smb_uid);
int tpscnt = SVAL(inbuf,smb_vwv0);
int tdscnt = SVAL(inbuf,smb_vwv1);
int dsoff = SVAL(inbuf,smb_vwv12);
int suwcnt = CVAL(inbuf,smb_vwv13);
- StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
+ bzero(name, sizeof(name));
+ fstrcpy(name,smb_buf(inbuf));
+
+ if (dscnt > tdscnt || pscnt > tpscnt) {
+ exit_server("invalid trans parameters\n");
+ }
if (tdscnt)
{
/* receive the rest of the trans packet */
while (pscnt < tpscnt || dscnt < tdscnt)
{
+ BOOL ret;
int pcnt,poff,dcnt,doff,pdisp,ddisp;
- if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
- CVAL(inbuf, smb_com) != SMBtrans)
+ ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
+
+ if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
{
- DEBUG(2,("Invalid secondary trans2 packet\n"));
+ if(ret)
+ DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
+ else
+ DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
+ (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
if (params) free(params);
if (data) free(data);
if (setup) free(setup);
pscnt += pcnt;
dscnt += dcnt;
+ if (dscnt > tdscnt || pscnt > tpscnt) {
+ exit_server("invalid trans parameters\n");
+ }
+
if (pcnt)
memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
if (dcnt)
DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
-
if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
- outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
+ {
+ DEBUG(5,("calling named_pipe\n"));
+ outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
+ }
+ else
+ {
+ DEBUG(3,("invalid pipe name\n"));
+ outsize = 0;
+ }
if (data) free(data);
if (setup) free(setup);
if (close_on_completion)
- close_cnum(cnum,uid);
+ close_cnum(cnum,vuid);
if (one_way)
return(-1);
return(outsize);
}
-
-