2000-04-19 11:00:22 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-04-19 11:00:22 +04:00
Inter - process communication and named pipe handling
Copyright ( C ) Andrew Tridgell 1992 - 1998
2007-03-31 05:14:00 +04:00
Copyright ( C ) Jeremy Allison 2007.
2000-04-19 11:00:22 +04:00
SMB Version handling
Copyright ( C ) John H Terpstra 1995 - 1998
2009-01-31 18:57:46 +03:00
2000-04-19 11:00:22 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-04-19 11:00:22 +04:00
( at your option ) any later version .
2009-01-31 18:57:46 +03:00
2000-04-19 11:00:22 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2009-01-31 18:57:46 +03:00
2000-04-19 11:00:22 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-04-19 11:00:22 +04:00
*/
/*
This file handles the named pipe and mailslot calls
in the SMBtrans protocol
*/
# include "includes.h"
2009-05-26 18:38:45 +04:00
# include "smbd/globals.h"
2009-11-26 20:21:28 +03:00
# include "../librpc/gen_ndr/cli_samr.h"
2010-03-18 20:13:40 +03:00
# include "../librpc/gen_ndr/cli_spoolss.h"
2009-11-26 20:21:28 +03:00
# include "../librpc/gen_ndr/srv_samr.h"
2010-03-18 20:13:40 +03:00
# include "../librpc/gen_ndr/srv_spoolss.h"
2010-04-26 17:42:47 +04:00
# include "../librpc/gen_ndr/rap.h"
2010-02-05 20:08:46 +03:00
# include "../lib/util/binsearch.h"
2000-04-19 11:00:22 +04:00
# ifdef CHECK_TYPES
# undef CHECK_TYPES
# endif
# define CHECK_TYPES 0
# define NERR_Success 0
# define NERR_badpass 86
# define NERR_notsupported 50
# define NERR_BASE (2100)
# define NERR_BufTooSmall (NERR_BASE+23)
# define NERR_JobNotFound (NERR_BASE+51)
# define NERR_DestNotFound (NERR_BASE+52)
# define ACCESS_READ 0x01
# define ACCESS_WRITE 0x02
# define ACCESS_CREATE 0x04
# define SHPWLEN 8 /* share password length */
2007-09-11 23:27:34 +04:00
/* Limit size of ipc replies */
static char * smb_realloc_limit ( void * ptr , size_t size )
{
char * val ;
size = MAX ( ( size ) , 4 * 1024 ) ;
val = ( char * ) SMB_REALLOC ( ptr , size ) ;
if ( val ) {
memset ( val , ' \0 ' , size ) ;
}
return val ;
}
2007-10-19 04:40:25 +04:00
static bool api_Unsupported ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len ) ;
2007-10-19 04:40:25 +04:00
static bool api_TooSmall ( connection_struct * conn , uint16 vuid , char * param , char * data ,
2005-11-05 07:21:55 +03:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len ) ;
2000-04-19 11:00:22 +04:00
2007-11-13 04:59:18 +03:00
static int CopyExpanded ( connection_struct * conn ,
int snum , char * * dst , char * src , int * p_space_remaining )
2000-04-19 11:00:22 +04:00
{
2007-11-13 04:59:18 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
char * buf = NULL ;
2000-04-19 11:00:22 +04:00
int l ;
2007-11-13 04:59:18 +03:00
if ( ! src | | ! dst | | ! p_space_remaining | | ! ( * dst ) | |
* p_space_remaining < = 0 ) {
2005-11-05 07:21:55 +03:00
return 0 ;
}
2000-04-19 11:00:22 +04:00
2007-11-13 04:59:18 +03:00
buf = talloc_strdup ( ctx , src ) ;
if ( ! buf ) {
* p_space_remaining = 0 ;
return 0 ;
}
buf = talloc_string_sub ( ctx , buf , " %S " , lp_servicename ( snum ) ) ;
if ( ! buf ) {
* p_space_remaining = 0 ;
return 0 ;
}
buf = talloc_sub_advanced ( ctx ,
lp_servicename ( SNUM ( conn ) ) ,
2008-05-08 18:06:42 +04:00
conn - > server_info - > unix_name ,
2007-11-13 04:59:18 +03:00
conn - > connectpath ,
2008-06-19 18:54:12 +04:00
conn - > server_info - > utok . gid ,
2008-05-11 13:26:33 +04:00
conn - > server_info - > sanitized_username ,
2008-05-11 03:02:52 +04:00
pdb_get_domain ( conn - > server_info - > sam_account ) ,
2007-11-13 04:59:18 +03:00
buf ) ;
if ( ! buf ) {
* p_space_remaining = 0 ;
return 0 ;
}
l = push_ascii ( * dst , buf , * p_space_remaining , STR_TERMINATE ) ;
2007-11-20 04:43:28 +03:00
if ( l = = - 1 ) {
return 0 ;
}
2000-04-19 11:00:22 +04:00
( * dst ) + = l ;
2007-11-13 04:59:18 +03:00
( * p_space_remaining ) - = l ;
2000-04-19 11:00:22 +04:00
return l ;
}
2005-11-05 07:21:55 +03:00
static int CopyAndAdvance ( char * * dst , char * src , int * n )
2000-04-19 11:00:22 +04:00
{
2005-11-05 07:21:55 +03:00
int l ;
if ( ! src | | ! dst | | ! n | | ! ( * dst ) ) {
return 0 ;
}
l = push_ascii ( * dst , src , * n , STR_TERMINATE ) ;
2007-11-20 04:43:28 +03:00
if ( l = = - 1 ) {
return 0 ;
}
2005-11-05 07:21:55 +03:00
( * dst ) + = l ;
( * n ) - = l ;
return l ;
2000-04-19 11:00:22 +04:00
}
2005-11-05 07:21:55 +03:00
static int StrlenExpanded ( connection_struct * conn , int snum , char * s )
2000-04-19 11:00:22 +04:00
{
2007-11-13 04:59:18 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
char * buf = NULL ;
2005-11-05 07:21:55 +03:00
if ( ! s ) {
return 0 ;
}
2007-11-13 04:59:18 +03:00
buf = talloc_strdup ( ctx , s ) ;
if ( ! buf ) {
return 0 ;
}
buf = talloc_string_sub ( ctx , buf , " %S " , lp_servicename ( snum ) ) ;
if ( ! buf ) {
return 0 ;
}
buf = talloc_sub_advanced ( ctx ,
lp_servicename ( SNUM ( conn ) ) ,
2008-05-08 18:06:42 +04:00
conn - > server_info - > unix_name ,
2007-11-13 04:59:18 +03:00
conn - > connectpath ,
2008-06-19 18:54:12 +04:00
conn - > server_info - > utok . gid ,
2008-05-11 13:26:33 +04:00
conn - > server_info - > sanitized_username ,
2008-05-11 03:02:52 +04:00
pdb_get_domain ( conn - > server_info - > sam_account ) ,
2007-11-13 04:59:18 +03:00
buf ) ;
if ( ! buf ) {
return 0 ;
}
2000-04-19 11:00:22 +04:00
return strlen ( buf ) + 1 ;
}
/*******************************************************************
2005-11-05 07:21:55 +03:00
Check a API string for validity when we only need to check the prefix .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool prefix_ok ( const char * str , const char * prefix )
2000-04-19 11:00:22 +04:00
{
2005-11-05 07:21:55 +03:00
return ( strncmp ( str , prefix , strlen ( prefix ) ) = = 0 ) ;
2000-04-19 11:00:22 +04:00
}
struct pack_desc {
2005-11-05 07:21:55 +03:00
const char * format ; /* formatstring for structure */
const char * subformat ; /* subformat for structure */
char * base ; /* baseaddress of buffer */
int buflen ; /* remaining size for fixed part; on init: length of base */
int subcount ; /* count of substructures */
char * structbuf ; /* pointer into buffer for remaining fixed part */
int stringlen ; /* remaining size for variable part */
char * stringbuf ; /* pointer into buffer for remaining variable part */
int neededlen ; /* total needed size */
int usedlen ; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
const char * curpos ; /* current position; pointer into format or subformat */
int errcode ;
2000-04-19 11:00:22 +04:00
} ;
2005-11-05 07:21:55 +03:00
static int get_counter ( const char * * p )
2000-04-19 11:00:22 +04:00
{
2005-11-05 07:21:55 +03:00
int i , n ;
if ( ! p | | ! ( * p ) ) {
return 1 ;
}
if ( ! isdigit ( ( int ) * * p ) ) {
return 1 ;
}
for ( n = 0 ; ; ) {
i = * * p ;
if ( isdigit ( i ) ) {
n = 10 * n + ( i - ' 0 ' ) ;
} else {
return n ;
}
( * p ) + + ;
}
2000-04-19 11:00:22 +04:00
}
2005-11-05 07:21:55 +03:00
static int getlen ( const char * p )
2000-04-19 11:00:22 +04:00
{
2005-11-05 07:21:55 +03:00
int n = 0 ;
if ( ! p ) {
return 0 ;
}
while ( * p ) {
switch ( * p + + ) {
case ' W ' : /* word (2 byte) */
n + = 2 ;
break ;
case ' K ' : /* status word? (2 byte) */
n + = 2 ;
break ;
case ' N ' : /* count of substructures (word) at end */
n + = 2 ;
break ;
case ' D ' : /* double word (4 byte) */
case ' z ' : /* offset to zero terminated string (4 byte) */
case ' l ' : /* offset to user data (4 byte) */
n + = 4 ;
break ;
case ' b ' : /* offset to data (with counter) (4 byte) */
n + = 4 ;
get_counter ( & p ) ;
break ;
case ' B ' : /* byte (with optional counter) */
n + = get_counter ( & p ) ;
break ;
}
}
return n ;
2000-04-19 11:00:22 +04:00
}
2007-10-19 04:40:25 +04:00
static bool init_package ( struct pack_desc * p , int count , int subcount )
2000-04-19 11:00:22 +04:00
{
2005-11-05 07:21:55 +03:00
int n = p - > buflen ;
int i ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
if ( ! p - > format | | ! p - > base ) {
return False ;
}
i = count * getlen ( p - > format ) ;
if ( p - > subformat ) {
i + = subcount * getlen ( p - > subformat ) ;
}
p - > structbuf = p - > base ;
p - > neededlen = 0 ;
p - > usedlen = 0 ;
p - > subcount = 0 ;
p - > curpos = p - > format ;
if ( i > n ) {
p - > neededlen = i ;
i = n = 0 ;
2000-11-16 22:08:55 +03:00
#if 0
2005-11-05 07:21:55 +03:00
/*
* This is the old error code we used . Aparently
* WinNT / 2 k systems return ERRbuftoosmall ( 2123 ) and
* OS / 2 needs this . I ' m leaving this here so we can revert
* if needed . JRA .
*/
p - > errcode = ERRmoredata ;
2000-11-16 22:08:55 +03:00
# else
2005-11-05 07:21:55 +03:00
p - > errcode = ERRbuftoosmall ;
2000-11-16 22:08:55 +03:00
# endif
2005-11-05 07:21:55 +03:00
} else {
p - > errcode = NERR_Success ;
}
p - > buflen = i ;
n - = i ;
p - > stringbuf = p - > base + i ;
p - > stringlen = n ;
return ( p - > errcode = = NERR_Success ) ;
2000-04-19 11:00:22 +04:00
}
2005-11-05 07:21:55 +03:00
static int package ( struct pack_desc * p , . . . )
2000-04-19 11:00:22 +04:00
{
2005-11-05 07:21:55 +03:00
va_list args ;
int needed = 0 , stringneeded ;
const char * str = NULL ;
int is_string = 0 , stringused ;
int32 temp ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
va_start ( args , p ) ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
if ( ! * p - > curpos ) {
if ( ! p - > subcount ) {
p - > curpos = p - > format ;
} else {
p - > curpos = p - > subformat ;
p - > subcount - - ;
}
}
2000-04-19 11:00:22 +04:00
# if CHECK_TYPES
2005-11-05 07:21:55 +03:00
str = va_arg ( args , char * ) ;
SMB_ASSERT ( strncmp ( str , p - > curpos , strlen ( str ) ) = = 0 ) ;
2000-04-19 11:00:22 +04:00
# endif
2005-11-05 07:21:55 +03:00
stringneeded = - 1 ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
if ( ! p - > curpos ) {
va_end ( args ) ;
return 0 ;
}
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
switch ( * p - > curpos + + ) {
case ' W ' : /* word (2 byte) */
needed = 2 ;
temp = va_arg ( args , int ) ;
if ( p - > buflen > = needed ) {
SSVAL ( p - > structbuf , 0 , temp ) ;
}
break ;
case ' K ' : /* status word? (2 byte) */
needed = 2 ;
temp = va_arg ( args , int ) ;
if ( p - > buflen > = needed ) {
SSVAL ( p - > structbuf , 0 , temp ) ;
}
break ;
case ' N ' : /* count of substructures (word) at end */
needed = 2 ;
p - > subcount = va_arg ( args , int ) ;
if ( p - > buflen > = needed ) {
SSVAL ( p - > structbuf , 0 , p - > subcount ) ;
}
break ;
case ' D ' : /* double word (4 byte) */
needed = 4 ;
temp = va_arg ( args , int ) ;
if ( p - > buflen > = needed ) {
SIVAL ( p - > structbuf , 0 , temp ) ;
}
break ;
case ' B ' : /* byte (with optional counter) */
needed = get_counter ( & p - > curpos ) ;
{
char * s = va_arg ( args , char * ) ;
if ( p - > buflen > = needed ) {
StrnCpy ( p - > structbuf , s ? s : " " , needed - 1 ) ;
}
}
break ;
case ' z ' : /* offset to zero terminated string (4 byte) */
str = va_arg ( args , char * ) ;
stringneeded = ( str ? strlen ( str ) + 1 : 0 ) ;
is_string = 1 ;
break ;
case ' l ' : /* offset to user data (4 byte) */
str = va_arg ( args , char * ) ;
stringneeded = va_arg ( args , int ) ;
is_string = 0 ;
break ;
case ' b ' : /* offset to data (with counter) (4 byte) */
str = va_arg ( args , char * ) ;
stringneeded = get_counter ( & p - > curpos ) ;
is_string = 0 ;
break ;
}
va_end ( args ) ;
if ( stringneeded > = 0 ) {
needed = 4 ;
if ( p - > buflen > = needed ) {
stringused = stringneeded ;
if ( stringused > p - > stringlen ) {
stringused = ( is_string ? p - > stringlen : 0 ) ;
if ( p - > errcode = = NERR_Success ) {
p - > errcode = ERRmoredata ;
}
}
if ( ! stringused ) {
SIVAL ( p - > structbuf , 0 , 0 ) ;
} else {
SIVAL ( p - > structbuf , 0 , PTR_DIFF ( p - > stringbuf , p - > base ) ) ;
memcpy ( p - > stringbuf , str ? str : " " , stringused ) ;
if ( is_string ) {
p - > stringbuf [ stringused - 1 ] = ' \0 ' ;
}
p - > stringbuf + = stringused ;
p - > stringlen - = stringused ;
p - > usedlen + = stringused ;
}
}
p - > neededlen + = stringneeded ;
}
p - > neededlen + = needed ;
if ( p - > buflen > = needed ) {
p - > structbuf + = needed ;
p - > buflen - = needed ;
p - > usedlen + = needed ;
} else {
if ( p - > errcode = = NERR_Success ) {
p - > errcode = ERRmoredata ;
}
}
return 1 ;
2000-04-19 11:00:22 +04:00
}
# if CHECK_TYPES
# define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
# define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
# else
# define PACK(desc,t,v) package(desc,v)
# define PACKl(desc,t,v,l) package(desc,v,l)
# endif
2003-01-03 11:28:12 +03:00
static void PACKI ( struct pack_desc * desc , const char * t , int v )
2000-04-19 11:00:22 +04:00
{
2005-08-13 04:13:21 +04:00
PACK ( desc , t , v ) ;
2000-04-19 11:00:22 +04:00
}
2002-11-16 00:43:57 +03:00
static void PACKS ( struct pack_desc * desc , const char * t , const char * v )
2000-04-19 11:00:22 +04:00
{
2005-08-13 04:13:21 +04:00
PACK ( desc , t , v ) ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
2005-11-05 07:21:55 +03:00
Get a print queue .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-19 11:00:22 +04:00
static void PackDriverData ( struct pack_desc * desc )
{
2005-08-13 04:13:21 +04:00
char drivdata [ 4 + 4 + 32 ] ;
SIVAL ( drivdata , 0 , sizeof drivdata ) ; /* cb */
SIVAL ( drivdata , 4 , 1000 ) ; /* lVersion */
memset ( drivdata + 8 , 0 , 32 ) ; /* szDeviceName */
2007-09-14 02:08:59 +04:00
push_ascii ( drivdata + 8 , " NULL " , 32 , STR_TERMINATE ) ;
2005-08-13 04:13:21 +04:00
PACKl ( desc , " l " , drivdata , sizeof drivdata ) ; /* pDriverData */
2000-04-19 11:00:22 +04:00
}
static int check_printq_info ( struct pack_desc * desc ,
2005-08-13 04:13:21 +04:00
unsigned int uLevel , char * id1 , char * id2 )
2000-04-19 11:00:22 +04:00
{
2005-08-13 04:13:21 +04:00
desc - > subformat = NULL ;
switch ( uLevel ) {
case 0 :
desc - > format = " B13 " ;
break ;
case 1 :
desc - > format = " B13BWWWzzzzzWW " ;
break ;
case 2 :
desc - > format = " B13BWWWzzzzzWN " ;
desc - > subformat = " WB21BB16B10zWWzDDz " ;
break ;
case 3 :
desc - > format = " zWWWWzzzzWWzzl " ;
break ;
case 4 :
desc - > format = " zWWWWzzzzWNzzl " ;
desc - > subformat = " WWzWWDDzz " ;
break ;
case 5 :
desc - > format = " z " ;
break ;
case 51 :
desc - > format = " K " ;
break ;
case 52 :
desc - > format = " WzzzzzzzzN " ;
desc - > subformat = " z " ;
break ;
default :
2007-04-04 04:03:12 +04:00
DEBUG ( 0 , ( " check_printq_info: invalid level %d \n " ,
uLevel ) ) ;
2005-08-13 04:13:21 +04:00
return False ;
}
2007-04-04 04:03:12 +04:00
if ( id1 = = NULL | | strcmp ( desc - > format , id1 ) ! = 0 ) {
DEBUG ( 0 , ( " check_printq_info: invalid format %s \n " ,
id1 ? id1 : " <NULL> " ) ) ;
2005-08-13 04:13:21 +04:00
return False ;
}
2007-04-04 04:03:12 +04:00
if ( desc - > subformat & & ( id2 = = NULL | | strcmp ( desc - > subformat , id2 ) ! = 0 ) ) {
DEBUG ( 0 , ( " check_printq_info: invalid subformat %s \n " ,
id2 ? id2 : " <NULL> " ) ) ;
2005-08-13 04:13:21 +04:00
return False ;
}
return True ;
2000-04-19 11:00:22 +04:00
}
2001-02-23 06:59:37 +03:00
# define RAP_JOB_STATUS_QUEUED 0
# define RAP_JOB_STATUS_PAUSED 1
# define RAP_JOB_STATUS_SPOOLING 2
# define RAP_JOB_STATUS_PRINTING 3
# define RAP_JOB_STATUS_PRINTED 4
2000-04-19 11:00:22 +04:00
2001-02-23 06:59:37 +03:00
# define RAP_QUEUE_STATUS_PAUSED 1
# define RAP_QUEUE_STATUS_ERROR 2
2000-04-19 11:00:22 +04:00
/* turn a print job status into a on the wire status
*/
2010-04-10 03:33:37 +04:00
static int printj_spoolss_status ( int v )
{
if ( v = = JOB_STATUS_QUEUED )
return RAP_JOB_STATUS_QUEUED ;
if ( v & JOB_STATUS_PAUSED )
return RAP_JOB_STATUS_PAUSED ;
if ( v & JOB_STATUS_SPOOLING )
return RAP_JOB_STATUS_SPOOLING ;
if ( v & JOB_STATUS_PRINTING )
return RAP_JOB_STATUS_PRINTING ;
return 0 ;
}
2000-04-19 11:00:22 +04:00
/* turn a print queue status into a on the wire status
*/
2010-04-28 00:55:11 +04:00
static int printq_spoolss_status ( int v )
{
if ( v = = PRINTER_STATUS_OK )
return 0 ;
if ( v & PRINTER_STATUS_PAUSED )
return RAP_QUEUE_STATUS_PAUSED ;
return RAP_QUEUE_STATUS_ERROR ;
}
2010-04-10 03:33:37 +04:00
static time_t spoolss_Time_to_time_t ( const struct spoolss_Time * r )
{
struct tm unixtime ;
unixtime . tm_year = r - > year - 1900 ;
unixtime . tm_mon = r - > month - 1 ;
unixtime . tm_wday = r - > day_of_week ;
unixtime . tm_mday = r - > day ;
unixtime . tm_hour = r - > hour ;
unixtime . tm_min = r - > minute ;
unixtime . tm_sec = r - > second ;
return mktime ( & unixtime ) ;
}
static void fill_spoolss_printjob_info ( int uLevel ,
struct pack_desc * desc ,
struct spoolss_JobInfo2 * info2 ,
int n )
{
time_t t = spoolss_Time_to_time_t ( & info2 - > submitted ) ;
/* the client expects localtime */
t - = get_time_zone ( t ) ;
PACKI ( desc , " W " , pjobid_to_rap ( info2 - > printer_name , info2 - > job_id ) ) ; /* uJobId */
if ( uLevel = = 1 ) {
PACKS ( desc , " B21 " , info2 - > user_name ) ; /* szUserName */
PACKS ( desc , " B " , " " ) ; /* pad */
PACKS ( desc , " B16 " , " " ) ; /* szNotifyName */
PACKS ( desc , " B10 " , " PM_Q_RAW " ) ; /* szDataType */
PACKS ( desc , " z " , " " ) ; /* pszParms */
PACKI ( desc , " W " , n + 1 ) ; /* uPosition */
PACKI ( desc , " W " , printj_spoolss_status ( info2 - > status ) ) ; /* fsStatus */
PACKS ( desc , " z " , " " ) ; /* pszStatus */
PACKI ( desc , " D " , t ) ; /* ulSubmitted */
PACKI ( desc , " D " , info2 - > size ) ; /* ulSize */
PACKS ( desc , " z " , info2 - > document_name ) ; /* pszComment */
}
if ( uLevel = = 2 | | uLevel = = 3 | | uLevel = = 4 ) {
PACKI ( desc , " W " , info2 - > priority ) ; /* uPriority */
PACKS ( desc , " z " , info2 - > user_name ) ; /* pszUserName */
PACKI ( desc , " W " , n + 1 ) ; /* uPosition */
PACKI ( desc , " W " , printj_spoolss_status ( info2 - > status ) ) ; /* fsStatus */
PACKI ( desc , " D " , t ) ; /* ulSubmitted */
PACKI ( desc , " D " , info2 - > size ) ; /* ulSize */
PACKS ( desc , " z " , " Samba " ) ; /* pszComment */
PACKS ( desc , " z " , info2 - > document_name ) ; /* pszDocument */
if ( uLevel = = 3 ) {
PACKS ( desc , " z " , " " ) ; /* pszNotifyName */
PACKS ( desc , " z " , " PM_Q_RAW " ) ; /* pszDataType */
PACKS ( desc , " z " , " " ) ; /* pszParms */
PACKS ( desc , " z " , " " ) ; /* pszStatus */
PACKS ( desc , " z " , info2 - > printer_name ) ; /* pszQueue */
PACKS ( desc , " z " , " lpd " ) ; /* pszQProcName */
PACKS ( desc , " z " , " " ) ; /* pszQProcParms */
PACKS ( desc , " z " , " NULL " ) ; /* pszDriverName */
PackDriverData ( desc ) ; /* pDriverData */
PACKS ( desc , " z " , " " ) ; /* pszPrinterName */
} else if ( uLevel = = 4 ) { /* OS2 */
PACKS ( desc , " z " , " " ) ; /* pszSpoolFileName */
PACKS ( desc , " z " , " " ) ; /* pszPortName */
PACKS ( desc , " z " , " " ) ; /* pszStatus */
PACKI ( desc , " D " , 0 ) ; /* ulPagesSpooled */
PACKI ( desc , " D " , 0 ) ; /* ulPagesSent */
PACKI ( desc , " D " , 0 ) ; /* ulPagesPrinted */
PACKI ( desc , " D " , 0 ) ; /* ulTimePrinted */
PACKI ( desc , " D " , 0 ) ; /* ulExtendJobStatus */
PACKI ( desc , " D " , 0 ) ; /* ulStartPage */
PACKI ( desc , " D " , 0 ) ; /* ulEndPage */
}
}
}
2000-08-18 00:05:05 +04:00
/********************************************************************
Respond to the DosPrintQInfo command with a level of 52
This is used to get printer driver information for Win9x clients
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-04-28 00:55:11 +04:00
static void fill_printq_info_52 ( struct spoolss_DriverInfo3 * driver ,
struct pack_desc * desc , int count ,
const char * printer_name )
2000-04-19 11:00:22 +04:00
{
2002-10-22 00:11:12 +04:00
int i ;
fstring location ;
2009-11-27 03:49:08 +03:00
trim_string ( ( char * ) driver - > driver_path , " \\ print$ \\ WIN40 \\ 0 \\ " , 0 ) ;
trim_string ( ( char * ) driver - > data_file , " \\ print$ \\ WIN40 \\ 0 \\ " , 0 ) ;
trim_string ( ( char * ) driver - > help_file , " \\ print$ \\ WIN40 \\ 0 \\ " , 0 ) ;
2007-03-31 02:25:08 +04:00
2002-10-22 00:11:12 +04:00
PACKI ( desc , " W " , 0x0400 ) ; /* don't know */
2009-11-27 03:49:08 +03:00
PACKS ( desc , " z " , driver - > driver_name ) ; /* long printer name */
PACKS ( desc , " z " , driver - > driver_path ) ; /* Driverfile Name */
PACKS ( desc , " z " , driver - > data_file ) ; /* Datafile name */
PACKS ( desc , " z " , driver - > monitor_name ) ; /* language monitor */
2007-03-31 02:25:08 +04:00
2004-10-02 00:34:12 +04:00
fstrcpy ( location , " \\ \\ %L \\ print$ \\ WIN40 \\ 0 " ) ;
2006-07-11 22:01:26 +04:00
standard_sub_basic ( " " , " " , location , sizeof ( location ) - 1 ) ;
2002-10-22 00:11:12 +04:00
PACKS ( desc , " z " , location ) ; /* share to retrieve files */
2007-03-31 02:25:08 +04:00
2009-11-27 03:49:08 +03:00
PACKS ( desc , " z " , driver - > default_datatype ) ; /* default data type */
PACKS ( desc , " z " , driver - > help_file ) ; /* helpfile name */
PACKS ( desc , " z " , driver - > driver_path ) ; /* driver name */
2002-10-22 00:11:12 +04:00
2009-11-27 03:49:08 +03:00
DEBUG ( 3 , ( " Printer Driver Name: %s: \n " , driver - > driver_name ) ) ;
DEBUG ( 3 , ( " Driver: %s: \n " , driver - > driver_path ) ) ;
DEBUG ( 3 , ( " Data File: %s: \n " , driver - > data_file ) ) ;
DEBUG ( 3 , ( " Language Monitor: %s: \n " , driver - > monitor_name ) ) ;
2002-10-22 00:11:12 +04:00
DEBUG ( 3 , ( " Driver Location: %s: \n " , location ) ) ;
2009-11-27 03:49:08 +03:00
DEBUG ( 3 , ( " Data Type: %s: \n " , driver - > default_datatype ) ) ;
DEBUG ( 3 , ( " Help File: %s: \n " , driver - > help_file ) ) ;
2002-10-22 00:11:12 +04:00
PACKI ( desc , " N " , count ) ; /* number of files to copy */
2009-11-27 03:49:08 +03:00
for ( i = 0 ; i < count & & driver - > dependent_files & & * driver - > dependent_files [ i ] ; i + + )
2002-10-22 00:11:12 +04:00
{
2009-11-27 03:49:08 +03:00
trim_string ( ( char * ) driver - > dependent_files [ i ] , " \\ print$ \\ WIN40 \\ 0 \\ " , 0 ) ;
PACKS ( desc , " z " , driver - > dependent_files [ i ] ) ; /* driver files to copy */
DEBUG ( 3 , ( " Dependent File: %s: \n " , driver - > dependent_files [ i ] ) ) ;
2000-08-01 00:41:51 +04:00
}
2007-03-31 02:25:08 +04:00
2002-10-22 00:11:12 +04:00
/* 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 ) ) ;
2007-03-31 02:25:08 +04:00
2010-04-28 00:55:11 +04:00
DEBUG ( 3 , ( " fill_printq_info on <%s> gave %d entries \n " , printer_name , i ) ) ;
2000-07-20 03:47:10 +04:00
2002-10-22 00:11:12 +04:00
desc - > errcode = NERR_Success ;
2000-09-01 22:49:26 +04:00
2000-04-19 11:00:22 +04:00
}
2010-04-28 00:55:11 +04:00
static void fill_printq_info ( int uLevel ,
2000-04-19 11:00:22 +04:00
struct pack_desc * desc ,
2010-04-28 00:55:11 +04:00
int count ,
union spoolss_JobInfo * job_info ,
struct spoolss_DriverInfo3 * driver_info ,
struct spoolss_PrinterInfo2 * printer_info )
2000-04-19 11:00:22 +04:00
{
switch ( uLevel ) {
case 1 :
case 2 :
2010-04-28 00:55:11 +04:00
PACKS ( desc , " B13 " , printer_info - > printername ) ;
2000-04-19 11:00:22 +04:00
break ;
case 3 :
case 4 :
case 5 :
2010-04-28 00:55:11 +04:00
PACKS ( desc , " z " , printer_info - > printername ) ;
2000-04-19 11:00:22 +04:00
break ;
case 51 :
2010-04-28 00:55:11 +04:00
PACKI ( desc , " K " , printq_spoolss_status ( printer_info - > status ) ) ;
2000-04-19 11:00:22 +04:00
break ;
}
if ( uLevel = = 1 | | uLevel = = 2 ) {
PACKS ( desc , " B " , " " ) ; /* alignment */
PACKI ( desc , " W " , 5 ) ; /* priority */
PACKI ( desc , " W " , 0 ) ; /* start time */
PACKI ( desc , " W " , 0 ) ; /* until time */
PACKS ( desc , " z " , " " ) ; /* pSepFile */
PACKS ( desc , " z " , " lpd " ) ; /* pPrProc */
2010-04-28 00:55:11 +04:00
PACKS ( desc , " z " , printer_info - > printername ) ; /* pDestinations */
2000-04-19 11:00:22 +04:00
PACKS ( desc , " z " , " " ) ; /* pParms */
2010-04-28 00:55:11 +04:00
if ( printer_info - > printername = = NULL ) {
2000-04-19 11:00:22 +04:00
PACKS ( desc , " z " , " UNKNOWN PRINTER " ) ;
PACKI ( desc , " W " , LPSTAT_ERROR ) ;
} else {
2010-04-28 00:55:11 +04:00
PACKS ( desc , " z " , printer_info - > comment ) ;
PACKI ( desc , " W " , printq_spoolss_status ( printer_info - > status ) ) ; /* status */
2000-04-19 11:00:22 +04:00
}
PACKI ( desc , ( uLevel = = 1 ? " W " : " N " ) , count ) ;
}
if ( uLevel = = 3 | | uLevel = = 4 ) {
PACKI ( desc , " W " , 5 ) ; /* uPriority */
PACKI ( desc , " W " , 0 ) ; /* uStarttime */
PACKI ( desc , " W " , 0 ) ; /* uUntiltime */
PACKI ( desc , " W " , 5 ) ; /* pad1 */
PACKS ( desc , " z " , " " ) ; /* pszSepFile */
PACKS ( desc , " z " , " WinPrint " ) ; /* pszPrProc */
2001-01-30 00:34:08 +03:00
PACKS ( desc , " z " , NULL ) ; /* pszParms */
2001-01-17 22:16:05 +03:00
PACKS ( desc , " z " , NULL ) ; /* pszComment - don't ask.... JRA */
2007-11-13 04:59:18 +03:00
/* "don't ask" that it's done this way to fix corrupted
2001-01-17 22:16:05 +03:00
Win9X / ME printer comments . */
2010-04-28 00:55:11 +04:00
PACKI ( desc , " W " , printq_spoolss_status ( printer_info - > status ) ) ; /* fsStatus */
2000-04-19 11:00:22 +04:00
PACKI ( desc , ( uLevel = = 3 ? " W " : " N " ) , count ) ; /* cJobs */
2010-04-28 00:55:11 +04:00
PACKS ( desc , " z " , printer_info - > printername ) ; /* pszPrinters */
PACKS ( desc , " z " , printer_info - > drivername ) ; /* pszDriverName */
2000-04-19 11:00:22 +04:00
PackDriverData ( desc ) ; /* pDriverData */
}
if ( uLevel = = 2 | | uLevel = = 4 ) {
int i ;
2010-04-28 00:55:11 +04:00
for ( i = 0 ; i < count ; i + + ) {
fill_spoolss_printjob_info ( uLevel = = 2 ? 1 : 2 , desc , & job_info [ i ] . info2 , i ) ;
}
2000-04-19 11:00:22 +04:00
}
2002-10-22 00:11:12 +04:00
if ( uLevel = = 52 )
2010-04-28 00:55:11 +04:00
fill_printq_info_52 ( driver_info , desc , count , printer_info - > printername ) ;
2000-04-19 11:00:22 +04:00
}
/* This function returns the number of files for a given driver */
2010-04-28 00:55:11 +04:00
static int get_printerdrivernumber ( const struct spoolss_DriverInfo3 * driver )
2000-04-19 11:00:22 +04:00
{
2002-10-22 00:11:12 +04:00
int result = 0 ;
2007-03-31 02:25:08 +04:00
2002-10-22 00:11:12 +04:00
/* count the number of files */
2009-11-27 03:49:08 +03:00
while ( driver - > dependent_files & & * driver - > dependent_files [ result ] )
2009-11-17 14:54:02 +03:00
result + + ;
2007-03-31 02:25:08 +04:00
2000-09-01 22:49:26 +04:00
return result ;
2000-04-19 11:00:22 +04:00
}
2007-10-19 04:40:25 +04:00
static bool api_DosPrintQGetInfo ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2001-08-07 02:39:51 +04:00
char * QueueName = p ;
2005-08-13 04:13:21 +04:00
unsigned int uLevel ;
2010-04-28 00:55:11 +04:00
uint32_t count = 0 ;
2007-03-31 02:25:08 +04:00
char * str3 ;
2001-08-07 02:39:51 +04:00
struct pack_desc desc ;
char * tmpdata = NULL ;
2010-04-28 00:55:11 +04:00
WERROR werr = WERR_OK ;
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle handle ;
struct spoolss_DevmodeContainer devmode_ctr ;
union spoolss_DriverInfo driver_info ;
union spoolss_JobInfo * job_info ;
union spoolss_PrinterInfo printer_info ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2001-08-07 02:39:51 +04:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
2007-03-31 02:25:08 +04:00
2007-04-03 00:10:21 +04:00
p = skip_string ( param , tpscnt , p ) ;
2007-03-31 02:25:08 +04:00
if ( ! p ) {
return False ;
}
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
str3 = get_safe_str_ptr ( param , tpscnt , p , 4 ) ;
2007-04-04 04:03:12 +04:00
/* str3 may be null here and is checked in check_printq_info(). */
2007-03-31 02:25:08 +04:00
2001-08-07 02:39:51 +04:00
/* remove any trailing username */
if ( ( p = strchr_m ( QueueName , ' % ' ) ) )
* p = 0 ;
2009-01-31 18:57:46 +03:00
2001-08-07 02:39:51 +04:00
DEBUG ( 3 , ( " api_DosPrintQGetInfo uLevel=%d name=%s \n " , uLevel , QueueName ) ) ;
2009-01-31 18:57:46 +03:00
2001-08-07 02:39:51 +04:00
/* check it's a supported varient */
if ( ! prefix_ok ( str1 , " zWrLh " ) )
return False ;
if ( ! check_printq_info ( & desc , uLevel , str2 , str3 ) ) {
/*
* Patch from Scott Moomaw < scott @ bridgewater . edu >
* to return the ' invalid info level ' error if an
* unknown level was requested .
*/
* rdata_len = 0 ;
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2001-08-10 09:50:47 +04:00
SSVALS ( * rparam , 0 , ERRunknownlevel ) ;
2001-08-07 02:39:51 +04:00
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , 0 ) ;
return ( True ) ;
}
2009-01-31 18:57:46 +03:00
2010-04-28 00:55:11 +04:00
ZERO_STRUCT ( handle ) ;
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_DosPrintQGetInfo: could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
ZERO_STRUCT ( devmode_ctr ) ;
status = rpccli_spoolss_OpenPrinter ( cli , mem_ctx ,
QueueName ,
NULL ,
devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
}
2009-01-31 18:57:46 +03:00
2001-08-07 02:39:51 +04:00
if ( uLevel = = 52 ) {
2010-04-28 00:55:11 +04:00
uint32_t server_major_version ;
uint32_t server_minor_version ;
werr = rpccli_spoolss_getprinterdriver2 ( cli , mem_ctx ,
& handle ,
" Windows 4.0 " ,
3 , /* level */
0 ,
0 , /* version */
0 ,
& driver_info ,
& server_major_version ,
& server_minor_version ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
}
count = get_printerdrivernumber ( & driver_info . info3 ) ;
2001-08-07 02:39:51 +04:00
DEBUG ( 3 , ( " api_DosPrintQGetInfo: Driver files count: %d \n " , count ) ) ;
} else {
2010-04-28 00:55:11 +04:00
uint32_t num_jobs ;
werr = rpccli_spoolss_enumjobs ( cli , mem_ctx ,
& handle ,
0 , /* firstjob */
0xff , /* numjobs */
2 , /* level */
0 , /* offered */
& num_jobs ,
& job_info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
}
count = num_jobs ;
2001-08-07 02:39:51 +04:00
}
2000-04-19 11:00:22 +04:00
2001-08-07 02:39:51 +04:00
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2001-08-07 02:39:51 +04:00
desc . base = * rdata ;
desc . buflen = mdrcnt ;
} else {
/*
* Don ' t return data but need to get correct length
* init_package will return wrong size if buflen = 0
*/
desc . buflen = getlen ( desc . format ) ;
2004-12-07 21:25:53 +03:00
desc . base = tmpdata = ( char * ) SMB_MALLOC ( desc . buflen ) ;
2001-08-07 02:39:51 +04:00
}
2001-03-23 06:12:58 +03:00
2001-08-07 02:39:51 +04:00
if ( init_package ( & desc , 1 , count ) ) {
desc . subcount = count ;
2010-04-28 00:55:11 +04:00
fill_printq_info ( uLevel , & desc , count , job_info , & driver_info . info3 , & printer_info . info2 ) ;
2001-08-07 02:39:51 +04:00
}
2000-04-19 11:00:22 +04:00
2001-08-07 02:39:51 +04:00
* rdata_len = desc . usedlen ;
2009-01-31 18:57:46 +03:00
2001-08-07 02:39:51 +04:00
/*
* We must set the return code to ERRbuftoosmall
* in order to support lanman style printing with Win NT / 2 k
* clients - - jerry
*/
2001-08-10 08:27:26 +04:00
if ( ! mdrcnt & & lp_disable_spoolss ( ) )
2001-08-07 02:39:51 +04:00
desc . errcode = ERRbuftoosmall ;
2009-01-31 18:57:46 +03:00
2010-04-28 00:55:11 +04:00
out :
if ( is_valid_policy_hnd ( & handle ) ) {
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & handle , NULL ) ;
}
2002-08-17 19:27:10 +04:00
* rdata_len = desc . usedlen ;
2001-08-07 02:39:51 +04:00
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
2007-07-19 14:23:36 +04:00
SAFE_FREE ( tmpdata ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
return False ;
}
2001-08-07 02:39:51 +04:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , desc . neededlen ) ;
2009-01-31 18:57:46 +03:00
2001-08-07 02:39:51 +04:00
DEBUG ( 4 , ( " printqgetinfo: errorcode %d \n " , desc . errcode ) ) ;
2000-04-19 11:00:22 +04:00
2001-09-17 15:25:41 +04:00
SAFE_FREE ( tmpdata ) ;
2001-03-23 06:12:58 +03:00
2001-08-07 02:39:51 +04:00
return ( True ) ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
2000-08-01 04:41:19 +04:00
View list of all print jobs on all queues .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_DosPrintQEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * param_format = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * output_format1 = skip_string ( param , tpscnt , param_format ) ;
char * p = skip_string ( param , tpscnt , output_format1 ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
unsigned int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
char * output_format2 = get_safe_str_ptr ( param , tpscnt , p , 4 ) ;
2010-04-28 00:55:11 +04:00
int i ;
2005-08-13 04:13:21 +04:00
struct pack_desc desc ;
int * subcntarr = NULL ;
int queuecnt = 0 , subcnt = 0 , succnt = 0 ;
2009-01-31 18:57:46 +03:00
2010-04-28 00:55:11 +04:00
WERROR werr = WERR_OK ;
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct spoolss_DevmodeContainer devmode_ctr ;
uint32_t num_printers ;
union spoolss_PrinterInfo * printer_info ;
2007-04-04 04:03:12 +04:00
if ( ! param_format | | ! output_format1 | | ! p ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2005-08-13 04:13:21 +04:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
2000-04-19 11:00:22 +04:00
2005-08-13 04:13:21 +04:00
DEBUG ( 3 , ( " DosPrintQEnum uLevel=%d \n " , uLevel ) ) ;
2009-01-31 18:57:46 +03:00
2005-08-13 04:13:21 +04:00
if ( ! prefix_ok ( param_format , " WrLeh " ) ) {
return False ;
}
if ( ! check_printq_info ( & desc , uLevel , output_format1 , output_format2 ) ) {
/*
* Patch from Scott Moomaw < scott @ bridgewater . edu >
* to return the ' invalid info level ' error if an
* unknown level was requested .
*/
* rdata_len = 0 ;
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2005-08-13 04:13:21 +04:00
SSVALS ( * rparam , 0 , ERRunknownlevel ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , 0 ) ;
return ( True ) ;
}
2000-04-19 11:00:22 +04:00
2010-04-28 00:55:11 +04:00
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_DosPrintQEnum: could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
2005-08-13 04:13:21 +04:00
}
2000-04-19 11:00:22 +04:00
2010-04-28 00:55:11 +04:00
werr = rpccli_spoolss_enumprinters ( cli , mem_ctx ,
PRINTER_ENUM_LOCAL ,
cli - > srv_name_slash ,
2 ,
0 ,
& num_printers ,
& printer_info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
2005-08-13 04:13:21 +04:00
}
2010-04-28 00:55:11 +04:00
queuecnt = num_printers ;
2005-08-13 04:13:21 +04:00
if ( ( subcntarr = SMB_MALLOC_ARRAY ( int , queuecnt ) ) = = NULL ) {
DEBUG ( 0 , ( " api_DosPrintQEnum: malloc fail ! \n " ) ) ;
goto err ;
}
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
2005-08-13 04:13:21 +04:00
if ( ! * rdata ) {
goto err ;
}
}
desc . base = * rdata ;
desc . buflen = mdrcnt ;
2010-04-28 00:55:11 +04:00
subcnt = 0 ;
for ( i = 0 ; i < num_printers ; i + + ) {
uint32_t num_jobs ;
struct policy_handle handle ;
union spoolss_DriverInfo driver_info ;
union spoolss_JobInfo * job_info ;
ZERO_STRUCT ( handle ) ;
ZERO_STRUCT ( devmode_ctr ) ;
status = rpccli_spoolss_OpenPrinter ( cli , mem_ctx ,
printer_info [ i ] . info2 . printername ,
NULL ,
devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
}
werr = rpccli_spoolss_enumjobs ( cli , mem_ctx ,
& handle ,
0 , /* firstjob */
0xff , /* numjobs */
2 , /* level */
0 , /* offered */
& num_jobs ,
& job_info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
}
if ( uLevel = = 52 ) {
uint32_t server_major_version ;
uint32_t server_minor_version ;
werr = rpccli_spoolss_getprinterdriver2 ( cli , mem_ctx ,
& handle ,
" Windows 4.0 " ,
3 , /* level */
0 ,
0 , /* version */
0 ,
& driver_info ,
& server_major_version ,
& server_minor_version ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
}
}
subcntarr [ i ] = num_jobs ;
subcnt + = subcntarr [ i ] ;
if ( init_package ( & desc , queuecnt , subcnt ) ) {
fill_printq_info ( uLevel , & desc , subcntarr [ i ] , job_info , & driver_info . info3 , & printer_info [ i ] . info2 ) ;
if ( desc . errcode = = NERR_Success ) {
succnt = i ;
2005-08-13 04:13:21 +04:00
}
}
2010-04-28 00:55:11 +04:00
if ( is_valid_policy_hnd ( & handle ) ) {
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & handle , NULL ) ;
}
2005-08-13 04:13:21 +04:00
}
2000-04-19 11:00:22 +04:00
2005-08-13 04:13:21 +04:00
SAFE_FREE ( subcntarr ) ;
2010-04-28 00:55:11 +04:00
out :
2005-08-13 04:13:21 +04:00
* rdata_len = desc . usedlen ;
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
2005-08-13 04:13:21 +04:00
if ( ! * rparam ) {
goto err ;
}
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , succnt ) ;
SSVAL ( * rparam , 6 , queuecnt ) ;
2009-01-31 18:57:46 +03:00
2005-08-13 04:13:21 +04:00
return True ;
err :
SAFE_FREE ( subcntarr ) ;
return False ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
2005-08-13 04:13:21 +04:00
Get info level for a server list query .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool check_server_info ( int uLevel , char * id )
2000-04-19 11:00:22 +04:00
{
2005-08-13 04:13:21 +04:00
switch ( uLevel ) {
case 0 :
if ( strcmp ( id , " B16 " ) ! = 0 ) {
return False ;
}
break ;
case 1 :
if ( strcmp ( id , " B16BBDz " ) ! = 0 ) {
return False ;
}
break ;
default :
return False ;
}
return True ;
2000-04-19 11:00:22 +04:00
}
2005-08-13 04:13:21 +04:00
struct srv_info_struct {
fstring name ;
uint32 type ;
fstring comment ;
fstring domain ;
2007-10-19 04:40:25 +04:00
bool server_added ;
2000-04-19 11:00:22 +04:00
} ;
/*******************************************************************
2005-08-13 04:13:21 +04:00
Get server info lists from the files saved by nmbd . Return the
number of entries .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-19 11:00:22 +04:00
static int get_server_info ( uint32 servertype ,
struct srv_info_struct * * servers ,
2002-11-13 02:20:50 +03:00
const char * domain )
2000-04-19 11:00:22 +04:00
{
2006-02-04 01:19:41 +03:00
int count = 0 ;
int alloced = 0 ;
char * * lines ;
2007-10-19 04:40:25 +04:00
bool local_list_only ;
2006-02-04 01:19:41 +03:00
int i ;
2000-04-19 11:00:22 +04:00
2009-01-16 02:40:48 +03:00
lines = file_lines_load ( cache_path ( SERVER_LIST ) , NULL , 0 , NULL ) ;
2006-02-04 01:19:41 +03:00
if ( ! lines ) {
2009-01-16 02:40:48 +03:00
DEBUG ( 4 , ( " Can't open %s - %s \n " , cache_path ( SERVER_LIST ) , strerror ( errno ) ) ) ;
2006-02-04 01:19:41 +03:00
return 0 ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
/* request for everything is code for request all servers */
if ( servertype = = SV_TYPE_ALL ) {
servertype & = ~ ( SV_TYPE_DOMAIN_ENUM | SV_TYPE_LOCAL_LIST_ONLY ) ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
local_list_only = ( servertype & SV_TYPE_LOCAL_LIST_ONLY ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 4 , ( " Servertype search: %8x \n " , servertype ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
for ( i = 0 ; lines [ i ] ; i + + ) {
fstring stype ;
struct srv_info_struct * s ;
const char * ptr = lines [ i ] ;
2007-10-19 04:40:25 +04:00
bool ok = True ;
2007-12-08 04:32:32 +03:00
TALLOC_CTX * frame = NULL ;
char * p ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
if ( ! * ptr ) {
continue ;
}
2007-12-08 04:32:32 +03:00
2006-02-04 01:19:41 +03:00
if ( count = = alloced ) {
alloced + = 10 ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
* servers = SMB_REALLOC_ARRAY ( * servers , struct srv_info_struct , alloced ) ;
if ( ! * servers ) {
2006-02-04 01:19:41 +03:00
DEBUG ( 0 , ( " get_server_info: failed to enlarge servers info struct! \n " ) ) ;
2008-10-12 19:34:43 +04:00
TALLOC_FREE ( lines ) ;
2006-02-04 01:19:41 +03:00
return 0 ;
}
memset ( ( char * ) ( ( * servers ) + count ) , ' \0 ' , sizeof ( * * servers ) * ( alloced - count ) ) ;
}
s = & ( * servers ) [ count ] ;
2007-12-08 04:32:32 +03:00
frame = talloc_stackframe ( ) ;
s - > name [ 0 ] = ' \0 ' ;
if ( ! next_token_talloc ( frame , & ptr , & p , NULL ) ) {
TALLOC_FREE ( frame ) ;
2006-02-04 01:19:41 +03:00
continue ;
}
2007-12-08 04:32:32 +03:00
fstrcpy ( s - > name , p ) ;
stype [ 0 ] = ' \0 ' ;
if ( ! next_token_talloc ( frame , & ptr , & p , NULL ) ) {
TALLOC_FREE ( frame ) ;
2006-02-04 01:19:41 +03:00
continue ;
}
2007-12-08 04:32:32 +03:00
fstrcpy ( stype , p ) ;
s - > comment [ 0 ] = ' \0 ' ;
if ( ! next_token_talloc ( frame , & ptr , & p , NULL ) ) {
TALLOC_FREE ( frame ) ;
2006-02-04 01:19:41 +03:00
continue ;
}
2007-12-08 04:32:32 +03:00
fstrcpy ( s - > comment , p ) ;
2009-06-16 13:51:11 +04:00
string_truncate ( s - > comment , MAX_SERVER_STRING_LENGTH ) ;
2007-12-08 04:32:32 +03:00
s - > domain [ 0 ] = ' \0 ' ;
if ( ! next_token_talloc ( frame , & ptr , & p , NULL ) ) {
2006-02-04 01:19:41 +03:00
/* this allows us to cope with an old nmbd */
2007-12-08 04:32:32 +03:00
fstrcpy ( s - > domain , lp_workgroup ( ) ) ;
} else {
fstrcpy ( s - > domain , p ) ;
2006-02-04 01:19:41 +03:00
}
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
if ( sscanf ( stype , " %X " , & s - > type ) ! = 1 ) {
DEBUG ( 4 , ( " r:host file " ) ) ;
ok = False ;
2006-02-04 01:19:41 +03:00
}
2007-12-08 04:32:32 +03:00
2006-02-04 01:19:41 +03:00
/* Filter the servers/domains we return based on what was asked for. */
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
/* Check to see if we are being asked for a local list only. */
if ( local_list_only & & ( ( s - > type & SV_TYPE_LOCAL_LIST_ONLY ) = = 0 ) ) {
DEBUG ( 4 , ( " r: local list only " ) ) ;
ok = False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
/* doesn't match up: don't want it */
2007-12-08 04:32:32 +03:00
if ( ! ( servertype & s - > type ) ) {
DEBUG ( 4 , ( " r:serv type " ) ) ;
ok = False ;
2006-02-04 01:19:41 +03:00
}
2007-12-08 04:32:32 +03:00
2006-02-04 01:19:41 +03:00
if ( ( servertype & SV_TYPE_DOMAIN_ENUM ) ! =
( s - > type & SV_TYPE_DOMAIN_ENUM ) ) {
DEBUG ( 4 , ( " s: dom mismatch " ) ) ;
ok = False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( ! strequal ( domain , s - > domain ) & & ! ( servertype & SV_TYPE_DOMAIN_ENUM ) ) {
ok = False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
/* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
s - > type & = ~ SV_TYPE_LOCAL_LIST_ONLY ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
if ( ok ) {
DEBUG ( 4 , ( " **SV** %20s %8x %25s %15s \n " ,
s - > name , s - > type , s - > comment , s - > domain ) ) ;
s - > server_added = True ;
count + + ;
} else {
DEBUG ( 4 , ( " %20s %8x %25s %15s \n " ,
s - > name , s - > type , s - > comment , s - > domain ) ) ;
}
}
2009-01-31 18:57:46 +03:00
2008-10-12 19:34:43 +04:00
TALLOC_FREE ( lines ) ;
2006-02-04 01:19:41 +03:00
return count ;
2000-04-19 11:00:22 +04:00
}
/*******************************************************************
2005-08-13 04:13:21 +04:00
Fill in a server info structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-19 11:00:22 +04:00
static int fill_srv_info ( struct srv_info_struct * service ,
int uLevel , char * * buf , int * buflen ,
char * * stringbuf , int * stringspace , char * baseaddr )
{
2006-02-04 01:19:41 +03:00
int struct_len ;
char * p ;
char * p2 ;
int l2 ;
int len ;
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
switch ( uLevel ) {
case 0 :
struct_len = 16 ;
break ;
case 1 :
struct_len = 26 ;
break ;
default :
return - 1 ;
2000-04-19 11:00:22 +04:00
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( ! buf ) {
len = 0 ;
switch ( uLevel ) {
case 1 :
len = strlen ( service - > comment ) + 1 ;
break ;
}
2000-04-19 11:00:22 +04:00
2006-08-28 09:41:32 +04:00
* buflen = struct_len ;
* stringspace = len ;
2006-02-04 01:19:41 +03:00
return struct_len + len ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
len = struct_len ;
p = * buf ;
if ( * buflen < struct_len ) {
return - 1 ;
}
if ( stringbuf ) {
p2 = * stringbuf ;
l2 = * stringspace ;
} else {
p2 = p + struct_len ;
l2 = * buflen - struct_len ;
}
if ( ! baseaddr ) {
baseaddr = p ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
switch ( uLevel ) {
case 0 :
push_ascii ( p , service - > name , MAX_NETBIOSNAME_LEN , STR_TERMINATE ) ;
break ;
case 1 :
push_ascii ( p , service - > name , MAX_NETBIOSNAME_LEN , STR_TERMINATE ) ;
SIVAL ( p , 18 , service - > type ) ;
SIVAL ( p , 22 , PTR_DIFF ( p2 , baseaddr ) ) ;
len + = CopyAndAdvance ( & p2 , service - > comment , & l2 ) ;
break ;
}
if ( stringbuf ) {
* buf = p + struct_len ;
* buflen - = struct_len ;
* stringbuf = p2 ;
* stringspace = l2 ;
} else {
* buf = p2 ;
* buflen - = len ;
}
return len ;
2000-04-19 11:00:22 +04:00
}
2010-02-09 20:54:41 +03:00
static int srv_comp ( struct srv_info_struct * s1 , struct srv_info_struct * s2 )
2000-04-19 11:00:22 +04:00
{
2010-02-09 20:58:36 +03:00
return StrCaseCmp ( s1 - > name , s2 - > name ) ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
2005-08-13 04:13:21 +04:00
View list of servers available ( or possibly domains ) . The info is
extracted from lists saved by nmbd on the local host .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-02-05 18:55:15 +03:00
static bool api_RNetServerEnum2 ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt , char * * rdata ,
char * * rparam , int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
int buf_len = get_safe_SVAL ( param , tpscnt , p , 2 , 0 ) ;
uint32 servertype = get_safe_IVAL ( param , tpscnt , p , 4 , 0 ) ;
2006-02-04 01:19:41 +03:00
char * p2 ;
int data_len , fixed_len , string_len ;
int f_len = 0 , s_len = 0 ;
struct srv_info_struct * servers = NULL ;
int counted = 0 , total = 0 ;
int i , missed ;
fstring domain ;
2007-10-19 04:40:25 +04:00
bool domain_request ;
bool local_request ;
2006-02-04 01:19:41 +03:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
/* If someone sets all the bits they don't really mean to set
DOMAIN_ENUM and LOCAL_LIST_ONLY , they just want all the
known servers . */
if ( servertype = = SV_TYPE_ALL ) {
servertype & = ~ ( SV_TYPE_DOMAIN_ENUM | SV_TYPE_LOCAL_LIST_ONLY ) ;
}
/* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
2007-11-26 17:28:13 +03:00
any other bit ( they may just set this bit on its own ) they
2006-02-04 01:19:41 +03:00
want all the locally seen servers . However this bit can be
set on its own so set the requested servers to be
ALL - DOMAIN_ENUM . */
if ( ( servertype & SV_TYPE_LOCAL_LIST_ONLY ) & & ! ( servertype & SV_TYPE_DOMAIN_ENUM ) ) {
servertype = SV_TYPE_ALL & ~ ( SV_TYPE_DOMAIN_ENUM ) ;
}
domain_request = ( ( servertype & SV_TYPE_DOMAIN_ENUM ) ! = 0 ) ;
local_request = ( ( servertype & SV_TYPE_LOCAL_LIST_ONLY ) ! = 0 ) ;
p + = 8 ;
if ( ! prefix_ok ( str1 , " WrLehD " ) ) {
return False ;
}
if ( ! check_server_info ( uLevel , str2 ) ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
DEBUG ( 4 , ( " server request level: %s %8x " , str2 , servertype ) ) ;
DEBUG ( 4 , ( " domains_req:%s " , BOOLSTR ( domain_request ) ) ) ;
DEBUG ( 4 , ( " local_only:%s \n " , BOOLSTR ( local_request ) ) ) ;
if ( strcmp ( str1 , " WrLehDz " ) = = 0 ) {
2007-04-03 00:10:21 +04:00
if ( skip_string ( param , tpscnt , p ) = = NULL ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2006-02-04 01:19:41 +03:00
pull_ascii_fstring ( domain , p ) ;
} else {
fstrcpy ( domain , lp_workgroup ( ) ) ;
}
2010-02-08 20:45:18 +03:00
DEBUG ( 4 , ( " domain [%s] \n " , domain ) ) ;
2006-02-04 01:19:41 +03:00
if ( lp_browse_list ( ) ) {
total = get_server_info ( servertype , & servers , domain ) ;
}
data_len = fixed_len = string_len = 0 ;
missed = 0 ;
2010-02-14 02:03:12 +03:00
TYPESAFE_QSORT ( servers , total , srv_comp ) ;
2006-02-04 01:19:41 +03:00
{
char * lastname = NULL ;
for ( i = 0 ; i < total ; i + + ) {
struct srv_info_struct * s = & servers [ i ] ;
if ( lastname & & strequal ( lastname , s - > name ) ) {
continue ;
}
lastname = s - > name ;
data_len + = fill_srv_info ( s , uLevel , 0 , & f_len , 0 , & s_len , 0 ) ;
2010-02-08 20:45:18 +03:00
DEBUG ( 4 , ( " fill_srv_info[%d] %20s %8x %25s %15s \n " ,
i , s - > name , s - > type , s - > comment , s - > domain ) ) ;
2009-01-31 18:57:46 +03:00
2010-02-10 02:14:38 +03:00
if ( data_len < buf_len ) {
2006-02-04 01:19:41 +03:00
counted + + ;
fixed_len + = f_len ;
string_len + = s_len ;
} else {
missed + + ;
}
}
}
* rdata_len = fixed_len + string_len ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
p2 = ( * rdata ) + fixed_len ; /* auxilliary data (strings) will go here */
p = * rdata ;
f_len = fixed_len ;
s_len = string_len ;
{
char * lastname = NULL ;
int count2 = counted ;
for ( i = 0 ; i < total & & count2 ; i + + ) {
struct srv_info_struct * s = & servers [ i ] ;
if ( lastname & & strequal ( lastname , s - > name ) ) {
continue ;
}
lastname = s - > name ;
fill_srv_info ( s , uLevel , & p , & f_len , & p2 , & s_len , * rdata ) ;
2010-02-08 20:45:18 +03:00
DEBUG ( 4 , ( " fill_srv_info[%d] %20s %8x %25s %15s \n " ,
i , s - > name , s - > type , s - > comment , s - > domain ) ) ;
2006-02-04 01:19:41 +03:00
count2 - - ;
}
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 0 , ( missed = = 0 ? NERR_Success : ERRmoredata ) ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , counted ) ;
SSVAL ( * rparam , 6 , counted + missed ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SAFE_FREE ( servers ) ;
2000-04-19 11:00:22 +04:00
2010-02-05 18:55:15 +03:00
DEBUG ( 3 , ( " NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d \n " ,
2006-02-04 01:19:41 +03:00
domain , uLevel , counted , counted + missed ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
2010-02-09 20:54:41 +03:00
static int srv_name_match ( const char * n1 , const char * n2 )
2010-02-05 20:08:46 +03:00
{
/*
* [ MS - RAP ] footnote < 88 > for Section 3.2 .5 .15 says :
*
* In Windows , FirstNameToReturn need not be an exact match :
* the server will return a list of servers that exist on
* the network greater than or equal to the FirstNameToReturn .
*/
2010-02-09 20:58:36 +03:00
int ret = StrCaseCmp ( n1 , n2 ) ;
2010-02-05 20:08:46 +03:00
if ( ret < = 0 ) {
return 0 ;
}
return ret ;
}
static bool api_RNetServerEnum3 ( 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 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
int buf_len = get_safe_SVAL ( param , tpscnt , p , 2 , 0 ) ;
uint32 servertype = get_safe_IVAL ( param , tpscnt , p , 4 , 0 ) ;
char * p2 ;
int data_len , fixed_len , string_len ;
int f_len = 0 , s_len = 0 ;
struct srv_info_struct * servers = NULL ;
int counted = 0 , first = 0 , total = 0 ;
int i , missed ;
fstring domain ;
fstring first_name ;
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 . */
if ( servertype = = SV_TYPE_ALL ) {
servertype & = ~ ( SV_TYPE_DOMAIN_ENUM | SV_TYPE_LOCAL_LIST_ONLY ) ;
}
/* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
any other bit ( they may just set this bit on its own ) they
want all the locally seen servers . However this bit can be
set on its own so set the requested servers to be
ALL - DOMAIN_ENUM . */
if ( ( servertype & SV_TYPE_LOCAL_LIST_ONLY ) & & ! ( servertype & SV_TYPE_DOMAIN_ENUM ) ) {
servertype = SV_TYPE_ALL & ~ ( SV_TYPE_DOMAIN_ENUM ) ;
}
domain_request = ( ( servertype & SV_TYPE_DOMAIN_ENUM ) ! = 0 ) ;
local_request = ( ( servertype & SV_TYPE_LOCAL_LIST_ONLY ) ! = 0 ) ;
p + = 8 ;
if ( strcmp ( str1 , " WrLehDzz " ) ! = 0 ) {
return false ;
}
if ( ! check_server_info ( uLevel , str2 ) ) {
return False ;
}
DEBUG ( 4 , ( " server request level: %s %8x " , str2 , servertype ) ) ;
DEBUG ( 4 , ( " domains_req:%s " , BOOLSTR ( domain_request ) ) ) ;
DEBUG ( 4 , ( " local_only:%s \n " , BOOLSTR ( local_request ) ) ) ;
if ( skip_string ( param , tpscnt , p ) = = NULL ) {
return False ;
}
pull_ascii_fstring ( domain , p ) ;
if ( domain [ 0 ] = = ' \0 ' ) {
fstrcpy ( domain , lp_workgroup ( ) ) ;
}
p = skip_string ( param , tpscnt , p ) ;
if ( skip_string ( param , tpscnt , p ) = = NULL ) {
return False ;
}
pull_ascii_fstring ( first_name , p ) ;
DEBUG ( 4 , ( " domain: '%s' first_name: '%s' \n " ,
domain , first_name ) ) ;
if ( lp_browse_list ( ) ) {
total = get_server_info ( servertype , & servers , domain ) ;
}
data_len = fixed_len = string_len = 0 ;
missed = 0 ;
2010-02-14 02:03:12 +03:00
TYPESAFE_QSORT ( servers , total , srv_comp ) ;
2010-02-05 20:08:46 +03:00
if ( first_name [ 0 ] ! = ' \0 ' ) {
struct srv_info_struct * first_server = NULL ;
BINARY_ARRAY_SEARCH ( servers , total , name , first_name ,
srv_name_match , first_server ) ;
if ( first_server ) {
first = PTR_DIFF ( first_server , servers ) / sizeof ( * servers ) ;
/*
* The binary search may not find the exact match
* so we need to search backward to find the first match
*
* This implements the strange matching windows
* implements . ( see the comment in srv_name_match ( ) .
*/
for ( ; first > 0 ; ) {
int ret ;
2010-02-09 20:58:36 +03:00
ret = StrCaseCmp ( first_name ,
2010-02-05 20:08:46 +03:00
servers [ first - 1 ] . name ) ;
if ( ret > 0 ) {
break ;
}
first - - ;
}
} else {
/* we should return no entries */
first = total ;
}
}
{
char * lastname = NULL ;
for ( i = first ; i < total ; i + + ) {
struct srv_info_struct * s = & servers [ i ] ;
if ( lastname & & strequal ( lastname , s - > name ) ) {
continue ;
}
lastname = s - > name ;
data_len + = fill_srv_info ( s , uLevel , 0 , & f_len , 0 , & s_len , 0 ) ;
DEBUG ( 4 , ( " fill_srv_info[%d] %20s %8x %25s %15s \n " ,
i , s - > name , s - > type , s - > comment , s - > domain ) ) ;
2010-02-10 02:14:38 +03:00
if ( data_len < buf_len ) {
2010-02-05 20:08:46 +03:00
counted + + ;
fixed_len + = f_len ;
string_len + = s_len ;
} else {
missed + + ;
}
}
}
* rdata_len = fixed_len + string_len ;
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
if ( ! * rdata ) {
return False ;
}
p2 = ( * rdata ) + fixed_len ; /* auxilliary data (strings) will go here */
p = * rdata ;
f_len = fixed_len ;
s_len = string_len ;
{
char * lastname = NULL ;
int count2 = counted ;
for ( i = first ; i < total & & count2 ; i + + ) {
struct srv_info_struct * s = & servers [ i ] ;
if ( lastname & & strequal ( lastname , s - > name ) ) {
continue ;
}
lastname = s - > name ;
fill_srv_info ( s , uLevel , & p , & f_len , & p2 , & s_len , * rdata ) ;
DEBUG ( 4 , ( " fill_srv_info[%d] %20s %8x %25s %15s \n " ,
i , s - > name , s - > type , s - > comment , s - > domain ) ) ;
count2 - - ;
}
}
* rparam_len = 8 ;
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
if ( ! * rparam ) {
return False ;
}
SSVAL ( * rparam , 0 , ( missed = = 0 ? NERR_Success : ERRmoredata ) ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , counted ) ;
SSVAL ( * rparam , 6 , counted + missed ) ;
DEBUG ( 3 , ( " NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d \n " ,
domain , uLevel , first , first_name ,
first < total ? servers [ first ] . name : " " ,
counted , counted + missed ) ) ;
SAFE_FREE ( servers ) ;
return True ;
}
2000-04-19 11:00:22 +04:00
/****************************************************************************
command 0x34 - suspected of being a " Lookup Names " stub api
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-13 04:13:21 +04:00
2007-10-19 04:40:25 +04:00
static bool api_RNetGroupGetUsers ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt , char * * rdata ,
char * * rparam , int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
int buf_len = get_safe_SVAL ( param , tpscnt , p , 2 , 0 ) ;
2006-02-04 01:19:41 +03:00
int counted = 0 ;
int missed = 0 ;
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2000-04-19 11:00:22 +04:00
DEBUG ( 5 , ( " RNetGroupGetUsers: %s %s %s %d %d \n " ,
str1 , str2 , p , uLevel , buf_len ) ) ;
2006-02-04 01:19:41 +03:00
if ( ! prefix_ok ( str1 , " zWrLeh " ) ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
* rdata_len = 0 ;
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 0 , 0x08AC ) ; /* informational warning message */
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , counted ) ;
SSVAL ( * rparam , 6 , counted + missed ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
get info about a share
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-13 04:13:21 +04:00
2007-10-19 04:40:25 +04:00
static bool check_share_info ( int uLevel , char * id )
2000-04-19 11:00:22 +04:00
{
2006-02-04 01:19:41 +03:00
switch ( uLevel ) {
case 0 :
if ( strcmp ( id , " B13 " ) ! = 0 ) {
return False ;
}
break ;
case 1 :
2010-01-12 00:18:40 +03:00
/* Level-2 descriptor is allowed (and ignored) */
if ( strcmp ( id , " B13BWz " ) ! = 0 & &
strcmp ( id , " B13BWzWWWzB9B " ) ! = 0 ) {
2006-02-04 01:19:41 +03:00
return False ;
}
break ;
case 2 :
if ( strcmp ( id , " B13BWzWWWzB9B " ) ! = 0 ) {
return False ;
}
break ;
case 91 :
if ( strcmp ( id , " B13BWzWWWzB9BB9BWzWWzWW " ) ! = 0 ) {
return False ;
}
break ;
default :
return False ;
}
return True ;
2000-04-19 11:00:22 +04:00
}
static int fill_share_info ( connection_struct * conn , int snum , int uLevel ,
char * * buf , int * buflen ,
char * * stringbuf , int * stringspace , char * baseaddr )
{
2006-02-04 01:19:41 +03:00
int struct_len ;
char * p ;
char * p2 ;
int l2 ;
int len ;
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
switch ( uLevel ) {
case 0 :
struct_len = 13 ;
break ;
case 1 :
struct_len = 20 ;
break ;
case 2 :
struct_len = 40 ;
break ;
case 91 :
struct_len = 68 ;
break ;
default :
return - 1 ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( ! buf ) {
len = 0 ;
if ( uLevel > 0 ) {
len + = StrlenExpanded ( conn , snum , lp_comment ( snum ) ) ;
}
if ( uLevel > 1 ) {
len + = strlen ( lp_pathname ( snum ) ) + 1 ;
}
if ( buflen ) {
* buflen = struct_len ;
}
if ( stringspace ) {
* stringspace = len ;
}
return struct_len + len ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
len = struct_len ;
p = * buf ;
if ( ( * buflen ) < struct_len ) {
return - 1 ;
}
if ( stringbuf ) {
p2 = * stringbuf ;
l2 = * stringspace ;
} else {
p2 = p + struct_len ;
l2 = ( * buflen ) - struct_len ;
}
if ( ! baseaddr ) {
baseaddr = p ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
push_ascii ( p , lp_servicename ( snum ) , 13 , STR_TERMINATE ) ;
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( uLevel > 0 ) {
int type ;
SCVAL ( p , 13 , 0 ) ;
type = STYPE_DISKTREE ;
if ( lp_print_ok ( snum ) ) {
type = STYPE_PRINTQ ;
}
if ( strequal ( " IPC " , lp_fstype ( snum ) ) ) {
type = STYPE_IPC ;
}
SSVAL ( p , 14 , type ) ; /* device type */
SIVAL ( p , 16 , PTR_DIFF ( p2 , baseaddr ) ) ;
len + = CopyExpanded ( conn , snum , & p2 , lp_comment ( snum ) , & l2 ) ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( uLevel > 1 ) {
SSVAL ( p , 20 , ACCESS_READ | ACCESS_WRITE | ACCESS_CREATE ) ; /* permissions */
SSVALS ( p , 22 , - 1 ) ; /* max uses */
SSVAL ( p , 24 , 1 ) ; /* current uses */
SIVAL ( p , 26 , PTR_DIFF ( p2 , baseaddr ) ) ; /* local pathname */
len + = CopyAndAdvance ( & p2 , lp_pathname ( snum ) , & l2 ) ;
memset ( p + 30 , 0 , SHPWLEN + 2 ) ; /* passwd (reserved), pad field */
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( uLevel > 2 ) {
memset ( p + 40 , 0 , SHPWLEN + 2 ) ;
SSVAL ( p , 50 , 0 ) ;
SIVAL ( p , 52 , 0 ) ;
SSVAL ( p , 56 , 0 ) ;
SSVAL ( p , 58 , 0 ) ;
SIVAL ( p , 60 , 0 ) ;
SSVAL ( p , 64 , 0 ) ;
SSVAL ( p , 66 , 0 ) ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( stringbuf ) {
( * buf ) = p + struct_len ;
( * buflen ) - = struct_len ;
( * stringbuf ) = p2 ;
( * stringspace ) = l2 ;
} else {
( * buf ) = p2 ;
( * buflen ) - = len ;
}
return len ;
2000-04-19 11:00:22 +04:00
}
2007-10-19 04:40:25 +04:00
static bool api_RNetShareGetInfo ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * netname = skip_string ( param , tpscnt , str2 ) ;
char * p = skip_string ( param , tpscnt , netname ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2007-03-31 02:25:08 +04:00
int snum ;
2009-01-31 18:57:46 +03:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! netname | | ! p ) {
return False ;
}
snum = find_service ( netname ) ;
2006-02-04 01:19:41 +03:00
if ( snum < 0 ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
/* check it's a supported varient */
if ( ! prefix_ok ( str1 , " zWrLh " ) ) {
return False ;
}
if ( ! check_share_info ( uLevel , str2 ) ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
p = * rdata ;
* rdata_len = fill_share_info ( conn , snum , uLevel , & p , & mdrcnt , 0 , 0 , 0 ) ;
if ( * rdata_len < 0 ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
SSVAL ( * rparam , 4 , * rdata_len ) ;
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
2004-01-29 02:41:55 +03:00
View the list of available shares .
This function is the server side of the NetShareEnum ( ) RAP call .
It fills the return buffer with share names and share comments .
Note that the return buffer normally ( in all known cases ) allows only
twelve byte strings for share names ( plus one for a nul terminator ) .
Share names longer than 12 bytes must be skipped .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-13 04:13:21 +04:00
2007-10-19 04:40:25 +04:00
static bool api_RNetShareEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt ,
int mprcnt ,
char * * rdata ,
char * * rparam ,
int * rdata_len ,
int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
int buf_len = get_safe_SVAL ( param , tpscnt , p , 2 , 0 ) ;
2006-02-04 01:19:41 +03:00
char * p2 ;
int count = 0 ;
int total = 0 , counted = 0 ;
2007-10-19 04:40:25 +04:00
bool missed = False ;
2006-02-04 01:19:41 +03:00
int i ;
int data_len , fixed_len , string_len ;
int f_len = 0 , s_len = 0 ;
2009-01-31 18:57:46 +03:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
if ( ! prefix_ok ( str1 , " WrLeh " ) ) {
return False ;
}
if ( ! check_share_info ( uLevel , str2 ) ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
/* Ensure all the usershares are loaded. */
become_root ( ) ;
2006-11-30 10:38:40 +03:00
load_registry_shares ( ) ;
2006-02-04 01:19:41 +03:00
count = load_usershare_shares ( ) ;
unbecome_root ( ) ;
data_len = fixed_len = string_len = 0 ;
for ( i = 0 ; i < count ; i + + ) {
fstring servicename_dos ;
if ( ! ( lp_browseable ( i ) & & lp_snum_ok ( i ) ) ) {
continue ;
}
push_ascii_fstring ( servicename_dos , lp_servicename ( i ) ) ;
/* Maximum name length = 13. */
if ( lp_browseable ( i ) & & lp_snum_ok ( i ) & & ( strlen ( servicename_dos ) < 13 ) ) {
total + + ;
data_len + = fill_share_info ( conn , i , uLevel , 0 , & f_len , 0 , & s_len , 0 ) ;
2010-02-10 02:14:38 +03:00
if ( data_len < buf_len ) {
2006-02-04 01:19:41 +03:00
counted + + ;
fixed_len + = f_len ;
string_len + = s_len ;
} else {
missed = True ;
}
}
}
* rdata_len = fixed_len + string_len ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
p2 = ( * rdata ) + fixed_len ; /* auxiliary data (strings) will go here */
p = * rdata ;
f_len = fixed_len ;
s_len = string_len ;
for ( i = 0 ; i < count ; i + + ) {
fstring servicename_dos ;
if ( ! ( lp_browseable ( i ) & & lp_snum_ok ( i ) ) ) {
continue ;
}
push_ascii_fstring ( servicename_dos , lp_servicename ( i ) ) ;
if ( lp_browseable ( i ) & & lp_snum_ok ( i ) & & ( strlen ( servicename_dos ) < 13 ) ) {
if ( fill_share_info ( conn , i , uLevel , & p , & f_len , & p2 , & s_len , * rdata ) < 0 ) {
break ;
}
}
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 0 , missed ? ERRmoredata : NERR_Success ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , counted ) ;
SSVAL ( * rparam , 6 , total ) ;
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " RNetShareEnum gave %d entries of %d (%d %d %d %d) \n " ,
counted , total , uLevel ,
buf_len , * rdata_len , mdrcnt ) ) ;
return True ;
2005-08-13 04:13:21 +04:00
}
2000-04-19 11:00:22 +04:00
2001-10-19 23:13:11 +04:00
/****************************************************************************
Add a share
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-13 04:13:21 +04:00
2007-10-19 04:40:25 +04:00
static bool api_RNetShareAdd ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2001-10-19 23:13:11 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2006-02-04 01:19:41 +03:00
fstring sharename ;
fstring comment ;
2007-11-13 04:59:18 +03:00
char * pathname = NULL ;
2006-02-04 01:19:41 +03:00
char * command , * cmdname ;
unsigned int offset ;
int snum ;
int res = ERRunsup ;
2008-04-30 01:36:24 +04:00
size_t converted_size ;
2007-11-13 04:59:18 +03:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
/* check it's a supported varient */
if ( ! prefix_ok ( str1 , RAP_WShareAdd_REQ ) ) {
2002-07-15 14:35:28 +04:00
return False ;
2006-02-04 01:19:41 +03:00
}
if ( ! check_share_info ( uLevel , str2 ) ) {
2002-07-15 14:35:28 +04:00
return False ;
2006-02-04 01:19:41 +03:00
}
if ( uLevel ! = 2 ) {
return False ;
}
2007-03-31 02:25:08 +04:00
/* Do we have a string ? */
2007-04-03 00:10:21 +04:00
if ( skip_string ( data , mdrcnt , data ) = = NULL ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2006-02-04 01:19:41 +03:00
pull_ascii_fstring ( sharename , data ) ;
snum = find_service ( sharename ) ;
if ( snum > = 0 ) { /* already exists */
res = ERRfilexists ;
goto error_exit ;
}
2007-03-31 02:25:08 +04:00
if ( mdrcnt < 28 ) {
return False ;
}
2006-02-04 01:19:41 +03:00
/* only support disk share adds */
if ( SVAL ( data , 14 ) ! = STYPE_DISKTREE ) {
return False ;
}
offset = IVAL ( data , 16 ) ;
if ( offset > = mdrcnt ) {
res = ERRinvalidparam ;
goto error_exit ;
}
2007-03-31 02:25:08 +04:00
/* Do we have a string ? */
2007-04-03 00:10:21 +04:00
if ( skip_string ( data , mdrcnt , data + offset ) = = NULL ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2006-02-04 01:19:41 +03:00
pull_ascii_fstring ( comment , offset ? ( data + offset ) : " " ) ;
offset = IVAL ( data , 26 ) ;
if ( offset > = mdrcnt ) {
res = ERRinvalidparam ;
goto error_exit ;
}
2007-03-31 02:25:08 +04:00
/* Do we have a string ? */
2007-04-03 00:10:21 +04:00
if ( skip_string ( data , mdrcnt , data + offset ) = = NULL ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2007-11-13 04:59:18 +03:00
2008-04-30 01:36:24 +04:00
if ( ! pull_ascii_talloc ( talloc_tos ( ) , & pathname ,
offset ? ( data + offset ) : " " , & converted_size ) )
{
DEBUG ( 0 , ( " api_RNetShareAdd: pull_ascii_talloc failed: %s " ,
strerror ( errno ) ) ) ;
}
2007-11-13 04:59:18 +03:00
if ( ! pathname ) {
return false ;
}
2006-02-04 01:19:41 +03:00
string_replace ( sharename , ' " ' , ' ' ) ;
string_replace ( pathname , ' " ' , ' ' ) ;
string_replace ( comment , ' " ' , ' ' ) ;
cmdname = lp_add_share_cmd ( ) ;
if ( ! cmdname | | * cmdname = = ' \0 ' ) {
return False ;
}
2008-04-02 17:54:49 +04:00
if ( asprintf ( & command , " %s \" %s \" \" %s \" \" %s \" \" %s \" " ,
lp_add_share_cmd ( ) , get_dyn_CONFIGFILE ( ) , sharename ,
pathname , comment ) = = - 1 ) {
return false ;
}
2006-02-04 01:19:41 +03:00
2008-04-02 17:54:49 +04:00
DEBUG ( 10 , ( " api_RNetShareAdd: Running [%s] \n " , command ) ) ;
2006-02-04 01:19:41 +03:00
2008-04-02 17:54:49 +04:00
if ( ( res = smbrun ( command , NULL ) ) ! = 0 ) {
DEBUG ( 1 , ( " api_RNetShareAdd: Running [%s] returned (%d) \n " ,
command , res ) ) ;
SAFE_FREE ( command ) ;
res = ERRnoaccess ;
goto error_exit ;
2006-02-04 01:19:41 +03:00
} else {
2008-04-02 17:54:49 +04:00
SAFE_FREE ( command ) ;
message_send_all ( smbd_messaging_context ( ) ,
MSG_SMB_CONF_UPDATED , NULL , 0 , NULL ) ;
2006-02-04 01:19:41 +03:00
}
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
SSVAL ( * rparam , 4 , * rdata_len ) ;
* rdata_len = 0 ;
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
return True ;
error_exit :
* rparam_len = 4 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
* rdata_len = 0 ;
SSVAL ( * rparam , 0 , res ) ;
SSVAL ( * rparam , 2 , 0 ) ;
return True ;
}
/****************************************************************************
view list of groups available
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_RNetGroupEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2006-02-04 01:19:41 +03:00
{
int i ;
int errflags = 0 ;
int resume_context , cli_buf_size ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
2009-02-07 17:30:54 +03:00
uint32_t num_groups ;
uint32_t resume_handle ;
struct rpc_pipe_client * samr_pipe ;
struct policy_handle samr_handle , domain_handle ;
NTSTATUS status ;
2009-01-31 18:57:46 +03:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
if ( strcmp ( str1 , " WrLeh " ) ! = 0 ) {
return False ;
}
/* parameters
* W - > resume context ( number of users to skip )
* r - > return parameter pointer to receive buffer
* L - > length of receive buffer
* e - > return parameter number of entries
* h - > return parameter total number of users
*/
if ( strcmp ( " B21 " , str2 ) ! = 0 ) {
return False ;
}
2009-02-07 17:30:54 +03:00
status = rpc_pipe_open_internal (
talloc_tos ( ) , & ndr_table_samr . syntax_id , rpc_samr_dispatch ,
conn - > server_info , & samr_pipe ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: Could not connect to samr: %s \n " ,
nt_errstr ( status ) ) ) ;
return false ;
}
2006-02-04 01:19:41 +03:00
2009-02-07 17:30:54 +03:00
status = rpccli_samr_Connect2 ( samr_pipe , talloc_tos ( ) , global_myname ( ) ,
2009-04-16 02:40:00 +04:00
SAMR_ACCESS_LOOKUP_DOMAIN , & samr_handle ) ;
2009-02-07 17:30:54 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_Connect2 failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return false ;
}
status = rpccli_samr_OpenDomain ( samr_pipe , talloc_tos ( ) , & samr_handle ,
SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS ,
get_global_sam_sid ( ) , & domain_handle ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_OpenDomain failed: %s \n " ,
nt_errstr ( status ) ) ) ;
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & samr_handle ) ;
return false ;
2001-08-28 20:05:55 +04:00
}
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
resume_context = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
cli_buf_size = get_safe_SVAL ( param , tpscnt , p , 2 , 0 ) ;
2005-04-10 19:45:46 +04:00
DEBUG ( 10 , ( " api_RNetGroupEnum:resume context: %d, client buffer size: "
" %d \n " , resume_context , cli_buf_size ) ) ;
2002-07-15 14:35:28 +04:00
* rdata_len = cli_buf_size ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2001-08-28 20:05:55 +04:00
p = * rdata ;
2009-02-07 17:30:54 +03:00
errflags = NERR_Success ;
num_groups = 0 ;
resume_handle = 0 ;
while ( true ) {
struct samr_SamArray * sam_entries ;
uint32_t num_entries ;
status = rpccli_samr_EnumDomainGroups ( samr_pipe , talloc_tos ( ) ,
& domain_handle ,
& resume_handle ,
& sam_entries , 1 ,
& num_entries ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " rpccli_samr_EnumDomainGroups returned "
" %s \n " , nt_errstr ( status ) ) ) ;
break ;
}
if ( num_entries = = 0 ) {
DEBUG ( 10 , ( " rpccli_samr_EnumDomainGroups returned "
" no entries -- done \n " ) ) ;
break ;
}
for ( i = 0 ; i < num_entries ; i + + ) {
const char * name ;
name = sam_entries - > entries [ i ] . name . string ;
if ( ( ( PTR_DIFF ( p , * rdata ) + 21 ) > * rdata_len ) ) {
/* set overflow error */
DEBUG ( 3 , ( " overflow on entry %d group %s \n " , i ,
name ) ) ;
errflags = 234 ;
break ;
}
2002-07-15 14:35:28 +04:00
/* truncate the name at 21 chars. */
2009-02-07 17:30:54 +03:00
memset ( p , 0 , 21 ) ;
strlcpy ( p , name , 21 ) ;
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " adding entry %d group %s \n " , i , p ) ) ;
2005-04-10 19:45:46 +04:00
p + = 21 ;
2009-02-07 17:30:54 +03:00
p + = 5 ; /* Both NT4 and W2k3SP1 do padding here. No
* idea why . . . */
num_groups + = 1 ;
}
if ( errflags ! = NERR_Success ) {
2002-07-15 14:35:28 +04:00
break ;
}
2009-02-07 17:30:54 +03:00
TALLOC_FREE ( sam_entries ) ;
2002-07-15 14:35:28 +04:00
}
2001-08-28 20:05:55 +04:00
2009-02-07 17:30:54 +03:00
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & domain_handle ) ;
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & samr_handle ) ;
2005-04-10 19:45:46 +04:00
2001-08-28 20:05:55 +04:00
* rdata_len = PTR_DIFF ( p , * rdata ) ;
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2002-07-15 14:35:28 +04:00
SSVAL ( * rparam , 0 , errflags ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
2009-02-07 17:30:54 +03:00
SSVAL ( * rparam , 4 , num_groups ) ; /* is this right?? */
SSVAL ( * rparam , 6 , resume_context + num_groups ) ; /* is this right?? */
2001-08-28 20:05:55 +04:00
return ( True ) ;
}
2002-07-15 14:35:28 +04:00
/*******************************************************************
2005-08-13 04:13:21 +04:00
Get groups that a user is a member of .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_NetUserGetGroups ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2001-08-28 20:05:55 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * UserName = skip_string ( param , tpscnt , str2 ) ;
char * p = skip_string ( param , tpscnt , UserName ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2003-01-03 11:28:12 +03:00
const char * level_string ;
2001-08-28 20:05:55 +04:00
int count = 0 ;
2007-10-19 04:40:25 +04:00
bool ret = False ;
2009-02-08 16:20:17 +03:00
uint32_t i ;
2007-12-04 02:19:22 +03:00
char * endp = NULL ;
2009-02-08 16:20:17 +03:00
struct rpc_pipe_client * samr_pipe ;
struct policy_handle samr_handle , domain_handle , user_handle ;
struct lsa_String name ;
struct lsa_Strings names ;
struct samr_Ids type , rid ;
struct samr_RidWithAttributeArray * rids ;
NTSTATUS status ;
2001-08-28 20:05:55 +04:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! UserName | | ! p ) {
return False ;
}
2002-07-15 14:35:28 +04:00
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2007-09-11 23:27:34 +04:00
2002-07-15 14:35:28 +04:00
/* check it's a supported varient */
2007-09-11 23:27:34 +04:00
2003-08-19 08:17:21 +04:00
if ( strcmp ( str1 , " zWrLeh " ) ! = 0 )
2002-07-15 14:35:28 +04:00
return False ;
2007-09-11 23:27:34 +04:00
2002-07-15 14:35:28 +04:00
switch ( uLevel ) {
case 0 :
2003-01-03 11:28:12 +03:00
level_string = " B21 " ;
2001-08-28 20:05:55 +04:00
break ;
2002-07-15 14:35:28 +04:00
default :
2001-08-28 20:05:55 +04:00
return False ;
}
2003-01-03 11:28:12 +03:00
if ( strcmp ( level_string , str2 ) ! = 0 )
2002-07-15 14:35:28 +04:00
return False ;
2001-08-28 20:05:55 +04:00
* rdata_len = mdrcnt + 1024 ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2007-09-11 23:27:34 +04:00
2001-08-28 20:05:55 +04:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
p = * rdata ;
2007-12-04 02:19:22 +03:00
endp = * rdata + * rdata_len ;
2001-08-28 20:05:55 +04:00
2009-02-08 16:20:17 +03:00
status = rpc_pipe_open_internal (
talloc_tos ( ) , & ndr_table_samr . syntax_id , rpc_samr_dispatch ,
conn - > server_info , & samr_pipe ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: Could not connect to samr: %s \n " ,
nt_errstr ( status ) ) ) ;
return false ;
2006-02-04 01:19:41 +03:00
}
2009-02-08 16:20:17 +03:00
status = rpccli_samr_Connect2 ( samr_pipe , talloc_tos ( ) , global_myname ( ) ,
2009-04-16 02:40:00 +04:00
SAMR_ACCESS_LOOKUP_DOMAIN , & samr_handle ) ;
2009-02-08 16:20:17 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_Connect2 failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return false ;
2006-06-15 05:54:09 +04:00
}
2009-02-08 16:20:17 +03:00
status = rpccli_samr_OpenDomain ( samr_pipe , talloc_tos ( ) , & samr_handle ,
SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT ,
get_global_sam_sid ( ) , & domain_handle ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_OpenDomain failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto close_sam ;
}
2004-11-12 18:49:47 +03:00
2009-02-08 16:20:17 +03:00
name . string = UserName ;
2003-08-19 08:17:21 +04:00
2009-02-08 16:20:17 +03:00
status = rpccli_samr_LookupNames ( samr_pipe , talloc_tos ( ) ,
& domain_handle , 1 , & name ,
& rid , & type ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_LookupNames failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto close_domain ;
2006-02-04 01:19:41 +03:00
}
2009-02-08 16:20:17 +03:00
if ( type . ids [ 0 ] ! = SID_NAME_USER ) {
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " %s is a %s, not a user \n " , UserName ,
2009-02-08 16:20:17 +03:00
sid_type_lookup ( type . ids [ 0 ] ) ) ) ;
goto close_domain ;
2006-02-04 01:19:41 +03:00
}
2009-02-08 16:20:17 +03:00
status = rpccli_samr_OpenUser ( samr_pipe , talloc_tos ( ) ,
& domain_handle ,
SAMR_USER_ACCESS_GET_GROUPS ,
rid . ids [ 0 ] , & user_handle ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_LookupNames failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto close_domain ;
2006-02-04 01:19:41 +03:00
}
2001-08-28 20:05:55 +04:00
2009-02-08 16:20:17 +03:00
status = rpccli_samr_GetGroupsForUser ( samr_pipe , talloc_tos ( ) ,
& user_handle , & rids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_LookupNames failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto close_user ;
2006-02-04 01:19:41 +03:00
}
2003-08-19 08:17:21 +04:00
2009-02-08 16:20:17 +03:00
for ( i = 0 ; i < rids - > count ; i + + ) {
2007-12-04 02:19:22 +03:00
2009-02-08 16:20:17 +03:00
status = rpccli_samr_LookupRids ( samr_pipe , talloc_tos ( ) ,
& domain_handle ,
1 , & rids - > rids [ i ] . rid ,
& names , & type ) ;
if ( NT_STATUS_IS_OK ( status ) & & ( names . count = = 1 ) ) {
strlcpy ( p , names . names [ 0 ] . string , PTR_DIFF ( endp , p ) ) ;
2007-12-04 02:19:22 +03:00
p + = 21 ;
2003-08-19 08:17:21 +04:00
count + + ;
}
}
2004-11-12 18:49:47 +03:00
2001-08-28 20:05:55 +04:00
* rdata_len = PTR_DIFF ( p , * rdata ) ;
2002-07-15 14:35:28 +04:00
SSVAL ( * rparam , 4 , count ) ; /* is this right?? */
SSVAL ( * rparam , 6 , count ) ; /* is this right?? */
2003-08-19 08:17:21 +04:00
ret = True ;
2009-02-08 16:20:17 +03:00
close_user :
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & user_handle ) ;
close_domain :
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & domain_handle ) ;
close_sam :
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & samr_handle ) ;
2003-08-19 08:17:21 +04:00
return ret ;
2002-07-15 14:35:28 +04:00
}
/*******************************************************************
2005-08-13 04:13:21 +04:00
Get all users .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_RNetUserEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2002-07-15 14:35:28 +04:00
{
int count_sent = 0 ;
2005-04-10 19:45:46 +04:00
int num_users = 0 ;
2002-07-15 14:35:28 +04:00
int errflags = 0 ;
2005-04-10 19:45:46 +04:00
int i , resume_context , cli_buf_size ;
2009-01-31 19:58:30 +03:00
uint32_t resume_handle ;
struct rpc_pipe_client * samr_pipe ;
struct policy_handle samr_handle , domain_handle ;
NTSTATUS status ;
2002-07-15 14:35:28 +04:00
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2007-12-04 02:19:22 +03:00
char * endp = NULL ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2002-07-15 14:35:28 +04:00
if ( strcmp ( str1 , " WrLeh " ) ! = 0 )
return False ;
/* parameters
* W - > resume context ( number of users to skip )
* r - > return parameter pointer to receive buffer
* L - > length of receive buffer
* e - > return parameter number of entries
* h - > return parameter total number of users
*/
2007-12-04 02:19:22 +03:00
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
resume_context = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
cli_buf_size = get_safe_SVAL ( param , tpscnt , p , 2 , 0 ) ;
2005-08-13 04:13:21 +04:00
DEBUG ( 10 , ( " api_RNetUserEnum:resume context: %d, client buffer size: %d \n " ,
resume_context , cli_buf_size ) ) ;
2002-07-15 14:35:28 +04:00
2001-08-28 20:05:55 +04:00
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2001-08-28 20:05:55 +04:00
2002-07-15 14:35:28 +04:00
/* check it's a supported varient */
if ( strcmp ( " B21 " , str2 ) ! = 0 )
return False ;
2001-08-28 20:05:55 +04:00
2002-07-15 14:35:28 +04:00
* rdata_len = cli_buf_size ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2001-08-28 20:05:55 +04:00
2002-07-15 14:35:28 +04:00
p = * rdata ;
2007-12-04 02:19:22 +03:00
endp = * rdata + * rdata_len ;
2002-07-15 14:35:28 +04:00
2009-01-31 19:58:30 +03:00
status = rpc_pipe_open_internal (
talloc_tos ( ) , & ndr_table_samr . syntax_id , rpc_samr_dispatch ,
conn - > server_info , & samr_pipe ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: Could not connect to samr: %s \n " ,
nt_errstr ( status ) ) ) ;
return false ;
2002-07-15 14:35:28 +04:00
}
2009-01-31 19:58:30 +03:00
status = rpccli_samr_Connect2 ( samr_pipe , talloc_tos ( ) , global_myname ( ) ,
2009-04-16 02:40:00 +04:00
SAMR_ACCESS_LOOKUP_DOMAIN , & samr_handle ) ;
2009-01-31 19:58:30 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_Connect2 failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return false ;
}
status = rpccli_samr_OpenDomain ( samr_pipe , talloc_tos ( ) , & samr_handle ,
SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS ,
get_global_sam_sid ( ) , & domain_handle ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RNetUserEnum: samr_OpenDomain failed: %s \n " ,
nt_errstr ( status ) ) ) ;
2009-02-07 13:28:38 +03:00
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & samr_handle ) ;
2009-01-31 19:58:30 +03:00
return false ;
}
2002-07-15 14:35:28 +04:00
2005-04-10 19:45:46 +04:00
errflags = NERR_Success ;
2009-01-31 19:58:30 +03:00
resume_handle = 0 ;
2007-12-04 02:19:22 +03:00
2009-01-31 19:58:30 +03:00
while ( true ) {
struct samr_SamArray * sam_entries ;
uint32_t num_entries ;
status = rpccli_samr_EnumDomainUsers ( samr_pipe , talloc_tos ( ) ,
& domain_handle ,
& resume_handle ,
0 , & sam_entries , 1 ,
& num_entries ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " rpccli_samr_EnumDomainUsers returned "
" %s \n " , nt_errstr ( status ) ) ) ;
break ;
}
if ( num_entries = = 0 ) {
DEBUG ( 10 , ( " rpccli_samr_EnumDomainUsers returned "
" no entries -- done \n " ) ) ;
2005-04-10 19:45:46 +04:00
break ;
}
2009-01-31 19:58:30 +03:00
for ( i = 0 ; i < num_entries ; i + + ) {
const char * name ;
name = sam_entries - > entries [ i ] . name . string ;
if ( ( ( PTR_DIFF ( p , * rdata ) + 21 ) < = * rdata_len )
& & ( strlen ( name ) < = 21 ) ) {
strlcpy ( p , name , PTR_DIFF ( endp , p ) ) ;
DEBUG ( 10 , ( " api_RNetUserEnum:adding entry %d "
" username %s \n " , count_sent , p ) ) ;
p + = 21 ;
count_sent + + ;
} else {
/* set overflow error */
DEBUG ( 10 , ( " api_RNetUserEnum:overflow on entry %d "
" username %s \n " , count_sent , name ) ) ;
errflags = 234 ;
break ;
}
}
if ( errflags ! = NERR_Success ) {
break ;
}
TALLOC_FREE ( sam_entries ) ;
2005-04-10 19:45:46 +04:00
}
2009-01-31 19:58:30 +03:00
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & domain_handle ) ;
rpccli_samr_Close ( samr_pipe , talloc_tos ( ) , & samr_handle ) ;
2002-07-15 14:35:28 +04:00
* rdata_len = PTR_DIFF ( p , * rdata ) ;
SSVAL ( * rparam , 0 , errflags ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
SSVAL ( * rparam , 4 , count_sent ) ; /* is this right?? */
2005-04-10 19:45:46 +04:00
SSVAL ( * rparam , 6 , num_users ) ; /* is this right?? */
2002-07-15 14:35:28 +04:00
return True ;
2001-08-28 20:05:55 +04:00
}
2000-04-19 11:00:22 +04:00
/****************************************************************************
2005-08-13 04:13:21 +04:00
Get the time of day info .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_NetRemoteTOD ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
2006-02-04 01:19:41 +03:00
struct tm * t ;
time_t unixdate = time ( NULL ) ;
char * p ;
* rparam_len = 4 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
* rdata_len = 21 ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
p = * rdata ;
srv_put_dos_date3 ( p , 0 , unixdate ) ; /* this is the time that is looked at
by NT in a " net time " operation ,
it seems to ignore the one below */
/* the client expects to get localtime, not GMT, in this bit
( I think , this needs testing ) */
t = localtime ( & unixdate ) ;
2006-06-15 01:36:49 +04:00
if ( ! t ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SIVAL ( p , 4 , 0 ) ; /* msecs ? */
SCVAL ( p , 8 , t - > tm_hour ) ;
SCVAL ( p , 9 , t - > tm_min ) ;
SCVAL ( p , 10 , t - > tm_sec ) ;
SCVAL ( p , 11 , 0 ) ; /* hundredths of seconds */
SSVALS ( p , 12 , get_time_zone ( unixdate ) / 60 ) ; /* timezone in minutes from GMT */
SSVAL ( p , 14 , 10000 ) ; /* timer interval in 0.0001 of sec */
SCVAL ( p , 16 , t - > tm_mday ) ;
SCVAL ( p , 17 , t - > tm_mon + 1 ) ;
SSVAL ( p , 18 , 1900 + t - > tm_year ) ;
SCVAL ( p , 20 , t - > tm_wday ) ;
return True ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
Set the user password .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_SetUserPassword ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
2000-04-19 11:00:22 +04:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * np = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * p = NULL ;
2003-07-31 05:33:44 +04:00
fstring user ;
fstring pass1 , pass2 ;
2000-04-19 11:00:22 +04:00
2007-04-03 00:10:21 +04:00
/* Skip 2 strings. */
p = skip_string ( param , tpscnt , np ) ;
p = skip_string ( param , tpscnt , p ) ;
2007-03-31 02:25:08 +04:00
if ( ! np | | ! p ) {
return False ;
}
/* Do we have a string ? */
2007-04-03 00:10:21 +04:00
if ( skip_string ( param , tpscnt , p ) = = NULL ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2003-07-31 05:33:44 +04:00
pull_ascii_fstring ( user , p ) ;
2000-04-19 11:00:22 +04:00
2007-04-03 00:10:21 +04:00
p = skip_string ( param , tpscnt , p ) ;
2007-03-31 02:25:08 +04:00
if ( ! p ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
memset ( pass1 , ' \0 ' , sizeof ( pass1 ) ) ;
memset ( pass2 , ' \0 ' , sizeof ( pass2 ) ) ;
2007-04-03 08:52:09 +04:00
/*
* We use 31 here not 32 as we ' re checking
* the last byte we want to access is safe .
*/
if ( ! is_offset_safe ( param , tpscnt , p , 31 ) ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2003-07-31 05:33:44 +04:00
memcpy ( pass1 , p , 16 ) ;
memcpy ( pass2 , p + 16 , 16 ) ;
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
* rparam_len = 4 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
* rdata_len = 0 ;
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
SSVAL ( * rparam , 0 , NERR_badpass ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
DEBUG ( 3 , ( " Set password for <%s> \n " , user ) ) ;
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
/*
* Attempt to verify the old password against smbpasswd entries
* Win98 clients send old and new password in plaintext for this call .
*/
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
{
2010-01-10 16:24:22 +03:00
struct auth_serversupplied_info * server_info = NULL ;
2003-07-31 05:33:44 +04:00
DATA_BLOB password = data_blob ( pass1 , strlen ( pass1 ) + 1 ) ;
2002-01-20 12:00:32 +03:00
2003-07-31 05:33:44 +04:00
if ( NT_STATUS_IS_OK ( check_plaintext_password ( user , password , & server_info ) ) ) {
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
become_root ( ) ;
2006-02-11 02:23:10 +03:00
if ( NT_STATUS_IS_OK ( change_oem_password ( server_info - > sam_account , pass1 , pass2 , False , NULL ) ) ) {
2003-07-31 05:33:44 +04:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
}
unbecome_root ( ) ;
2000-04-19 11:00:22 +04:00
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( server_info ) ;
2003-07-31 05:33:44 +04:00
}
data_blob_clear_free ( & password ) ;
}
2000-04-19 11:00:22 +04:00
2003-07-31 05:33:44 +04:00
/*
* If the plaintext change failed , attempt
* the old encrypted method . NT will generate this
* after trying the samr method . Note that this
* method is done as a last resort as this
* password change method loses the NT password hash
* and cannot change the UNIX password as no plaintext
* is received .
*/
2001-05-04 19:44:27 +04:00
2003-07-31 05:33:44 +04:00
if ( SVAL ( * rparam , 0 ) ! = NERR_Success ) {
2006-02-20 23:09:36 +03:00
struct samu * hnd = NULL ;
2003-07-31 05:33:44 +04:00
if ( check_lanman_password ( user , ( unsigned char * ) pass1 , ( unsigned char * ) pass2 , & hnd ) ) {
become_root ( ) ;
2003-08-15 05:42:30 +04:00
if ( change_lanman_password ( hnd , ( uchar * ) pass2 ) ) {
2003-07-31 05:33:44 +04:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
}
unbecome_root ( ) ;
2006-02-20 23:09:36 +03:00
TALLOC_FREE ( hnd ) ;
2003-07-31 05:33:44 +04:00
}
}
memset ( ( char * ) pass1 , ' \0 ' , sizeof ( fstring ) ) ;
memset ( ( char * ) pass2 , ' \0 ' , sizeof ( fstring ) ) ;
2009-01-31 18:57:46 +03:00
2003-07-31 05:33:44 +04:00
return ( True ) ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
Set the user password ( SamOEM version - gets plaintext ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_SamOEMChangePassword ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
2000-04-19 11:00:22 +04:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
2009-05-26 18:38:45 +04:00
struct smbd_server_connection * sconn = smbd_server_conn ;
2003-09-04 22:02:17 +04:00
fstring user ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * p = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2003-09-04 22:02:17 +04:00
* rparam_len = 2 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( ! p ) {
return False ;
}
2003-09-04 22:02:17 +04:00
* rdata_len = 0 ;
2000-04-19 11:00:22 +04:00
2003-09-04 22:02:17 +04:00
SSVAL ( * rparam , 0 , NERR_badpass ) ;
2000-04-19 11:00:22 +04:00
2003-09-04 22:02:17 +04:00
/*
* Check the parameter definition is correct .
*/
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
/* Do we have a string ? */
2007-04-03 00:10:21 +04:00
if ( skip_string ( param , tpscnt , p ) = = 0 ) {
2007-03-31 02:25:08 +04:00
return False ;
}
if ( ! strequal ( p , " zsT " ) ) {
DEBUG ( 0 , ( " api_SamOEMChangePassword: Invalid parameter string %s \n " , p ) ) ;
return False ;
}
2007-04-03 00:10:21 +04:00
p = skip_string ( param , tpscnt , p ) ;
2007-03-31 02:25:08 +04:00
if ( ! p ) {
2003-09-04 22:02:17 +04:00
return False ;
}
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
/* Do we have a string ? */
2007-04-03 00:10:21 +04:00
if ( skip_string ( param , tpscnt , p ) = = 0 ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2003-09-04 22:02:17 +04:00
if ( ! strequal ( p , " B516B16 " ) ) {
DEBUG ( 0 , ( " api_SamOEMChangePassword: Invalid data parameter string %s \n " , p ) ) ;
return False ;
}
2007-04-03 00:10:21 +04:00
p = skip_string ( param , tpscnt , p ) ;
2007-03-31 02:25:08 +04:00
if ( ! p ) {
return False ;
}
/* Do we have a string ? */
2007-04-03 00:10:21 +04:00
if ( skip_string ( param , tpscnt , p ) = = 0 ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2003-09-04 22:02:17 +04:00
p + = pull_ascii_fstring ( user , p ) ;
2000-04-19 11:00:22 +04:00
2003-09-04 22:02:17 +04:00
DEBUG ( 3 , ( " api_SamOEMChangePassword: Change password for <%s> \n " , user ) ) ;
2000-04-19 11:00:22 +04:00
2003-09-04 22:02:17 +04:00
/*
* Pass the user through the NT - > unix user mapping
* function .
*/
2000-04-19 11:00:22 +04:00
2009-05-26 18:38:45 +04:00
( void ) map_username ( sconn , user ) ;
2000-04-19 11:00:22 +04:00
2006-02-11 02:23:10 +03:00
if ( NT_STATUS_IS_OK ( pass_oem_change ( user , ( uchar * ) data , ( uchar * ) & data [ 516 ] , NULL , NULL , NULL ) ) ) {
2003-09-04 22:02:17 +04:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
}
2000-04-19 11:00:22 +04:00
2003-09-04 22:02:17 +04:00
return ( True ) ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
delete a print job
Form : < W > < >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-13 04:13:21 +04:00
2007-10-19 04:40:25 +04:00
static bool api_RDosPrintJobDel ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
2000-04-19 11:00:22 +04:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int function = get_safe_SVAL ( param , tpscnt , param , 0 , 0 ) ;
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2002-08-17 19:27:10 +04:00
uint32 jobid ;
2004-10-18 23:57:03 +04:00
fstring sharename ;
2002-08-17 19:27:10 +04:00
int errcode ;
2001-09-04 11:13:01 +04:00
WERROR werr = WERR_OK ;
2000-04-19 11:00:22 +04:00
2010-03-18 21:19:28 +03:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle handle ;
struct spoolss_DevmodeContainer devmode_ctr ;
enum spoolss_JobControl command ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2007-04-03 08:52:09 +04:00
/*
* We use 1 here not 2 as we ' re checking
* the last byte we want to access is safe .
*/
if ( ! is_offset_safe ( param , tpscnt , p , 1 ) ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2004-10-18 23:57:03 +04:00
if ( ! rap_to_pjobid ( SVAL ( p , 0 ) , sharename , & jobid ) )
2002-08-17 19:27:10 +04:00
return False ;
2000-04-19 11:00:22 +04:00
/* check it's a supported varient */
if ( ! ( strcsequal ( str1 , " W " ) & & strcsequal ( str2 , " " ) ) )
return ( False ) ;
* rparam_len = 4 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
* rdata_len = 0 ;
2010-03-18 21:19:28 +03:00
ZERO_STRUCT ( handle ) ;
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_RDosPrintJobDel: could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
2000-04-19 11:00:22 +04:00
goto out ;
}
2010-03-18 21:19:28 +03:00
ZERO_STRUCT ( devmode_ctr ) ;
status = rpccli_spoolss_OpenPrinter ( cli , mem_ctx ,
sharename ,
NULL ,
devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
errcode = W_ERROR_V ( werr ) ;
2004-11-18 18:13:58 +03:00
goto out ;
}
2010-03-18 21:19:28 +03:00
/* FIXME: formerly NERR_JobNotFound was returned if job did not exist
* and NERR_DestNotFound if share did not exist */
errcode = NERR_Success ;
2009-01-31 18:57:46 +03:00
2000-04-19 11:00:22 +04:00
switch ( function ) {
2010-03-18 21:19:28 +03:00
case 81 : /* delete */
command = SPOOLSS_JOB_CONTROL_DELETE ;
2000-04-19 11:00:22 +04:00
break ;
case 82 : /* pause */
2010-03-18 21:19:28 +03:00
command = SPOOLSS_JOB_CONTROL_PAUSE ;
2000-04-19 11:00:22 +04:00
break ;
case 83 : /* resume */
2010-03-18 21:19:28 +03:00
command = SPOOLSS_JOB_CONTROL_RESUME ;
break ;
default :
errcode = NERR_notsupported ;
2010-04-23 17:31:21 +04:00
goto out ;
2000-04-19 11:00:22 +04:00
}
2001-09-04 11:13:01 +04:00
2010-03-18 21:19:28 +03:00
status = rpccli_spoolss_SetJob ( cli , mem_ctx ,
& handle ,
jobid ,
NULL , /* unique ptr ctr */
command ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
2001-09-04 11:13:01 +04:00
errcode = W_ERROR_V ( werr ) ;
2010-03-18 21:19:28 +03:00
goto out ;
}
2009-01-31 18:57:46 +03:00
2000-04-19 11:00:22 +04:00
out :
2010-03-18 21:19:28 +03:00
if ( is_valid_policy_hnd ( & handle ) ) {
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & handle , NULL ) ;
}
2000-04-19 11:00:22 +04:00
SSVAL ( * rparam , 0 , errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
return ( True ) ;
}
/****************************************************************************
Purge a print queue - or pause or resume it .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-13 04:13:21 +04:00
2007-10-19 04:40:25 +04:00
static bool api_WPrintQueueCtrl ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int function = get_safe_SVAL ( param , tpscnt , param , 0 , 0 ) ;
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * QueueName = skip_string ( param , tpscnt , str2 ) ;
2000-04-19 11:00:22 +04:00
int errcode = NERR_notsupported ;
2001-09-04 11:13:01 +04:00
WERROR werr = WERR_OK ;
2010-03-18 20:13:40 +03:00
NTSTATUS status ;
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle handle ;
struct spoolss_SetPrinterInfoCtr info_ctr ;
struct spoolss_DevmodeContainer devmode_ctr ;
struct sec_desc_buf secdesc_ctr ;
enum spoolss_PrinterControl command ;
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! QueueName ) {
return False ;
}
2000-04-19 11:00:22 +04:00
/* check it's a supported varient */
if ( ! ( strcsequal ( str1 , " z " ) & & strcsequal ( str2 , " " ) ) )
return ( False ) ;
* rparam_len = 4 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
* rdata_len = 0 ;
2007-04-03 00:10:21 +04:00
if ( skip_string ( param , tpscnt , QueueName ) = = NULL ) {
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
return False ;
}
2000-04-19 11:00:22 +04:00
2010-03-18 20:13:40 +03:00
ZERO_STRUCT ( handle ) ;
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_WPrintQueueCtrl: could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
ZERO_STRUCT ( devmode_ctr ) ;
status = rpccli_spoolss_OpenPrinter ( cli , mem_ctx ,
QueueName ,
NULL ,
devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
errcode = W_ERROR_V ( werr ) ;
2000-04-19 11:00:22 +04:00
goto out ;
}
switch ( function ) {
case 74 : /* Pause queue */
2010-03-18 20:13:40 +03:00
command = SPOOLSS_PRINTER_CONTROL_PAUSE ;
2000-04-19 11:00:22 +04:00
break ;
case 75 : /* Resume queue */
2010-03-18 20:13:40 +03:00
command = SPOOLSS_PRINTER_CONTROL_RESUME ;
2000-04-19 11:00:22 +04:00
break ;
case 103 : /* Purge */
2010-03-18 20:13:40 +03:00
command = SPOOLSS_PRINTER_CONTROL_PURGE ;
2009-05-06 03:10:33 +04:00
break ;
default :
werr = WERR_NOT_SUPPORTED ;
2000-04-19 11:00:22 +04:00
break ;
}
2010-03-18 20:13:40 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
errcode = W_ERROR_V ( werr ) ;
goto out ;
}
ZERO_STRUCT ( info_ctr ) ;
ZERO_STRUCT ( secdesc_ctr ) ;
status = rpccli_spoolss_SetPrinter ( cli , mem_ctx ,
& handle ,
& info_ctr ,
& devmode_ctr ,
& secdesc_ctr ,
command ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
errcode = W_ERROR_V ( werr ) ;
goto out ;
}
2009-05-06 03:10:33 +04:00
errcode = W_ERROR_V ( werr ) ;
2001-09-04 11:13:01 +04:00
2000-04-19 11:00:22 +04:00
out :
2010-03-18 20:13:40 +03:00
if ( is_valid_policy_hnd ( & handle ) ) {
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & handle , NULL ) ;
}
2000-04-19 11:00:22 +04:00
SSVAL ( * rparam , 0 , errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
return ( True ) ;
}
/****************************************************************************
set the property of a print job ( undocumented ? )
? function = 0xb - > set name of print job
? function = 0x6 - > move print job up / down
Form : < WWsTP > < WWzWWDDzzzzzzzzzzlz >
or < WWsTP > < WB21BB16B10zWWzDDz >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-13 04:13:21 +04:00
2000-04-19 11:00:22 +04:00
static int check_printjob_info ( struct pack_desc * desc ,
int uLevel , char * id )
{
desc - > subformat = NULL ;
switch ( uLevel ) {
case 0 : desc - > format = " W " ; break ;
case 1 : desc - > format = " WB21BB16B10zWWzDDz " ; break ;
case 2 : desc - > format = " WWzWWDDzz " ; break ;
case 3 : desc - > format = " WWzWWDDzzzzzzzzzzlz " ; break ;
2001-03-23 06:12:58 +03:00
case 4 : desc - > format = " WWzWWDDzzzzzDDDDDDD " ; break ;
2007-04-04 04:03:12 +04:00
default :
DEBUG ( 0 , ( " check_printjob_info: invalid level %d \n " ,
uLevel ) ) ;
return False ;
}
if ( id = = NULL | | strcmp ( desc - > format , id ) ! = 0 ) {
DEBUG ( 0 , ( " check_printjob_info: invalid format %s \n " ,
id ? id : " <NULL> " ) ) ;
return False ;
2000-04-19 11:00:22 +04:00
}
return True ;
}
2007-10-19 04:40:25 +04:00
static bool api_PrintJobInfo ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
struct pack_desc desc ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2002-08-17 19:27:10 +04:00
uint32 jobid ;
2004-10-18 23:57:03 +04:00
fstring sharename ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 2 , - 1 ) ;
int function = get_safe_SVAL ( param , tpscnt , p , 4 , - 1 ) ;
2010-04-27 21:58:32 +04:00
int errcode ;
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
WERROR werr ;
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle handle ;
struct spoolss_DevmodeContainer devmode_ctr ;
struct spoolss_JobInfoContainer ctr ;
union spoolss_JobInfo info ;
struct spoolss_SetJobInfo1 info1 ;
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2007-04-03 08:52:09 +04:00
/*
* We use 1 here not 2 as we ' re checking
* the last byte we want to access is safe .
*/
if ( ! is_offset_safe ( param , tpscnt , p , 1 ) ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2004-10-18 23:57:03 +04:00
if ( ! rap_to_pjobid ( SVAL ( p , 0 ) , sharename , & jobid ) )
2002-08-17 19:27:10 +04:00
return False ;
2000-04-19 11:00:22 +04:00
* rparam_len = 4 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2004-11-11 20:40:49 +03:00
2010-04-27 21:58:32 +04:00
ZERO_STRUCT ( handle ) ;
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_PrintJobInfo: could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
ZERO_STRUCT ( devmode_ctr ) ;
status = rpccli_spoolss_OpenPrinter ( cli , mem_ctx ,
sharename ,
NULL ,
devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
errcode = W_ERROR_V ( werr ) ;
goto out ;
2004-11-11 20:40:49 +03:00
}
2009-01-31 18:57:46 +03:00
2000-04-19 11:00:22 +04:00
* rdata_len = 0 ;
2009-01-31 18:57:46 +03:00
2000-04-19 11:00:22 +04:00
/* check it's a supported varient */
if ( ( strcmp ( str1 , " WWsTP " ) ) | |
( ! check_printjob_info ( & desc , uLevel , str2 ) ) )
return ( False ) ;
2010-04-27 21:58:32 +04:00
werr = rpccli_spoolss_getjob ( cli , mem_ctx ,
& handle ,
jobid ,
1 , /* level */
0 , /* offered */
& info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
errcode = W_ERROR_V ( werr ) ;
2000-04-19 11:00:22 +04:00
goto out ;
}
errcode = NERR_notsupported ;
switch ( function ) {
2010-04-27 21:58:32 +04:00
case 0xb :
2000-04-19 11:00:22 +04:00
/* change print job name, data gives the name */
break ;
default :
2010-04-27 21:58:32 +04:00
goto out ;
2000-04-19 11:00:22 +04:00
}
2010-04-27 21:58:32 +04:00
ZERO_STRUCT ( ctr ) ;
info1 . job_id = info . info1 . job_id ;
info1 . printer_name = info . info1 . printer_name ;
info1 . user_name = info . info1 . user_name ;
info1 . document_name = data ;
info1 . data_type = info . info1 . data_type ;
info1 . text_status = info . info1 . text_status ;
info1 . status = info . info1 . status ;
info1 . priority = info . info1 . priority ;
info1 . position = info . info1 . position ;
info1 . total_pages = info . info1 . total_pages ;
info1 . pages_printed = info . info1 . pages_printed ;
info1 . submitted = info . info1 . submitted ;
ctr . level = 1 ;
ctr . info . info1 = & info1 ;
status = rpccli_spoolss_SetJob ( cli , mem_ctx ,
& handle ,
jobid ,
& ctr ,
0 ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
errcode = W_ERROR_V ( werr ) ;
goto out ;
}
errcode = NERR_Success ;
2000-04-19 11:00:22 +04:00
out :
2010-04-27 21:58:32 +04:00
if ( is_valid_policy_hnd ( & handle ) ) {
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & handle , NULL ) ;
}
2000-04-19 11:00:22 +04:00
SSVALS ( * rparam , 0 , errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
2009-01-31 18:57:46 +03:00
2000-04-19 11:00:22 +04:00
return ( True ) ;
}
/****************************************************************************
2005-08-13 04:13:21 +04:00
Get info about the server .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_RNetServerGetInfo ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2006-02-04 01:19:41 +03:00
char * p2 ;
int struct_len ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
DEBUG ( 4 , ( " NetServerGetInfo level %d \n " , uLevel ) ) ;
/* check it's a supported varient */
if ( ! prefix_ok ( str1 , " WrLh " ) ) {
return False ;
}
switch ( uLevel ) {
case 0 :
if ( strcmp ( str2 , " B16 " ) ! = 0 ) {
return False ;
}
struct_len = 16 ;
break ;
case 1 :
if ( strcmp ( str2 , " B16BBDz " ) ! = 0 ) {
return False ;
}
struct_len = 26 ;
break ;
case 2 :
if ( strcmp ( str2 , " B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz " ) ! = 0 ) {
return False ;
}
struct_len = 134 ;
break ;
case 3 :
if ( strcmp ( str2 , " B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz " ) ! = 0 ) {
return False ;
}
struct_len = 144 ;
break ;
case 20 :
if ( strcmp ( str2 , " DN " ) ! = 0 ) {
return False ;
}
struct_len = 6 ;
break ;
case 50 :
if ( strcmp ( str2 , " B16BBDzWWzzz " ) ! = 0 ) {
return False ;
}
struct_len = 42 ;
break ;
default :
return False ;
}
* rdata_len = mdrcnt ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
p = * rdata ;
p2 = p + struct_len ;
if ( uLevel ! = 20 ) {
2007-08-02 21:37:38 +04:00
srvstr_push ( NULL , 0 , p , global_myname ( ) , 16 ,
2006-02-04 01:19:41 +03:00
STR_ASCII | STR_UPPER | STR_TERMINATE ) ;
}
p + = 16 ;
if ( uLevel > 0 ) {
struct srv_info_struct * servers = NULL ;
int i , count ;
2007-11-13 04:59:18 +03:00
char * comment = NULL ;
TALLOC_CTX * ctx = talloc_tos ( ) ;
2006-02-04 01:19:41 +03:00
uint32 servertype = lp_default_server_announce ( ) ;
2007-11-13 04:59:18 +03:00
comment = talloc_strdup ( ctx , lp_serverstring ( ) ) ;
if ( ! comment ) {
return false ;
}
2006-02-04 01:19:41 +03:00
if ( ( count = get_server_info ( SV_TYPE_ALL , & servers , lp_workgroup ( ) ) ) > 0 ) {
for ( i = 0 ; i < count ; i + + ) {
2006-10-09 17:26:29 +04:00
if ( strequal ( servers [ i ] . name , global_myname ( ) ) ) {
2006-02-04 01:19:41 +03:00
servertype = servers [ i ] . type ;
2007-11-13 04:59:18 +03:00
TALLOC_FREE ( comment ) ;
comment = talloc_strdup ( ctx ,
servers [ i ] . comment ) ;
if ( comment ) {
return false ;
}
2006-02-04 01:19:41 +03:00
}
}
}
SAFE_FREE ( servers ) ;
SCVAL ( p , 0 , lp_major_announce_version ( ) ) ;
SCVAL ( p , 1 , lp_minor_announce_version ( ) ) ;
SIVAL ( p , 2 , servertype ) ;
if ( mdrcnt = = struct_len ) {
SIVAL ( p , 6 , 0 ) ;
} else {
SIVAL ( p , 6 , PTR_DIFF ( p2 , * rdata ) ) ;
2008-05-11 03:02:52 +04:00
comment = talloc_sub_advanced (
ctx ,
lp_servicename ( SNUM ( conn ) ) ,
conn - > server_info - > unix_name ,
conn - > connectpath ,
2008-06-19 18:54:12 +04:00
conn - > server_info - > utok . gid ,
2008-05-11 13:26:33 +04:00
conn - > server_info - > sanitized_username ,
2008-05-11 03:02:52 +04:00
pdb_get_domain ( conn - > server_info - > sam_account ) ,
comment ) ;
2007-11-13 04:59:18 +03:00
if ( comment ) {
return false ;
}
if ( mdrcnt - struct_len < = 0 ) {
return false ;
}
push_ascii ( p2 ,
comment ,
MIN ( mdrcnt - struct_len ,
MAX_SERVER_STRING_LENGTH ) ,
STR_TERMINATE ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2006-02-04 01:19:41 +03:00
}
}
if ( uLevel > 1 ) {
return False ; /* not yet implemented */
}
* rdata_len = PTR_DIFF ( p2 , * rdata ) ;
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
SSVAL ( * rparam , 4 , * rdata_len ) ;
return True ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
2005-08-13 04:13:21 +04:00
Get info about the server .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_NetWkstaGetInfo ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
2000-04-19 11:00:22 +04:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
char * p2 ;
2007-12-04 02:19:22 +03:00
char * endp ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int level = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 4 , ( " NetWkstaGetInfo level %d \n " , level ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
/* check it's a supported varient */
if ( ! ( level = = 10 & & strcsequal ( str1 , " WrLh " ) & & strcsequal ( str2 , " zzzBBzz " ) ) ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rdata_len = mdrcnt + 1024 ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
p = * rdata ;
2007-12-04 02:19:22 +03:00
endp = * rdata + * rdata_len ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
p2 = get_safe_ptr ( * rdata , * rdata_len , p , 22 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SIVAL ( p , 0 , PTR_DIFF ( p2 , * rdata ) ) ; /* host name */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , get_local_machine_name ( ) , PTR_DIFF ( endp , p2 ) ) ;
2006-02-04 01:19:41 +03:00
strupper_m ( p2 ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2006-02-04 01:19:41 +03:00
p + = 4 ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SIVAL ( p , 0 , PTR_DIFF ( p2 , * rdata ) ) ;
2008-05-11 03:02:52 +04:00
strlcpy ( p2 , conn - > server_info - > sanitized_username , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2006-02-04 01:19:41 +03:00
p + = 4 ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SIVAL ( p , 0 , PTR_DIFF ( p2 , * rdata ) ) ; /* login domain */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , lp_workgroup ( ) , PTR_DIFF ( endp , p2 ) ) ;
2006-02-04 01:19:41 +03:00
strupper_m ( p2 ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2006-02-04 01:19:41 +03:00
p + = 4 ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SCVAL ( p , 0 , lp_major_announce_version ( ) ) ; /* system version - e.g 4 in 4.1 */
SCVAL ( p , 1 , lp_minor_announce_version ( ) ) ; /* system version - e.g .1 in 4.1 */
p + = 2 ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SIVAL ( p , 0 , PTR_DIFF ( p2 , * rdata ) ) ;
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , lp_workgroup ( ) , PTR_DIFF ( endp , p2 ) ) ; /* don't know. login domain?? */
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2006-02-04 01:19:41 +03:00
p + = 4 ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SIVAL ( p , 0 , PTR_DIFF ( p2 , * rdata ) ) ; /* don't know */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , " " , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2006-02-04 01:19:41 +03:00
p + = 4 ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rdata_len = PTR_DIFF ( p2 , * rdata ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
SSVAL ( * rparam , 4 , * rdata_len ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
get info about a user
struct user_info_11 {
char usri11_name [ 21 ] ; 0 - 20
char usri11_pad ; 21
char * usri11_comment ; 22 - 25
char * usri11_usr_comment ; 26 - 29
unsigned short usri11_priv ; 30 - 31
unsigned long usri11_auth_flags ; 32 - 35
long usri11_password_age ; 36 - 39
char * usri11_homedir ; 40 - 43
char * usri11_parms ; 44 - 47
long usri11_last_logon ; 48 - 51
long usri11_last_logoff ; 52 - 55
unsigned short usri11_bad_pw_count ; 56 - 57
unsigned short usri11_num_logons ; 58 - 59
char * usri11_logon_server ; 60 - 63
unsigned short usri11_country_code ; 64 - 65
char * usri11_workstations ; 66 - 69
unsigned long usri11_max_storage ; 70 - 73
unsigned short usri11_units_per_week ; 74 - 75
unsigned char * usri11_logon_hours ; 76 - 79
unsigned short usri11_code_page ; 80 - 81
} ;
where :
2008-02-05 17:32:14 +03:00
usri11_name specifies the user name for which information is retrieved
2000-04-19 11:00:22 +04:00
usri11_pad aligns the next data structure element to a word boundary
usri11_comment is a null terminated ASCII comment
usri11_user_comment is a null terminated ASCII comment about the user
usri11_priv specifies the level of the privilege assigned to the user .
The possible values are :
Name Value Description
USER_PRIV_GUEST 0 Guest privilege
USER_PRIV_USER 1 User privilege
USER_PRV_ADMIN 2 Administrator privilege
usri11_auth_flags specifies the account operator privileges . The
possible values are :
Name Value Description
AF_OP_PRINT 0 Print operator
2000-08-18 00:05:05 +04:00
Leach , Naik [ Page 28 ]
2000-04-19 11:00:22 +04:00
INTERNET - DRAFT CIFS Remote Admin Protocol January 10 , 1997
AF_OP_COMM 1 Communications operator
AF_OP_SERVER 2 Server operator
AF_OP_ACCOUNTS 3 Accounts operator
usri11_password_age specifies how many seconds have elapsed since the
password was last changed .
usri11_home_dir points to a null terminated ASCII string that contains
the path name of the user ' s home directory .
usri11_parms points to a null terminated ASCII string that is set
aside for use by applications .
usri11_last_logon specifies the time when the user last logged on .
This value is stored as the number of seconds elapsed since
00 : 00 : 00 , January 1 , 1970.
usri11_last_logoff specifies the time when the user last logged off .
This value is stored as the number of seconds elapsed since
00 : 00 : 00 , January 1 , 1970. A value of 0 means the last logoff
time is unknown .
usri11_bad_pw_count specifies the number of incorrect passwords
entered since the last successful logon .
usri11_log1_num_logons specifies the number of times this user has
logged on . A value of - 1 means the number of logons is unknown .
usri11_logon_server points to a null terminated ASCII string that
contains the name of the server to which logon requests are sent .
A null string indicates logon requests should be sent to the
domain controller .
usri11_country_code specifies the country code for the user ' s language
of choice .
usri11_workstations points to a null terminated ASCII string that
contains the names of workstations the user may log on from .
There may be up to 8 workstations , with the names separated by
commas . A null strings indicates there are no restrictions .
usri11_max_storage specifies the maximum amount of disk space the user
can occupy . A value of 0xffffffff indicates there are no
restrictions .
usri11_units_per_week specifies the equal number of time units into
which a week is divided . This value must be equal to 168.
usri11_logon_hours points to a 21 byte ( 168 bits ) string that
specifies the time during which the user can log on . Each bit
represents one unique hour in a week . The first bit ( bit 0 , word
0 ) is Sunday , 0 : 00 to 0 : 59 , the second bit ( bit 1 , word 0 ) is
2000-08-18 00:05:05 +04:00
Leach , Naik [ Page 29 ]
2000-04-19 11:00:22 +04:00
INTERNET - DRAFT CIFS Remote Admin Protocol January 10 , 1997
Sunday , 1 : 00 to 1 : 59 and so on . A null pointer indicates there
are no restrictions .
usri11_code_page specifies the code page for the user ' s language of
choice
All of the pointers in this data structure need to be treated
specially . The pointer is a 32 bit pointer . The higher 16 bits need
to be ignored . The converter word returned in the parameters section
needs to be subtracted from the lower 16 bits to calculate an offset
into the return buffer where this ASCII string resides .
There is no auxiliary data in the response .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define usri11_name 0
# define usri11_pad 21
# define usri11_comment 22
# define usri11_usr_comment 26
# define usri11_full_name 30
# define usri11_priv 34
# define usri11_auth_flags 36
# define usri11_password_age 40
# define usri11_homedir 44
# define usri11_parms 48
# define usri11_last_logon 52
# define usri11_last_logoff 56
# define usri11_bad_pw_count 60
# define usri11_num_logons 62
# define usri11_logon_server 64
# define usri11_country_code 68
# define usri11_workstations 70
# define usri11_max_storage 74
# define usri11_units_per_week 78
# define usri11_logon_hours 80
# define usri11_code_page 84
# define usri11_end 86
# define USER_PRIV_GUEST 0
# define USER_PRIV_USER 1
# define USER_PRIV_ADMIN 2
# define AF_OP_PRINT 0
# define AF_OP_COMM 1
# define AF_OP_SERVER 2
# define AF_OP_ACCOUNTS 3
2007-10-19 04:40:25 +04:00
static bool api_RNetUserGetInfo ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
2000-04-19 11:00:22 +04:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
2009-05-26 18:38:45 +04:00
struct smbd_server_connection * sconn = smbd_server_conn ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * UserName = skip_string ( param , tpscnt , str2 ) ;
char * p = skip_string ( param , tpscnt , UserName ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
int uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2000-04-19 11:00:22 +04:00
char * p2 ;
2007-12-04 02:19:22 +03:00
char * endp ;
2003-01-03 11:28:12 +03:00
const char * level_string ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
/* get NIS home of a previously validated user - simeon */
/* With share level security vuid will always be zero.
Don ' t depend on vuser being non - null ! ! . JRA */
2009-05-26 18:38:45 +04:00
user_struct * vuser = get_valid_user_struct ( sconn , vuid ) ;
2005-11-05 07:21:55 +03:00
if ( vuser ! = NULL ) {
2008-04-29 15:43:10 +04:00
DEBUG ( 3 , ( " Username of UID %d is %s \n " ,
2008-06-19 18:54:12 +04:00
( int ) vuser - > server_info - > utok . uid ,
2008-04-30 19:42:39 +04:00
vuser - > server_info - > unix_name ) ) ;
2005-11-05 07:21:55 +03:00
}
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! UserName | | ! p ) {
return False ;
}
2005-11-05 07:21:55 +03:00
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
DEBUG ( 4 , ( " RNetUserGetInfo level=%d \n " , uLevel ) ) ;
2007-11-13 04:59:18 +03:00
2000-04-19 11:00:22 +04:00
/* check it's a supported variant */
2005-11-05 07:21:55 +03:00
if ( strcmp ( str1 , " zWrLh " ) ! = 0 ) {
return False ;
}
switch ( uLevel ) {
2003-01-03 11:28:12 +03:00
case 0 : level_string = " B21 " ; break ;
case 1 : level_string = " B21BB16DWzzWz " ; break ;
case 2 : level_string = " B21BB16DWzzWzDzzzzDDDDWb21WWzWW " ; break ;
case 10 : level_string = " B21Bzzz " ; break ;
case 11 : level_string = " B21BzzzWDDzzDDWWzWzDWb21W " ; break ;
2000-04-19 11:00:22 +04:00
default : return False ;
}
2005-11-05 07:21:55 +03:00
if ( strcmp ( level_string , str2 ) ! = 0 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
* rdata_len = mdrcnt + 1024 ;
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , * rdata_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SSVAL ( * rparam , 0 , NERR_Success ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
p = * rdata ;
2007-12-04 02:19:22 +03:00
endp = * rdata + * rdata_len ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
p2 = get_safe_ptr ( * rdata , * rdata_len , p , usri11_end ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2007-11-13 04:59:18 +03:00
memset ( p , 0 , 21 ) ;
2000-04-19 11:00:22 +04:00
fstrcpy ( p + usri11_name , UserName ) ; /* 21 bytes - user name */
2005-11-05 07:21:55 +03:00
if ( uLevel > 0 ) {
2000-04-19 11:00:22 +04:00
SCVAL ( p , usri11_pad , 0 ) ; /* padding - 1 byte */
* p2 = 0 ;
}
2005-11-05 07:21:55 +03:00
if ( uLevel > = 10 ) {
2000-04-19 11:00:22 +04:00
SIVAL ( p , usri11_comment , PTR_DIFF ( p2 , p ) ) ; /* comment */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , " Comment " , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SIVAL ( p , usri11_usr_comment , PTR_DIFF ( p2 , p ) ) ; /* user_comment */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , " UserComment " , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
/* EEK! the cifsrap.txt doesn't have this in!!!! */
SIVAL ( p , usri11_full_name , PTR_DIFF ( p2 , p ) ) ; /* full name */
2008-04-30 19:42:39 +04:00
strlcpy ( p2 , ( ( vuser ! = NULL )
? pdb_get_fullname ( vuser - > server_info - > sam_account )
: UserName ) , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
}
2005-11-05 07:21:55 +03:00
if ( uLevel = = 11 ) {
2008-04-29 14:47:55 +04:00
const char * homedir = " " ;
if ( vuser ! = NULL ) {
homedir = pdb_get_homedir (
vuser - > server_info - > sam_account ) ;
}
2005-11-05 07:21:55 +03:00
/* modelled after NTAS 3.51 reply */
2010-03-15 22:13:30 +03:00
SSVAL ( p , usri11_priv ,
( get_current_uid ( conn ) = = sec_initial_uid ( ) ) ?
USER_PRIV_ADMIN : USER_PRIV_USER ) ;
2000-04-19 11:00:22 +04:00
SIVAL ( p , usri11_auth_flags , AF_OP_PRINT ) ; /* auth flags */
SIVALS ( p , usri11_password_age , - 1 ) ; /* password age */
SIVAL ( p , usri11_homedir , PTR_DIFF ( p2 , p ) ) ; /* home dir */
2008-04-29 14:47:55 +04:00
strlcpy ( p2 , homedir , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SIVAL ( p , usri11_parms , PTR_DIFF ( p2 , p ) ) ; /* parms */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , " " , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
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 */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , " \\ \\ * " , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SSVAL ( p , usri11_country_code , 0 ) ; /* country code */
SIVAL ( p , usri11_workstations , PTR_DIFF ( p2 , p ) ) ; /* workstations */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , " " , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SIVALS ( p , usri11_max_storage , - 1 ) ; /* max storage */
SSVAL ( p , usri11_units_per_week , 168 ) ; /* units per week */
SIVAL ( p , usri11_logon_hours , PTR_DIFF ( p2 , p ) ) ; /* logon hours */
/* a simple way to get logon hours at all times. */
memset ( p2 , 0xff , 21 ) ;
SCVAL ( p2 , 21 , 0 ) ; /* fix zero termination */
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SSVAL ( p , usri11_code_page , 0 ) ; /* code page */
}
2005-11-05 07:21:55 +03:00
if ( uLevel = = 1 | | uLevel = = 2 ) {
2000-04-19 11:00:22 +04:00
memset ( p + 22 , ' ' , 16 ) ; /* password */
SIVALS ( p , 38 , - 1 ) ; /* password age */
SSVAL ( p , 42 ,
2010-03-15 22:13:30 +03:00
( get_current_uid ( conn ) = = sec_initial_uid ( ) ) ?
USER_PRIV_ADMIN : USER_PRIV_USER ) ;
2000-04-19 11:00:22 +04:00
SIVAL ( p , 44 , PTR_DIFF ( p2 , * rdata ) ) ; /* home dir */
2008-04-29 15:28:40 +04:00
strlcpy ( p2 , vuser ? pdb_get_homedir (
vuser - > server_info - > sam_account ) : " " ,
PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SIVAL ( p , 48 , PTR_DIFF ( p2 , * rdata ) ) ; /* comment */
* p2 + + = 0 ;
SSVAL ( p , 52 , 0 ) ; /* flags */
SIVAL ( p , 54 , PTR_DIFF ( p2 , * rdata ) ) ; /* script_path */
2008-04-29 15:28:40 +04:00
strlcpy ( p2 , vuser ? pdb_get_logon_script (
vuser - > server_info - > sam_account ) : " " ,
PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2005-11-05 07:21:55 +03:00
if ( uLevel = = 2 ) {
2000-04-19 11:00:22 +04:00
SIVAL ( p , 60 , 0 ) ; /* auth_flags */
SIVAL ( p , 64 , PTR_DIFF ( p2 , * rdata ) ) ; /* full_name */
2008-04-30 19:42:39 +04:00
strlcpy ( p2 , ( ( vuser ! = NULL )
? pdb_get_fullname ( vuser - > server_info - > sam_account )
: UserName ) , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SIVAL ( p , 68 , 0 ) ; /* urs_comment */
SIVAL ( p , 72 , PTR_DIFF ( p2 , * rdata ) ) ; /* parms */
2007-12-04 02:19:22 +03:00
strlcpy ( p2 , " " , PTR_DIFF ( endp , p2 ) ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SIVAL ( p , 76 , 0 ) ; /* workstations */
SIVAL ( p , 80 , 0 ) ; /* last_logon */
SIVAL ( p , 84 , 0 ) ; /* last_logoff */
SIVALS ( p , 88 , - 1 ) ; /* acct_expires */
SIVALS ( p , 92 , - 1 ) ; /* max_storage */
SSVAL ( p , 96 , 168 ) ; /* units_per_week */
SIVAL ( p , 98 , PTR_DIFF ( p2 , * rdata ) ) ; /* logon_hours */
memset ( p2 , - 1 , 21 ) ;
p2 + = 21 ;
SSVALS ( p , 102 , - 1 ) ; /* bad_pw_count */
SSVALS ( p , 104 , - 1 ) ; /* num_logons */
SIVAL ( p , 106 , PTR_DIFF ( p2 , * rdata ) ) ; /* logon_server */
2006-07-11 22:01:26 +04:00
{
2007-11-13 04:59:18 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
int space_rem = * rdata_len - ( p2 - * rdata ) ;
char * tmp ;
if ( space_rem < = 0 ) {
return false ;
}
tmp = talloc_strdup ( ctx , " \\ \\ %L " ) ;
if ( ! tmp ) {
return false ;
}
tmp = talloc_sub_basic ( ctx ,
" " ,
" " ,
tmp ) ;
if ( ! tmp ) {
return false ;
}
push_ascii ( p2 ,
tmp ,
space_rem ,
STR_TERMINATE ) ;
2006-07-11 22:01:26 +04:00
}
2007-04-03 00:10:21 +04:00
p2 = skip_string ( * rdata , * rdata_len , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
SSVAL ( p , 110 , 49 ) ; /* country_code */
SSVAL ( p , 112 , 860 ) ; /* code page */
}
}
* rdata_len = PTR_DIFF ( p2 , * rdata ) ;
SSVAL ( * rparam , 4 , * rdata_len ) ; /* is this right?? */
return ( True ) ;
}
2007-10-19 04:40:25 +04:00
static bool api_WWkstaUserLogon ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
2000-04-19 11:00:22 +04:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
2009-05-26 18:38:45 +04:00
struct smbd_server_connection * sconn = smbd_server_conn ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
int uLevel ;
struct pack_desc desc ;
char * name ;
/* With share level security vuid will always be zero.
Don ' t depend on vuser being non - null ! ! . JRA */
2009-05-26 18:38:45 +04:00
user_struct * vuser = get_valid_user_struct ( sconn , vuid ) ;
2006-02-04 01:19:41 +03:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
if ( vuser ! = NULL ) {
2008-04-29 15:43:10 +04:00
DEBUG ( 3 , ( " Username of UID %d is %s \n " ,
2008-06-19 18:54:12 +04:00
( int ) vuser - > server_info - > utok . uid ,
2008-04-30 19:42:39 +04:00
vuser - > server_info - > unix_name ) ) ;
2006-02-04 01:19:41 +03:00
}
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
name = get_safe_str_ptr ( param , tpscnt , p , 2 ) ;
if ( ! name ) {
2007-03-31 02:25:08 +04:00
return False ;
}
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
DEBUG ( 3 , ( " WWkstaUserLogon uLevel=%d name=%s \n " , uLevel , name ) ) ;
/* check it's a supported varient */
if ( strcmp ( str1 , " OOWb54WrLh " ) ! = 0 ) {
return False ;
}
if ( uLevel ! = 1 | | strcmp ( str2 , " WB21BWDWWDDDDDDDzzzD " ) ! = 0 ) {
return False ;
}
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
}
desc . base = * rdata ;
desc . buflen = mdrcnt ;
desc . subformat = NULL ;
desc . format = str2 ;
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( init_package ( & desc , 1 , 0 ) ) {
PACKI ( & desc , " W " , 0 ) ; /* code */
PACKS ( & desc , " B21 " , name ) ; /* eff. name */
PACKS ( & desc , " B " , " " ) ; /* pad */
2010-03-15 22:13:30 +03:00
PACKI ( & desc , " W " ,
( get_current_uid ( conn ) = = sec_initial_uid ( ) ) ?
USER_PRIV_ADMIN : USER_PRIV_USER ) ;
2006-02-04 01:19:41 +03:00
PACKI ( & desc , " D " , 0 ) ; /* auth flags XXX */
PACKI ( & desc , " W " , 0 ) ; /* num logons */
PACKI ( & desc , " W " , 0 ) ; /* bad pw count */
PACKI ( & desc , " D " , 0 ) ; /* last logon */
PACKI ( & desc , " D " , - 1 ) ; /* last logoff */
PACKI ( & desc , " D " , - 1 ) ; /* logoff time */
PACKI ( & desc , " D " , - 1 ) ; /* kickoff time */
PACKI ( & desc , " D " , 0 ) ; /* password age */
PACKI ( & desc , " D " , 0 ) ; /* password can change */
PACKI ( & desc , " D " , - 1 ) ; /* password must change */
{
fstring mypath ;
fstrcpy ( mypath , " \\ \\ " ) ;
fstrcat ( mypath , get_local_machine_name ( ) ) ;
strupper_m ( mypath ) ;
PACKS ( & desc , " z " , mypath ) ; /* computer */
}
PACKS ( & desc , " z " , lp_workgroup ( ) ) ; /* domain */
2008-04-29 15:28:40 +04:00
PACKS ( & desc , " z " , vuser ? pdb_get_logon_script (
vuser - > server_info - > sam_account ) : " " ) ; /* script path */
2006-02-04 01:19:41 +03:00
PACKI ( & desc , " D " , 0x00000000 ) ; /* reserved */
}
* rdata_len = desc . usedlen ;
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , desc . neededlen ) ;
DEBUG ( 4 , ( " WWkstaUserLogon: errorcode %d \n " , desc . errcode ) ) ;
return True ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
2005-08-13 04:13:21 +04:00
api_WAccessGetUserPerms
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_WAccessGetUserPerms ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * user = skip_string ( param , tpscnt , str2 ) ;
char * resource = skip_string ( param , tpscnt , user ) ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! user | | ! resource ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2007-04-03 00:10:21 +04:00
if ( skip_string ( param , tpscnt , resource ) = = NULL ) {
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
return False ;
}
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " WAccessGetUserPerms user=%s resource=%s \n " , user , resource ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
/* check it's a supported varient */
if ( strcmp ( str1 , " zzh " ) ! = 0 ) {
return False ;
}
if ( strcmp ( str2 , " " ) ! = 0 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , 0 ) ; /* errorcode */
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
SSVAL ( * rparam , 4 , 0x7f ) ; /* permission flags */
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
api_WPrintJobEnumerate
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-13 04:13:21 +04:00
2007-10-19 04:40:25 +04:00
static bool api_WPrintJobGetInfo ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
int uLevel ;
fstring sharename ;
uint32 jobid ;
struct pack_desc desc ;
char * tmpdata = NULL ;
2010-04-10 03:44:08 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
WERROR werr ;
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle handle ;
struct spoolss_DevmodeContainer devmode_ctr ;
union spoolss_JobInfo info ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 2 , - 1 ) ;
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
memset ( ( char * ) & status , ' \0 ' , sizeof ( status ) ) ;
DEBUG ( 3 , ( " WPrintJobGetInfo uLevel=%d uJobId=0x%X \n " , uLevel , SVAL ( p , 0 ) ) ) ;
/* check it's a supported varient */
if ( strcmp ( str1 , " WWrLh " ) ! = 0 ) {
return False ;
}
if ( ! check_printjob_info ( & desc , uLevel , str2 ) ) {
return False ;
}
if ( ! rap_to_pjobid ( SVAL ( p , 0 ) , sharename , & jobid ) ) {
return False ;
}
2010-04-10 03:44:08 +04:00
ZERO_STRUCT ( handle ) ;
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_WPrintJobGetInfo: could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
2006-02-04 01:19:41 +03:00
}
2010-04-10 03:44:08 +04:00
ZERO_STRUCT ( devmode_ctr ) ;
status = rpccli_spoolss_OpenPrinter ( cli , mem_ctx ,
sharename ,
NULL ,
devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
}
werr = rpccli_spoolss_getjob ( cli , mem_ctx ,
& handle ,
jobid ,
2 , /* level */
0 , /* offered */
& info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
2006-02-04 01:19:41 +03:00
}
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
desc . base = * rdata ;
desc . buflen = mdrcnt ;
} else {
/*
* Don ' t return data but need to get correct length
* init_package will return wrong size if buflen = 0
*/
desc . buflen = getlen ( desc . format ) ;
desc . base = tmpdata = ( char * ) SMB_MALLOC ( desc . buflen ) ;
}
if ( init_package ( & desc , 1 , 0 ) ) {
2010-04-10 03:44:08 +04:00
fill_spoolss_printjob_info ( uLevel , & desc , & info . info2 , info . info2 . position ) ;
* rdata_len = desc . usedlen ;
} else {
desc . errcode = NERR_JobNotFound ;
* rdata_len = 0 ;
}
out :
if ( is_valid_policy_hnd ( & handle ) ) {
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & handle , NULL ) ;
2006-02-04 01:19:41 +03:00
}
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , desc . neededlen ) ;
SAFE_FREE ( tmpdata ) ;
DEBUG ( 4 , ( " WPrintJobGetInfo: errorcode %d \n " , desc . errcode ) ) ;
return True ;
}
2007-10-19 04:40:25 +04:00
static bool api_WPrintJobEnumerate ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2007-03-31 02:25:08 +04:00
char * name = p ;
2006-02-04 01:19:41 +03:00
int uLevel ;
int i , succnt = 0 ;
struct pack_desc desc ;
2010-04-10 03:33:37 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
WERROR werr ;
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle handle ;
struct spoolss_DevmodeContainer devmode_ctr ;
uint32_t count ;
union spoolss_JobInfo * info ;
2006-02-04 01:19:41 +03:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
2007-04-03 00:10:21 +04:00
p = skip_string ( param , tpscnt , p ) ;
2007-03-31 02:25:08 +04:00
if ( ! p ) {
return False ;
}
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " WPrintJobEnumerate uLevel=%d name=%s \n " , uLevel , name ) ) ;
/* check it's a supported variant */
if ( strcmp ( str1 , " zWrLeh " ) ! = 0 ) {
return False ;
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( uLevel > 2 ) {
return False ; /* defined only for uLevel 0,1,2 */
}
2009-01-31 18:57:46 +03:00
2006-02-04 01:19:41 +03:00
if ( ! check_printjob_info ( & desc , uLevel , str2 ) ) {
return False ;
}
2010-04-10 03:33:37 +04:00
ZERO_STRUCT ( handle ) ;
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-04-28 03:10:49 +04:00
DEBUG ( 0 , ( " api_WPrintJobEnumerate: could not connect to spoolss: %s \n " ,
2010-04-10 03:33:37 +04:00
nt_errstr ( status ) ) ) ;
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
ZERO_STRUCT ( devmode_ctr ) ;
status = rpccli_spoolss_OpenPrinter ( cli , mem_ctx ,
name ,
NULL ,
devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
}
werr = rpccli_spoolss_enumjobs ( cli , mem_ctx ,
& handle ,
0 , /* firstjob */
0xff , /* numjobs */
2 , /* level */
0 , /* offered */
& count ,
& info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
goto out ;
2006-02-04 01:19:41 +03:00
}
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
}
desc . base = * rdata ;
desc . buflen = mdrcnt ;
if ( init_package ( & desc , count , 0 ) ) {
succnt = 0 ;
for ( i = 0 ; i < count ; i + + ) {
2010-04-10 03:33:37 +04:00
fill_spoolss_printjob_info ( uLevel , & desc , & info [ i ] . info2 , i ) ;
2006-02-04 01:19:41 +03:00
if ( desc . errcode = = NERR_Success ) {
succnt = i + 1 ;
}
}
}
2010-04-10 03:33:37 +04:00
out :
if ( is_valid_policy_hnd ( & handle ) ) {
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & handle , NULL ) ;
}
2006-02-04 01:19:41 +03:00
* rdata_len = desc . usedlen ;
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , succnt ) ;
SSVAL ( * rparam , 6 , count ) ;
DEBUG ( 4 , ( " WPrintJobEnumerate: errorcode %d \n " , desc . errcode ) ) ;
return True ;
2000-04-19 11:00:22 +04:00
}
static int check_printdest_info ( struct pack_desc * desc ,
int uLevel , char * id )
{
2006-02-04 01:19:41 +03:00
desc - > subformat = NULL ;
switch ( uLevel ) {
case 0 :
desc - > format = " B9 " ;
break ;
case 1 :
desc - > format = " B9B21WWzW " ;
break ;
case 2 :
desc - > format = " z " ;
break ;
case 3 :
desc - > format = " zzzWWzzzWW " ;
break ;
default :
2007-04-04 04:03:12 +04:00
DEBUG ( 0 , ( " check_printdest_info: invalid level %d \n " ,
uLevel ) ) ;
2006-02-04 01:19:41 +03:00
return False ;
}
2007-04-04 04:03:12 +04:00
if ( id = = NULL | | strcmp ( desc - > format , id ) ! = 0 ) {
DEBUG ( 0 , ( " check_printdest_info: invalid string %s \n " ,
id ? id : " <NULL> " ) ) ;
2006-02-04 01:19:41 +03:00
return False ;
}
return True ;
2000-04-19 11:00:22 +04:00
}
2010-04-28 03:11:19 +04:00
static void fill_printdest_info ( struct spoolss_PrinterInfo2 * info2 , int uLevel ,
2000-04-19 11:00:22 +04:00
struct pack_desc * desc )
{
2006-02-04 01:19:41 +03:00
char buf [ 100 ] ;
2010-04-28 03:11:19 +04:00
strncpy ( buf , info2 - > printername , sizeof ( buf ) - 1 ) ;
2006-02-04 01:19:41 +03:00
buf [ sizeof ( buf ) - 1 ] = 0 ;
strupper_m ( buf ) ;
if ( uLevel < = 1 ) {
PACKS ( desc , " B9 " , buf ) ; /* szName */
if ( uLevel = = 1 ) {
PACKS ( desc , " B21 " , " " ) ; /* szUserName */
PACKI ( desc , " W " , 0 ) ; /* uJobId */
PACKI ( desc , " W " , 0 ) ; /* fsStatus */
PACKS ( desc , " z " , " " ) ; /* pszStatus */
PACKI ( desc , " W " , 0 ) ; /* time */
}
}
if ( uLevel = = 2 | | uLevel = = 3 ) {
PACKS ( desc , " z " , buf ) ; /* pszPrinterName */
if ( uLevel = = 3 ) {
PACKS ( desc , " z " , " " ) ; /* pszUserName */
PACKS ( desc , " z " , " " ) ; /* pszLogAddr */
PACKI ( desc , " W " , 0 ) ; /* uJobId */
PACKI ( desc , " W " , 0 ) ; /* fsStatus */
PACKS ( desc , " z " , " " ) ; /* pszStatus */
PACKS ( desc , " z " , " " ) ; /* pszComment */
PACKS ( desc , " z " , " NULL " ) ; /* pszDrivers */
PACKI ( desc , " W " , 0 ) ; /* time */
PACKI ( desc , " W " , 0 ) ; /* pad1 */
}
}
2000-04-19 11:00:22 +04:00
}
2007-10-19 04:40:25 +04:00
static bool api_WPrintDestGetInfo ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
char * PrinterName = p ;
int uLevel ;
struct pack_desc desc ;
char * tmpdata = NULL ;
2010-04-28 03:11:19 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
WERROR werr ;
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
struct policy_handle handle ;
struct spoolss_DevmodeContainer devmode_ctr ;
union spoolss_PrinterInfo info ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
2007-04-03 00:10:21 +04:00
p = skip_string ( param , tpscnt , p ) ;
2007-03-31 02:25:08 +04:00
if ( ! p ) {
return False ;
}
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " WPrintDestGetInfo uLevel=%d PrinterName=%s \n " , uLevel , PrinterName ) ) ;
/* check it's a supported varient */
if ( strcmp ( str1 , " zWrLh " ) ! = 0 ) {
return False ;
}
if ( ! check_printdest_info ( & desc , uLevel , str2 ) ) {
return False ;
}
2010-04-28 03:11:19 +04:00
ZERO_STRUCT ( handle ) ;
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_WPrintDestGetInfo: could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
}
ZERO_STRUCT ( devmode_ctr ) ;
status = rpccli_spoolss_OpenPrinter ( cli , mem_ctx ,
PrinterName ,
NULL ,
devmode_ctr ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& handle ,
& werr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
* rdata_len = 0 ;
desc . errcode = NERR_DestNotFound ;
desc . neededlen = 0 ;
goto out ;
}
if ( ! W_ERROR_IS_OK ( werr ) ) {
* rdata_len = 0 ;
desc . errcode = NERR_DestNotFound ;
desc . neededlen = 0 ;
goto out ;
}
werr = rpccli_spoolss_getprinter ( cli , mem_ctx ,
& handle ,
2 ,
0 ,
& info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
2006-02-04 01:19:41 +03:00
* rdata_len = 0 ;
desc . errcode = NERR_DestNotFound ;
desc . neededlen = 0 ;
2010-04-28 03:11:19 +04:00
goto out ;
}
if ( mdrcnt > 0 ) {
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
if ( ! * rdata ) {
return False ;
2006-02-04 01:19:41 +03:00
}
2010-04-28 03:11:19 +04:00
desc . base = * rdata ;
desc . buflen = mdrcnt ;
} else {
/*
* Don ' t return data but need to get correct length
* init_package will return wrong size if buflen = 0
*/
desc . buflen = getlen ( desc . format ) ;
desc . base = tmpdata = ( char * ) SMB_MALLOC ( desc . buflen ) ;
}
if ( init_package ( & desc , 1 , 0 ) ) {
fill_printdest_info ( & info . info2 , uLevel , & desc ) ;
2006-02-04 01:19:41 +03:00
}
2010-04-28 03:11:19 +04:00
out :
if ( is_valid_policy_hnd ( & handle ) ) {
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & handle , NULL ) ;
}
* rdata_len = desc . usedlen ;
2006-02-04 01:19:41 +03:00
* rparam_len = 6 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , desc . neededlen ) ;
DEBUG ( 4 , ( " WPrintDestGetInfo: errorcode %d \n " , desc . errcode ) ) ;
SAFE_FREE ( tmpdata ) ;
return True ;
2000-04-19 11:00:22 +04:00
}
2007-10-19 04:40:25 +04:00
static bool api_WPrintDestEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
int uLevel ;
int queuecnt ;
int i , n , succnt = 0 ;
struct pack_desc desc ;
2010-04-28 03:11:19 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
WERROR werr ;
NTSTATUS status ;
struct rpc_pipe_client * cli = NULL ;
union spoolss_PrinterInfo * info ;
uint32_t count ;
2006-02-04 01:19:41 +03:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " WPrintDestEnum uLevel=%d \n " , uLevel ) ) ;
/* check it's a supported varient */
if ( strcmp ( str1 , " WrLeh " ) ! = 0 ) {
return False ;
}
if ( ! check_printdest_info ( & desc , uLevel , str2 ) ) {
return False ;
}
queuecnt = 0 ;
2010-04-28 03:11:19 +04:00
status = rpc_pipe_open_internal ( mem_ctx , & ndr_table_spoolss . syntax_id ,
rpc_spoolss_dispatch , conn - > server_info ,
& cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " api_WPrintDestEnum: could not connect to spoolss: %s \n " ,
nt_errstr ( status ) ) ) ;
desc . errcode = W_ERROR_V ( ntstatus_to_werror ( status ) ) ;
goto out ;
2006-02-04 01:19:41 +03:00
}
2010-04-28 03:11:19 +04:00
werr = rpccli_spoolss_enumprinters ( cli , mem_ctx ,
PRINTER_ENUM_LOCAL ,
cli - > srv_name_slash ,
2 ,
0 ,
& count ,
& info ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
desc . errcode = W_ERROR_V ( werr ) ;
* rdata_len = 0 ;
desc . errcode = NERR_DestNotFound ;
desc . neededlen = 0 ;
goto out ;
}
queuecnt = count ;
2006-02-04 01:19:41 +03:00
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
}
desc . base = * rdata ;
desc . buflen = mdrcnt ;
if ( init_package ( & desc , queuecnt , 0 ) ) {
succnt = 0 ;
n = 0 ;
2010-04-28 03:11:19 +04:00
for ( i = 0 ; i < count ; i + + ) {
fill_printdest_info ( & info [ i ] . info2 , uLevel , & desc ) ;
n + + ;
if ( desc . errcode = = NERR_Success ) {
succnt = n ;
2006-02-04 01:19:41 +03:00
}
}
}
2010-04-28 03:11:19 +04:00
out :
2006-02-04 01:19:41 +03:00
* rdata_len = desc . usedlen ;
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , succnt ) ;
SSVAL ( * rparam , 6 , queuecnt ) ;
DEBUG ( 4 , ( " WPrintDestEnumerate: errorcode %d \n " , desc . errcode ) ) ;
return True ;
2000-04-19 11:00:22 +04:00
}
2007-10-19 04:40:25 +04:00
static bool api_WPrintDriverEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
int uLevel ;
int succnt ;
struct pack_desc desc ;
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
2000-04-19 11:00:22 +04:00
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " WPrintDriverEnum uLevel=%d \n " , uLevel ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
/* check it's a supported varient */
if ( strcmp ( str1 , " WrLeh " ) ! = 0 ) {
return False ;
}
if ( uLevel ! = 0 | | strcmp ( str2 , " B41 " ) ! = 0 ) {
return False ;
}
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
}
desc . base = * rdata ;
desc . buflen = mdrcnt ;
if ( init_package ( & desc , 1 , 0 ) ) {
PACKS ( & desc , " B41 " , " NULL " ) ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
succnt = ( desc . errcode = = NERR_Success ? 1 : 0 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rdata_len = desc . usedlen ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , succnt ) ;
SSVAL ( * rparam , 6 , 1 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 4 , ( " WPrintDriverEnum: errorcode %d \n " , desc . errcode ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
2007-10-19 04:40:25 +04:00
static bool api_WPrintQProcEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
2000-04-19 11:00:22 +04:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
int uLevel ;
int succnt ;
struct pack_desc desc ;
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
2000-04-19 11:00:22 +04:00
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " WPrintQProcEnum uLevel=%d \n " , uLevel ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
/* check it's a supported varient */
if ( strcmp ( str1 , " WrLeh " ) ! = 0 ) {
return False ;
}
if ( uLevel ! = 0 | | strcmp ( str2 , " B13 " ) ! = 0 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
}
desc . base = * rdata ;
desc . buflen = mdrcnt ;
desc . format = str2 ;
if ( init_package ( & desc , 1 , 0 ) ) {
PACKS ( & desc , " B13 " , " lpd " ) ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
succnt = ( desc . errcode = = NERR_Success ? 1 : 0 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rdata_len = desc . usedlen ;
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , succnt ) ;
SSVAL ( * rparam , 6 , 1 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 4 , ( " WPrintQProcEnum: errorcode %d \n " , desc . errcode ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
2007-10-19 04:40:25 +04:00
static bool api_WPrintPortEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
int uLevel ;
int succnt ;
struct pack_desc desc ;
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
2000-04-19 11:00:22 +04:00
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " WPrintPortEnum uLevel=%d \n " , uLevel ) ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
/* check it's a supported varient */
if ( strcmp ( str1 , " WrLeh " ) ! = 0 ) {
return False ;
}
if ( uLevel ! = 0 | | strcmp ( str2 , " B9 " ) ! = 0 ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
}
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
desc . base = * rdata ;
desc . buflen = mdrcnt ;
desc . format = str2 ;
if ( init_package ( & desc , 1 , 0 ) ) {
PACKS ( & desc , " B13 " , " lp0 " ) ;
}
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
succnt = ( desc . errcode = = NERR_Success ? 1 : 0 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rdata_len = desc . usedlen ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ;
SSVAL ( * rparam , 4 , succnt ) ;
SSVAL ( * rparam , 6 , 1 ) ;
2000-04-19 11:00:22 +04:00
2006-02-04 01:19:41 +03:00
DEBUG ( 4 , ( " WPrintPortEnum: errorcode %d \n " , desc . errcode ) ) ;
return True ;
2000-04-19 11:00:22 +04:00
}
2001-10-22 22:14:42 +04:00
/****************************************************************************
List open sessions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-31 02:25:08 +04:00
2007-10-19 04:40:25 +04:00
static bool api_RNetSessionEnum ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2001-10-22 22:14:42 +04:00
{
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
char * str1 = get_safe_str_ptr ( param , tpscnt , param , 2 ) ;
2007-04-03 00:10:21 +04:00
char * str2 = skip_string ( param , tpscnt , str1 ) ;
char * p = skip_string ( param , tpscnt , str2 ) ;
2006-02-04 01:19:41 +03:00
int uLevel ;
struct pack_desc desc ;
struct sessionid * session_list ;
int i , num_sessions ;
2007-03-31 02:25:08 +04:00
if ( ! str1 | | ! str2 | | ! p ) {
return False ;
}
2006-02-04 01:19:41 +03:00
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
r22042: Try and clean up my own mess using the API Volker
suggested. I now use :
BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
Volker, please criticize and comment. Thanks,
Jeremy.
(This used to be commit d47af7c9263f519e7307859b6a696d854c5dfca3)
2007-04-02 23:04:57 +04:00
uLevel = get_safe_SVAL ( param , tpscnt , p , 0 , - 1 ) ;
2006-02-04 01:19:41 +03:00
DEBUG ( 3 , ( " RNetSessionEnum uLevel=%d \n " , uLevel ) ) ;
DEBUG ( 7 , ( " RNetSessionEnum req string=%s \n " , str1 ) ) ;
DEBUG ( 7 , ( " RNetSessionEnum ret string=%s \n " , str2 ) ) ;
/* check it's a supported varient */
if ( strcmp ( str1 , RAP_NetSessionEnum_REQ ) ! = 0 ) {
return False ;
}
if ( uLevel ! = 2 | | strcmp ( str2 , RAP_SESSION_INFO_L2 ) ! = 0 ) {
return False ;
}
2007-08-30 23:48:31 +04:00
num_sessions = list_sessions ( talloc_tos ( ) , & session_list ) ;
2006-02-04 01:19:41 +03:00
if ( mdrcnt > 0 ) {
2007-09-11 23:27:34 +04:00
* rdata = smb_realloc_limit ( * rdata , mdrcnt ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rdata ) {
return False ;
}
2006-02-04 01:19:41 +03:00
}
memset ( ( char * ) & desc , ' \0 ' , sizeof ( desc ) ) ;
desc . base = * rdata ;
desc . buflen = mdrcnt ;
desc . format = str2 ;
if ( ! init_package ( & desc , num_sessions , 0 ) ) {
return False ;
}
for ( i = 0 ; i < num_sessions ; i + + ) {
PACKS ( & desc , " z " , session_list [ i ] . remote_machine ) ;
PACKS ( & desc , " z " , session_list [ i ] . username ) ;
PACKI ( & desc , " W " , 1 ) ; /* num conns */
PACKI ( & desc , " W " , 0 ) ; /* num opens */
PACKI ( & desc , " W " , 1 ) ; /* num users */
PACKI ( & desc , " D " , 0 ) ; /* session time */
PACKI ( & desc , " D " , 0 ) ; /* idle time */
PACKI ( & desc , " D " , 0 ) ; /* flags */
PACKS ( & desc , " z " , " Unknown Client " ) ; /* client type string */
}
* rdata_len = desc . usedlen ;
* rparam_len = 8 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2006-02-04 01:19:41 +03:00
SSVALS ( * rparam , 0 , desc . errcode ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter */
SSVAL ( * rparam , 4 , num_sessions ) ; /* count */
DEBUG ( 4 , ( " RNetSessionEnum: errorcode %d \n " , desc . errcode ) ) ;
return True ;
2001-10-22 22:14:42 +04:00
}
2000-04-19 11:00:22 +04:00
/****************************************************************************
2005-11-05 07:21:55 +03:00
The buffer was too small .
2000-04-19 11:00:22 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_TooSmall ( connection_struct * conn , uint16 vuid , char * param , char * data ,
2005-11-05 07:21:55 +03:00
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
2005-11-05 07:21:55 +03:00
* rparam_len = MIN ( * rparam_len , mprcnt ) ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
* rdata_len = 0 ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
SSVAL ( * rparam , 0 , NERR_BufTooSmall ) ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
DEBUG ( 3 , ( " Supplied buffer too small in API command \n " ) ) ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
/****************************************************************************
2005-11-05 07:21:55 +03:00
The request is not supported .
2000-04-19 11:00:22 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool api_Unsupported ( connection_struct * conn , uint16 vuid ,
2007-03-31 02:25:08 +04:00
char * param , int tpscnt ,
char * data , int tdscnt ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
2000-04-19 11:00:22 +04:00
{
2005-11-05 07:21:55 +03:00
* rparam_len = 4 ;
2007-09-11 23:27:34 +04:00
* rparam = smb_realloc_limit ( * rparam , * rparam_len ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( ! * rparam ) {
return False ;
}
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
* rdata_len = 0 ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
SSVAL ( * rparam , 0 , NERR_notsupported ) ;
SSVAL ( * rparam , 2 , 0 ) ; /* converter word */
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
DEBUG ( 3 , ( " Unsupported API command \n " ) ) ;
2000-04-19 11:00:22 +04:00
2005-11-05 07:21:55 +03:00
return True ;
2000-04-19 11:00:22 +04:00
}
2005-08-13 04:13:21 +04:00
static const struct {
const char * name ;
int id ;
2007-10-19 04:40:25 +04:00
bool ( * fn ) ( connection_struct * , uint16 ,
2007-03-31 02:25:08 +04:00
char * , int ,
char * , int ,
2005-08-13 04:13:21 +04:00
int , int , char * * , char * * , int * , int * ) ;
2007-10-19 04:40:25 +04:00
bool auth_user ; /* Deny anonymous access? */
2000-04-19 11:00:22 +04:00
} api_commands [ ] = {
2005-08-13 04:13:21 +04:00
{ " RNetShareEnum " , RAP_WshareEnum , api_RNetShareEnum , True } ,
{ " RNetShareGetInfo " , RAP_WshareGetInfo , api_RNetShareGetInfo } ,
{ " RNetShareAdd " , RAP_WshareAdd , api_RNetShareAdd } ,
{ " RNetSessionEnum " , RAP_WsessionEnum , api_RNetSessionEnum , True } ,
{ " RNetServerGetInfo " , RAP_WserverGetInfo , api_RNetServerGetInfo } ,
{ " RNetGroupEnum " , RAP_WGroupEnum , api_RNetGroupEnum , True } ,
{ " RNetGroupGetUsers " , RAP_WGroupGetUsers , api_RNetGroupGetUsers , True } ,
{ " RNetUserEnum " , RAP_WUserEnum , api_RNetUserEnum , True } ,
{ " RNetUserGetInfo " , RAP_WUserGetInfo , api_RNetUserGetInfo } ,
{ " NetUserGetGroups " , RAP_WUserGetGroups , api_NetUserGetGroups } ,
{ " NetWkstaGetInfo " , RAP_WWkstaGetInfo , api_NetWkstaGetInfo } ,
{ " DosPrintQEnum " , RAP_WPrintQEnum , api_DosPrintQEnum , True } ,
{ " DosPrintQGetInfo " , RAP_WPrintQGetInfo , api_DosPrintQGetInfo } ,
{ " WPrintQueuePause " , RAP_WPrintQPause , api_WPrintQueueCtrl } ,
{ " WPrintQueueResume " , RAP_WPrintQContinue , api_WPrintQueueCtrl } ,
{ " WPrintJobEnumerate " , RAP_WPrintJobEnum , api_WPrintJobEnumerate } ,
{ " WPrintJobGetInfo " , RAP_WPrintJobGetInfo , api_WPrintJobGetInfo } ,
{ " RDosPrintJobDel " , RAP_WPrintJobDel , api_RDosPrintJobDel } ,
{ " RDosPrintJobPause " , RAP_WPrintJobPause , api_RDosPrintJobDel } ,
{ " RDosPrintJobResume " , RAP_WPrintJobContinue , api_RDosPrintJobDel } ,
{ " WPrintDestEnum " , RAP_WPrintDestEnum , api_WPrintDestEnum } ,
{ " WPrintDestGetInfo " , RAP_WPrintDestGetInfo , api_WPrintDestGetInfo } ,
{ " NetRemoteTOD " , RAP_NetRemoteTOD , api_NetRemoteTOD } ,
{ " WPrintQueuePurge " , RAP_WPrintQPurge , api_WPrintQueueCtrl } ,
2010-02-05 18:55:15 +03:00
{ " NetServerEnum2 " , RAP_NetServerEnum2 , api_RNetServerEnum2 } , /* anon OK */
2010-02-05 20:08:46 +03:00
{ " NetServerEnum3 " , RAP_NetServerEnum3 , api_RNetServerEnum3 } , /* anon OK */
2005-08-13 04:13:21 +04:00
{ " WAccessGetUserPerms " , RAP_WAccessGetUserPerms , api_WAccessGetUserPerms } ,
{ " SetUserPassword " , RAP_WUserPasswordSet2 , api_SetUserPassword } ,
{ " WWkstaUserLogon " , RAP_WWkstaUserLogon , api_WWkstaUserLogon } ,
{ " PrintJobInfo " , RAP_WPrintJobSetInfo , api_PrintJobInfo } ,
{ " WPrintDriverEnum " , RAP_WPrintDriverEnum , api_WPrintDriverEnum } ,
{ " WPrintQProcEnum " , RAP_WPrintQProcessorEnum , api_WPrintQProcEnum } ,
{ " WPrintPortEnum " , RAP_WPrintPortEnum , api_WPrintPortEnum } ,
{ " SamOEMChangePassword " , RAP_SamOEMChgPasswordUser2_P , api_SamOEMChangePassword } , /* anon OK */
{ NULL , - 1 , api_Unsupported }
/* The following RAP calls are not implemented by Samba:
RAP_WFileEnum2 - anon not OK
*/
} ;
2000-04-19 11:00:22 +04:00
/****************************************************************************
2007-04-20 02:40:32 +04:00
Handle remote api calls .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-19 11:00:22 +04:00
2007-08-05 15:19:24 +04:00
void api_reply ( connection_struct * conn , uint16 vuid ,
struct smb_request * req ,
char * data , char * params ,
int tdscnt , int tpscnt ,
int mdrcnt , int mprcnt )
2000-04-19 11:00:22 +04:00
{
2009-05-26 18:38:45 +04:00
struct smbd_server_connection * sconn = smbd_server_conn ;
2005-08-13 03:49:57 +04:00
int api_command ;
char * rdata = NULL ;
char * rparam = NULL ;
2007-03-31 02:25:08 +04:00
const char * name1 = NULL ;
const char * name2 = NULL ;
2005-08-13 03:49:57 +04:00
int rdata_len = 0 ;
int rparam_len = 0 ;
2007-10-19 04:40:25 +04:00
bool reply = False ;
2005-08-13 03:49:57 +04:00
int i ;
2000-04-19 11:00:22 +04:00
2005-08-13 03:49:57 +04:00
if ( ! params ) {
DEBUG ( 0 , ( " ERROR: NULL params in api_reply() \n " ) ) ;
2007-08-05 15:19:24 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2005-08-13 03:49:57 +04:00
}
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
if ( tpscnt < 2 ) {
2007-08-05 15:19:24 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2007-03-31 02:25:08 +04:00
}
2005-08-13 03:49:57 +04:00
api_command = SVAL ( params , 0 ) ;
2007-03-31 02:25:08 +04:00
/* Is there a string at position params+2 ? */
2007-04-03 00:10:21 +04:00
if ( skip_string ( params , tpscnt , params + 2 ) ) {
2007-03-31 02:25:08 +04:00
name1 = params + 2 ;
} else {
name1 = " " ;
}
2007-04-03 00:10:21 +04:00
name2 = skip_string ( params , tpscnt , params + 2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! name2 ) {
name2 = " " ;
}
2000-04-19 11:00:22 +04:00
2005-08-13 03:49:57 +04:00
DEBUG ( 3 , ( " Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d) \n " ,
api_command ,
2007-03-31 02:25:08 +04:00
name1 ,
name2 ,
2005-08-13 03:49:57 +04:00
tdscnt , tpscnt , mdrcnt , mprcnt ) ) ;
2000-04-19 11:00:22 +04:00
2005-08-13 03:49:57 +04:00
for ( i = 0 ; api_commands [ i ] . name ; i + + ) {
if ( api_commands [ i ] . id = = api_command & & api_commands [ i ] . fn ) {
DEBUG ( 3 , ( " Doing %s \n " , api_commands [ i ] . name ) ) ;
break ;
}
}
2000-04-19 11:00:22 +04:00
2005-08-13 03:49:57 +04:00
/* Check whether this api call can be done anonymously */
2002-07-15 14:35:28 +04:00
2005-08-13 03:49:57 +04:00
if ( api_commands [ i ] . auth_user & & lp_restrict_anonymous ( ) ) {
2009-05-26 18:38:45 +04:00
user_struct * user = get_valid_user_struct ( sconn , vuid ) ;
2002-07-15 14:35:28 +04:00
2008-04-29 15:45:58 +04:00
if ( ! user | | user - > server_info - > guest ) {
2007-08-05 15:19:24 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
return ;
2005-08-13 03:49:57 +04:00
}
}
2002-07-15 14:35:28 +04:00
2005-08-13 03:49:57 +04:00
rdata = ( char * ) SMB_MALLOC ( 1024 ) ;
if ( rdata ) {
memset ( rdata , ' \0 ' , 1024 ) ;
}
2000-04-19 11:00:22 +04:00
2005-08-13 03:49:57 +04:00
rparam = ( char * ) SMB_MALLOC ( 1024 ) ;
if ( rparam ) {
memset ( rparam , ' \0 ' , 1024 ) ;
}
2000-04-19 11:00:22 +04:00
2005-08-13 03:49:57 +04:00
if ( ! rdata | | ! rparam ) {
DEBUG ( 0 , ( " api_reply: malloc fail ! \n " ) ) ;
SAFE_FREE ( rdata ) ;
SAFE_FREE ( rparam ) ;
2007-08-05 15:19:24 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
2005-08-13 03:49:57 +04:00
}
2000-04-19 11:00:22 +04:00
2007-03-31 02:25:08 +04:00
reply = api_commands [ i ] . fn ( conn ,
vuid ,
params , tpscnt , /* params + length */
data , tdscnt , /* data + length */
mdrcnt , mprcnt ,
2005-08-13 03:49:57 +04:00
& rdata , & rparam , & rdata_len , & rparam_len ) ;
2000-04-19 11:00:22 +04:00
2005-08-13 04:13:21 +04:00
if ( rdata_len > mdrcnt | | rparam_len > mprcnt ) {
2005-08-13 03:49:57 +04:00
reply = api_TooSmall ( conn , vuid , params , data , mdrcnt , mprcnt ,
& rdata , & rparam , & rdata_len , & rparam_len ) ;
}
2000-04-19 11:00:22 +04:00
2005-08-13 03:49:57 +04:00
/* if we get False back then it's actually unsupported */
if ( ! reply ) {
2007-03-31 02:25:08 +04:00
reply = api_Unsupported ( conn , vuid , params , tpscnt , data , tdscnt , mdrcnt , mprcnt ,
2005-08-13 03:49:57 +04:00
& rdata , & rparam , & rdata_len , & rparam_len ) ;
}
2000-04-19 11:00:22 +04:00
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
/* If api_Unsupported returns false we can't return anything. */
if ( reply ) {
2008-11-02 23:24:28 +03:00
send_trans_reply ( conn , req , rparam , rparam_len ,
2007-08-05 15:34:57 +04:00
rdata , rdata_len , False ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
}
2000-04-19 11:00:22 +04:00
2005-08-13 03:49:57 +04:00
SAFE_FREE ( rdata ) ;
SAFE_FREE ( rparam ) ;
2007-08-05 15:19:24 +04:00
return ;
2000-04-19 11:00:22 +04:00
}