From 3e074dcd9664edc32d1d4947179ce90d5c4ae801 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 5 Sep 1997 19:44:48 +0000 Subject: Updated code on 1.9.17 branch to add bug fixes. This is *NOT* the same branch as the main (ie. 1.9.18) branch. Jeremy (jallison@whistle.com) --- source/lib/util.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'source/lib/util.c') diff --git a/source/lib/util.c b/source/lib/util.c index d78ecf2728a..7f922def7e3 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -68,6 +68,7 @@ BOOL case_mangle; fstring remote_machine=""; fstring local_machine=""; fstring remote_arch="UNKNOWN"; +static enum remote_arch_types ra_type = RA_UNKNOWN; fstring remote_proto="UNKNOWN"; pstring myhostname=""; pstring user_socket_options=""; @@ -91,7 +92,11 @@ void setup_logging(char *pname,BOOL interactive) if (!interactive) { char *p = strrchr(pname,'/'); if (p) pname = p+1; +#ifdef LOG_DAEMON openlog(pname, LOG_PID, LOG_DAEMON); +#else /* LOG_DAEMON - for old systems that have no facility codes. */ + openlog(pname, LOG_PID); +#endif /* LOG_DAEMON */ } #endif if (interactive) { @@ -3301,13 +3306,13 @@ sub strings with useful parameters Rewritten by Stefaan A Eeckels and Paul Rippin ********************************************************************/ -void standard_sub_basic(char *string) +void standard_sub_basic(char *str) { char *s, *p; char pidstr[10]; struct passwd *pass; - for (s = string ; (p = strchr(s,'%')) != NULL ; s = p ) + for (s = str ; (p = strchr(s,'%')) != NULL ; s = p ) { switch (*(p+1)) { @@ -3864,3 +3869,41 @@ BOOL is_myname(const char *s) DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret)); return(ret); } + +/******************************************************************* +set the horrid remote_arch string based on an enum. +********************************************************************/ +void set_remote_arch(enum remote_arch_types type) +{ + ra_type = type; + switch( type ) + { + case RA_WFWG: + strcpy(remote_arch, "WfWg"); + return; + case RA_OS2: + strcpy(remote_arch, "OS2"); + return; + case RA_WIN95: + strcpy(remote_arch, "Win95"); + return; + case RA_WINNT: + strcpy(remote_arch, "WinNT"); + return; + case RA_SAMBA: + strcpy(remote_arch,"Samba"); + return; + default: + ra_type = RA_UNKNOWN; + strcpy(remote_arch, "UNKNOWN"); + break; + } +} + +/******************************************************************* + Get the remote_arch type. +********************************************************************/ +enum remote_arch_types get_remote_arch() +{ + return ra_type; +} -- cgit From e8dd34b0d3ba704deff696c1683297536a494893 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 26 Sep 1997 12:39:45 +0000 Subject: This commit fixes the security hole due to buffer overflows. The main fix is just a couple of lines long, but I have now also put precautionary checks on a large number of other places in the code where unchecked string copies were being performed. An exploit via one of these copies is unlikely, but is is better to be safe. I also added a routine to log possible exploit attempts using the code that was posted for obtaining root access on a Samba server. --- source/lib/util.c | 114 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 29 deletions(-) (limited to 'source/lib/util.c') diff --git a/source/lib/util.c b/source/lib/util.c index 7f922def7e3..0c4999c789c 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -1079,7 +1079,7 @@ void unix_format(char *fname) if (*fname == '/') { - strcpy(namecopy,fname); + pstrcpy(namecopy,fname); strcpy(fname,"."); strcat(fname,namecopy); } @@ -1290,7 +1290,7 @@ void dos_clean_name(char *s) pstring s1; *p = 0; - strcpy(s1,p+3); + pstrcpy(s1,p+3); if ((p=strrchr(s,'\\')) != NULL) *p = 0; @@ -1328,7 +1328,7 @@ void unix_clean_name(char *s) pstring s1; *p = 0; - strcpy(s1,p+3); + pstrcpy(s1,p+3); if ((p=strrchr(s,'/')) != NULL) *p = 0; @@ -1355,7 +1355,7 @@ int ChDir(char *path) DEBUG(3,("chdir to %s\n",path)); res = sys_chdir(path); if (!res) - strcpy(LastDir,path); + pstrcpy(LastDir,path); return(res); } @@ -1515,7 +1515,7 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks) /* remove any double slashes */ string_sub(s,"//","/"); - strcpy(basename,s); + pstrcpy(basename,s); p = strrchr(basename,'/'); if (!p) @@ -1585,12 +1585,12 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks) if (relative) { if (newname[l] == '/') - strcpy(s,newname + l + 1); + pstrcpy(s,newname + l + 1); else - strcpy(s,newname+l); + pstrcpy(s,newname+l); } else - strcpy(s,newname); + pstrcpy(s,newname); } ChDir(wd); @@ -1614,10 +1614,10 @@ static void expand_one(char *Mask,int len) int lfill = (len+1) - strlen(Mask); int l1= (p1 - Mask); pstring tmp; - strcpy(tmp,Mask); + pstrcpy(tmp,Mask); memset(tmp+l1,'?',lfill); - strcpy(tmp + l1 + lfill,Mask + l1 + 1); - strcpy(Mask,tmp); + pstrcpy(tmp + l1 + lfill,Mask + l1 + 1); + pstrcpy(Mask,tmp); } } @@ -1641,20 +1641,20 @@ void expand_mask(char *Mask,BOOL doext) filename_dos(Mask,filepart); - strcpy(mbeg,filepart); + pstrcpy(mbeg,filepart); if ((p1 = strchr(mbeg,'.')) != NULL) { hasdot = True; *p1 = 0; p1++; - strcpy(mext,p1); + pstrcpy(mext,p1); } else { strcpy(mext,""); if (strlen(mbeg) > 8) { - strcpy(mext,mbeg + 8); + pstrcpy(mext,mbeg + 8); mbeg[8] = 0; } } @@ -1672,7 +1672,7 @@ void expand_mask(char *Mask,BOOL doext) if (*mext) expand_one(mext,3); - strcpy(Mask,dirpart); + pstrcpy(Mask,dirpart); if (*dirpart || absolute) strcat(Mask,"\\"); strcat(Mask,mbeg); strcat(Mask,"."); @@ -1773,7 +1773,7 @@ void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode char *p; pstring mask2; - strcpy(mask2,mask); + pstrcpy(mask2,mask); if ((mode & aDIR) != 0) size = 0; @@ -2421,7 +2421,12 @@ BOOL string_init(char **dest,char *src) } else { - *dest = (char *)malloc(l+1); + (*dest) = (char *)malloc(l+1); + if ((*dest) == NULL) { + DEBUG(0,("Out of memory in string_init\n")); + return False; + } + strcpy(*dest,src); } return(True); @@ -2593,25 +2598,25 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig)); if (trans2) { - strcpy(ebase,p1); - strcpy(sbase,p2); + fstrcpy(ebase,p1); + fstrcpy(sbase,p2); } else { if ((p=strrchr(p1,'.'))) { *p = 0; - strcpy(ebase,p1); - strcpy(eext,p+1); + fstrcpy(ebase,p1); + fstrcpy(eext,p+1); } else { - strcpy(ebase,p1); + fstrcpy(ebase,p1); eext[0] = 0; } if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) { *p = 0; - strcpy(sbase,p2); - strcpy(sext,p+1); + fstrcpy(sbase,p2); + fstrcpy(sext,p+1); } else { - strcpy(sbase,p2); - strcpy(sext,""); + fstrcpy(sbase,p2); + fstrcpy(sext,""); } } @@ -2927,7 +2932,7 @@ BOOL get_myname(char *my_name,struct in_addr *ip) char *p = strchr(hostname,'.'); if (p) *p = 0; - strcpy(my_name,hostname); + fstrcpy(my_name,hostname); } if (ip) @@ -3295,7 +3300,7 @@ char *client_addr(void) return addr_buf; } - strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr)); + fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr)); global_client_addr_done = True; return addr_buf; @@ -3552,7 +3557,7 @@ char *readdirname(void *p) { static pstring buf; - strcpy(buf, dname); + pstrcpy(buf, dname); unix_to_dos(buf, True); dname = buf; } @@ -3907,3 +3912,54 @@ enum remote_arch_types get_remote_arch() { return ra_type; } + + +/******************************************************************* +safe string copy into a fstring +********************************************************************/ +void fstrcpy(char *dest, char *src) +{ + int maxlength = sizeof(fstring) - 1; + if (!dest) { + DEBUG(0,("ERROR: NULL dest in fstrcpy\n")); + return; + } + + if (!src) { + *dest = 0; + return; + } + + while (maxlength-- && *src) + *dest++ = *src++; + *dest = 0; + if (*src) { + DEBUG(0,("ERROR: string overflow by %d in fstrcpy\n", + strlen(src))); + } +} + +/******************************************************************* +safe string copy into a pstring +********************************************************************/ +void pstrcpy(char *dest, char *src) +{ + int maxlength = sizeof(pstring) - 1; + if (!dest) { + DEBUG(0,("ERROR: NULL dest in pstrcpy\n")); + return; + } + + if (!src) { + *dest = 0; + return; + } + + while (maxlength-- && *src) + *dest++ = *src++; + *dest = 0; + if (*src) { + DEBUG(0,("ERROR: string overflow by %d in pstrcpy\n", + strlen(src))); + } +} -- cgit From 1de1a22d0cd4ca1a977f35411ca57ce0768a46d7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Oct 1997 19:54:33 +0000 Subject: locking.c: Finally fixed nasty crash bug when deleting invalid share mode entries. util.c: Tried to stop put_ip core dump seemingly caused by bad returns from gethostbyname. Jeremy (jallison@whistle.com) --- source/lib/util.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/lib/util.c') diff --git a/source/lib/util.c b/source/lib/util.c index 0c4999c789c..7f785332e6a 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -3150,6 +3150,10 @@ uint32 interpret_addr(char *str) DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str)); return 0; } + if(hp->h_addr == NULL) { + DEBUG(3,("Get_Hostbyname: host address is invalid for host %s.\n",str)); + return 0; + } putip((char *)&res,(char *)hp->h_addr); } -- cgit From a70d0fc26ff0eed6ab4adea1b17f2d184d133d05 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 10 Oct 1997 02:35:55 +0000 Subject: fixed the log wrapping bug. This is a very nasty bug that I think explains quite a few intermittent problems people have been having with Samba. It may be worth checking on other cases where errno can be overwritten by seemingly innocuous things (in this case a DEBUG() line) --- source/lib/util.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'source/lib/util.c') diff --git a/source/lib/util.c b/source/lib/util.c index 7f785332e6a..459745b8b14 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -156,7 +156,7 @@ static void check_log_size(void) int maxlog; struct stat st; - if (debug_count++ < 100) return; + if (debug_count++ < 100 || getuid() != 0) return; maxlog = lp_max_log_size() * 1024; if (!dbf || maxlog <= 0) return; @@ -175,7 +175,6 @@ static void check_log_size(void) debug_count=0; } - /******************************************************************* write an debug message on the debugfile. This is called by the DEBUG macro @@ -190,7 +189,8 @@ va_dcl char *format_str; #endif va_list ap; - + int old_errno = errno; + if (stdout_logging) { #ifdef __STDC__ va_start(ap, format_str); @@ -200,6 +200,7 @@ va_dcl #endif vfprintf(dbf,format_str,ap); va_end(ap); + errno = old_errno; return(0); } @@ -207,16 +208,17 @@ va_dcl if (!lp_syslog_only()) #endif { - if (!dbf) - { - int oldumask = umask(022); - dbf = fopen(debugf,"w"); - umask(oldumask); - if (dbf) - setbuf(dbf,NULL); - else - return(0); - } + if (!dbf) { + int oldumask = umask(022); + dbf = fopen(debugf,"w"); + umask(oldumask); + if (dbf) { + setbuf(dbf,NULL); + } else { + errno = old_errno; + return(0); + } + } } #ifdef SYSLOG @@ -273,6 +275,8 @@ va_dcl check_log_size(); + errno = old_errno; + return(0); } -- cgit From 4200f5a328e1934d4d9cbc4e069e723b639a49db Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 15 Oct 1997 01:34:04 +0000 Subject: Added #ifdef'ed code with BIND_LOCAL_OUTPUT_SOCKET that causes optput sockets to be bound to the same local address as input ones are. Jeremy (jallison@whistle.com) --- source/lib/util.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'source/lib/util.c') diff --git a/source/lib/util.c b/source/lib/util.c index 459745b8b14..54b2dc08ac8 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -3035,8 +3035,26 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) if (res == -1) { DEBUG(0,("socket error\n")); return -1; } - if (type != SOCK_STREAM) return(res); +#ifdef BIND_LOCAL_OUTPUT_SOCKET + { + struct sockaddr_in sock_in; + /* Bind the local part of this socket to the address + given in the socket address parameter. */ + + bzero((char *)&sock_in,sizeof(sock_in)); + putip((char *)&sock_in.sin_addr,(char *)interpret_addr2(lp_socket_address())); + sock_in.sin_port = 0; + sock_in.sin_family = PF_INET; + + if (bind(res, (struct sockaddr * ) &sock_in,sizeof(sock_in)) < 0) + DEBUG(0,("Failed to bind local socket address for output socket. Error was %s\n", + strerror(errno))); + } +#endif /* BIND_LOCAL_OUTPUT_SOCKET */ + + if (type != SOCK_STREAM) return(res); + bzero((char *)&sock_out,sizeof(sock_out)); putip((char *)&sock_out.sin_addr,(char *)addr); -- cgit