r22014: Make us pass RANDOMIPC test again :-(. This is an ugly check-in,
authorJeremy Allison <jra@samba.org>
Fri, 30 Mar 2007 22:25:08 +0000 (22:25 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:19:01 +0000 (12:19 -0500)
but I've no option.
Jeremy.
(This used to be commit c3a565081d70b209a4f9e6e8f1859bf7194a5f74)

13 files changed:
source3/lib/util.c
source3/lib/util_str.c
source3/libsmb/clidgram.c
source3/libsmb/cliprint.c
source3/libsmb/clirap.c
source3/libsmb/clirap2.c
source3/nmbd/nmbd_browsesync.c
source3/nmbd/nmbd_elections.c
source3/nmbd/nmbd_incomingdgrams.c
source3/nmbd/nmbd_packets.c
source3/nmbd/nmbd_processlogon.c
source3/nmbd/nmbd_sendannounce.c
source3/smbd/lanman.c

index cf8d49c502e1938f8b222b84599fa6bca117cf1b..809071662d5ea43dadb2c4aa3a3aba7eeaa06ea0 100644 (file)
@@ -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;
+}
index ccf0af8b6239226276c631650dcaad69526c3156..032627db94b484b815631112dd188940f5eeba2d 100644 (file)
@@ -424,16 +424,45 @@ 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;
        return(buf);
 }
 
+/**
+ 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,
@@ -2591,4 +2620,3 @@ size_t utf16_len_n(const void *src, size_t n)
 
        return len;
 }
-
index a983f485ab4ccc3d25e02322e8f4fa8404a9555e..b6a9cfb31a3c1a0135172b1debfb1e63fc555a8c 100644 (file)
@@ -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;
index 5798e945541fe8ebb40db26b4a97344b606ddfc2..e33a3564eb4f972a9905089843cc3b0f71c2c0fe 100644 (file)
@@ -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;
        
index 4be03e16f079a26124f77bf057c1f64c62d6381d..3fc95e8429e3baa58e9adce5d75766bfe77b30ed 100644 (file)
@@ -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;
 
index d6a44f4ea223fdcc531884ce33927d5f73468766..9ab899787111e9b2948c414663eff93a8247697a 100644 (file)
@@ -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 {\
 /* 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 {\
index 9535a3115a68683620bb64dafefe9ffd68e5c0c2..ddb223de9f5ce8d5f3a0eb64f953721f66c318f2 100644 (file)
@@ -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" );
index 3aadd70b83ccdee828b5aa2d1520ff4471c00c21..fbdb6c4524f225115f153759386e77026acb1899 100644 (file)
@@ -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,
index 880700c72cb9d98742836e9b5df30cf59ca4f0a4..616b5df9dbe680d88288d4af31de64a9871d9b6b 100644 (file)
@@ -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;
index 89362392fe7f7e92d17aad597f81e6eb77d8408e..5ec6be130712d454759de21f71ceb1030bbfc3f5 100644 (file)
@@ -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"));
index 232f430b660f9b34222f1e6cc5a89a78ed738fea..6b10d612672185ad007931e2ff517bfdc7505f3d 100644 (file)
@@ -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;
                                }
index 7fcedc557ee77a45b736acc17549fa9535b1fbec..0cd481649dcbf57586e61206fa2188ee7a6d63f3 100644 (file)
@@ -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 */
index e42d96b11e96aefd07170b9bac52af4531faea87..905b6a023aaa9cb7ede8a50dc5645c4ad993315e 100644 (file)
@@ -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;
-       charstr3;
+       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);
-       charname = 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);
        }