diff options
Diffstat (limited to 'source3/smbd/ipc.c')
-rw-r--r-- | source3/smbd/ipc.c | 3013 |
1 files changed, 377 insertions, 2636 deletions
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 8852e57e8b..c2f3b7b2f0 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -1,8 +1,10 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. 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 @@ -24,2756 +26,495 @@ */ #include "includes.h" -#include "loadparm.h" -#include "pcap.h" - -#ifdef CHECK_TYPES -#undef CHECK_TYPES -#endif -#define CHECK_TYPES 0 -extern int DEBUGLEVEL; -extern int maxxmit; -extern files_struct Files[]; -extern connection_struct Connections[]; +extern int max_send; extern fstring local_machine; -#define NERR_Success 0 -#define NERR_badpass 86 #define NERR_notsupported 50 -#define NERR_BASE (2100) -#define NERR_BufTooSmall (NERR_BASE+23) -#define NERR_JobNotFound (NERR_BASE+51) -#define NERR_DestNotFound (NERR_BASE+52) -#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 SHPWLEN 8 /* share password length */ -#define NNLEN 12 /* 8.3 net name length */ -#define SNLEN 15 /* service name length */ -#define QNLEN 12 /* queue name maximum length */ - -extern int Client; - -static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) -{ - pstring buf; - int l; - - if (!src || !dst || !n || !(*dst)) return(0); - - StrnCpy(buf,src,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - StrnCpy(*dst,buf,*n); - l = strlen(*dst) + 1; - (*dst) += l; - (*n) -= l; - return l; -} - -static int CopyAndAdvance(char** dst, char* src, int* n) -{ - int l; - if (!src || !dst || !n || !(*dst)) return(0); - StrnCpy(*dst,src,*n); - l = strlen(*dst) + 1; - (*dst) += l; - (*n) -= l; - return l; -} - -static int StrlenExpanded(int cnum, int snum, char* s) -{ - pstring buf; - if (!s) return(0); - StrnCpy(buf,s,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - return strlen(buf) + 1; -} - -static char* Expand(int cnum, int snum, char* s) -{ - static pstring buf; - if (!s) return(NULL); - StrnCpy(buf,s,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - return &buf[0]; -} +extern int smb_read_error; /******************************************************************* - check a API string for validity when we only need to check the prefix - ******************************************************************/ -static BOOL prefix_ok(char *str,char *prefix) -{ - 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 -/**************************************************************************** - send a trans reply - ****************************************************************************/ -static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup) -{ - 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)); - - align = (this_lparam%4); - - 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); - - 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; - } -} - + ******************************************************************/ - -/**************************************************************************** - get a print queue - ****************************************************************************/ - -struct pack_desc { - char* format; /* formatstring for structure */ - char* subformat; /* subformat for structure */ - char* base; /* baseaddress of buffer */ - int buflen; /* remaining size for fixed part; on init: length of base */ - int subcount; /* count of substructures */ - char* structbuf; /* pointer into buffer for remaining fixed part */ - int stringlen; /* remaining size for variable part */ - char* stringbuf; /* pointer into buffer for remaining variable part */ - int neededlen; /* total needed size */ - int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */ - char* curpos; /* current position; pointer into format or subformat */ - int errcode; -}; - -static int get_counter(char** p) +static void copy_trans_params_and_data(char *outbuf, int align, + char *rparam, int param_offset, int param_len, + char *rdata, int data_offset, int data_len) { - int i, n; - if (!p || !(*p)) return(1); - if (!isdigit(**p)) return 1; - for (n = 0;;) { - i = **p; - if (isdigit(i)) - n = 10 * n + (i - '0'); - else - return n; - (*p)++; - } -} + char *copy_into = smb_buf(outbuf)+1; -static int getlen(char* p) -{ - int n = 0; - if (!p) return(0); - while (*p) { - switch( *p++ ) { - case 'W': /* word (2 byte) */ - n += 2; - break; - case 'N': /* count of substructures (word) at end */ - n += 2; - break; - case 'D': /* double word (4 byte) */ - case 'z': /* offset to zero terminated string (4 byte) */ - case 'l': /* offset to user data (4 byte) */ - n += 4; - break; - case 'b': /* offset to data (with counter) (4 byte) */ - n += 4; - get_counter(&p); - break; - case 'B': /* byte (with optional counter) */ - n += get_counter(&p); - break; - } - } - return n; -} + if(param_len < 0) + param_len = 0; -static BOOL init_package(struct pack_desc* p, int count, int subcount) -{ - int n = p->buflen; - int i; - - if (!p->format || !p->base) return(False); - - i = count * getlen(p->format); - if (p->subformat) i += subcount * getlen(p->subformat); - p->structbuf = p->base; - p->neededlen = 0; - p->usedlen = 0; - p->subcount = 0; - p->curpos = p->format; - if (i > n) { - i = n = 0; - p->errcode = NERR_BufTooSmall; - } - - p->errcode = NERR_Success; - p->buflen = i; - n -= i; - p->stringbuf = p->base + i; - p->stringlen = n; - return(p->errcode == NERR_Success); -} - -#ifdef __STDC__ -static int package(struct pack_desc* p, ...) -{ -#else -static int package(va_alist) -va_dcl -{ - struct pack_desc* p; -#endif - va_list args; - int needed=0, stringneeded; - char* str=NULL; - int is_string=0, stringused; - int32 temp; - -#ifdef __STDC__ - va_start(args,p); -#else - va_start(args); - p = va_arg(args,struct pack_desc *); -#endif - - if (!*p->curpos) { - if (!p->subcount) - p->curpos = p->format; - else { - p->curpos = p->subformat; - p->subcount--; - } - } -#if CHECK_TYPES - str = va_arg(args,char*); - if (strncmp(str,p->curpos,strlen(str)) != 0) { - DEBUG(2,("type error in package: %s instead of %*s\n",str, - strlen(str),p->curpos)); - va_end(args); -#if AJT - ajt_panic(); -#endif - return 0; - } -#endif - stringneeded = -1; - - if (!p->curpos) return(0); - - switch( *p->curpos++ ) { - case 'W': /* word (2 byte) */ - needed = 2; - temp = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); - break; - case 'N': /* count of substructures (word) at end */ - needed = 2; - p->subcount = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount); - break; - case 'D': /* double word (4 byte) */ - needed = 4; - temp = va_arg(args,int); - if (p->buflen >= needed) SIVAL(p->structbuf,0,temp); - break; - case 'B': /* byte (with optional counter) */ - needed = get_counter(&p->curpos); - { - char *s = va_arg(args,char*); - if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed); - } - break; - case 'z': /* offset to zero terminated string (4 byte) */ - str = va_arg(args,char*); - stringneeded = (str ? strlen(str)+1 : 0); - is_string = 1; - break; - case 'l': /* offset to user data (4 byte) */ - str = va_arg(args,char*); - stringneeded = va_arg(args,int); - is_string = 0; - break; - case 'b': /* offset to data (with counter) (4 byte) */ - str = va_arg(args,char*); - stringneeded = get_counter(&p->curpos); - is_string = 0; - break; - } - va_end(args); - if (stringneeded >= 0) { - needed = 4; - if (p->buflen >= needed) { - stringused = stringneeded; - if (stringused > p->stringlen) { - stringused = (is_string ? p->stringlen : 0); - if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA; - } - if (!stringused) - SIVAL(p->structbuf,0,0); - else { - SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base)); - memcpy(p->stringbuf,str?str:"",stringused); - if (is_string) p->stringbuf[stringused-1] = '\0'; - p->stringbuf += stringused; - p->stringlen -= stringused; - p->usedlen += stringused; - } - } - p->neededlen += stringneeded; - } - p->neededlen += needed; - if (p->buflen >= needed) { - p->structbuf += needed; - p->buflen -= needed; - p->usedlen += needed; - } - else { - if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall; - } - return 1; -} + if(data_len < 0) + data_len = 0; -#if CHECK_TYPES -#define PACK(desc,t,v) package(desc,t,v,0,0,0,0) -#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0) -#else -#define PACK(desc,t,v) package(desc,v) -#define PACKl(desc,t,v,l) package(desc,v,l) -#endif + 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)); -static void PACKI(struct pack_desc* desc,char *t,int v) -{ - PACK(desc,t,v); -} + if (param_len) + memcpy(copy_into, &rparam[param_offset], param_len); -static void PACKS(struct pack_desc* desc,char *t,char *v) -{ - PACK(desc,t,v); -} + copy_into += param_len + align; -static void PackDriverData(struct pack_desc* desc) -{ - char drivdata[4+4+32]; - SIVAL(drivdata,0,sizeof drivdata); /* cb */ - SIVAL(drivdata,4,1000); /* lVersion */ - memset(drivdata+8,0,32); /* szDeviceName */ - strcpy(drivdata+8,"NULL"); - PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ + if (data_len ) + memcpy(copy_into, &rdata[data_offset], data_len); } -static int check_printq_info(struct pack_desc* desc, - int uLevel, const char* id1, const char* id2) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: - desc->format = "B13"; - break; - case 1: - desc->format = "B13BWWWzzzzzWW"; - break; - case 2: - desc->format = "B13BWWWzzzzzWN"; - desc->subformat = "WB21BB16B10zWWzDDz"; - break; - case 3: - desc->format = "zWWWWzzzzWWzzl"; - break; - case 4: - desc->format = "zWWWWzzzzWNzzl"; - desc->subformat = "WWzWWDDzz"; - break; - case 5: - desc->format = "z"; - break; - default: return False; - } - if (strcmp(desc->format,id1) != 0) return False; - if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False; - return True; -} - -static void fill_printjob_info(int cnum, int snum, int uLevel, - struct pack_desc* desc, - print_queue_struct* queue, int n) -{ - time_t t = queue->time; - - /* the client expects localtime */ - t += GMT_TO_LOCAL*TimeDiff(t); - - PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */ - if (uLevel == 1) { - PACKS(desc,"B21",queue->user); /* szUserName */ - PACKS(desc,"B",""); /* pad */ - PACKS(desc,"B16",""); /* szNotifyName */ - PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ - PACKS(desc,"z",""); /* pszParms */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",queue->status); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",queue->time); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z",queue->file); /* pszComment */ - } - if (uLevel == 2 || uLevel == 3) { - PACKI(desc,"W",queue->priority); /* uPriority */ - PACKS(desc,"z",queue->user); /* pszUserName */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",queue->status); /* fsStatus */ - PACKI(desc,"D",queue->time); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z","Samba"); /* pszComment */ - PACKS(desc,"z",queue->file); /* pszDocument */ - if (uLevel == 3) { - PACKS(desc,"z",""); /* pszNotifyName */ - PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ - PACKS(desc,"z",""); /* pszParms */ - PACKS(desc,"z",""); /* pszStatus */ - PACKS(desc,"z",SERVICE(snum)); /* pszQueue */ - PACKS(desc,"z","lpd"); /* pszQProcName */ - PACKS(desc,"z",""); /* pszQProcParms */ - PACKS(desc,"z","NULL"); /* pszDriverName */ - PackDriverData(desc); /* pDriverData */ - PACKS(desc,"z",""); /* pszPrinterName */ - } - } -} - -static void fill_printq_info(int cnum, int snum, int uLevel, - struct pack_desc* desc, - 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))); - } - if (uLevel == 1 || uLevel == 2) { - PACKS(desc,"B",""); /* alignment */ - PACKI(desc,"W",5); /* priority */ - PACKI(desc,"W",0); /* start time */ - PACKI(desc,"W",0); /* until time */ - PACKS(desc,"z",""); /* pSepFile */ - PACKS(desc,"z","lpd"); /* pPrProc */ - PACKS(desc,"z",SERVICE(snum)); /* pDestinations */ - PACKS(desc,"z",""); /* pParms */ - if (snum < 0) { - PACKS(desc,"z","UNKNOWN PRINTER"); - PACKI(desc,"W",LPSTAT_ERROR); - } - else if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); - PACKI(desc,"W",LPSTAT_OK); /* status */ - } else { - PACKS(desc,"z",status->message); - PACKI(desc,"W",status->status); /* status */ - } - PACKI(desc,(uLevel == 1 ? "W" : "N"),count); - } - if (uLevel == 3 || uLevel == 4) { - PACKI(desc,"W",5); /* uPriority */ - PACKI(desc,"W",0); /* uStarttime */ - PACKI(desc,"W",0); /* uUntiltime */ - PACKI(desc,"W",5); /* pad1 */ - PACKS(desc,"z",""); /* pszSepFile */ - PACKS(desc,"z","lpd"); /* pszPrProc */ - PACKS(desc,"z",""); /* pszParms */ - if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */ - PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ - } else { - PACKS(desc,"z",status->message); /* pszComment */ - PACKI(desc,"W",status->status); /* fsStatus */ - } - PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ - PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ - PACKS(desc,"z","NULL"); /* pszDriverName */ - PackDriverData(desc); /* pDriverData */ - } - if (uLevel == 2 || uLevel == 4) { - int i; - 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)); -} - -static BOOL api_DosPrintQGetInfo(int cnum,int uid, 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); - char *QueueName = p; - int uLevel,cbBuf; - int count=0; - int snum; - char* str3; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - bzero(&status,sizeof(status)); - bzero(&desc,sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - str3 = p + 4; - - if ((p = strchr(QueueName,'%'))) *p = 0; - - DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName)); - - /* check it's a supported varient */ - if (!prefix_ok(str1,"zWrLh")) return False; - if (!check_printq_info(&desc,uLevel,str2,str3)) return False; - - snum = lp_servicenumber(QueueName); - if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(QueueName,pnum); - snum = lp_servicenumber(QueueName); - } - } - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = get_printqueue(snum,cnum,&queue,&status); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,count)) { - desc.subcount = count; - fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status); - } - - *rdata_len = desc.usedlen; - - *rparam_len = 6; - *rparam = REALLOC(*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)); - - if (queue) free(queue); - - return(True); -} - - /**************************************************************************** - view list of all print jobs on all queues - ****************************************************************************/ -static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data, - int mdrcnt, int mprcnt, - char **rdata, char** rparam, - int *rdata_len, int *rparam_len) -{ - char *param_format = param+2; - char *output_format1 = skip_string(param_format,1); - char *p = skip_string(output_format1,1); - int uLevel = SVAL(p,0); - char *output_format2 = p + 4; - int services = lp_numservices(); - int i, n; - struct pack_desc desc; - print_queue_struct **queue = NULL; - print_status_struct *status = NULL; - int* subcntarr = NULL; - int queuecnt, subcnt=0, succnt=0; - - bzero(&desc,sizeof(desc)); - - DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); - - if (prefix_ok(param_format,"WrLeh")) return False; - if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) - return False; - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - if (uLevel > 0) { - queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*)); - memset(queue,0,queuecnt*sizeof(print_queue_struct*)); - status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct)); - memset(status,0,queuecnt*sizeof(print_status_struct)); - subcntarr = (int*)malloc(queuecnt*sizeof(int)); - subcnt = 0; - n = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]); - subcnt += subcntarr[n]; - n++; - } - } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,queuecnt,subcnt)) { - n = 0; - succnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } - - if (subcntarr) free(subcntarr); - - *rdata_len = desc.usedlen; - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,queuecnt); - - for (i = 0; i < queuecnt; i++) { - if (queue && queue[i]) free(queue[i]); - } - - if (queue) free(queue); - if (status) free(status); - - return True; -} + Send a trans reply. + ****************************************************************************/ -/**************************************************************************** - get info level for a server list query - ****************************************************************************/ -static BOOL check_server_info(int uLevel, char* id) +void send_trans_reply(char *outbuf, + char *rparam, int rparam_len, + char *rdata, int rdata_len, + BOOL buffer_too_large) { - switch( uLevel ) { - case 0: - if (strcmp(id,"B16") != 0) return False; - break; - case 1: - if (strcmp(id,"B16BBDz") != 0) return False; - break; - default: - return False; - } - return True; -} + int this_ldata,this_lparam; + int tot_data_sent = 0; + int tot_param_sent = 0; + int align; -/* 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 */ -}; + int ldata = rdata ? rdata_len : 0; + int lparam = rparam ? rparam_len : 0; -/******************************************************************* - filter out unwanted server info - ******************************************************************/ -static BOOL filter_server_info(struct srv_info_struct *server, - char *domain) -{ - if (*domain) - return(strequal(domain, server->domain)); - - return (True); /* be indiscriminate: get all servers! */ -} + if (buffer_too_large) + DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata )); -/******************************************************************* - find server in the files saved by nmbd. Return True if we find it. - ******************************************************************/ -static BOOL find_server(struct srv_info_struct *servers, int num_servers, - char *domain, char *name) -{ - int count; + this_lparam = MIN(lparam,max_send - 500); /* hack */ + this_ldata = MIN(ldata,max_send - (500+this_lparam)); - if (!servers || num_servers == 0) return (False); + align = ((this_lparam)%4); - for (count = 0; count < num_servers; count++) { - struct srv_info_struct *s; + if (buffer_too_large) { + ERROR_NT(STATUS_BUFFER_OVERFLOW); + } - s = &servers[count]; + set_message(outbuf,10,1+align+this_ldata+this_lparam,True); - if (strequal(name, s->name)) { - StrnCpy(domain, s->domain, sizeof(pstring)-1); - return (True); - } - } - return (False); -} + copy_trans_params_and_data(outbuf, align, + rparam, tot_param_sent, this_lparam, + rdata, tot_data_sent, 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)+1,outbuf)); + SSVAL(outbuf,smb_vwv5,0); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,0); + SSVAL(outbuf,smb_vwv9,0); -/******************************************************************* - 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) -{ - FILE *f; - pstring fname; - int count=0; - int alloced=0; - pstring line; - - strcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,SERVER_LIST); - - f = fopen(fname,"r"); - - if (!f) { - DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno))); - return(0); - } - if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM; - - while (!feof(f)) - { - fstring stype; - struct srv_info_struct *s; - char *ptr = line; - *ptr = 0; - - fgets(line,sizeof(line)-1,f); - if (!*line) continue; - - if (count == alloced) { - alloced += 10; - (*servers) = (struct srv_info_struct *) - Realloc(*servers,sizeof(**servers)*alloced); - if (!(*servers)) return(0); - bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count)); - } - s = &(*servers)[count]; - - s->server_added = True; - - if (!next_token(&ptr,s->name , NULL)) continue; - if (!next_token(&ptr,stype , NULL)) continue; - if (!next_token(&ptr,s->comment, NULL)) continue; - if (!next_token(&ptr,s->domain , NULL)) { - /* this allows us to cop with an old nmbd */ - strcpy(s->domain,my_workgroup()); - } - - if (sscanf(stype,"%X",&s->type) != 1) continue; - - /* doesn't match up: don't want it */ - if (!(servertype & s->type)) continue; - - /* server entry is a domain, we haven't asked for domains: don't want it */ - if ((s->type&SV_TYPE_DOMAIN_ENUM) && !(servertype&SV_TYPE_DOMAIN_ENUM)) - continue; - - DEBUG(4,("Server %20s %8x %25s %15s\n", - s->name, stype, s->comment, s->domain)); - - count++; - } - - fclose(f); - return(count); -} + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_trans_reply: send_smb failed."); -/******************************************************************* - fill in a server info structure - ******************************************************************/ -static int fill_srv_info(struct srv_info_struct *service, - int uLevel, char **buf, int *buflen, - char **stringbuf, int *stringspace, char *baseaddr) -{ - int struct_len; - char* p; - char* p2; - int l2; - int len; - - switch (uLevel) { - case 0: struct_len = 16; break; - case 1: struct_len = 26; break; - default: return -1; - } - - if (!buf) - { - len = 0; - switch (uLevel) - { - case 1: - len = strlen(service->comment)+1; - break; - } - - if (buflen) *buflen = struct_len; - if (stringspace) *stringspace = len; - return struct_len + len; - } - - len = struct_len; - p = *buf; - if (*buflen < struct_len) return -1; - if (stringbuf) - { - p2 = *stringbuf; - l2 = *stringspace; - } - else - { - p2 = p + struct_len; - l2 = *buflen - struct_len; - } - if (!baseaddr) baseaddr = p; - - switch (uLevel) - { - case 0: - StrnCpy(p,service->name,15); - break; - - case 1: - StrnCpy(p,service->name,15); - SIVAL(p,18,service->type); - SIVAL(p,22,PTR_DIFF(p2,baseaddr)); - len += CopyAndAdvance(&p2,service->comment,&l2); - break; - } - - if (stringbuf) - { - *buf = p + struct_len; - *buflen -= struct_len; - *stringbuf = p2; - *stringspace = l2; - } - else - { - *buf = p2; - *buflen -= len; - } - return len; -} + tot_data_sent = this_ldata; + tot_param_sent = this_lparam; - -/**************************************************************************** - 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, - 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); - uint32 servertype = IVAL(p,4); - char *p2; - int data_len, fixed_len, string_len; - int f_len, s_len; - struct srv_info_struct *servers=NULL; - int counted=0,total=0; - int i; - fstring domain; - BOOL domain_request = (servertype & SV_TYPE_DOMAIN_ENUM) && - !(servertype == SV_TYPE_ALL); - - domain[0] = 0; - p += 8; - - if (!prefix_ok(str1,"WrLehD")) return False; - if (!check_server_info(uLevel,str2)) return False; - - DEBUG(4, ("server request level: %s\n", str2)); - - if (strcmp(str1, "WrLehDO") == 0) - { - /* asking for servers. we will have to work out which workgroup was - requested, as we maintain lists for multiple workgroups */ - } - else if (strcmp(str1, "WrLehDz") == 0) - { - /* asking for a specific workgroup */ - StrnCpy(domain, p, sizeof(fstring)-1); - } - - if (lp_browse_list()) - { - total = get_server_info(servertype,&servers); - } - - if (!domain[0] && !domain_request) { - extern fstring remote_machine; - /* must be a server request with an assumed domain. find a domain */ - - if (find_server(servers, total, domain, remote_machine)) { - DEBUG(4, ("No domain specified: using %s for %s\n", - domain, remote_machine)); - } else { - /* default to soemthing sensible */ - strcpy(domain,my_workgroup()); - } - } - - data_len = fixed_len = string_len = 0; - - for (i=0;i<total;i++) - if (filter_server_info(&servers[i],domain)) { - data_len += fill_srv_info(&servers[i],uLevel,0,&f_len,0,&s_len,0); - if (data_len <= buf_len) + while (tot_data_sent < ldata || tot_param_sent < lparam) { - counted++; - fixed_len += f_len; - string_len += s_len; - } - } + this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */ + this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam)); - *rdata_len = fixed_len + string_len; - *rdata = REALLOC(*rdata,*rdata_len); - bzero(*rdata,*rdata_len); - - p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ - p = *rdata; - f_len = fixed_len; - s_len = string_len; - - { - int count2 = counted; - for (i = 0; i < total && count2;i++) { - if (filter_server_info(&servers[i],domain)) { - fill_srv_info(&servers[i],uLevel,&p,&f_len,&p2,&s_len,*rdata); - count2--; - } - } - } - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,total); + if(this_lparam < 0) + this_lparam = 0; - if (servers) free(servers); + if(this_ldata < 0) + this_ldata = 0; - DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", - domain,uLevel,counted,total)); - - return(True); -} + align = (this_lparam%4); + set_message(outbuf,10,1+this_ldata+this_lparam+align,False); -/**************************************************************************** - get info about a share - ****************************************************************************/ -static BOOL check_share_info(int uLevel, char* id) -{ - switch( uLevel ) { - case 0: - if (strcmp(id,"B13") != 0) return False; - break; - case 1: - if (strcmp(id,"B13BWz") != 0) return False; - break; - case 2: - if (strcmp(id,"B13BWzWWWzB9B") != 0) return False; - break; - case 91: - if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False; - break; - default: return False; - } - return True; -} + copy_trans_params_and_data(outbuf, align, + rparam, tot_param_sent, this_lparam, + rdata, tot_data_sent, this_ldata); -static int fill_share_info(int cnum, int snum, int uLevel, - char** buf, int* buflen, - char** stringbuf, int* stringspace, char* baseaddr) -{ - int struct_len; - char* p; - char* p2; - int l2; - int len; - - switch( uLevel ) { - case 0: struct_len = 13; break; - case 1: struct_len = 20; break; - case 2: struct_len = 40; break; - case 91: struct_len = 68; break; - default: return -1; - } - - - if (!buf) - { - len = 0; - if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum)); - if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1; - if (buflen) *buflen = struct_len; - if (stringspace) *stringspace = len; - return struct_len + len; - } - - len = struct_len; - p = *buf; - if ((*buflen) < struct_len) return -1; - if (stringbuf) - { - p2 = *stringbuf; - l2 = *stringspace; - } - else - { - p2 = p + struct_len; - l2 = (*buflen) - struct_len; - } - if (!baseaddr) baseaddr = p; - - StrnCpy(p,lp_servicename(snum),13); - - if (uLevel > 0) - { - int type; - CVAL(p,13) = 0; - type = STYPE_DISKTREE; - if (lp_print_ok(snum)) type = STYPE_PRINTQ; - if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC; - SSVAL(p,14,type); /* device type */ - SIVAL(p,16,PTR_DIFF(p2,baseaddr)); - len += CopyExpanded(cnum,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 */ - SSVAL(p,24,1); /* current uses */ - SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */ - 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); - SIVAL(p,52,0); - SSVAL(p,56,0); - SSVAL(p,58,0); - SIVAL(p,60,0); - SSVAL(p,64,0); - SSVAL(p,66,0); - } - - if (stringbuf) - { - (*buf) = p + struct_len; - (*buflen) -= struct_len; - (*stringbuf) = p2; - (*stringspace) = l2; - } - else - { - (*buf) = p2; - (*buflen) -= len; - } - return len; -} + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); + SSVAL(outbuf,smb_vwv5,tot_param_sent); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,tot_data_sent); + SSVAL(outbuf,smb_vwv9,0); -static BOOL api_RNetShareGetInfo(int cnum,int uid, 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 *netname = skip_string(str2,1); - char *p = skip_string(netname,1); - int uLevel = SVAL(p,0); - int snum = find_service(netname); - - 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 = REALLOC(*rdata,mdrcnt); - p = *rdata; - *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0); - if (*rdata_len < 0) return False; - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); - - return(True); -} + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("send_trans_reply: send_smb failed."); -/**************************************************************************** - view list of shares available - ****************************************************************************/ -static BOOL api_RNetShareEnum(int cnum,int uid, 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); - char *p2; - int count=lp_numservices(); - int total=0,counted=0; - int i; - int data_len, fixed_len, string_len; - int f_len, s_len; - - if (!prefix_ok(str1,"WrLeh")) return False; - if (!check_share_info(uLevel,str2)) return False; - - data_len = fixed_len = string_len = 0; - for (i=0;i<count;i++) - if (lp_browseable(i) && lp_snum_ok(i)) - { - total++; - data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0); - if (data_len <= buf_len) - { - counted++; - fixed_len += f_len; - string_len += s_len; - } - } - *rdata_len = fixed_len + string_len; - *rdata = REALLOC(*rdata,*rdata_len); - memset(*rdata,0,*rdata_len); - - p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */ - p = *rdata; - f_len = fixed_len; - s_len = string_len; - for (i = 0; i < count;i++) - if (lp_browseable(i) && lp_snum_ok(i)) - if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0) - break; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - 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)); - return(True); + tot_data_sent += this_ldata; + tot_param_sent += this_lparam; + } } - - /**************************************************************************** - get the time of day info - ****************************************************************************/ -static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *p; - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 21; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - - { - struct tm *t; - time_t unixdate = time(NULL); - - put_dos_date3(p,0,unixdate); /* this is the time that is looked at - by NT in a "net time" operation, - it seems to ignore the one below */ - - /* the client expects to get localtime, not GMT, in this bit - (I think, this needs testing) */ - t = LocalTime(&unixdate,GMT_TO_LOCAL); - - SIVAL(p,4,0); /* msecs ? */ - CVAL(p,8) = t->tm_hour; - CVAL(p,9) = t->tm_min; - CVAL(p,10) = t->tm_sec; - CVAL(p,11) = 0; /* hundredths of seconds */ - SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */ - SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ - CVAL(p,16) = t->tm_mday; - CVAL(p,17) = t->tm_mon + 1; - SSVAL(p,18,1900+t->tm_year); - CVAL(p,20) = t->tm_wday; - } - - - return(True); -} + Start the first part of an RPC reply which began with an SMBtrans request. +****************************************************************************/ -/**************************************************************************** - set the user password - ****************************************************************************/ -static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p) { - char *p = skip_string(param+2,2); - fstring user; - fstring pass1,pass2; - - strcpy(user,p); + BOOL is_data_outstanding; + char *rdata = malloc(p->max_trans_reply); + int data_len; - p = skip_string(p,1); - - StrnCpy(pass1,p,16); - StrnCpy(pass2,p+16,16); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ + if(rdata == NULL) { + DEBUG(0,("api_rpc_trans_reply: malloc fail.\n")); + return False; + } - DEBUG(3,("Set password for <%s>\n",user)); + if((data_len = read_from_pipe( p, rdata, p->max_trans_reply, + &is_data_outstanding)) < 0) { + SAFE_FREE(rdata); + return False; + } - if (!password_ok(user,pass1,strlen(pass1),NULL,False) || - !chgpasswd(user,pass1,pass2)) - SSVAL(*rparam,0,NERR_badpass); + send_trans_reply(outbuf, NULL, 0, rdata, data_len, is_data_outstanding); - bzero(pass1,sizeof(fstring)); - bzero(pass2,sizeof(fstring)); - - return(True); + SAFE_FREE(rdata); + return True; } /**************************************************************************** - delete a print job - Form: <W> <> - ****************************************************************************/ -static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - int function = SVAL(param,0); - 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 i, count; - - - /* check it's a supported varient */ - if (!(strcsequal(str1,"W") && strcsequal(str2,""))) - return(False); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_Success); - - if (snum >= 0 && VALID_SNUM(snum)) - { - print_queue_struct *queue=NULL; - lpq_reset(snum); - count = get_printqueue(snum,cnum,&queue,NULL); - - for (i=0;i<count;i++) - if ((queue[i].job%0xFF) == jobid) - { - switch (function) { - case 81: /* delete */ - DEBUG(3,("Deleting queue entry %d\n",queue[i].job)); - del_printqueue(cnum,snum,queue[i].job); - break; - case 82: /* pause */ - case 83: /* resume */ - DEBUG(3,("%s queue entry %d\n", - (function==82?"pausing":"resuming"),queue[i].job)); - status_printjob(cnum,snum,queue[i].job, - (function==82?LPQ_PAUSED:LPQ_QUEUED)); - break; - } - break; - } - - if (i==count) - SSVAL(*rparam,0,NERR_JobNotFound); - - if (queue) free(queue); - } - - SSVAL(*rparam,2,0); /* converter word */ - - return(True); -} + WaitNamedPipeHandleState +****************************************************************************/ -static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *QueueName = skip_string(str2,1); - int snum; - - /* check it's a supported varient */ - if (!(strcsequal(str1,"z") && strcsequal(str2,""))) - return(False); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - snum = lp_servicenumber(QueueName); - if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(QueueName,pnum); - snum = lp_servicenumber(QueueName); - } - } - - if (snum >= 0 && VALID_SNUM(snum)) { - print_queue_struct *queue=NULL; - int i, count; - lpq_reset(snum); - - count = get_printqueue(snum,cnum,&queue,NULL); - for (i = 0; i < count; i++) - del_printqueue(cnum,snum,queue[i].job); - - if (queue) free(queue); - } - - DEBUG(3,("Print queue purge, queue=%s\n",QueueName)); - - return(True); -} + uint16 priority; + if (!param || param_len < 2) + return False; -/**************************************************************************** - set the property of a print job (undocumented?) - ? function = 0xb -> set name of print job - ? function = 0x6 -> move print job up/down - Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> - or <WWsTP> <WB21BB16B10zWWzDDz> -****************************************************************************/ -static int check_printjob_info(struct pack_desc* desc, - int uLevel, char* id) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: desc->format = "W"; break; - case 1: desc->format = "WB21BB16B10zWWzDDz"; break; - case 2: desc->format = "WWzWWDDzz"; break; - case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; - default: return False; - } - if (strcmp(desc->format,id) != 0) return False; - return True; -} + priority = SVAL(param,0); + DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority)); -static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - struct pack_desc desc; - 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 uLevel = SVAL(p,2); - int function = SVAL(p,4); /* what is this ?? */ - int i; - char *s = data; - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - /* check it's a supported varient */ - if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2))) - return(False); - - switch (function) { - case 0x6: /* change job place in the queue, data gives the new place */ - if (snum >= 0 && VALID_SNUM(snum)) - { - print_queue_struct *queue=NULL; - int count; - - 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 (i==count) { - desc.errcode=NERR_JobNotFound; - if (queue) free(queue); + if (wait_rpc_pipe_hnd_state(p, priority)) { + /* now send the reply */ + send_trans_reply(outbuf, NULL, 0, NULL, 0, False); + return True; } - else { - desc.errcode=NERR_Success; - i++; -#if 0 - { - int place= SVAL(data,0); - /* we currently have no way of doing this. Can any unix do it? */ - if (i < place) /* move down */; - else if (i > place ) /* move up */; - } -#endif - desc.errcode=NERR_notsupported; /* not yet supported */ - if (queue) free(queue); - } - } - else desc.errcode=NERR_JobNotFound; - break; - case 0xb: /* change print job name, data gives the name */ - /* jobid, snum should be zero */ - if (isalpha(*s)) - { - pstring name; - int l = 0; - while (l<64 && *s) - { - if (isalnum(*s) || strchr("-._",*s)) - name[l++] = *s; - s++; - } - name[l] = 0; - - DEBUG(3,("Setting print name to %s\n",name)); - - for (i=0;i<MAX_OPEN_FILES;i++) - if (Files[i].open && Files[i].print_file) - { - pstring wd; - GetWd(wd); - unbecome_user(); - - if (!become_user(Files[i].cnum,uid) || - !become_service(Files[i].cnum,True)) - break; - - if (sys_rename(Files[i].name,name) == 0) - string_set(&Files[i].name,name); - break; - } - } - desc.errcode=NERR_Success; - - break; - default: /* not implemented */ - return False; - } - - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); /* converter word */ - - return(True); + return False; } /**************************************************************************** - get info about the server - ****************************************************************************/ -static BOOL api_RNetServerGetInfo(int cnum,int uid, 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); - char *p2; - int struct_len; - - DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); - - /* check it's a supported varient */ - if (!prefix_ok(str1,"WrLh")) return False; - switch( uLevel ) { - case 0: - if (strcmp(str2,"B16") != 0) return False; - struct_len = 16; - break; - case 1: - if (strcmp(str2,"B16BBDz") != 0) return False; - struct_len = 26; - break; - case 2: - if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz") - != 0) return False; - struct_len = 134; - break; - case 3: - if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") - != 0) return False; - struct_len = 144; - break; - case 20: - if (strcmp(str2,"DN") != 0) return False; - struct_len = 6; - break; - case 50: - if (strcmp(str2,"B16BBDzWWzzz") != 0) return False; - struct_len = 42; - break; - default: return False; - } - - *rdata_len = mdrcnt; - *rdata = REALLOC(*rdata,*rdata_len); - - p = *rdata; - p2 = p + struct_len; - if (uLevel != 20) { - StrnCpy(p,local_machine,16); - strupper(p); - } - p += 16; - if (uLevel > 0) - { - 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; - - strcpy(comment,lp_serverstring()); - - if ((count=get_server_info(SV_TYPE_ALL,&servers))>0) { - for (i=0;i<count;i++) - if (strequal(servers[i].name,local_machine)) { - servertype = servers[i].type; - strcpy(comment,servers[i].comment); - } - } - if (servers) free(servers); - - SCVAL(p,0,2); /* version_major */ - SCVAL(p,1,0); /* version_minor */ - SIVAL(p,2,servertype); - if (mdrcnt == struct_len) { - SIVAL(p,6,0); - } else { - SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub(cnum,comment); - StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); - p2 = skip_string(p2,1); - } - } - if (uLevel > 1) - { - return False; /* not yet implemented */ - } - - *rdata_len = PTR_DIFF(p2,*rdata); - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); - - return(True); -} - + SetNamedPipeHandleState +****************************************************************************/ -/**************************************************************************** - get info about the server - ****************************************************************************/ -static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char *p2; - extern pstring sesssetup_user; - int level = SVAL(p,0); - - DEBUG(4,("NetWkstaGetInfo level %d\n",level)); - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - - /* check it's a supported varient */ - if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) - return(False); + uint16 id; - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); + if (!param || param_len < 2) + return False; - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ + id = SVAL(param,0); + DEBUG(4,("SetNamedPipeHandleState to code %x\n", id)); - p = *rdata; - p2 = p + 22; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,local_machine); - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,sesssetup_user); - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,my_workgroup()); - p2 = skip_string(p2,1); - p += 4; - - SCVAL(p,0,2); /* major version?? */ - SCVAL(p,1,1); /* minor version?? */ - p += 2; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,my_workgroup()); /* login domain?? */ - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,""); - p2 = skip_string(p2,1); - p += 4; - - *rdata_len = PTR_DIFF(p2,*rdata); - - SSVAL(*rparam,4,*rdata_len); - - return(True); + if (set_rpc_pipe_hnd_state(p, id)) { + /* now send the reply */ + send_trans_reply(outbuf, NULL, 0, NULL, 0, False); + return True; + } + return False; } /**************************************************************************** - get info about a user - ****************************************************************************/ + When no reply is generated, indicate unsupported. + ****************************************************************************/ -#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, - 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; - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - - /* 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); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - p2 = p + 86; - - 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 */ - } - } - } - - *rdata_len = PTR_DIFF(p2,*rdata); - - 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, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_no_reply(char *outbuf, int max_rdata_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; - int count=0; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLeh") != 0) return False; - switch( uLevel ) { - case 0: p2 = "B21"; break; - default: return False; - } - if (strcmp(p2,str2) != 0) return False; - - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ + char rparam[4]; - p = *rdata; + /* unsupported */ + SSVAL(rparam,0,NERR_notsupported); + SSVAL(rparam,2,0); /* converter word */ - /* XXXX we need a real SAM database some day */ - strcpy(p,"Users"); p += 21; count++; - strcpy(p,"Domain Users"); p += 21; count++; - strcpy(p,"Guests"); p += 21; count++; - strcpy(p,"Domain Guests"); p += 21; count++; + DEBUG(3,("Unsupported API fd command\n")); - *rdata_len = PTR_DIFF(p,*rdata); + /* now send the reply */ + send_trans_reply(outbuf, rparam, 4, NULL, 0, False); - SSVAL(*rparam,4,count); /* is this right?? */ - SSVAL(*rparam,6,count); /* is this right?? */ - - return(True); + return -1; } - -static BOOL api_WWkstaUserLogon(int cnum,int uid, 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; - struct pack_desc desc; - char* name; - - uLevel = SVAL(p,0); - name = p + 2; - - bzero(&desc,sizeof(desc)); - - DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); - - /* check it's a supported varient */ - if (strcmp(str1,"OOWb54WrLh") != 0) return False; - if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False; - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.subformat = NULL; - desc.format = str2; - - - - if (init_package(&desc,1,0)) { - PACKI(&desc,"W",0); /* code */ - PACKS(&desc,"B21",name); /* eff. name */ - PACKS(&desc,"B",""); /* pad */ - PACKI(&desc,"W", - Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - PACKI(&desc,"D",0); /* auth flags XXX */ - PACKI(&desc,"W",0); /* num logons */ - PACKI(&desc,"W",0); /* bad pw count */ - PACKI(&desc,"D",-1); /* last logon */ - PACKI(&desc,"D",-1); /* last logoff */ - PACKI(&desc,"D",-1); /* logoff time */ - PACKI(&desc,"D",-1); /* kickoff time */ - PACKI(&desc,"D",0); /* password age */ - PACKI(&desc,"D",0); /* password can change */ - PACKI(&desc,"D",-1); /* password must change */ - { - fstring mypath; - strcpy(mypath,"\\\\"); - strcat(mypath,local_machine); - 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 */ - } - - *rdata_len = desc.usedlen; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); - return(True); -} - - /**************************************************************************** - api_WAccessGetUserPerms - ****************************************************************************/ -static BOOL api_WAccessGetUserPerms(int cnum,int uid, 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 *user = skip_string(str2,1); - char *resource = skip_string(user,1); - - DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); - - /* check it's a supported varient */ - if (strcmp(str1,"zzh") != 0) return False; - if (strcmp(str2,"") != 0) return False; - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,0); /* errorcode */ - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,0x7f); /* permission flags */ - - return(True); -} - -/**************************************************************************** - api_WPrintJobEnumerate - ****************************************************************************/ -static BOOL api_WPrintJobGetInfo(int cnum,int uid, 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; - int snum; - int job; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - uLevel = SVAL(p,2); - cbBuf = SVAL(p,4); - - bzero(&desc,sizeof(desc)); - bzero(&status,sizeof(status)); - - DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId)); - - /* 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; - - 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 (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,1,0)) { - if (i < count) { - fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i); - *rdata_len = desc.usedlen; - } - else { - desc.errcode = NERR_JobNotFound; - *rdata_len = 0; - } - } - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - if (queue) free(queue); - - DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); - return(True); -} + Handle remote api calls delivered to a named pipe already opened. + ****************************************************************************/ -static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, + uint16 *setup,char *data,char *params, + int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* name = p; - int uLevel,cbBuf; - int count; - int i, succnt=0; - int snum; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - bzero(&desc,sizeof(desc)); - bzero(&status,sizeof(status)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); - - /* check it's a supported varient */ - 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; - - snum = lp_servicenumber(name); - if (snum < 0 && pcap_printername_ok(name,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(name,pnum); - snum = lp_servicenumber(name); - } - } - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = get_printqueue(snum,cnum,&queue,&status); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,count,0)) { - succnt = 0; - for (i = 0; i < count; i++) { - fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i); - if (desc.errcode == NERR_Success) succnt = i+1; - } - } - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,count); - - if (queue) free(queue); - - DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); - return(True); -} - -static int check_printdest_info(struct pack_desc* desc, - int uLevel, char* id) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: desc->format = "B9"; break; - case 1: desc->format = "B9B21WWzW"; break; - case 2: desc->format = "z"; break; - case 3: desc->format = "zzzWWzzzWW"; break; - default: return False; - } - if (strcmp(desc->format,id) != 0) return False; - return True; -} - -static void fill_printdest_info(int cnum, int snum, int uLevel, - struct pack_desc* desc) -{ - char buf[100]; - strcpy(buf,SERVICE(snum)); - strupper(buf); - if (uLevel <= 1) { - PACKS(desc,"B9",buf); /* szName */ - if (uLevel == 1) { - PACKS(desc,"B21",""); /* szUserName */ - PACKI(desc,"W",0); /* uJobId */ - PACKI(desc,"W",0); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"W",0); /* time */ - } - } - if (uLevel == 2 || uLevel == 3) { - PACKS(desc,"z",buf); /* pszPrinterName */ - if (uLevel == 3) { - PACKS(desc,"z",""); /* pszUserName */ - PACKS(desc,"z",""); /* pszLogAddr */ - PACKI(desc,"W",0); /* uJobId */ - PACKI(desc,"W",0); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKS(desc,"z",""); /* pszComment */ - PACKS(desc,"z","NULL"); /* pszDrivers */ - PACKI(desc,"W",0); /* time */ - PACKI(desc,"W",0); /* pad1 */ - } - } -} - -static BOOL api_WPrintDestGetInfo(int cnum,int uid, 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); - char* PrinterName = p; - int uLevel,cbBuf; - struct pack_desc desc; - int snum; - - bzero(&desc,sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLh") != 0) return False; - if (!check_printdest_info(&desc,uLevel,str2)) return False; - - snum = lp_servicenumber(PrinterName); - if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(PrinterName,pnum); - snum = lp_servicenumber(PrinterName); - } - } - - if (snum < 0) { - *rdata_len = 0; - desc.errcode = NERR_DestNotFound; - desc.neededlen = 0; - } - else { - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,0)) { - fill_printdest_info(cnum,snum,uLevel,&desc); - } - *rdata_len = desc.usedlen; - } - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintDestEnum(int cnum,int uid, 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,cbBuf; - int queuecnt; - int i, n, succnt=0; - struct pack_desc desc; - int services = lp_numservices(); - - bzero(&desc,sizeof(desc)); - - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (!check_printdest_info(&desc,uLevel,str2)) return False; - - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,queuecnt,0)) { - succnt = 0; - n = 0; - for (i = 0; i < services; i++) { - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printdest_info(cnum,i,uLevel,&desc); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } - } - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,queuecnt); - - DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintDriverEnum(int cnum,int uid, 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,cbBuf; - int succnt; - struct pack_desc desc; - - bzero(&desc,sizeof(desc)); - - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B41") != 0) return False; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B41","NULL"); - } - - succnt = (desc.errcode == NERR_Success ? 1 : 0); + BOOL reply = False; + smb_np_struct *p = NULL; + int pnum; + int subcommand; - *rdata_len = desc.usedlen; + DEBUG(5,("api_fd_reply\n")); - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); - - DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintQProcEnum(int cnum,int uid, 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,cbBuf; - int succnt; - struct pack_desc desc; - - bzero(&desc,sizeof(desc)); - - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); + /* First find out the name of this file. */ + if (suwcnt != 2) { + DEBUG(0,("Unexpected named pipe transaction.\n")); + return(-1); + } - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B13") != 0) return False; + /* Get the file handle and hence the file name. */ + /* + * NB. The setup array has already been transformed + * via SVAL and so is in gost byte order. + */ + pnum = ((int)setup[1]) & 0xFFFF; + subcommand = ((int)setup[0]) & 0xFFFF; + + if(!(p = get_rpc_pipe(pnum))) { + DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); + return api_no_reply(outbuf, mdrcnt); + } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lpd"); - } + DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum)); - succnt = (desc.errcode == NERR_Success ? 1 : 0); + /* record maximum data length that can be transmitted in an SMBtrans */ + p->max_trans_reply = mdrcnt; - *rdata_len = desc.usedlen; + DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply)); - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); + switch (subcommand) { + case 0x26: + /* dce/rpc command */ + reply = write_to_pipe(p, data, tdscnt); + if (reply) + reply = api_rpc_trans_reply(outbuf, p); + break; + case 0x53: + /* Wait Named Pipe Handle state */ + reply = api_WNPHS(outbuf, p, params, tpscnt); + break; + case 0x01: + /* Set Named Pipe Handle state */ + reply = api_SNPHS(outbuf, p, params, tpscnt); + break; + } - DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); - return(True); -} + if (!reply) + return api_no_reply(outbuf, mdrcnt); -static BOOL api_WPrintPortEnum(int cnum,int uid, 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,cbBuf; - int succnt; - struct pack_desc desc; - - bzero(&desc,sizeof(desc)); - - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B9") != 0) return False; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - bzero(&desc,sizeof(desc)); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lp0"); - } - - succnt = (desc.errcode == NERR_Success ? 1 : 0); - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); - - DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); - return(True); + return -1; } /**************************************************************************** - the buffer was too small + handle named pipe commands ****************************************************************************/ -static BOOL api_TooSmall(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name, + uint16 *setup,char *data,char *params, + int suwcnt,int tdscnt,int tpscnt, + int msrcnt,int mdrcnt,int mprcnt) { - *rparam_len = MIN(*rparam_len,mprcnt); - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_BufTooSmall); + DEBUG(3,("named pipe command on <%s> name\n", name)); - DEBUG(3,("Supplied buffer too small in API command\n")); + if (strequal(name,"LANMAN")) + return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt); - return(True); -} - - -/**************************************************************************** - the request is not supported - ****************************************************************************/ -static BOOL api_Unsupported(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; + if (strequal(name,"WKSSVC") || + strequal(name,"SRVSVC") || + strequal(name,"WINREG") || + strequal(name,"SAMR") || + strequal(name,"LSARPC")) + { + DEBUG(4,("named pipe command from Win95 (wow!)\n")); + return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); + } - SSVAL(*rparam,0,NERR_notsupported); - SSVAL(*rparam,2,0); /* converter word */ + if (strlen(name) < 1) + return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt); - DEBUG(3,("Unsupported API command\n")); + if (setup) + DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1])); - return(True); + return 0; } - - -struct -{ - char *name; - int id; - BOOL (*fn)(); - int flags; -} api_commands[] = { - {"RNetShareEnum", 0, api_RNetShareEnum,0}, - {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0}, - {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0}, - {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0}, - {"NetUserGetGroups", 59, api_NetUserGetGroups,0}, - {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0}, - {"DosPrintQEnum", 69, api_DosPrintQEnum,0}, - {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0}, - {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0}, - {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0}, - {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0}, - {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0}, - {"RDosPrintJobResume",83, api_RDosPrintJobDel,0}, - {"WPrintDestEnum", 84, api_WPrintDestEnum,0}, - {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0}, - {"NetRemoteTOD", 91, api_NetRemoteTOD,0}, - {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0}, - {"NetServerEnum", 104, api_RNetServerEnum,0}, - {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0}, - {"SetUserPassword", 115, api_SetUserPassword,0}, - {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0}, - {"PrintJobInfo", 147, api_PrintJobInfo,0}, - {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0}, - {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0}, - {"WPrintPortEnum", 207, api_WPrintPortEnum,0}, - {NULL, -1, api_Unsupported,0}}; - - /**************************************************************************** - handle remote api calls - ****************************************************************************/ -static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params, - int tdscnt,int tpscnt,int mdrcnt,int mprcnt) -{ - int api_command = SVAL(params,0); - char *rdata = NULL; - char *rparam = NULL; - int rdata_len = 0; - int rparam_len = 0; - BOOL reply=False; - int i; - - DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", - api_command,params+2,skip_string(params+2,1), - tdscnt,tpscnt,mdrcnt,mprcnt)); - - for (i=0;api_commands[i].name;i++) - if (api_commands[i].id == api_command && api_commands[i].fn) - { - DEBUG(3,("Doing %s\n",api_commands[i].name)); - break; - } - - 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, - &rdata,&rparam,&rdata_len,&rparam_len); - - - if (rdata_len > mdrcnt || - rparam_len > mprcnt) - { - reply = api_TooSmall(cnum,uid,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, - &rdata,&rparam,&rdata_len,&rparam_len); - - - - /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); - - if (rdata) - free(rdata); - if (rparam) - free(rparam); + Reply to a SMBtrans. + ****************************************************************************/ + +int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize) +{ + fstring name; + int name_offset = 0; + char *data=NULL,*params=NULL; + uint16 *setup=NULL; + int outsize = 0; + uint16 vuid = SVAL(inbuf,smb_uid); + int tpscnt = SVAL(inbuf,smb_vwv0); + int tdscnt = SVAL(inbuf,smb_vwv1); + int mprcnt = SVAL(inbuf,smb_vwv2); + int mdrcnt = SVAL(inbuf,smb_vwv3); + int msrcnt = CVAL(inbuf,smb_vwv4); + BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0); + BOOL one_way = BITSETW(inbuf+smb_vwv5,1); + int pscnt = SVAL(inbuf,smb_vwv9); + int psoff = SVAL(inbuf,smb_vwv10); + int dscnt = SVAL(inbuf,smb_vwv11); + int dsoff = SVAL(inbuf,smb_vwv12); + int suwcnt = CVAL(inbuf,smb_vwv13); + START_PROFILE(SMBtrans); + + memset(name, '\0',sizeof(name)); + srvstr_pull(inbuf, name, smb_buf(inbuf), sizeof(name), -1, STR_TERMINATE); + + if (dscnt > tdscnt || pscnt > tpscnt) { + exit_server("invalid trans parameters"); + } - return(-1); -} - -/**************************************************************************** - handle named pipe commands - ****************************************************************************/ -static int named_pipe(int cnum,int uid, char *outbuf,char *name, - uint16 *setup,char *data,char *params, - int suwcnt,int tdscnt,int tpscnt, - int msrcnt,int mdrcnt,int mprcnt) -{ + if (tdscnt) { + if((data = (char *)malloc(tdscnt)) == NULL) { + DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt)); + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRDOS,ERRnomem)); + } + memcpy(data,smb_base(inbuf)+dsoff,dscnt); + } - if (strequal(name,"LANMAN")) - return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt)); + if (tpscnt) { + if((params = (char *)malloc(tpscnt)) == NULL) { + DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt)); + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRDOS,ERRnomem)); + } + memcpy(params,smb_base(inbuf)+psoff,pscnt); + } - DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n", - name,(int)setup[0],(int)setup[1])); - - return(0); -} + if (suwcnt) { + int i; + if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) { + DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16)))); + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRDOS,ERRnomem)); + } + for (i=0;i<suwcnt;i++) + setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD); + } -/**************************************************************************** - reply to a SMBtrans - ****************************************************************************/ -int reply_trans(char *inbuf,char *outbuf) -{ - fstring name; - - char *data=NULL,*params=NULL; - uint16 *setup=NULL; - - int outsize = 0; - int cnum = SVAL(inbuf,smb_tid); - int uid = SVAL(inbuf,smb_uid); - - int tpscnt = SVAL(inbuf,smb_vwv0); - int tdscnt = SVAL(inbuf,smb_vwv1); - int mprcnt = SVAL(inbuf,smb_vwv2); - int mdrcnt = SVAL(inbuf,smb_vwv3); - int msrcnt = CVAL(inbuf,smb_vwv4); - BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0); - BOOL one_way = BITSETW(inbuf+smb_vwv5,1); - int pscnt = SVAL(inbuf,smb_vwv9); - int psoff = SVAL(inbuf,smb_vwv10); - int dscnt = SVAL(inbuf,smb_vwv11); - int dsoff = SVAL(inbuf,smb_vwv12); - int suwcnt = CVAL(inbuf,smb_vwv13); - - StrnCpy(name,smb_buf(inbuf),sizeof(name)-1); - - if (tdscnt) - { - data = (char *)malloc(tdscnt); - memcpy(data,smb_base(inbuf)+dsoff,dscnt); - } - if (tpscnt) - { - params = (char *)malloc(tpscnt); - memcpy(params,smb_base(inbuf)+psoff,pscnt); - } - - if (suwcnt) - { - int i; - setup = (uint16 *)malloc(suwcnt*sizeof(setup[0])); - for (i=0;i<suwcnt;i++) - setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD); - } - - - if (pscnt < tpscnt || dscnt < tdscnt) - { - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); - show_msg(outbuf); - send_smb(Client,outbuf); - } - - /* receive the rest of the trans packet */ - while (pscnt < tpscnt || dscnt < tdscnt) - { - int pcnt,poff,dcnt,doff,pdisp,ddisp; - - receive_smb(Client,inbuf, 0); - show_msg(inbuf); - - /* Ensure this is still a trans packet (sanity check) */ - if(CVAL(inbuf, smb_com) != SMBtrans) - { - DEBUG(2,("Invalid secondary trans2 packet\n")); - if (params) free(params); - if (data) free(data); - if (setup) free(setup); - return(ERROR(ERRSRV,ERRerror)); + if (pscnt < tpscnt || dscnt < tdscnt) { + /* We need to send an interim response then receive the rest + of the parameter/data bytes */ + outsize = set_message(outbuf,0,0,True); + show_msg(outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("reply_trans: send_smb failed."); } - - tpscnt = SVAL(inbuf,smb_vwv0); - tdscnt = SVAL(inbuf,smb_vwv1); - pcnt = SVAL(inbuf,smb_vwv2); - poff = SVAL(inbuf,smb_vwv3); - pdisp = SVAL(inbuf,smb_vwv4); + /* receive the rest of the trans packet */ + while (pscnt < tpscnt || dscnt < tdscnt) { + BOOL ret; + int pcnt,poff,dcnt,doff,pdisp,ddisp; - dcnt = SVAL(inbuf,smb_vwv5); - doff = SVAL(inbuf,smb_vwv6); - ddisp = SVAL(inbuf,smb_vwv7); + ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + + if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) { + 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" )); + } + SAFE_FREE(params); + SAFE_FREE(data); + SAFE_FREE(setup); + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRSRV,ERRerror)); + } + + show_msg(inbuf); - pscnt += pcnt; - dscnt += dcnt; - - if (pcnt) - memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); - if (dcnt) - memcpy(data+ddisp,smb_base(inbuf)+doff,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, - suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); - - - if (data) free(data); - if (params) free(params); - if (setup) free(setup); - - if (close_on_completion) - close_cnum(cnum,uid); + tpscnt = SVAL(inbuf,smb_vwv0); + tdscnt = SVAL(inbuf,smb_vwv1); + + pcnt = SVAL(inbuf,smb_vwv2); + poff = SVAL(inbuf,smb_vwv3); + pdisp = SVAL(inbuf,smb_vwv4); + + dcnt = SVAL(inbuf,smb_vwv5); + doff = SVAL(inbuf,smb_vwv6); + ddisp = SVAL(inbuf,smb_vwv7); + + pscnt += pcnt; + dscnt += dcnt; + + if (dscnt > tdscnt || pscnt > tpscnt) { + exit_server("invalid trans parameters"); + } + + if (pcnt) + memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); + if (dcnt) + memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); + } + + + DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n", + name,tdscnt,tpscnt,suwcnt)); + + /* + * WinCE wierdness.... + */ + + if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, strlen(local_machine)) == 0) && + (name[strlen(local_machine)+1] == '\\')) + name_offset = strlen(local_machine)+1; + + if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) { + name_offset += strlen("\\PIPE"); + + /* Win9x weirdness. When talking to a unicode server Win9x + only sends \PIPE instead of \PIPE\ */ + + if (name[name_offset] == '\\') + name_offset++; + + DEBUG(5,("calling named_pipe\n")); + outsize = named_pipe(conn,vuid,outbuf, + name+name_offset,setup,data,params, + suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); + } else { + DEBUG(3,("invalid pipe name\n")); + outsize = 0; + } - if (one_way) - return(-1); - - if (outsize == 0) - return(ERROR(ERRSRV,ERRnosupport)); + + SAFE_FREE(data); + SAFE_FREE(params); + SAFE_FREE(setup); + + if (close_on_completion) + close_cnum(conn,vuid); - return(outsize); + if (one_way) { + END_PROFILE(SMBtrans); + return(-1); + } + + if (outsize == 0) { + END_PROFILE(SMBtrans); + return(ERROR_DOS(ERRSRV,ERRnosupport)); + } + + END_PROFILE(SMBtrans); + return(outsize); } - - |