X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fsmbd%2Flanman.c;h=2d6db8f2a30a508b21138719d6e7d32330c3c18e;hb=fbdcf2663b56007a438ac4f0d8d82436b1bfe688;hp=d755bb42f8bf668bf045f741331b8ab0e2aee286;hpb=a03b5e3864ac6044694fe0b4e7f83098598b60dc;p=kai%2Fsamba.git diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index d755bb42f8b..2d6db8f2a30 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 1.9. + Unix SMB/CIFS implementation. Inter-process communication and named pipe handling Copyright (C) Andrew Tridgell 1992-1998 @@ -28,15 +27,14 @@ #include "includes.h" +extern struct current_user current_user; +extern userdom_struct current_user_info; + #ifdef CHECK_TYPES #undef CHECK_TYPES #endif #define CHECK_TYPES 0 -extern fstring local_machine; -extern pstring global_myname; -extern fstring global_myworkgroup; - #define NERR_Success 0 #define NERR_badpass 86 #define NERR_notsupported 50 @@ -52,276 +50,326 @@ extern fstring global_myworkgroup; #define SHPWLEN 8 /* share password length */ -static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); -static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); +static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len); +static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len); static int CopyExpanded(connection_struct *conn, - int snum, char** dst, char* src, int* n) + int snum, char **dst, char *src, int *n) { pstring buf; int l; - if (!src || !dst || !n || !(*dst)) return(0); + if (!src || !dst || !n || !(*dst)) { + return 0; + } StrnCpy(buf,src,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); - l = push_ascii(*dst,buf,*n-1, STR_TERMINATE); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); + l = push_ascii(*dst,buf,*n, STR_TERMINATE); (*dst) += l; (*n) -= l; return l; } -static int CopyAndAdvance(char** dst, char* src, int* n) +static int CopyAndAdvance(char **dst, char *src, int *n) { - int l; - if (!src || !dst || !n || !(*dst)) return(0); - l = push_ascii(*dst,src,*n-1, STR_TERMINATE); - (*dst) += l; - (*n) -= l; - return l; + int l; + if (!src || !dst || !n || !(*dst)) { + return 0; + } + l = push_ascii(*dst,src,*n, STR_TERMINATE); + (*dst) += l; + (*n) -= l; + return l; } -static int StrlenExpanded(connection_struct *conn, int snum, char* s) +static int StrlenExpanded(connection_struct *conn, int snum, char *s) { pstring buf; - if (!s) return(0); + if (!s) { + return 0; + } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); return strlen(buf) + 1; } -static char* Expand(connection_struct *conn, int snum, char* s) +static char *Expand(connection_struct *conn, int snum, char *s) { static pstring buf; - if (!s) return(NULL); + if (!s) { + return NULL; + } StrnCpy(buf,s,sizeof(buf)/2); pstring_sub(buf,"%S",lp_servicename(snum)); - standard_sub_conn(conn,buf); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + buf, sizeof(buf)); return &buf[0]; } /******************************************************************* - check a API string for validity when we only need to check the prefix - ******************************************************************/ -static BOOL prefix_ok(char *str,char *prefix) + Check a API string for validity when we only need to check the prefix. +******************************************************************/ + +static BOOL prefix_ok(const char *str, const char *prefix) { - return(strncmp(str,prefix,strlen(prefix)) == 0); + return(strncmp(str,prefix,strlen(prefix)) == 0); } 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; + const char *format; /* formatstring for structure */ + const 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) */ + const char *curpos; /* current position; pointer into format or subformat */ + int errcode; }; -static int get_counter(char** p) +static int get_counter(const char **p) { - int i, n; - if (!p || !(*p)) return(1); - if (!isdigit((int)**p)) return 1; - for (n = 0;;) { - i = **p; - if (isdigit(i)) - n = 10 * n + (i - '0'); - else - return n; - (*p)++; - } + int i, n; + if (!p || !(*p)) { + return 1; + } + if (!isdigit((int)**p)) { + return 1; + } + for (n = 0;;) { + i = **p; + if (isdigit(i)) { + n = 10 * n + (i - '0'); + } else { + return n; + } + (*p)++; + } } -static int getlen(char* p) +static int getlen(const char *p) { - int n = 0; - if (!p) return(0); - while (*p) { - switch( *p++ ) { - case 'W': /* word (2 byte) */ - n += 2; - break; - case 'K': /* status 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; + int n = 0; + if (!p) { + return 0; + } + + while (*p) { + switch( *p++ ) { + case 'W': /* word (2 byte) */ + n += 2; + break; + case 'K': /* status 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; } -static BOOL init_package(struct pack_desc* p, int count, int subcount) +static BOOL init_package(struct pack_desc *p, int count, int subcount) { - int n = p->buflen; - int i; - - 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) { - p->neededlen = i; - i = n = 0; + 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) { + p->neededlen = i; + i = n = 0; #if 0 - /* - * This is the old error code we used. Aparently - * WinNT/2k systems return ERRbuftoosmall (2123) and - * OS/2 needs this. I'm leaving this here so we can revert - * if needed. JRA. - */ - p->errcode = ERRmoredata; + /* + * This is the old error code we used. Aparently + * WinNT/2k systems return ERRbuftoosmall (2123) and + * OS/2 needs this. I'm leaving this here so we can revert + * if needed. JRA. + */ + p->errcode = ERRmoredata; #else - p->errcode = ERRbuftoosmall; + p->errcode = ERRbuftoosmall; #endif - } - else - p->errcode = NERR_Success; - p->buflen = i; - n -= i; - p->stringbuf = p->base + i; - p->stringlen = n; - return(p->errcode == NERR_Success); + } else { + p->errcode = NERR_Success; + } + p->buflen = i; + n -= i; + p->stringbuf = p->base + i; + p->stringlen = n; + return (p->errcode == NERR_Success); } -static int package(struct pack_desc* p, ...) +static int package(struct pack_desc *p, ...) { - va_list args; - int needed=0, stringneeded; - char* str=NULL; - int is_string=0, stringused; - int32 temp; - - va_start(args,p); - - if (!*p->curpos) { - if (!p->subcount) - p->curpos = p->format; - else { - p->curpos = p->subformat; - p->subcount--; - } - } + va_list args; + int needed=0, stringneeded; + const char *str=NULL; + int is_string=0, stringused; + int32 temp; + + va_start(args,p); + + 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*); - SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); + str = va_arg(args,char*); + SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); #endif - stringneeded = -1; - - if (!p->curpos) { - va_end(args); - 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 'K': /* status 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-1); - } - 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 = ERRmoredata; - } - 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 = ERRmoredata; - } - return 1; + stringneeded = -1; + + if (!p->curpos) { + va_end(args); + 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 'K': /* status 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-1); + } + } + 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 = ERRmoredata; + } + } + 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 = ERRmoredata; + } + } + return 1; } #if CHECK_TYPES @@ -332,67 +380,72 @@ static int package(struct pack_desc* p, ...) #define PACKl(desc,t,v,l) package(desc,v,l) #endif -static void PACKI(struct pack_desc* desc,char *t,int v) +static void PACKI(struct pack_desc* desc, const char *t,int v) { - PACK(desc,t,v); + PACK(desc,t,v); } -static void PACKS(struct pack_desc* desc,char *t,char *v) +static void PACKS(struct pack_desc* desc,const char *t,const char *v) { - PACK(desc,t,v); + PACK(desc,t,v); } - /**************************************************************************** - get a print queue - ****************************************************************************/ + Get a print queue. +****************************************************************************/ + 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 */ - push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE); - PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ + char drivdata[4+4+32]; + SIVAL(drivdata,0,sizeof drivdata); /* cb */ + SIVAL(drivdata,4,1000); /* lVersion */ + memset(drivdata+8,0,32); /* szDeviceName */ + push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE); + PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ } static int check_printq_info(struct pack_desc* desc, - int uLevel, char *id1, char *id2) + unsigned int uLevel, char *id1, 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; - case 51: - desc->format = "K"; - break; - case 52: - desc->format = "WzzzzzzzzN"; - desc->subformat = "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; + 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; + case 51: + desc->format = "K"; + break; + case 52: + desc->format = "WzzzzzzzzN"; + desc->subformat = "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; } @@ -436,66 +489,66 @@ static int printq_status(int v) } static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc, - print_queue_struct* queue, int n) + struct pack_desc *desc, + print_queue_struct *queue, int n) { - time_t t = queue->time; - - /* the client expects localtime */ - t -= TimeDiff(t); - - PACKI(desc,"W",queue->job); /* 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",printj_status(queue->status)); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",t); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z",queue->file); /* pszComment */ - } - if (uLevel == 2 || uLevel == 3 || uLevel == 4) { - PACKI(desc,"W",queue->priority); /* uPriority */ - PACKS(desc,"z",queue->user); /* pszUserName */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ - PACKI(desc,"D",t); /* 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 */ - } else if (uLevel == 4) { /* OS2 */ - PACKS(desc,"z",""); /* pszSpoolFileName */ - PACKS(desc,"z",""); /* pszPortName */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",0); /* ulPagesSpooled */ - PACKI(desc,"D",0); /* ulPagesSent */ - PACKI(desc,"D",0); /* ulPagesPrinted */ - PACKI(desc,"D",0); /* ulTimePrinted */ - PACKI(desc,"D",0); /* ulExtendJobStatus */ - PACKI(desc,"D",0); /* ulStartPage */ - PACKI(desc,"D",0); /* ulEndPage */ - } - } + time_t t = queue->time; + + /* the client expects localtime */ + t -= get_time_zone(t); + + PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */ + if (uLevel == 1) { + PACKS(desc,"B21",queue->fs_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",printj_status(queue->status)); /* fsStatus */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"D",t); /* ulSubmitted */ + PACKI(desc,"D",queue->size); /* ulSize */ + PACKS(desc,"z",queue->fs_file); /* pszComment */ + } + if (uLevel == 2 || uLevel == 3 || uLevel == 4) { + PACKI(desc,"W",queue->priority); /* uPriority */ + PACKS(desc,"z",queue->fs_user); /* pszUserName */ + PACKI(desc,"W",n+1); /* uPosition */ + PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ + PACKI(desc,"D",t); /* ulSubmitted */ + PACKI(desc,"D",queue->size); /* ulSize */ + PACKS(desc,"z","Samba"); /* pszComment */ + PACKS(desc,"z",queue->fs_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 */ + } else if (uLevel == 4) { /* OS2 */ + PACKS(desc,"z",""); /* pszSpoolFileName */ + PACKS(desc,"z",""); /* pszPortName */ + PACKS(desc,"z",""); /* pszStatus */ + PACKI(desc,"D",0); /* ulPagesSpooled */ + PACKI(desc,"D",0); /* ulPagesSent */ + PACKI(desc,"D",0); /* ulPagesPrinted */ + PACKI(desc,"D",0); /* ulTimePrinted */ + PACKI(desc,"D",0); /* ulExtendJobStatus */ + PACKI(desc,"D",0); /* ulStartPage */ + PACKI(desc,"D",0); /* ulEndPage */ + } + } } /******************************************************************** Return a driver name given an snum. - Looks in a tdb first. Returns True if from tdb, False otherwise. + Returns True if from tdb, False otherwise. ********************************************************************/ static BOOL get_driver_name(int snum, pstring drivername) @@ -503,13 +556,11 @@ static BOOL get_driver_name(int snum, pstring drivername) NT_PRINTER_INFO_LEVEL *info = NULL; BOOL in_tdb = False; - get_a_printer (&info, 2, lp_servicename(snum)); + get_a_printer (NULL, &info, 2, lp_servicename(snum)); if (info != NULL) { pstrcpy( drivername, info->info_2->drivername); in_tdb = True; free_a_printer(&info, 2); - } else { - pstrcpy( drivername, lp_printerdriver(snum)); } return in_tdb; @@ -519,162 +570,84 @@ static BOOL get_driver_name(int snum, pstring drivername) Respond to the DosPrintQInfo command with a level of 52 This is used to get printer driver information for Win9x clients ********************************************************************/ -static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc, - int count, print_queue_struct* queue, - print_status_struct* status) +static void fill_printq_info_52(connection_struct *conn, int snum, + struct pack_desc* desc, int count ) { - int i; - BOOL ok = False; - pstring tok,driver,datafile,langmon,helpfile,datatype; - char *p; - char **lines = NULL; - pstring gen_line; - BOOL in_tdb = False; - fstring location; - pstring drivername; - - /* - * Check in the tdb *first* before checking the legacy - * files. This allows an NT upload to take precedence over - * the existing fileset. JRA. - * - * we need to lookup the driver name prior to making the call - * to get_a_printer_driver_9x_compatible() and not rely on the - * 'print driver' parameter --jerry - */ + int i; + fstring location; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + NT_PRINTER_INFO_LEVEL *printer = NULL; + ZERO_STRUCT(driver); - if ((get_driver_name(snum,drivername)) && - ((ok = get_a_printer_driver_9x_compatible(gen_line, drivername)) == True)) - { - in_tdb = True; - p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line)); - } - else - { - /* didn't find driver in tdb */ - - DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n", - snum, drivername, lp_driverfile(snum))); - - lines = file_lines_load(lp_driverfile(snum),NULL); - if (!lines) - { - DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum), - strerror(errno))); - desc->errcode=NERR_notsupported; - goto done; - } - - /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) - { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(drivername) == strlen(tok)) && - (!strncmp(tok,drivername,strlen(drivername)))) - { - ok = True; - } - } + if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { + DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", + lp_servicename(snum))); + goto err; } - - if (ok) + + if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, + "Windows 4.0", 0)) ) { - /* driver file name */ - if (!next_token(&p,driver,":",sizeof(driver))) - goto err; - - /* data file name */ - if (!next_token(&p,datafile,":",sizeof(datafile))) - goto err; - - /* - * 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 */ + DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n", + printer->info_2->drivername)); + goto err; + } - /* help file */ - if (*p == ':') - { - *helpfile = '\0'; - p++; - } - else if (!next_token(&p,helpfile,":",sizeof(helpfile))) - goto err; + trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0); + trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0); + trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0); - /* language monitor */ - if (*p == ':') - { - *langmon = '\0'; - p++; - } - else if (!next_token(&p,langmon,":",sizeof(langmon))) - goto err; + PACKI(desc, "W", 0x0400); /* don't know */ + PACKS(desc, "z", driver.info_3->name); /* long printer name */ + PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */ + PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */ + PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */ - /* default data type */ - if (!next_token(&p,datatype,":",sizeof(datatype))) - goto err; + fstrcpy(location, "\\\\%L\\print$\\WIN40\\0"); + standard_sub_basic( "", "", location, sizeof(location)-1 ); + PACKS(desc,"z", location); /* share to retrieve files */ - PACKI(desc,"W",0x0400); /* don't know */ - PACKS(desc,"z",drivername); /* long printer name */ - PACKS(desc,"z",driver); /* Driverfile Name */ - PACKS(desc,"z",datafile); /* Datafile name */ - PACKS(desc,"z",langmon); /* language monitor */ - if (in_tdb) - { - fstrcpy(location, "\\\\"); - fstrcat(location, global_myname); - fstrcat(location, "\\print$\\WIN40\\0"); - PACKS(desc,"z",location); /* share to retrieve files */ - } - else - { - 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,("printerdriver:%s:\n",drivername)); - DEBUG(3,("Driver:%s:\n",driver)); - DEBUG(3,("Data File:%s:\n",datafile)); - DEBUG(3,("Language Monitor:%s:\n",langmon)); - if (in_tdb) - DEBUG(3,("lp_driverlocation:%s:\n",location)); - else - DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum))); - 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 gave %d entries\n", - SERVICE(snum),count)); - - desc->errcode=NERR_Success; - goto done; + PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ + PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */ + PACKS(desc,"z", driver.info_3->driverpath); /* driver name */ + + DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name)); + DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath)); + DEBUG(3,("Data File: %s:\n",driver.info_3->datafile)); + DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname)); + DEBUG(3,("Driver Location: %s:\n",location)); + DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype)); + DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile)); + PACKI(desc,"N",count); /* number of files to copy */ + + for ( i=0; idependentfiles && *driver.info_3->dependentfiles[i]; i++) + { + trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0); + PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */ + DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i])); } + + /* sanity check */ + if ( i != count ) + DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n", + count, i)); + + DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i)); - err: + desc->errcode=NERR_Success; + goto done; +err: DEBUG(3,("fill_printq_info: Can't supply driver files\n")); desc->errcode=NERR_notsupported; - done: - file_lines_free(lines); +done: + if ( printer ) + free_a_printer( &printer, 2 ); + + if ( driver.info_3 ) + free_a_printer_driver( driver, 3 ); } @@ -752,88 +725,44 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel, fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i); } - if (uLevel==52) { - fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status); - } + if (uLevel==52) + fill_printq_info_52( conn, snum, desc, count ); } /* This function returns the number of files for a given driver */ static int get_printerdrivernumber(int snum) { - int i, result = 0; - BOOL ok = False; - pstring tok; - char *p; - char **lines = NULL; - pstring gen_line; - pstring drivername; - - /* - * Check in the tdb *first* before checking the legacy - * files. This allows an NT upload to take precedence over - * the existing fileset. JRA. - * - * we need to lookup the driver name prior to making the call - * to get_a_printer_driver_9x_compatible() and not rely on the - * 'print driver' parameter --jerry - */ - - if ((get_driver_name(snum,drivername)) && - (ok = get_a_printer_driver_9x_compatible(gen_line, drivername) == True)) - { - p = gen_line; - DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line)); - } - else - { - /* didn't find driver in tdb */ - - DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n", - snum, drivername, lp_driverfile(snum))); - - lines = file_lines_load(lp_driverfile(snum), NULL); - if (!lines) - { - DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno))); - goto done; - } + int result = 0; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + NT_PRINTER_INFO_LEVEL *printer = NULL; - /* lookup the long printer driver name in the file description */ - for (i=0;lines[i] && !ok;i++) - { - p = lines[i]; - if (next_token(&p,tok,":",sizeof(tok)) && - (strlen(drivername) == strlen(tok)) && - (!strncmp(tok,drivername,strlen(drivername)))) - { - ok = True; - } - } + ZERO_STRUCT(driver); + + if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { + DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", + lp_servicename(snum))); + goto done; } - - if( ok ) - { - /* skip 5 fields */ - i = 5; - while (*p && i) { - if (*p++ == ':') i--; - } - if (!*p || i) { - DEBUG(3,("Can't determine number of printer driver files\n")); - goto done; - } - /* count the number of files */ - while (next_token(&p,tok,",",sizeof(tok))) - i++; - - result = i; + if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, + "Windows 4.0", 0)) ) + { + DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n", + printer->info_2->drivername)); + goto done; } - + + /* count the number of files */ + while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] ) + result++; + \ done: - - file_lines_free(lines); - + if ( printer ) + free_a_printer( &printer, 2 ); + + if ( driver.info_3 ) + free_a_printer_driver( driver, 3 ); + return result; } @@ -847,7 +776,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); char *QueueName = p; - int uLevel; + unsigned int uLevel; int count=0; int snum; char* str3; @@ -880,25 +809,20 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, */ *rdata_len = 0; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,ERRunknownlevel); SSVAL(*rparam,2,0); SSVAL(*rparam,4,0); return(True); } - 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); - + snum = find_service(QueueName); + if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) + return False; + if (uLevel==52) { count = get_printerdrivernumber(snum); DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); @@ -907,7 +831,10 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, } if (mdrcnt > 0) { - *rdata = REALLOC(*rdata,mdrcnt); + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } desc.base = *rdata; desc.buflen = mdrcnt; } else { @@ -916,7 +843,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, * init_package will return wrong size if buflen=0 */ desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *) malloc (desc.buflen); + desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen); } if (init_package(&desc,1,count)) { @@ -934,9 +861,12 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, if (!mdrcnt && lp_disable_spoolss()) desc.errcode = ERRbuftoosmall; - *rdata_len = desc.usedlen; + *rdata_len = desc.usedlen; *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } SSVALS(*rparam,0,desc.errcode); SSVAL(*rparam,2,0); SSVAL(*rparam,4,desc.neededlen); @@ -958,604 +888,702 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, 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; + char *param_format = param+2; + char *output_format1 = skip_string(param_format,1); + char *p = skip_string(output_format1,1); + unsigned 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 = 0, subcnt = 0, succnt = 0; - memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); - DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); + 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)) { - /* - * Patch from Scott Moomaw - * to return the 'invalid info level' error if an - * unknown level was requested. - */ - *rdata_len = 0; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,ERRunknownlevel); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,0); - return(True); - } - - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - if (uLevel > 0) { - if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - memset(queue,0,queuecnt*sizeof(print_queue_struct*)); - if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - memset(status,0,queuecnt*sizeof(print_status_struct)); - if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) { - DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); - return False; - } - subcnt = 0; - n = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - subcntarr[n] = print_queue_status(i, &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(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } - - SAFE_FREE(subcntarr); + if (!prefix_ok(param_format,"WrLeh")) { + return False; + } + if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) { + /* + * Patch from Scott Moomaw + * to return the 'invalid info level' error if an + * unknown level was requested. + */ + *rdata_len = 0; + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVALS(*rparam,0,ERRunknownlevel); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,0); + return(True); + } + + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + queuecnt++; + } + } + + if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + goto err; + } + memset(queue,0,queuecnt*sizeof(print_queue_struct*)); + if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + goto err; + } + memset(status,0,queuecnt*sizeof(print_status_struct)); + if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) { + DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); + goto err; + } + + subcnt = 0; + n = 0; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + subcntarr[n] = print_queue_status(i, &queue[n],&status[n]); + subcnt += subcntarr[n]; + n++; + } + } + + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + goto err; + } + } + 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(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); + n++; + if (desc.errcode == NERR_Success) { + succnt = n; + } + } + } + } + + SAFE_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); + *rdata_len = desc.usedlen; + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + goto err; + } + 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) SAFE_FREE(queue[i]); - } + for (i = 0; i < queuecnt; i++) { + if (queue) { + SAFE_FREE(queue[i]); + } + } - SAFE_FREE(queue); - SAFE_FREE(status); + SAFE_FREE(queue); + SAFE_FREE(status); - return True; + return True; + + err: + + SAFE_FREE(subcntarr); + for (i = 0; i < queuecnt; i++) { + if (queue) { + SAFE_FREE(queue[i]); + } + } + SAFE_FREE(queue); + SAFE_FREE(status); + + return False; } /**************************************************************************** - get info level for a server list query - ****************************************************************************/ + Get info level for a server list query. +****************************************************************************/ + static BOOL check_server_info(int uLevel, char* id) { - 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; + 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; } -struct srv_info_struct -{ - fstring name; - uint32 type; - fstring comment; - fstring domain; - BOOL server_added; +struct srv_info_struct { + fstring name; + uint32 type; + fstring comment; + fstring domain; + BOOL server_added; }; - /******************************************************************* - get server info lists from the files saved by nmbd. Return the - number of entries - ******************************************************************/ + 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, - char *domain) + const char *domain) { - int count=0; - int alloced=0; - char **lines; - BOOL local_list_only; - int i; + int count=0; + int alloced=0; + char **lines; + BOOL local_list_only; + int i; - lines = file_lines_load(lock_path(SERVER_LIST), NULL); - if (!lines) { - DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); - return(0); - } + lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0); + if (!lines) { + DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); + return 0; + } - /* request for everything is code for request all servers */ - if (servertype == SV_TYPE_ALL) - servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + /* request for everything is code for request all servers */ + if (servertype == SV_TYPE_ALL) { + servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); + } - local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); + local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); - DEBUG(4,("Servertype search: %8x\n",servertype)); + DEBUG(4,("Servertype search: %8x\n",servertype)); - for (i=0;lines[i];i++) { - fstring stype; - struct srv_info_struct *s; - char *ptr = lines[i]; - BOOL ok = True; + for (i=0;lines[i];i++) { + fstring stype; + struct srv_info_struct *s; + const char *ptr = lines[i]; + BOOL ok = True; - if (!*ptr) continue; + if (!*ptr) { + continue; + } - if (count == alloced) { - struct srv_info_struct *ts; - - alloced += 10; - ts = (struct srv_info_struct *) - Realloc(*servers,sizeof(**servers)*alloced); - if (!ts) { - DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); - return(0); - } - else *servers = ts; - memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); - } - s = &(*servers)[count]; + if (count == alloced) { + alloced += 10; + *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); + if (!*servers) { + DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); + file_lines_free(lines); + return 0; + } + memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); + } + s = &(*servers)[count]; - if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue; - if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue; - if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue; - if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) { - /* this allows us to cope with an old nmbd */ - pstrcpy(s->domain,global_myworkgroup); - } + if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) { + continue; + } + if (!next_token(&ptr,stype, NULL, sizeof(stype))) { + continue; + } + if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) { + continue; + } + if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) { + /* this allows us to cope with an old nmbd */ + fstrcpy(s->domain,lp_workgroup()); + } - if (sscanf(stype,"%X",&s->type) != 1) { - DEBUG(4,("r:host file ")); - ok = False; - } + if (sscanf(stype,"%X",&s->type) != 1) { + DEBUG(4,("r:host file ")); + ok = False; + } - /* Filter the servers/domains we return based on what was asked for. */ + /* 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; - } + /* 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; - } + /* 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) != - (s->type & SV_TYPE_DOMAIN_ENUM)) - { - DEBUG(4,("s: dom mismatch ")); - ok = False; - } + if ((servertype & SV_TYPE_DOMAIN_ENUM) != + (s->type & SV_TYPE_DOMAIN_ENUM)) { + DEBUG(4,("s: dom mismatch ")); + ok = False; + } - if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) - { - ok = False; - } + if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) { + ok = False; + } - /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ - s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; - - if (ok) - { - DEBUG(4,("**SV** %20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - - s->server_added = True; - count++; - } - else - { - DEBUG(4,("%20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - } - } + /* 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->server_added = True; + count++; + } else { + DEBUG(4,("%20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); + } + } - file_lines_free(lines); - return(count); + file_lines_free(lines); + return count; } - /******************************************************************* - fill in a server info structure - ******************************************************************/ + 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; - } + int struct_len; + char* p; + char* p2; + int l2; + int len; - if (!buf) - { - len = 0; - switch (uLevel) - { - case 1: - len = strlen(service->comment)+1; - break; + 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; - } + 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; + 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: - push_ascii(p,service->name, 15, STR_TERMINATE); - break; - - case 1: - push_ascii(p,service->name,15, STR_TERMINATE); - 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; + switch (uLevel) { + case 0: + push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE); + break; + + case 1: + push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE); + 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; } static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) { - return(strcmp(s1->name,s2->name)); + return(strcmp(s1->name,s2->name)); } /**************************************************************************** - view list of servers available (or possibly domains). The info is - extracted from lists saved by nmbd on the local host - ****************************************************************************/ + 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(connection_struct *conn, 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); - uint32 servertype = IVAL(p,4); - char *p2; - int data_len, fixed_len, string_len; - int f_len = 0, s_len = 0; - struct srv_info_struct *servers=NULL; - int counted=0,total=0; - int i,missed; - fstring domain; - BOOL domain_request; - 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 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); - - p += 8; - - if (!prefix_ok(str1,"WrLehD")) return False; - if (!check_server_info(uLevel,str2)) return False; + 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 = 0, s_len = 0; + struct srv_info_struct *servers=NULL; + int counted=0,total=0; + int i,missed; + fstring domain; + BOOL domain_request; + 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 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); + + p += 8; + + if (!prefix_ok(str1,"WrLehD")) { + return False; + } + if (!check_server_info(uLevel,str2)) { + return False; + } - DEBUG(4, ("server request level: %s %8x ", str2, servertype)); - DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request))); - DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); - - if (strcmp(str1, "WrLehDz") == 0) { - pull_ascii_fstring(domain, p); - } else { - fstrcpy(domain, global_myworkgroup); - } - - if (lp_browse_list()) - total = get_server_info(servertype,&servers,domain); - - data_len = fixed_len = string_len = 0; - missed = 0; - - if (total > 0) - qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); - - { - char *lastname=NULL; - - for (i=0;iname)) 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)); + DEBUG(4, ("server request level: %s %8x ", str2, servertype)); + DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request))); + DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); + + if (strcmp(str1, "WrLehDz") == 0) { + pull_ascii_fstring(domain, p); + } else { + fstrcpy(domain, lp_workgroup()); + } + + if (lp_browse_list()) { + total = get_server_info(servertype,&servers,domain); + } + + data_len = fixed_len = string_len = 0; + missed = 0; + + if (total > 0) { + qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); + } + + { + char *lastname=NULL; + + for (i=0;iname)) { + 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++; - } - } - } - - *rdata_len = fixed_len + string_len; - *rdata = REALLOC(*rdata,*rdata_len); - memset(*rdata,'\0',*rdata_len); + if (data_len <= buf_len) { + counted++; + fixed_len += f_len; + string_len += s_len; + } else { + missed++; + } + } + } + + *rdata_len = fixed_len + string_len; + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } + memset(*rdata,'\0',*rdata_len); - p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ - p = *rdata; - f_len = fixed_len; - s_len = string_len; - - { - char *lastname=NULL; - int count2 = counted; - for (i = 0; i < total && count2;i++) - { - struct srv_info_struct *s = &servers[i]; - if (lastname && strequal(lastname,s->name)) continue; - lastname = s->name; - fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata); - DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - count2--; - } - } + p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ + p = *rdata; + f_len = fixed_len; + s_len = string_len; + + { + char *lastname=NULL; + int count2 = counted; + + for (i = 0; i < total && count2;i++) { + struct srv_info_struct *s = &servers[i]; + + if (lastname && strequal(lastname,s->name)) { + continue; + } + lastname = s->name; + fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata); + DEBUG(4,("fill_srv_info %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,(missed == 0 ? NERR_Success : ERRmoredata)); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,counted+missed); + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,counted); + SSVAL(*rparam,6,counted+missed); - SAFE_FREE(servers); + SAFE_FREE(servers); - DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", - domain,uLevel,counted,counted+missed)); + DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", + domain,uLevel,counted,counted+missed)); - return(True); + return True; } /**************************************************************************** command 0x34 - suspected of being a "Lookup Names" stub api ****************************************************************************/ + static BOOL api_RNetGroupGetUsers(connection_struct *conn, 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; + 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; + if (!prefix_ok(str1,"zWrLeh")) { + return False; + } - *rdata_len = 0; + *rdata_len = 0; - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } - SSVAL(*rparam,0,0x08AC); /* informational warning message */ - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,counted+missed); + SSVAL(*rparam,0,0x08AC); /* informational warning message */ + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,counted); + SSVAL(*rparam,6,counted+missed); - return(True); + return True; } /**************************************************************************** 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; + 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; } static int fill_share_info(connection_struct *conn, 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; + 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; - } + 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(conn,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; - } + if (!buf) { + len = 0; + + if (uLevel > 0) { + len += StrlenExpanded(conn,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; + 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; + } - push_ascii(p,lp_servicename(snum),13, STR_TERMINATE); + push_ascii(p,lp_servicename(snum),13, STR_TERMINATE); - if (uLevel > 0) - { - int type; - SCVAL(p,13,0); - type = STYPE_DISKTREE; - if (lp_print_ok(snum)) type = STYPE_PRINTQ; - if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC; - SSVAL(p,14,type); /* device type */ - SIVAL(p,16,PTR_DIFF(p2,baseaddr)); - len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); - } + if (uLevel > 0) { + int type; + + SCVAL(p,13,0); + type = STYPE_DISKTREE; + if (lp_print_ok(snum)) { + type = STYPE_PRINTQ; + } + if (strequal("IPC",lp_fstype(snum))) { + type = STYPE_IPC; + } + SSVAL(p,14,type); /* device type */ + SIVAL(p,16,PTR_DIFF(p2,baseaddr)); + len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); + } - if (uLevel > 1) - { - SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ - SSVALS(p,22,-1); /* max uses */ - 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 > 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 (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; + if (stringbuf) { + (*buf) = p + struct_len; + (*buflen) -= struct_len; + (*stringbuf) = p2; + (*stringspace) = l2; + } else { + (*buf) = p2; + (*buflen) -= len; + } + + return len; } static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, @@ -1563,351 +1591,657 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para 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); + 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; + 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; + /* 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(conn,snum,uLevel,&p,&mdrcnt,0,0,0); - if (*rdata_len < 0) return False; + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + p = *rdata; + *rdata_len = fill_share_info(conn,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); + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); - return(True); + return True; } /**************************************************************************** - view list of shares available - ****************************************************************************/ -static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) + View the list of available shares. + + This function is the server side of the NetShareEnum() RAP call. + It fills the return buffer with share names and share comments. + Note that the return buffer normally (in all known cases) allows only + twelve byte strings for share names (plus one for a nul terminator). + Share names longer than 12 bytes must be skipped. + ****************************************************************************/ + +static BOOL api_RNetShareEnum( connection_struct *conn, + 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); - char *p2; - int count=lp_numservices(); - int total=0,counted=0; - BOOL missed = False; - int i; - int data_len, fixed_len, string_len; - int f_len = 0, s_len = 0; + 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 = 0; + int total=0,counted=0; + BOOL missed = False; + int i; + int data_len, fixed_len, string_len; + int f_len = 0, s_len = 0; - if (!prefix_ok(str1,"WrLeh")) return False; - if (!check_share_info(uLevel,str2)) return False; + 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= 0) { /* already exists */ - res = ERRfilexists; - goto error_exit; - } - - /* only support disk share adds */ - if (SVAL(data,14)!=STYPE_DISKTREE) return False; - - offset = IVAL(data, 16); - if (offset >= mdrcnt) { - res = ERRinvalidparam; - goto error_exit; - } - pull_ascii_fstring(comment, offset? (data+offset) : ""); - - offset = IVAL(data, 26); - if (offset >= mdrcnt) { - res = ERRinvalidparam; - goto error_exit; - } - pull_ascii_pstring(pathname, offset? (data+offset) : ""); - - string_replace(sharename, '"', ' '); - string_replace(pathname, '"', ' '); - string_replace(comment, '"', ' '); - - cmdname = lp_add_share_cmd(); - - if (!cmdname || *cmdname == '\0') return False; - - asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", - lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment); - - if (command) { - DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); - if ((res = smbrun(command, NULL)) != 0) { - DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); - SAFE_FREE(command); - res = ERRnoaccess; - goto error_exit; - } else { - SAFE_FREE(command); - message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); - } - } else 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); - *rdata_len = 0; - - return True; - - error_exit: - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; - SSVAL(*rparam,0,res); - SSVAL(*rparam,2,0); - return True; - -} - -/**************************************************************************** - view list of groups available - ****************************************************************************/ -static BOOL api_RNetGroupEnum(connection_struct *conn,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); - char *p2; - int count=0; - - if (!prefix_ok(str1,"WrLeh")) return False; + fstring sharename; + fstring comment; + pstring pathname; + char *command, *cmdname; + unsigned int offset; + int snum; + int res = ERRunsup; - /* check it's a supported variant */ - switch( uLevel ) - { - case 0: - p2 = "B21"; - break; - default: - return False; + /* check it's a supported varient */ + if (!prefix_ok(str1,RAP_WShareAdd_REQ)) { + return False; + } + if (!check_share_info(uLevel,str2)) { + return False; + } + if (uLevel != 2) { + return False; } - if (strcmp(p2,str2) != 0) return False; + pull_ascii_fstring(sharename,data); + snum = find_service(sharename); + if (snum >= 0) { /* already exists */ + res = ERRfilexists; + goto error_exit; + } - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); + /* only support disk share adds */ + if (SVAL(data,14)!=STYPE_DISKTREE) { + return False; + } - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ + offset = IVAL(data, 16); + if (offset >= mdrcnt) { + res = ERRinvalidparam; + goto error_exit; + } - p = *rdata; + pull_ascii_fstring(comment, offset? (data+offset) : ""); - /* XXXX we need a real SAM database some day */ - pstrcpy(p,"Users"); p += 21; count++; - pstrcpy(p,"Domain Users"); p += 21; count++; - pstrcpy(p,"Guests"); p += 21; count++; - pstrcpy(p,"Domain Guests"); p += 21; count++; + offset = IVAL(data, 26); - *rdata_len = PTR_DIFF(p,*rdata); + if (offset >= mdrcnt) { + res = ERRinvalidparam; + goto error_exit; + } - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); + pull_ascii_pstring(pathname, offset? (data+offset) : ""); - SSVAL(*rparam,4,count); /* is this right?? */ - SSVAL(*rparam,6,count); /* is this right?? */ + string_replace(sharename, '"', ' '); + string_replace(pathname, '"', ' '); + string_replace(comment, '"', ' '); - DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count)); + cmdname = lp_add_share_cmd(); - return(True); + if (!cmdname || *cmdname == '\0') { + return False; + } + + asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", + lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment); + + if (command) { + DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); + + if ((res = smbrun(command, NULL)) != 0) { + DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); + SAFE_FREE(command); + res = ERRnoaccess; + goto error_exit; + } else { + SAFE_FREE(command); + message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); + } + } else { + return False; + } + + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + *rdata_len = 0; + + return True; + + error_exit: + + *rparam_len = 4; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + *rdata_len = 0; + SSVAL(*rparam,0,res); + SSVAL(*rparam,2,0); + return True; } /**************************************************************************** view list of groups available ****************************************************************************/ -static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + +static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { + int i; + int errflags=0; + int resume_context, cli_buf_size; char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); + + struct pdb_search *search; + struct samr_displayentry *entries; + + int num_entries; + + if (strcmp(str1,"WrLeh") != 0) { + return False; + } + + /* parameters + * W-> resume context (number of users to skip) + * r -> return parameter pointer to receive buffer + * L -> length of receive buffer + * e -> return parameter number of entries + * h -> return parameter total number of users + */ + + if (strcmp("B21",str2) != 0) { + return False; + } + + /* get list of domain groups SID_DOMAIN_GRP=2 */ + become_root(); + search = pdb_search_groups(); + unbecome_root(); + + if (search == NULL) { + DEBUG(3,("api_RNetGroupEnum:failed to get group list")); + return False; + } + + resume_context = SVAL(p,0); + cli_buf_size=SVAL(p+2,0); + DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: " + "%d\n", resume_context, cli_buf_size)); + + become_root(); + num_entries = pdb_search_entries(search, resume_context, 0xffffffff, + &entries); + unbecome_root(); + + *rdata_len = cli_buf_size; + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } + + p = *rdata; + + for(i=0; i resume context (number of users to skip) + * r -> return parameter pointer to receive buffer + * L -> length of receive buffer + * e -> return parameter number of entries + * h -> return parameter total number of users + */ + + resume_context = SVAL(p,0); + cli_buf_size=SVAL(p+2,0); + DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", + resume_context, cli_buf_size)); + + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + + /* check it's a supported varient */ + if (strcmp("B21",str2) != 0) + return False; + + *rdata_len = cli_buf_size; + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } + + p = *rdata; + + become_root(); + search = pdb_search_users(ACB_NORMAL); + unbecome_root(); + if (search == NULL) { + DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n")); + return False; + } + + become_root(); + num_users = pdb_search_entries(search, resume_context, 0xffffffff, + &users); + unbecome_root(); + + errflags=NERR_Success; + + for (i=0; itm_hour); - SCVAL(p,9,t->tm_min); - SCVAL(p,10,t->tm_sec); - SCVAL(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 */ - SCVAL(p,16,t->tm_mday); - SCVAL(p,17,t->tm_mon + 1); - SSVAL(p,18,1900+t->tm_year); - SCVAL(p,20,t->tm_wday); - } + /* the client expects to get localtime, not GMT, in this bit + (I think, this needs testing) */ + t = localtime(&unixdate); + if (!t) { + return False; + } + SIVAL(p,4,0); /* msecs ? */ + SCVAL(p,8,t->tm_hour); + SCVAL(p,9,t->tm_min); + SCVAL(p,10,t->tm_sec); + SCVAL(p,11,0); /* hundredths of seconds */ + SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */ + SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ + SCVAL(p,16,t->tm_mday); + SCVAL(p,17,t->tm_mon + 1); + SSVAL(p,18,1900+t->tm_year); + SCVAL(p,20,t->tm_wday); - return(True); + return True; } /**************************************************************************** @@ -1919,93 +2253,81 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *p = skip_string(param+2,2); - fstring user; - fstring pass1,pass2; + char *p = skip_string(param+2,2); + fstring user; + fstring pass1,pass2; - pull_ascii_fstring(user,p); + pull_ascii_fstring(user,p); - p = skip_string(p,1); + p = skip_string(p,1); - memset(pass1,'\0',sizeof(pass1)); - memset(pass2,'\0',sizeof(pass2)); - memcpy(pass1,p,16); - memcpy(pass2,p+16,16); + memset(pass1,'\0',sizeof(pass1)); + memset(pass2,'\0',sizeof(pass2)); + memcpy(pass1,p,16); + memcpy(pass2,p+16,16); - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam_len = 4; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_badpass); - SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,0,NERR_badpass); + SSVAL(*rparam,2,0); /* converter word */ - DEBUG(3,("Set password for <%s>\n",user)); + DEBUG(3,("Set password for <%s>\n",user)); - /* - * Attempt to verify the old password against smbpasswd entries - * Win98 clients send old and new password in plaintext for this call. - */ + /* + * Attempt to verify the old password against smbpasswd entries + * Win98 clients send old and new password in plaintext for this call. + */ - { - auth_serversupplied_info *server_info = NULL; - DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); - if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - if (change_oem_password(server_info->sam_account,pass2)) - { - SSVAL(*rparam,0,NERR_Success); - } - - /* - * If unix password sync was requested, attempt to change - * the /etc/passwd database also. Return failure if this cannot - * be done. - * - * This occours regardless of the previous result, becouse - * It might not have been testing the password against the SAM backend. - * (and therefore the change_oem_password would fail). - * - * Conditional on lp_unix_password_sync() becouse we don't want - * to touch the unix db unless we have admin permission. - */ - - if(lp_unix_password_sync() && !chgpasswd(pdb_get_username(server_info->sam_account), - pass1,pass2,False)) { - SSVAL(*rparam,0,NERR_badpass); - } - - free_server_info(&server_info); - } - data_blob_clear_free(&password); - } - - /* - * If the plaintext change failed, attempt - * the old encrypted method. NT will generate this - * after trying the samr method. Note that this - * method is done as a last resort as this - * password change method loses the NT password hash - * and cannot change the UNIX password as no plaintext - * is received. - */ + { + auth_serversupplied_info *server_info = NULL; + DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); + + if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { + + become_root(); + if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) { + SSVAL(*rparam,0,NERR_Success); + } + unbecome_root(); + + TALLOC_FREE(server_info); + } + data_blob_clear_free(&password); + } - if(SVAL(*rparam,0) != NERR_Success) - { - SAM_ACCOUNT *hnd = NULL; + /* + * If the plaintext change failed, attempt + * the old encrypted method. NT will generate this + * after trying the samr method. Note that this + * method is done as a last resort as this + * password change method loses the NT password hash + * and cannot change the UNIX password as no plaintext + * is received. + */ - if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) && - change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2)) - { - SSVAL(*rparam,0,NERR_Success); - } - pdb_free_sam(&hnd); - } + if(SVAL(*rparam,0) != NERR_Success) { + struct samu *hnd = NULL; + if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { + become_root(); + if (change_lanman_password(hnd,(uchar *)pass2)) { + SSVAL(*rparam,0,NERR_Success); + } + unbecome_root(); + TALLOC_FREE(hnd); + } + } - memset((char *)pass1,'\0',sizeof(fstring)); - memset((char *)pass2,'\0',sizeof(fstring)); + memset((char *)pass1,'\0',sizeof(fstring)); + memset((char *)pass2,'\0',sizeof(fstring)); - return(True); + return(True); } /**************************************************************************** @@ -2017,53 +2339,56 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - fstring user; - char *p = param + 2; - *rparam_len = 2; - *rparam = REALLOC(*rparam,*rparam_len); + fstring user; + char *p = param + 2; + *rparam_len = 2; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_badpass); + SSVAL(*rparam,0,NERR_badpass); - /* - * Check the parameter definition is correct. - */ - if(!strequal(param + 2, "zsT")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); - return False; - } - p = skip_string(p, 1); + /* + * Check the parameter definition is correct. + */ - if(!strequal(p, "B516B16")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); - return False; - } - p = skip_string(p,1); + if(!strequal(param + 2, "zsT")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); + return False; + } + p = skip_string(p, 1); - p += pull_ascii_fstring(user,p); + if(!strequal(p, "B516B16")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); + return False; + } + p = skip_string(p,1); + p += pull_ascii_fstring(user,p); - DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); + DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); - /* - * Pass the user through the NT -> unix user mapping - * function. - */ + /* + * Pass the user through the NT -> unix user mapping + * function. + */ - (void)map_username(user); + (void)map_username(user); - if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)) - { - SSVAL(*rparam,0,NERR_Success); - } + if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) { + SSVAL(*rparam,0,NERR_Success); + } - return(True); + return(True); } /**************************************************************************** delete a print job Form: <> ****************************************************************************/ + static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -2073,38 +2398,50 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int jobid, errcode; - extern struct current_user current_user; + uint32 jobid; + int snum; + fstring sharename; + int errcode; WERROR werr = WERR_OK; - jobid = SVAL(p,0); + if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) + return False; /* check it's a supported varient */ if (!(strcsequal(str1,"W") && strcsequal(str2,""))) return(False); *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; - if (!print_job_exists(jobid)) { + if (!print_job_exists(sharename, jobid)) { errcode = NERR_JobNotFound; goto out; } + snum = lp_servicenumber( sharename); + if (snum == -1) { + errcode = NERR_DestNotFound; + goto out; + } + errcode = NERR_notsupported; switch (function) { case 81: /* delete */ - if (print_job_delete(¤t_user, jobid, &werr)) + if (print_job_delete(¤t_user, snum, jobid, &werr)) errcode = NERR_Success; break; case 82: /* pause */ - if (print_job_pause(¤t_user, jobid, &werr)) + if (print_job_pause(¤t_user, snum, jobid, &werr)) errcode = NERR_Success; break; case 83: /* resume */ - if (print_job_resume(¤t_user, jobid, &werr)) + if (print_job_resume(¤t_user, snum, jobid, &werr)) errcode = NERR_Success; break; } @@ -2122,6 +2459,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param /**************************************************************************** Purge a print queue - or pause or resume it. ****************************************************************************/ + static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, @@ -2134,14 +2472,16 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param int errcode = NERR_notsupported; int snum; WERROR werr = WERR_OK; - extern struct current_user current_user; /* check it's a supported varient */ if (!(strcsequal(str1,"z") && strcsequal(str2,""))) return(False); *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } *rdata_len = 0; snum = print_queue_snum(QueueName); @@ -2172,7 +2512,6 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param return(True); } - /**************************************************************************** set the property of a print job (undocumented?) ? function = 0xb -> set name of print job @@ -2180,6 +2519,7 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param Form: or ****************************************************************************/ + static int check_printjob_info(struct pack_desc* desc, int uLevel, char* id) { @@ -2205,14 +2545,25 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - int jobid; + uint32 jobid; + fstring sharename; int uLevel = SVAL(p,2); int function = SVAL(p,4); int place, errcode; - jobid = SVAL(p,0); + if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) + return False; *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + + if (!share_defined(sharename)) { + DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n", + sharename)); + return False; + } *rdata_len = 0; @@ -2221,7 +2572,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha (!check_printjob_info(&desc,uLevel,str2))) return(False); - if (!print_job_exists(jobid)) { + if (!print_job_exists(sharename, jobid)) { errcode=NERR_JobNotFound; goto out; } @@ -2233,14 +2584,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha /* change job place in the queue, data gives the new place */ place = SVAL(data,0); - if (print_job_set_place(jobid, place)) { + if (print_job_set_place(sharename, jobid, place)) { errcode=NERR_Success; } break; case 0xb: /* change print job name, data gives the name */ - if (print_job_set_name(jobid, data)) { + if (print_job_set_name(sharename, jobid, data)) { errcode=NERR_Success; } break; @@ -2258,183 +2609,213 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha /**************************************************************************** - get info about the server - ****************************************************************************/ + Get info about the server. +****************************************************************************/ + static BOOL api_RNetServerGetInfo(connection_struct *conn,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); - 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) { - srvstr_push(NULL, p,local_machine,16, - STR_ASCII|STR_UPPER|STR_TERMINATE); - } - p += 16; - if (uLevel > 0) - { - struct srv_info_struct *servers=NULL; - int i,count; - pstring comment; - uint32 servertype= lp_default_server_announce(); - - pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); - - if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) { - for (i=0;i 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); -} + 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 = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } + + p = *rdata; + p2 = p + struct_len; + if (uLevel != 20) { + srvstr_push(NULL, p,get_local_machine_name(),16, + STR_ASCII|STR_UPPER|STR_TERMINATE); + } + p += 16; + if (uLevel > 0) { + struct srv_info_struct *servers=NULL; + int i,count; + pstring comment; + uint32 servertype= lp_default_server_announce(); + + push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE); + + if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { + for (i=0;iuser, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + comment, sizeof(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 = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,*rdata_len); + + return True; +} + +/**************************************************************************** + Get info about the server. +****************************************************************************/ -/**************************************************************************** - get info about the server - ****************************************************************************/ static BOOL api_NetWkstaGetInfo(connection_struct *conn,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); - char *p2; - extern userdom_struct current_user_info; - int level = SVAL(p,0); - - DEBUG(4,("NetWkstaGetInfo level %d\n",level)); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char *p2; + int level = SVAL(p,0); - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + DEBUG(4,("NetWkstaGetInfo level %d\n",level)); - /* check it's a supported varient */ - if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) - return(False); + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); + /* check it's a supported varient */ + if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) { + return False; + } - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ + *rdata_len = mdrcnt + 1024; + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } - p = *rdata; - p2 = p + 22; + SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,2,0); /* converter word */ + p = *rdata; + p2 = p + 22; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ - pstrcpy(p2,local_machine); - strupper(p2); - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ + pstrcpy(p2,get_local_machine_name()); + strupper_m(p2); + p2 = skip_string(p2,1); + p += 4; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - pstrcpy(p2,current_user_info.smb_name); - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + pstrcpy(p2,current_user_info.smb_name); + p2 = skip_string(p2,1); + p += 4; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ - pstrcpy(p2,global_myworkgroup); - strupper(p2); - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ + pstrcpy(p2,lp_workgroup()); + strupper_m(p2); + p2 = skip_string(p2,1); + p += 4; - 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; + 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)); - pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */ - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); + pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */ + p2 = skip_string(p2,1); + p += 4; - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ - pstrcpy(p2,""); - p2 = skip_string(p2,1); - p += 4; + SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ + pstrcpy(p2,""); + p2 = skip_string(p2,1); + p += 4; - *rdata_len = PTR_DIFF(p2,*rdata); + *rdata_len = PTR_DIFF(p2,*rdata); - SSVAL(*rparam,4,*rdata_len); + SSVAL(*rparam,4,*rdata_len); - return(True); + return True; } /**************************************************************************** @@ -2618,36 +2999,47 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param char *p = skip_string(UserName,1); int uLevel = SVAL(p,0); char *p2; + const char *level_string; + + /* get NIS home of a previously validated user - simeon */ + /* With share level security vuid will always be zero. + Don't depend on vuser being non-null !!. JRA */ + user_struct *vuser = get_valid_user_struct(vuid); + if(vuser != NULL) { + DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, + vuser->user.unix_name)); + } - /* 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", (int)vuser->uid, - vuser->user.unix_name)); - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } - DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); + 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; + if (strcmp(str1,"zWrLh") != 0) { + return False; + } + switch( uLevel ) { + case 0: level_string = "B21"; break; + case 1: level_string = "B21BB16DWzzWz"; break; + case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; + case 10: level_string = "B21Bzzz"; break; + case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break; default: return False; } - if (strcmp(p2,str2) != 0) return False; + if (strcmp(level_string,str2) != 0) { + return False; + } *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); + *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); + if (!*rdata) { + return False; + } SSVAL(*rparam,0,NERR_Success); SSVAL(*rparam,2,0); /* converter word */ @@ -2658,13 +3050,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param memset(p,0,21); fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */ - if (uLevel > 0) - { + if (uLevel > 0) { SCVAL(p,usri11_pad,0); /* padding - 1 byte */ *p2 = 0; } - if (uLevel >= 10) - { + + if (uLevel >= 10) { SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ pstrcpy(p2,"Comment"); p2 = skip_string(p2,1); @@ -2679,14 +3070,13 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param p2 = skip_string(p2,1); } - if (uLevel == 11) /* modelled after NTAS 3.51 reply */ - { + if (uLevel == 11) { + /* modelled after NTAS 3.51 reply */ SSVAL(p,usri11_priv,conn->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 */ - pstrcpy(p2, lp_logon_home()); - standard_sub_conn(conn, p2); + pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); p2 = skip_string(p2,1); SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ pstrcpy(p2,""); @@ -2715,25 +3105,22 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(p,usri11_code_page,0); /* code page */ } - if (uLevel == 1 || uLevel == 2) - { + + if (uLevel == 1 || uLevel == 2) { memset(p+22,' ',16); /* password */ SIVALS(p,38,-1); /* password age */ SSVAL(p,42, conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - pstrcpy(p2,lp_logon_home()); - standard_sub_conn(conn, p2); + pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); p2 = skip_string(p2,1); SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ *p2++ = 0; SSVAL(p,52,0); /* flags */ SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ - pstrcpy(p2,lp_logon_script()); - standard_sub_conn( conn, p2 ); + pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : ""); p2 = skip_string(p2,1); - if (uLevel == 2) - { + if (uLevel == 2) { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); @@ -2754,8 +3141,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVALS(p,102,-1); /* bad_pw_count */ SSVALS(p,104,-1); /* num_logons */ SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ - pstrcpy(p2,"\\\\%L"); - standard_sub_conn(conn, p2); + { + pstring tmp; + pstrcpy(tmp, "\\\\%L"); + standard_sub_basic("", "", tmp, sizeof(tmp)); + pstrcpy(p2, tmp); + } p2 = skip_string(p2,1); SSVAL(p,110,49); /* country_code */ SSVAL(p,112,860); /* code page */ @@ -2769,653 +3160,694 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param return(True); } -/******************************************************************* - get groups that a user is a member of - ******************************************************************/ -static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WWkstaUserLogon(connection_struct *conn,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; - int count=0; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*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; + /* 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", (int)vuser->uid, + vuser->user.unix_name)); + } - /* 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; + uLevel = SVAL(p,0); + name = p + 2; - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); + memset((char *)&desc,'\0',sizeof(desc)); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ + DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); - p = *rdata; + /* 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 = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + } - /* XXXX we need a real SAM database some day */ - pstrcpy(p,"Users"); p += 21; count++; - pstrcpy(p,"Domain Users"); p += 21; count++; - pstrcpy(p,"Guests"); p += 21; count++; - pstrcpy(p,"Domain Guests"); p += 21; count++; + 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", conn->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",0); /* 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 */ - *rdata_len = PTR_DIFF(p,*rdata); + { + fstring mypath; + fstrcpy(mypath,"\\\\"); + fstrcat(mypath,get_local_machine_name()); + strupper_m(mypath); + PACKS(&desc,"z",mypath); /* computer */ + } - SSVAL(*rparam,4,count); /* is this right?? */ - SSVAL(*rparam,6,count); /* is this right?? */ + PACKS(&desc,"z",lp_workgroup());/* domain */ + PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */ + PACKI(&desc,"D",0x00000000); /* reserved */ + } - return(True); -} + *rdata_len = desc.usedlen; + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); -static BOOL api_WWkstaUserLogon(connection_struct *conn,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; - struct pack_desc desc; - char* name; - - uLevel = SVAL(p,0); - name = p + 2; - - memset((char *)&desc,'\0',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", - conn->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",0); /* 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; - fstrcpy(mypath,"\\\\"); - fstrcat(mypath,local_machine); - strupper(mypath); - PACKS(&desc,"z",mypath); /* computer */ - } - PACKS(&desc,"z",global_myworkgroup);/* domain */ - -/* JHT - By calling lp_logon_script() and standard_sub() we have */ -/* made sure all macros are fully substituted and available */ - { - pstring logon_script; - pstrcpy(logon_script,lp_logon_script()); - standard_sub_conn( conn, logon_script ); - PACKS(&desc,"z", logon_script); /* script path */ - } -/* End of JHT mods */ - - PACKI(&desc,"D",0x00000000); /* 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); + return True; } - /**************************************************************************** - api_WAccessGetUserPerms - ****************************************************************************/ + api_WAccessGetUserPerms +****************************************************************************/ + static BOOL api_WAccessGetUserPerms(connection_struct *conn,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 *user = skip_string(str2,1); - char *resource = skip_string(user,1); + 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)); + 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; + /* 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 */ + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVALS(*rparam,0,0); /* errorcode */ + SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,4,0x7f); /* permission flags */ - return(True); + return True; } /**************************************************************************** api_WPrintJobEnumerate ****************************************************************************/ + static BOOL api_WPrintJobGetInfo(connection_struct *conn,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; - int count; - int i; - int snum; - int job; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - char *tmpdata=NULL; - - uLevel = SVAL(p,2); - - memset((char *)&desc,'\0',sizeof(desc)); - memset((char *)&status,'\0',sizeof(status)); - - 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; - - job = SVAL(p,0); - snum = print_job_snum(job); - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = print_queue_status(snum,&queue,&status); - for (i = 0; i < count; i++) { - if (queue[i].job == job) break; - } - - if (mdrcnt > 0) { - *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - } else { - /* - * Don't return data but need to get correct length - * init_package will return wrong size if buflen=0 - */ - desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *)malloc ( desc.buflen ); - } - - if (init_package(&desc,1,0)) { - if (i < count) { - fill_printjob_info(conn,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); - - SAFE_FREE(queue); - SAFE_FREE(tmpdata); - - DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintJobEnumerate(connection_struct *conn,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); - char* name = p; - int uLevel; - int count; - int i, succnt=0; - int snum; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - memset((char *)&desc,'\0',sizeof(desc)); - memset((char *)&status,'\0',sizeof(status)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - - 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 = print_queue_status(snum,&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(conn,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); - - SAFE_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; -} + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int count; + int i; + int snum; + fstring sharename; + uint32 jobid; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; + char *tmpdata=NULL; -static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, - struct pack_desc* desc) -{ - char buf[100]; - strncpy(buf,SERVICE(snum),sizeof(buf)-1); - buf[sizeof(buf)-1] = 0; - 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 */ - } - } -} + uLevel = SVAL(p,2); -static BOOL api_WPrintDestGetInfo(connection_struct *conn,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); - char* PrinterName = p; - int uLevel; - struct pack_desc desc; - int snum; - char *tmpdata=NULL; - - memset((char *)&desc,'\0',sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - - 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; - } else { - /* - * Don't return data but need to get correct length - * init_package will return wrong size if buflen=0 - */ - desc.buflen = getlen(desc.format); - desc.base = tmpdata = (char *)malloc ( desc.buflen ); - } - if (init_package(&desc,1,0)) { - fill_printdest_info(conn,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)); - SAFE_FREE(tmpdata); - return(True); -} + memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); -static BOOL api_WPrintDestEnum(connection_struct *conn,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; - int queuecnt; - int i, n, succnt=0; - struct pack_desc desc; - int services = lp_numservices(); - - memset((char *)&desc,'\0',sizeof(desc)); - - uLevel = SVAL(p,0); - - 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(conn,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); -} + DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0))); -static BOOL api_WPrintDriverEnum(connection_struct *conn,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; - int succnt; - struct pack_desc desc; + /* check it's a supported varient */ + if (strcmp(str1,"WWrLh") != 0) { + return False; + } + if (!check_printjob_info(&desc,uLevel,str2)) { + return False; + } - memset((char *)&desc,'\0',sizeof(desc)); + if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) { + return False; + } - uLevel = SVAL(p,0); + snum = lp_servicenumber( sharename); + if (snum < 0 || !VALID_SNUM(snum)) { + return(False); + } - DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); + count = print_queue_status(snum,&queue,&status); + for (i = 0; i < count; i++) { + if (queue[i].job == jobid) { + break; + } + } - /* 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 = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); + } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B41","NULL"); - } + if (init_package(&desc,1,0)) { + if (i < count) { + fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); + *rdata_len = desc.usedlen; + } else { + desc.errcode = NERR_JobNotFound; + *rdata_len = 0; + } + } - succnt = (desc.errcode == NERR_Success ? 1 : 0); + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); - *rdata_len = desc.usedlen; + SAFE_FREE(queue); + SAFE_FREE(tmpdata); - *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,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); - DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); - return(True); + return True; } -static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintJobEnumerate(connection_struct *conn,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; - int succnt; - struct pack_desc desc; - - memset((char *)&desc,'\0',sizeof(desc)); + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + char* name = p; + int uLevel; + int count; + int i, succnt=0; + int snum; + struct pack_desc desc; + print_queue_struct *queue=NULL; + print_status_struct status; - uLevel = SVAL(p,0); + memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&status,'\0',sizeof(status)); - DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); + p = skip_string(p,1); + uLevel = SVAL(p,0); - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B13") != 0) return False; + DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); - 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"); - } + /* check it's a supported variant */ + 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; + } - succnt = (desc.errcode == NERR_Success ? 1 : 0); + snum = find_service(name); + if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { + return False; + } - *rdata_len = desc.usedlen; + count = print_queue_status(snum,&queue,&status); + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + } + desc.base = *rdata; + desc.buflen = mdrcnt; + + if (init_package(&desc,count,0)) { + succnt = 0; + for (i = 0; i < count; i++) { + fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); + if (desc.errcode == NERR_Success) { + succnt = i+1; + } + } + } - *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); + *rdata_len = desc.usedlen; - DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); - return(True); + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,count); + + SAFE_FREE(queue); + + DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); + + return True; } -static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data, +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(connection_struct *conn, int snum, int uLevel, + struct pack_desc* desc) +{ + char buf[100]; + + strncpy(buf,SERVICE(snum),sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; + strupper_m(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(connection_struct *conn,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); + char* PrinterName = p; + int uLevel; + struct pack_desc desc; + int snum; + char *tmpdata=NULL; + + memset((char *)&desc,'\0',sizeof(desc)); + + p = skip_string(p,1); + uLevel = SVAL(p,0); + + 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 = find_service(PrinterName); + if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { + *rdata_len = 0; + desc.errcode = NERR_DestNotFound; + desc.neededlen = 0; + } else { + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + desc.base = *rdata; + desc.buflen = mdrcnt; + } else { + /* + * Don't return data but need to get correct length + * init_package will return wrong size if buflen=0 + */ + desc.buflen = getlen(desc.format); + desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); + } + if (init_package(&desc,1,0)) { + fill_printdest_info(conn,snum,uLevel,&desc); + } + *rdata_len = desc.usedlen; + } + + *rparam_len = 6; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,desc.neededlen); + + DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); + SAFE_FREE(tmpdata); + + return True; +} + +static BOOL api_WPrintDestEnum(connection_struct *conn,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; - int succnt; - struct pack_desc desc; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int queuecnt; + int i, n, succnt=0; + struct pack_desc desc; + int services = lp_numservices(); - memset((char *)&desc,'\0',sizeof(desc)); + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = SVAL(p,0); - DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); + DEBUG(3,("WPrintDestEnum 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; + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) { + return False; + } + if (!check_printdest_info(&desc,uLevel,str2)) { + return False; + } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - memset((char *)&desc,'\0',sizeof(desc)); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lp0"); - } + queuecnt = 0; + for (i = 0; i < services; i++) { + if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { + queuecnt++; + } + } - succnt = (desc.errcode == NERR_Success ? 1 : 0); + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + } - *rdata_len = desc.usedlen; + 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(conn,i,uLevel,&desc); + n++; + if (desc.errcode == NERR_Success) { + succnt = 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); + *rdata_len = desc.usedlen; - DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); - return(True); + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + 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; } -struct session_info { - char machine[31]; - char username[24]; - char clitype[24]; - int opens; - int time; -}; +static BOOL api_WPrintDriverEnum(connection_struct *conn,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; + int succnt; + struct pack_desc desc; -struct sessions_info { - int count; - struct session_info *session_list; -}; + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + 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 = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + } + desc.base = *rdata; + desc.buflen = mdrcnt; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B41","NULL"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + 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 int gather_sessioninfo(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) +static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - struct sessions_info *sinfo = state; - struct session_info *curinfo = NULL; - struct sessionid *sessid = (struct sessionid *) dbuf.dptr; - - sinfo->count += 1; - sinfo->session_list = REALLOC(sinfo->session_list, sinfo->count * sizeof(struct session_info)); - - curinfo = &(sinfo->session_list[sinfo->count - 1]); - - safe_strcpy(curinfo->machine, sessid->remote_machine, - sizeof(curinfo->machine)); - safe_strcpy(curinfo->username, uidtoname(sessid->uid), - sizeof(curinfo->username)); - DEBUG(7,("gather_sessioninfo session from %s@%s\n", - curinfo->username, curinfo->machine)); - return 0; + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel; + int succnt; + struct pack_desc desc; + + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); + + /* check it's a supported varient */ + if (strcmp(str1,"WrLeh") != 0) { + return False; + } + if (uLevel != 0 || strcmp(str2,"B13") != 0) { + return False; + } + + if (mdrcnt > 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + } + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (init_package(&desc,1,0)) { + PACKS(&desc,"B13","lpd"); + } + + succnt = (desc.errcode == NERR_Success ? 1 : 0); + + *rdata_len = desc.usedlen; + + *rparam_len = 8; + *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + SSVALS(*rparam,0,desc.errcode); + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,succnt); + SSVAL(*rparam,6,1); + + DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); + + return True; +} + +static BOOL api_WPrintPortEnum(connection_struct *conn,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; + int succnt; + struct pack_desc desc; + + memset((char *)&desc,'\0',sizeof(desc)); + + uLevel = SVAL(p,0); + + 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 = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + } + memset((char *)&desc,'\0',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 = SMB_REALLOC_LIMIT(*rparam,*rparam_len); + if (!*rparam) { + return False; + } + 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; } + /**************************************************************************** List open sessions ****************************************************************************/ @@ -3425,157 +3857,170 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param 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; - struct sessions_info sinfo; - int i; - - memset((char *)&desc,'\0',sizeof(desc)); - - uLevel = SVAL(p,0); - - DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel)); - DEBUG(7,("RNetSessionEnum req string=%s\n",str1)); - DEBUG(7,("RNetSessionEnum ret string=%s\n",str2)); - - /* check it's a supported varient */ - if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False; - if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False; - - sinfo.count = 0; - sinfo.session_list = NULL; - - if (!session_traverse(gather_sessioninfo, &sinfo)) { - DEBUG(4,("RNetSessionEnum session_traverse failed\n")); - return False; - } - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - memset((char *)&desc,'\0',sizeof(desc)); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (!init_package(&desc,sinfo.count,0)) { - return False; - } - - for(i=0; i 0) { + *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); + if (!*rdata) { + return False; + } + } + memset((char *)&desc,'\0',sizeof(desc)); + desc.base = *rdata; + desc.buflen = mdrcnt; + desc.format = str2; + if (!init_package(&desc,num_sessions,0)) { + return False; + } + + for(i=0; i <%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) - memset(rdata,'\0',1024); - - rparam = (char *)malloc(1024); - if (rparam) - memset(rparam,'\0',1024); - - if(!rdata || !rparam) { - DEBUG(0,("api_reply: malloc fail !\n")); - return -1; - } - - reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - - - if (rdata_len > mdrcnt || - rparam_len > mprcnt) { - reply = api_TooSmall(conn,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(conn,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - - send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); - - SAFE_FREE(rdata); - SAFE_FREE(rparam); - - return -1; + int api_command; + char *rdata = NULL; + char *rparam = NULL; + int rdata_len = 0; + int rparam_len = 0; + BOOL reply=False; + int i; + + if (!params) { + DEBUG(0,("ERROR: NULL params in api_reply()\n")); + return 0; + } + + api_command = SVAL(params,0); + + 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; + } + } + + /* Check whether this api call can be done anonymously */ + + if (api_commands[i].auth_user && lp_restrict_anonymous()) { + user_struct *user = get_valid_user_struct(vuid); + + if (!user || user->guest) { + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + } + + rdata = (char *)SMB_MALLOC(1024); + if (rdata) { + memset(rdata,'\0',1024); + } + + rparam = (char *)SMB_MALLOC(1024); + if (rparam) { + memset(rparam,'\0',1024); + } + + if(!rdata || !rparam) { + DEBUG(0,("api_reply: malloc fail !\n")); + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return -1; + } + + reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + + if (rdata_len > mdrcnt || rparam_len > mprcnt) { + reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + } + + /* if we get False back then it's actually unsupported */ + if (!reply) { + reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + } + + /* If api_Unsupported returns false we can't return anything. */ + if (reply) { + send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); + } + + SAFE_FREE(rdata); + SAFE_FREE(rparam); + return -1; }