diff options
-rw-r--r-- | source3/lib/util.c | 23 | ||||
-rw-r--r-- | source3/lib/util_str.c | 36 | ||||
-rw-r--r-- | source3/libsmb/clidgram.c | 5 | ||||
-rw-r--r-- | source3/libsmb/cliprint.c | 12 | ||||
-rw-r--r-- | source3/libsmb/clirap.c | 18 | ||||
-rw-r--r-- | source3/libsmb/clirap2.c | 4 | ||||
-rw-r--r-- | source3/nmbd/nmbd_browsesync.c | 2 | ||||
-rw-r--r-- | source3/nmbd/nmbd_elections.c | 2 | ||||
-rw-r--r-- | source3/nmbd/nmbd_incomingdgrams.c | 18 | ||||
-rw-r--r-- | source3/nmbd/nmbd_packets.c | 6 | ||||
-rw-r--r-- | source3/nmbd/nmbd_processlogon.c | 38 | ||||
-rw-r--r-- | source3/nmbd/nmbd_sendannounce.c | 2 | ||||
-rw-r--r-- | source3/smbd/lanman.c | 878 |
13 files changed, 714 insertions, 330 deletions
diff --git a/source3/lib/util.c b/source3/lib/util.c index cf8d49c502..809071662d 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -3124,3 +3124,26 @@ int this_is_smp(void) return 0; #endif } + +/**************************************************************** + Return a safe offset into a buffer, or NULL. +****************************************************************/ + +char *get_safe_offset(const char *buf_base, size_t buf_len, char *ptr, size_t off) +{ + const char *end_base = buf_base + buf_len; + const char *end_ptr = ptr + off; + + if (!buf_base || !ptr) { + return NULL; + } + + if (end_base < buf_base || end_ptr < ptr) { + return NULL; /* wrap. */ + } + + if (end_ptr < end_base) { + return ptr; + } + return NULL; +} diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index ccf0af8b62..032627db94 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -424,10 +424,10 @@ void string_replace( pstring s, char oldc, char newc ) } /** - Skip past some strings in a buffer. -**/ + * Skip past some strings in a buffer - old version - no checks. + * **/ -char *skip_string(char *buf,size_t n) +char *push_skip_string(char *buf,size_t n) { while (n--) buf += strlen(buf) + 1; @@ -435,6 +435,35 @@ char *skip_string(char *buf,size_t n) } /** + Skip past some strings in a buffer. Buffer may not be + null terminated. end_ptr points to the first byte after + then end of the buffer. +**/ + +char *skip_string(const char *base, size_t len, char *buf, size_t n) +{ + const char *end_ptr = base + len; + + if (end_ptr < base || !base || !buf || buf >= end_ptr) { + return NULL; + } + + while (n--) { + /* Skip the string */ + while (*buf) { + buf++; + if (buf >= end_ptr) { + return NULL; + } + } + /* Skip the '\0' */ + buf++; + } + + return buf; +} + +/** Count the number of characters in a string. Normally this will be the same as the number of bytes in a string for single byte strings, but will be different for multibyte. @@ -2591,4 +2620,3 @@ size_t utf16_len_n(const void *src, size_t n) return len; } - diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c index a983f485ab..b6a9cfb31a 100644 --- a/source3/libsmb/clidgram.c +++ b/source3/libsmb/clidgram.c @@ -85,7 +85,10 @@ BOOL cli_send_mailslot(BOOL unique, const char *mailslot, SSVAL(ptr,smb_vwv16,2); p2 = smb_buf(ptr); fstrcpy(p2,mailslot); - p2 = skip_string(p2,1); + p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2,1); + if (!p2) { + return False; + } memcpy(p2,buf,len); p2 += len; diff --git a/source3/libsmb/cliprint.c b/source3/libsmb/cliprint.c index 5798e94554..e33a3564eb 100644 --- a/source3/libsmb/cliprint.c +++ b/source3/libsmb/cliprint.c @@ -64,16 +64,16 @@ int cli_print_queue(struct cli_state *cli, SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */ p += 2; pstrcpy_base(p,"zWrLeh", param); /* parameter description? */ - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); pstrcpy_base(p,"WWzWWDDzz", param); /* returned data format */ - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); pstrcpy_base(p,cli->share, param); /* name of queue */ - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */ SSVAL(p,2,1000); /* size of bytes of returned data buffer */ p += 4; pstrcpy_base(p,"", param); /* subformat */ - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); DEBUG(4,("doing cli_print_queue for %s\n", cli->share)); @@ -133,9 +133,9 @@ int cli_printjob_del(struct cli_state *cli, int job) SSVAL(p,0,81); /* DosPrintJobDel() */ p += 2; pstrcpy_base(p,"W", param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); pstrcpy_base(p,"", param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); SSVAL(p,0,job); p += 2; diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index 4be03e16f0..3fc95e8429 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -86,9 +86,9 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation) SSVAL(p,0,132); /* api number */ p += 2; pstrcpy_base(p,"OOWb54WrLh",param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); SSVAL(p,0,1); p += 2; pstrcpy_base(p,user,param); @@ -147,9 +147,9 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co SSVAL(p,0,0); /* api number */ p += 2; pstrcpy_base(p,"WrLeh",param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); pstrcpy_base(p,"B13BWz",param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); SSVAL(p,0,1); /* * Win2k needs a *smaller* buffer than 0xFFFF here - @@ -225,11 +225,11 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, SSVAL(p,0,0x68); /* api number */ p += 2; pstrcpy_base(p,"WrLehDz", param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); pstrcpy_base(p,"B16BBDz", param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); SSVAL(p,0,uLevel); SSVAL(p,2,CLI_BUFFER_SIZE); p += 4; @@ -314,11 +314,11 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char SSVAL(p,0,214); /* SamOEMChangePassword command. */ p += 2; pstrcpy_base(p, "zsT", param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); pstrcpy_base(p, "B516B16", param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); pstrcpy_base(p,user, param); - p = skip_string(p,1); + p = skip_string(param,sizeof(param),p,1); SSVAL(p,0,532); p += 2; diff --git a/source3/libsmb/clirap2.c b/source3/libsmb/clirap2.c index d6a44f4ea2..9ab8997871 100644 --- a/source3/libsmb/clirap2.c +++ b/source3/libsmb/clirap2.c @@ -91,7 +91,7 @@ /* put string s at p with max len n and increment p past string */ #define PUTSTRING(p,s,n) do {\ push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\ - p = skip_string(p,1);\ + p = push_skip_string(p,1);\ } while(0) /* put string s and p, using fixed len l, and increment p by l */ #define PUTSTRINGF(p,s,l) do {\ @@ -111,7 +111,7 @@ /* get asciiz string s from p, increment p past string */ #define GETSTRING(p,s) do {\ pull_ascii_pstring(s,p);\ - p = skip_string(p,1);\ + p = push_skip_string(p,1);\ } while(0) /* get fixed length l string s from p, increment p by l */ #define GETSTRINGF(p,s,l) do {\ diff --git a/source3/nmbd/nmbd_browsesync.c b/source3/nmbd/nmbd_browsesync.c index 9535a3115a..ddb223de9f 100644 --- a/source3/nmbd/nmbd_browsesync.c +++ b/source3/nmbd/nmbd_browsesync.c @@ -125,7 +125,7 @@ static void announce_local_master_browser_to_domain_master_browser( struct work_ /* The call below does CH_UNIX -> CH_DOS conversion. JRA */ push_pstring_base(p, myname, outbuf); - p = skip_string(p,1); + p = skip_string(outbuf,sizeof(outbuf),p,1); if( DEBUGLVL( 4 ) ) { dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); diff --git a/source3/nmbd/nmbd_elections.c b/source3/nmbd/nmbd_elections.c index 3aadd70b83..fbdb6c4524 100644 --- a/source3/nmbd/nmbd_elections.c +++ b/source3/nmbd/nmbd_elections.c @@ -53,7 +53,7 @@ static void send_election_dgram(struct subnet_record *subrec, const char *workgr strupper_m(srv_name); /* The following call does UNIX -> DOS charset conversion. */ pstrcpy_base(p, srv_name, outbuf); - p = skip_string(p,1); + p = skip_string(outbuf,sizeof(outbuf),p,1); send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), global_myname(), 0, diff --git a/source3/nmbd/nmbd_incomingdgrams.c b/source3/nmbd/nmbd_incomingdgrams.c index 880700c72c..616b5df9db 100644 --- a/source3/nmbd/nmbd_incomingdgrams.c +++ b/source3/nmbd/nmbd_incomingdgrams.c @@ -416,7 +416,7 @@ done: Process an incoming LanMan host announcement packet. *******************************************************************/ -void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) +void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf, int len) { struct dgram_packet *dgram = &p->packet.dgram; uint32 servertype = IVAL(buf,1); @@ -429,10 +429,16 @@ void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct unstring work_name; unstring source_name; fstring comment; - char *s = buf+9; + char *s = get_safe_offset(buf,len,buf,9); + if (!s) { + return; + } START_PROFILE(lm_host_announce); - s = skip_string(s,1); + s = skip_string(buf,len,s,1); + if (!s) { + return; + } pull_ascii(comment, s, sizeof(fstring), 43, STR_TERMINATE); pull_ascii_nstring(announce_name,sizeof(announce_name),buf+9); @@ -568,7 +574,7 @@ static void send_backup_list_response(struct subnet_record *subrec, myname[15]='\0'; push_pstring_base(p, myname, outbuf); - p = skip_string(p,1); + p = skip_string(outbuf,sizeof(outbuf),p,1); /* Look for backup browsers in this workgroup. */ @@ -604,7 +610,7 @@ static void send_backup_list_response(struct subnet_record *subrec, DEBUG(5,("send_backup_list_response: Adding server %s number %d\n", p, count)); - p = skip_string(p,1); + p = skip_string(outbuf,sizeof(outbuf),p,1); } #endif @@ -809,7 +815,7 @@ done: through the "lm announce" parameter in smb.conf) ******************************************************************/ -void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf) +void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf, int len) { struct dgram_packet *dgram = &p->packet.dgram; unstring workgroup_name; diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c index 89362392fe..5ec6be1307 100644 --- a/source3/nmbd/nmbd_packets.c +++ b/source3/nmbd/nmbd_packets.c @@ -1153,10 +1153,10 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope())); switch (command) { case ANN_HostAnnouncement: debug_browse_data(buf, len); - process_lm_host_announce(subrec, p, buf+1); + process_lm_host_announce(subrec, p, buf+1, len > 1 ? len-1 : 0); break; case ANN_AnnouncementRequest: - process_lm_announce_request(subrec, p, buf+1); + process_lm_announce_request(subrec, p, buf+1, len > 1 ? len-1 : 0); break; default: DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \ @@ -1899,7 +1899,7 @@ BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len, SSVAL(ptr,smb_vwv16,2); p2 = smb_buf(ptr); safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data)); - p2 = skip_string(p2,1); + p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2,1); if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) { DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n")); diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index 232f430b66..6b10d61267 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -91,7 +91,7 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); pstrcpy(my_name, global_myname()); - code = SVAL(buf,0); + code = get_safe_offset(buf,len,buf,2) ? SVAL(buf,0) : -1; DEBUG(4,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code)); switch (code) { @@ -100,21 +100,21 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); fstring mach_str, user_str, getdc_str; char *q = buf + 2; char *machine = q; - char *user = skip_string(machine,1); + char *user = skip_string(buf,len,machine,1); - if (PTR_DIFF(user, buf) >= len) { + if (!user || PTR_DIFF(user, buf) >= len) { DEBUG(0,("process_logon_packet: bad packet\n")); return; } - getdc = skip_string(user,1); + getdc = skip_string(buf,len,user,1); - if (PTR_DIFF(getdc, buf) >= len) { + if (!getdc || PTR_DIFF(getdc, buf) >= len) { DEBUG(0,("process_logon_packet: bad packet\n")); return; } - q = skip_string(getdc,1); + q = skip_string(buf,len,getdc,1); - if (PTR_DIFF(q + 5, buf) > len) { + if (!q || PTR_DIFF(q + 5, buf) > len) { DEBUG(0,("process_logon_packet: bad packet\n")); return; } @@ -136,7 +136,7 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); fstrcpy(reply_name, "\\\\"); fstrcat(reply_name, my_name); push_ascii_fstring(q, reply_name); - q = skip_string(q, 1); /* PDC name */ + q = skip_string(outbuf,sizeof(outbuf),q, 1); /* PDC name */ SSVAL(q, 0, token); q += 2; @@ -164,15 +164,15 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); return; } - getdc = skip_string(machine,1); + getdc = skip_string(buf,len,machine,1); - if (PTR_DIFF(getdc, buf) >= len) { + if (!getdc || PTR_DIFF(getdc, buf) >= len) { DEBUG(0,("process_logon_packet: bad packet\n")); return; } - q = skip_string(getdc,1); + q = skip_string(buf,len,getdc,1); - if (PTR_DIFF(q, buf) >= len) { + if (!q || PTR_DIFF(q, buf) >= len) { DEBUG(0,("process_logon_packet: bad packet\n")); return; } @@ -232,7 +232,7 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); fstrcpy(reply_name,my_name); push_ascii_fstring(q, reply_name); - q = skip_string(q, 1); /* PDC name */ + q = skip_string(outbuf,sizeof(outbuf),q, 1); /* PDC name */ /* PDC and domain name */ if (!short_request) { @@ -301,9 +301,9 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", return; } - q = skip_string(getdc,1); + q = skip_string(buf,len,getdc,1); - if (PTR_DIFF(q + 8, buf) >= len) { + if (!q || PTR_DIFF(q + 8, buf) >= len) { DEBUG(0,("process_logon_packet: bad packet\n")); return; } @@ -540,16 +540,16 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", /* Domain info */ - q = skip_string(q, 1); /* PDC name */ + q = skip_string(buf,len,q, 1); /* PDC name */ - if (PTR_DIFF(q, buf) >= len) { + if (!q || PTR_DIFF(q, buf) >= len) { DEBUG(0,("process_logon_packet: bad packet\n")); return; } - q = skip_string(q, 1); /* Domain name */ + q = skip_string(buf,len,q, 1); /* Domain name */ - if (PTR_DIFF(q, buf) >= len) { + if (!q || PTR_DIFF(q, buf) >= len) { DEBUG(0,("process_logon_packet: bad packet\n")); return; } diff --git a/source3/nmbd/nmbd_sendannounce.c b/source3/nmbd/nmbd_sendannounce.c index 7fcedc557e..0cd481649d 100644 --- a/source3/nmbd/nmbd_sendannounce.c +++ b/source3/nmbd/nmbd_sendannounce.c @@ -566,7 +566,7 @@ for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name )); myname[15]='\0'; push_pstring_base(p, myname, outbuf); - p = skip_string(p,1); + p = skip_string(outbuf,sizeof(outbuf),p,1); for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) { /* The entries are of the form a.b.c.d */ diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index e42d96b11e..905b6a023a 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -50,10 +50,13 @@ extern userdom_struct current_user_info; #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_Unsupported(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len); + static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data, int mdrcnt, int mprcnt, char **rdata, char **rparam, @@ -585,7 +588,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, lp_servicename(snum))); goto err; } - + if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, "Windows 4.0", 0)) ) { @@ -597,17 +600,17 @@ static void fill_printq_info_52(connection_struct *conn, int snum, 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); - + 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 */ - + fstrcpy(location, "\\\\%L\\print$\\WIN40\\0"); standard_sub_basic( "", "", location, sizeof(location)-1 ); PACKS(desc,"z", location); /* share to retrieve files */ - + PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */ PACKS(desc,"z", driver.info_3->driverpath); /* driver name */ @@ -627,12 +630,12 @@ static void fill_printq_info_52(connection_struct *conn, int snum, 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)); desc->errcode=NERR_Success; @@ -645,7 +648,7 @@ err: done: if ( printer ) free_a_printer( &printer, 2 ); - + if ( driver.info_3 ) free_a_printer_driver( driver, 3 ); } @@ -743,7 +746,7 @@ static int get_printerdrivernumber(int snum) lp_servicename(snum))); goto done; } - + if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, "Windows 4.0", 0)) ) { @@ -751,7 +754,7 @@ static int get_printerdrivernumber(int snum) printer->info_2->drivername)); goto done; } - + /* count the number of files */ while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] ) result++; @@ -759,39 +762,50 @@ static int get_printerdrivernumber(int snum) done: if ( printer ) free_a_printer( &printer, 2 ); - + if ( driver.info_3 ) free_a_printer_driver( driver, 3 ); - + return result; } -static BOOL api_DosPrintQGetInfo(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_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); char *QueueName = p; unsigned int uLevel; int count=0; int snum; - char* str3; + char *str3; struct pack_desc desc; print_queue_struct *queue=NULL; print_status_struct status; char* tmpdata=NULL; + if (!str1 || !str2 || !p) { + return False; + } memset((char *)&status,'\0',sizeof(status)); memset((char *)&desc,'\0',sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - str3 = p + 4; - + + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + str3 = get_safe_offset(param,tpscnt,p,4) ? p + 4 : 0; + /* Check if string exists. */ + if (skip_string(param,tpscnt,str3,1) == NULL) { + return False; + } + /* remove any trailing username */ if ((p = strchr_m(QueueName,'%'))) *p = 0; @@ -883,16 +897,18 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn, View list of all print jobs on all queues. ****************************************************************************/ -static BOOL api_DosPrintQEnum(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_DosPrintQEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, + char **rdata, char** rparam, + int *rdata_len, int *rparam_len) { - char *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; + char *param_format = get_safe_offset(param,tpscnt,param,2); + char *output_format1 = skip_string(param,tpscnt,param_format,1); + char *p = skip_string(param,tpscnt,output_format1,1); + unsigned int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + char *output_format2 = get_safe_offset(param,tpscnt,p,4); int services = lp_numservices(); int i, n; struct pack_desc desc; @@ -901,6 +917,13 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, int *subcntarr = NULL; int queuecnt = 0, subcnt = 0, succnt = 0; + if (!param_format || !output_format1 || !p || !output_format2) { + return False; + } + + uLevel = SVAL(p,0); + output_format2 = p + 4; + memset((char *)&desc,'\0',sizeof(desc)); DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); @@ -1252,16 +1275,18 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) extracted from lists saved by nmbd on the local host. ****************************************************************************/ -static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data, - int mdrcnt, int mprcnt, char **rdata, - char **rparam, int *rdata_len, int *rparam_len) +static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) { - char *str1 = 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 *str1 = get_safe_offset(param, tpscnt, param, 2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param, tpscnt, p, 2) ? SVAL(p,0) : -1; + int buf_len = get_safe_offset(param,tpscnt, p, 4) ? SVAL(p,2) : 0; + uint32 servertype = get_safe_offset(param,tpscnt,p,8) ? IVAL(p,4) : 0; char *p2; int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; @@ -1272,6 +1297,10 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param BOOL domain_request; BOOL local_request; + if (!str1 || !str2 || !p) { + return False; + } + /* If someone sets all the bits they don't really mean to set DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the known servers. */ @@ -1307,6 +1336,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); if (strcmp(str1, "WrLehDz") == 0) { + if (skip_string(param,tpscnt,p,1) == NULL) { + return False; + } pull_ascii_fstring(domain, p); } else { fstrcpy(domain, lp_workgroup()); @@ -1399,18 +1431,24 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param 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) +static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) { - char *str1 = 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 *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int buf_len = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : 0; int counted=0; int missed=0; + if (!str1 || !str2 || !p) { + return False; + } + DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n", str1, str2, p, uLevel, buf_len)); @@ -1582,18 +1620,25 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel, return len; } -static BOOL api_RNetShareGetInfo(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_RNetShareGetInfo(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = 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 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *netname = skip_string(param,tpscnt,str2,1); + char *p = skip_string(param,tpscnt,netname,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int snum; + if (!str1 || !str2 || !netname || !p) { + return False; + } + + snum = find_service(netname); if (snum < 0) { return False; } @@ -1638,22 +1683,21 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para 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 ) +static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, + int mprcnt, + char **rdata, + char **rparam, + int *rdata_len, + int *rparam_len ) { - char *str1 = 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 *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + int buf_len = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : 0; char *p2; int count = 0; int total=0,counted=0; @@ -1662,6 +1706,10 @@ static BOOL api_RNetShareEnum( connection_struct *conn, int data_len, fixed_len, string_len; int f_len = 0, s_len = 0; + if (!str1 || !str2 || !p) { + return False; + } + if (!prefix_ok(str1,"WrLeh")) { return False; } @@ -1743,15 +1791,17 @@ static BOOL api_RNetShareEnum( connection_struct *conn, Add a share ****************************************************************************/ -static BOOL api_RNetShareAdd(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_RNetShareAdd(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; fstring sharename; fstring comment; pstring pathname; @@ -1760,6 +1810,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch int snum; int res = ERRunsup; + if (!str1 || !str2 || !p) { + return False; + } + /* check it's a supported varient */ if (!prefix_ok(str1,RAP_WShareAdd_REQ)) { return False; @@ -1771,6 +1825,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch return False; } + /* Do we have a string ? */ + if (skip_string(data,mdrcnt,data,1) == NULL) { + return False; + } pull_ascii_fstring(sharename,data); snum = find_service(sharename); if (snum >= 0) { /* already exists */ @@ -1778,6 +1836,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch goto error_exit; } + if (mdrcnt < 28) { + return False; + } + /* only support disk share adds */ if (SVAL(data,14)!=STYPE_DISKTREE) { return False; @@ -1789,6 +1851,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch goto error_exit; } + /* Do we have a string ? */ + if (skip_string(data,mdrcnt,data+offset,1) == NULL) { + return False; + } pull_ascii_fstring(comment, offset? (data+offset) : ""); offset = IVAL(data, 26); @@ -1798,6 +1864,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch goto error_exit; } + /* Do we have a string ? */ + if (skip_string(data,mdrcnt,data+offset,1) == NULL) { + return False; + } pull_ascii_pstring(pathname, offset? (data+offset) : ""); string_replace(sharename, '"', ' '); @@ -1858,23 +1928,29 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch 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) +static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { 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); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); struct pdb_search *search; struct samr_displayentry *entries; int num_entries; + if (!str1 || !str2 || !p) { + return False; + } + if (strcmp(str1,"WrLeh") != 0) { return False; } @@ -1901,8 +1977,8 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c return False; } - resume_context = SVAL(p,0); - cli_buf_size=SVAL(p+2,0); + resume_context = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + cli_buf_size= get_safe_offset(param,tpscnt,p,4) ? SVAL(p+2,0) : 0; DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: " "%d\n", resume_context, cli_buf_size)); @@ -1958,16 +2034,18 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c 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_NetUserGetGroups(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = 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 *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *UserName = skip_string(param,tpscnt,str2,1); + char *p = skip_string(param,tpscnt,UserName,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; const char *level_string; int count=0; struct samu *sampw = NULL; @@ -1981,6 +2059,10 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para enum lsa_SidType type; TALLOC_CTX *mem_ctx; + if (!str1 || !str2 || !UserName || !p) { + return False; + } + *rparam_len = 8; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if (!*rparam) { @@ -2091,10 +2173,12 @@ done: Get all users. ******************************************************************/ -static BOOL api_RNetUserEnum(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_RNetUserEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { int count_sent=0; int num_users=0; @@ -2103,9 +2187,13 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch struct pdb_search *search; struct samr_displayentry *users; - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + + if (!str1 || !str2 || !p) { + return False; + } if (strcmp(str1,"WrLeh") != 0) return False; @@ -2117,8 +2205,8 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch * h -> return parameter total number of users */ - resume_context = SVAL(p,0); - cli_buf_size=SVAL(p+2,0); + resume_context = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + cli_buf_size= get_safe_offset(param,tpscnt,p,4) ? SVAL(p+2,0) : 0; DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); @@ -2189,10 +2277,12 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch Get the time of day info. ****************************************************************************/ -static BOOL api_NetRemoteTOD(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_NetRemoteTOD(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { struct tm *t; time_t unixdate = time(NULL); @@ -2245,21 +2335,38 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch Set the user password. *****************************************************************************/ -static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *p = skip_string(param+2,2); + char *np = get_safe_offset(param,tpscnt,param,2); + char *p = skip_string(param,tpscnt,np,2); fstring user; fstring pass1,pass2; + if (!np || !p) { + return False; + } + + /* Do we have a string ? */ + if (skip_string(param,tpscnt,p,1) == NULL) { + return False; + } pull_ascii_fstring(user,p); - p = skip_string(p,1); + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } memset(pass1,'\0',sizeof(pass1)); memset(pass2,'\0',sizeof(pass2)); + if (get_safe_offset(param,tpscnt,p,32) == NULL) { + return False; + } memcpy(pass1,p,16); memcpy(pass2,p+16,16); @@ -2331,19 +2438,24 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param Set the user password (SamOEM version - gets plaintext). ****************************************************************************/ -static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { fstring user; - char *p = param + 2; + char *p = get_safe_offset(param,tpscnt,param,2); *rparam_len = 2; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if (!*rparam) { return False; } + if (!p) { + return False; + } *rdata_len = 0; SSVAL(*rparam,0,NERR_badpass); @@ -2352,17 +2464,35 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * * Check the parameter definition is correct. */ - if(!strequal(param + 2, "zsT")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); + /* Do we have a string ? */ + if (skip_string(param,tpscnt,p,1) == 0) { + return False; + } + if(!strequal(p, "zsT")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p)); + return False; + } + p = skip_string(param, tpscnt, p, 1); + if (!p) { return False; } - p = skip_string(p, 1); + /* Do we have a string ? */ + if (skip_string(param,tpscnt,p,1) == 0) { + return False; + } if(!strequal(p, "B516B16")) { DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); return False; } - p = skip_string(p,1); + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } + /* Do we have a string ? */ + if (skip_string(param,tpscnt,p,1) == 0) { + return False; + } p += pull_ascii_fstring(user,p); DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); @@ -2386,21 +2516,29 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * Form: <W> <> ****************************************************************************/ -static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - int function = SVAL(param,0); - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + int function = get_safe_offset(param,tpscnt,param,2) ? SVAL(param,0) : 0; + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); uint32 jobid; int snum; fstring sharename; int errcode; WERROR werr = WERR_OK; + if (!str1 || !str2 || !p) { + return False; + } + if (get_safe_offset(param,tpscnt,p,2) == NULL) { + return False; + } if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; @@ -2457,19 +2595,25 @@ 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, - int *rdata_len,int *rparam_len) +static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - int function = SVAL(param,0); - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *QueueName = skip_string(str2,1); + int function = get_safe_offset(param,tpscnt,param,2) ? SVAL(param,0) : 0; + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *QueueName = skip_string(param,tpscnt,str2,1); int errcode = NERR_notsupported; int snum; WERROR werr = WERR_OK; + if (!str1 || !str2 || !QueueName) { + return False; + } + /* check it's a supported varient */ if (!(strcsequal(str1,"z") && strcsequal(str2,""))) return(False); @@ -2533,21 +2677,29 @@ static int check_printjob_info(struct pack_desc* desc, return True; } -static BOOL api_PrintJobInfo(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_PrintJobInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { struct pack_desc desc; - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); uint32 jobid; fstring sharename; - int uLevel = SVAL(p,2); - int function = SVAL(p,4); + int uLevel = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : -1; + int function = get_safe_offset(param,tpscnt,p,6) ? SVAL(p,4) : -1; int place, errcode; + if (!str1 || !str2 || !p) { + return False; + } + if (get_safe_offset(param,tpscnt,p,2) == NULL) { + return False; + } if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) return False; *rparam_len = 4; @@ -2609,18 +2761,24 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha 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) +static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; char *p2; int struct_len; + if (!str1 || !str2 || !p) { + return False; + } + DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); /* check it's a supported varient */ @@ -2715,7 +2873,10 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par current_user_info.domain, comment, sizeof(comment)); StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } } } @@ -2741,16 +2902,22 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par Get info about the server. ****************************************************************************/ -static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); char *p2; - int level = SVAL(p,0); + int level = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + + if (!str1 || !str2 || !p) { + return False; + } DEBUG(4,("NetWkstaGetInfo level %d\n",level)); @@ -2775,23 +2942,35 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(*rparam,2,0); /* converter word */ p = *rdata; - p2 = p + 22; + p2 = get_safe_offset(*rdata,*rdata_len,p,22); + if (!p2) { + return False; + } SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ pstrcpy(p2,get_local_machine_name()); strupper_m(p2); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); pstrcpy(p2,current_user_info.smb_name); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ pstrcpy(p2,lp_workgroup()); strupper_m(p2); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ @@ -2800,12 +2979,18 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,0,PTR_DIFF(p2,*rdata)); pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */ - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ pstrcpy(p2,""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } p += 4; *rdata_len = PTR_DIFF(p2,*rdata); @@ -2985,16 +3170,18 @@ There is no auxiliary data in the response. #define AF_OP_ACCOUNTS 3 -static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = 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 *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *UserName = skip_string(param,tpscnt,str2,1); + char *p = skip_string(param,tpscnt,UserName,1); + int uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; char *p2; const char *level_string; @@ -3007,6 +3194,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param vuser->user.unix_name)); } + if (!str1 || !str2 || !UserName || !p) { + return False; + } + *rparam_len = 6; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); if (!*rparam) { @@ -3042,7 +3233,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SSVAL(*rparam,2,0); /* converter word */ p = *rdata; - p2 = p + usri11_end; + p2 = get_safe_offset(*rdata,*rdata_len,p,usri11_end); + if (!p2) { + return False; + } memset(p,0,21); fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */ @@ -3055,16 +3249,25 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param if (uLevel >= 10) { SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ pstrcpy(p2,"Comment"); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ pstrcpy(p2,"UserComment"); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } } if (uLevel == 11) { @@ -3074,22 +3277,34 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param SIVALS(p,usri11_password_age,-1); /* password age */ SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ pstrcpy(p2,""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,usri11_last_logon,0); /* last logon */ SIVAL(p,usri11_last_logoff,0); /* last logoff */ SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */ SSVALS(p,usri11_num_logons,-1); /* num logons */ SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ pstrcpy(p2,"\\\\*"); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SSVAL(p,usri11_country_code,0); /* country code */ SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ pstrcpy(p2,""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVALS(p,usri11_max_storage,-1); /* max storage */ SSVAL(p,usri11_units_per_week,168); /* units per week */ @@ -3098,7 +3313,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param /* a simple way to get logon hours at all times. */ memset(p2,0xff,21); SCVAL(p2,21,0); /* fix zero termination */ - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SSVAL(p,usri11_code_page,0); /* code page */ } @@ -3110,22 +3328,34 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } 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,vuser && vuser->logon_script ? vuser->logon_script : ""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } 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)); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ pstrcpy(p2,""); - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SIVAL(p,76,0); /* workstations */ SIVAL(p,80,0); /* last_logon */ SIVAL(p,84,0); /* last_logoff */ @@ -3144,7 +3374,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param standard_sub_basic("", "", tmp, sizeof(tmp)); pstrcpy(p2, tmp); } - p2 = skip_string(p2,1); + p2 = skip_string(*rdata,*rdata_len,p2,1); + if (!p2) { + return False; + } SSVAL(p,110,49); /* country_code */ SSVAL(p,112,860); /* code page */ } @@ -3157,14 +3390,16 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param return(True); } -static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; struct pack_desc desc; char* name; @@ -3172,12 +3407,19 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param Don't depend on vuser being non-null !!. JRA */ user_struct *vuser = get_valid_user_struct(vuid); + if (!str1 || !str2 || !p) { + return False; + } + if(vuser != NULL) { DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->user.unix_name)); } - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; + if (skip_string(param,tpscnt,p+2,1) == NULL) { + return False; + } name = p + 2; memset((char *)&desc,'\0',sizeof(desc)); @@ -3251,15 +3493,21 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param 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) +static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *user = skip_string(str2,1); - char *resource = skip_string(user,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *user = skip_string(param,tpscnt,str2,1); + char *resource = skip_string(param,tpscnt,user,1); + + if (!str1 || !str2 || !user || !resource) { + return False; + } DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); @@ -3287,14 +3535,16 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p 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) +static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int count; int i; @@ -3306,7 +3556,11 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para print_status_struct status; char *tmpdata=NULL; - uLevel = SVAL(p,2); + if (!str1 || !str2 || !p) { + return False; + } + + uLevel = get_safe_offset(param,tpscnt,p,4) ? SVAL(p,2) : -1; memset((char *)&desc,'\0',sizeof(desc)); memset((char *)&status,'\0',sizeof(status)); @@ -3380,15 +3634,17 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para 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) +static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* name = p; + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); + char *name = p; int uLevel; int count; int i, succnt=0; @@ -3397,11 +3653,18 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa print_queue_struct *queue=NULL; print_status_struct status; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); memset((char *)&status,'\0',sizeof(status)); - p = skip_string(p,1); - uLevel = SVAL(p,0); + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); @@ -3524,24 +3787,33 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, } } -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) +static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); char* PrinterName = p; int uLevel; struct pack_desc desc; int snum; char *tmpdata=NULL; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - p = skip_string(p,1); - uLevel = SVAL(p,0); + p = skip_string(param,tpscnt,p,1); + if (!p) { + return False; + } + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); @@ -3595,23 +3867,29 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par 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) +static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int queuecnt; int i, n, succnt=0; struct pack_desc desc; int services = lp_numservices(); + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); @@ -3670,21 +3948,27 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param, return True; } -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) +static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int succnt; struct pack_desc desc; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : 0; DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); @@ -3727,21 +4011,26 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para return True; } -static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data, +static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int succnt; struct pack_desc desc; + if (!str1 || !str2 || !p) { + return False; + } memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); @@ -3785,21 +4074,27 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param 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) +static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; int succnt; struct pack_desc desc; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); @@ -3844,27 +4139,33 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param, return True; } - /**************************************************************************** List open sessions ****************************************************************************/ -static BOOL api_RNetSessionEnum(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_RNetSessionEnum(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len) { - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); + char *str1 = get_safe_offset(param,tpscnt,param,2); + char *str2 = skip_string(param,tpscnt,str1,1); + char *p = skip_string(param,tpscnt,str2,1); int uLevel; struct pack_desc desc; struct sessionid *session_list; int i, num_sessions; + if (!str1 || !str2 || !p) { + return False; + } + memset((char *)&desc,'\0',sizeof(desc)); - uLevel = SVAL(p,0); + uLevel = get_safe_offset(param,tpscnt,p,2) ? SVAL(p,0) : -1; DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel)); DEBUG(7,("RNetSessionEnum req string=%s\n",str1)); @@ -3951,10 +4252,12 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char The request is not supported. ****************************************************************************/ -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_Unsupported(connection_struct *conn, uint16 vuid, + char *param, int tpscnt, + char *data, int tdscnt, + int mdrcnt, int mprcnt, + char **rdata, char **rparam, + int *rdata_len, int *rparam_len) { *rparam_len = 4; *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); @@ -3975,7 +4278,9 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, c static const struct { const char *name; int id; - BOOL (*fn)(connection_struct *,uint16,char *,char *, + BOOL (*fn)(connection_struct *, uint16, + char *, int, + char *, int, int,int,char **,char **,int *,int *); BOOL auth_user; /* Deny anonymous access? */ } api_commands[] = { @@ -4030,6 +4335,8 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * int api_command; char *rdata = NULL; char *rparam = NULL; + const char *name1 = NULL; + const char *name2 = NULL; int rdata_len = 0; int rparam_len = 0; BOOL reply=False; @@ -4040,12 +4347,25 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * return 0; } + if (tpscnt < 2) { + return 0; + } api_command = SVAL(params,0); + /* Is there a string at position params+2 ? */ + if (skip_string(params,tpscnt,params+2,1)) { + name1 = params + 2; + } else { + name1 = ""; + } + name2 = skip_string(params,tpscnt,params+2,1); + if (!name2) { + name2 = ""; + } 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), + name1, + name2, tdscnt,tpscnt,mdrcnt,mprcnt)); for (i=0;api_commands[i].name;i++) { @@ -4082,7 +4402,11 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * return -1; } - reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt, + reply = api_commands[i].fn(conn, + vuid, + params,tpscnt, /* params + length */ + data,tdscnt, /* data + length */ + mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); @@ -4093,7 +4417,7 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char * /* if we get False back then it's actually unsupported */ if (!reply) { - reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt, + reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt, &rdata,&rparam,&rdata_len,&rparam_len); } |