diff -u -r --new-file --exclude=CVS rsync-2.0.3/authenticate.c rsync-2.0.4/authenticate.c --- rsync-2.0.3/authenticate.c Wed May 13 22:21:10 1998 +++ rsync-2.0.4/authenticate.c Fri May 15 20:57:36 1998 @@ -28,7 +28,6 @@ char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int bit_offset, byte_offset, idx, i; unsigned char *d = (unsigned char *)buf; - char *p; int bytes = (len*8 + 5)/6; memset(out, 0, bytes+1); @@ -56,7 +55,7 @@ memset(input, 0, sizeof(input)); - strncpy((char *)input, addr, 16); + strlcpy((char *)input, addr, 16); gettimeofday(&tv, NULL); SIVAL(input, 16, tv.tv_sec); SIVAL(input, 20, tv.tv_usec); @@ -74,8 +73,8 @@ { char *fname = lp_secrets_file(module); int fd, found=0; - char line[1024]; - char *p, *pass; + char line[MAXPATHLEN]; + char *p, *pass=NULL; if (!fname || !*fname) return 0; @@ -108,12 +107,7 @@ close(fd); if (!found) return 0; - if (strlen(pass) > len-1) { - memset(line, 0, sizeof(line)); - return 0; - } - - strcpy(secret, pass); + strlcpy(secret, pass, len); return 1; } @@ -137,7 +131,7 @@ char *users = lp_auth_users(module); char challenge[16]; char b64_challenge[30]; - char line[1024]; + char line[MAXPATHLEN]; char user[100]; char secret[100]; char pass[30]; diff -u -r --new-file --exclude=CVS rsync-2.0.3/clientserver.c rsync-2.0.4/clientserver.c --- rsync-2.0.3/clientserver.c Fri May 15 11:19:11 1998 +++ rsync-2.0.4/clientserver.c Fri May 15 20:57:36 1998 @@ -30,7 +30,7 @@ int fd, i; char *sargs[MAX_ARGS]; int sargc=0; - char line[1024]; + char line[MAXPATHLEN]; char *p, *user=NULL; extern int remote_version; @@ -102,13 +102,12 @@ int argc=0; char *argv[MAX_ARGS]; char **argp; - char line[1024]; - uid_t uid; - gid_t gid; + char line[MAXPATHLEN]; + uid_t uid = (uid_t)-2; + gid_t gid = (gid_t)-2; char *p; char *addr = client_addr(fd); char *host = client_name(fd); - char *auth; char *name = lp_name(i); int start_glob=0; @@ -134,8 +133,6 @@ return -1; } - rprintf(FINFO,"rsync on module %s from %s (%s)\n", - name, host, addr); module_id = i; @@ -168,22 +165,28 @@ p = lp_exclude(i); add_exclude_line(p); + log_open(); + if (chroot(lp_path(i))) { + rprintf(FERROR,"chroot %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chroot failed\n"); return -1; } if (chdir("/")) { + rprintf(FERROR,"chdir %s failed\n", lp_path(i)); io_printf(fd,"@ERROR: chdir failed\n"); return -1; } - if (setgid(gid)) { + if (setgid(gid) || getgid() != gid) { + rprintf(FERROR,"setgid %d failed\n", gid); io_printf(fd,"@ERROR: setgid failed\n"); return -1; } - if (setuid(uid)) { + if (setuid(uid) || getuid() != uid) { + rprintf(FERROR,"setuid %d failed\n", uid); io_printf(fd,"@ERROR: setuid failed\n"); return -1; } @@ -201,18 +204,18 @@ p = line; - if (start_glob && strncmp(p, name, strlen(name)) == 0) { - p += strlen(name); - if (!*p) p = "."; - } - argv[argc] = strdup(p); if (!argv[argc]) { return -1; } if (start_glob) { - glob_expand(argv, &argc, MAX_ARGS); + if (start_glob == 1) { + rprintf(FINFO,"rsync on %s from %s (%s)\n", + p, host, addr); + start_glob++; + } + glob_expand(name, argv, &argc, MAX_ARGS); } else { argc++; } @@ -263,7 +266,7 @@ extern char *config_file; extern int remote_version; - if (!lp_load(config_file)) { + if (!lp_load(config_file, 0)) { exit_cleanup(1); } @@ -324,12 +327,23 @@ int daemon_main(void) { + extern char *config_file; + if (is_a_socket(STDIN_FILENO)) { /* we are running via inetd */ return start_daemon(STDIN_FILENO); } become_daemon(); + + if (!lp_load(config_file, 1)) { + fprintf(stderr,"failed to load config file %s\n", config_file); + exit_cleanup(1); + } + + log_open(); + + rprintf(FINFO,"rsyncd version %s starting\n",VERSION); start_accept_loop(rsync_port, start_daemon); return -1; diff -u -r --new-file --exclude=CVS rsync-2.0.3/cvs.log rsync-2.0.4/cvs.log --- rsync-2.0.3/cvs.log Fri May 15 17:55:14 1998 +++ rsync-2.0.4/cvs.log Fri May 15 20:58:09 1998 @@ -3877,3 +3877,86 @@ Log Message: preparing for release of 2.0.3 + +**************************************** +Date: Friday May 15, 1998 @ 18:43 +Author: tridge + +Update of /data/cvs/rsync +In directory samba:/tmp/cvs-serv22057 + +Modified Files: + clientserver.c proto.h util.c +Log Message: +allow the specification of multiple filenames (with or without +wildcards) to a rsync server. For example you can do: + +rsync -avz samba::'ftp/pub/samba/README ftp/pub/samba/*.gz' . + + + + + +**************************************** +Date: Friday May 15, 1998 @ 19:26 +Author: tridge + +Update of /data/cvs/rsync +In directory samba:/tmp/cvs-serv10988 + +Modified Files: + authenticate.c clientserver.c exclude.c flist.c io.c log.c + main.c proto.h rsync.c util.c +Log Message: +use strlcat() strlcpy() and slprintf() whenever possible to avoid any +chance of a buffer overflow + + + + +**************************************** +Date: Friday May 15, 1998 @ 20:34 +Author: tridge + +Update of /data/cvs/rsync +In directory samba:/tmp/cvs-serv6224 + +Modified Files: + authenticate.c clientserver.c flist.c loadparm.c log.c +Log Message: +- changed the log messages to show the requested path +- some more paranoid buffer size checks +- separate open syslog call +- handle systems without LOG_NDELAY + + + + + +**************************************** +Date: Friday May 15, 1998 @ 20:52 +Author: tridge + +Update of /data/cvs/rsync +In directory samba:/tmp/cvs-serv968 + +Modified Files: + clientserver.c loadparm.c params.c proto.h +Log Message: +load just the globals section of the config file when the daemon +starts so we know the syslog facility for the "starting" message + + + +**************************************** +Date: Friday May 15, 1998 @ 20:58 +Author: rsync-bu + +Update of /data/cvs/rsync +In directory samba:/data/people/rsync-bugs/rsync + +Modified Files: + version.h +Log Message: +preparing for release of 2.0.4 + diff -u -r --new-file --exclude=CVS rsync-2.0.3/exclude.c rsync-2.0.4/exclude.c --- rsync-2.0.3/exclude.c Fri May 15 11:03:10 1998 +++ rsync-2.0.4/exclude.c Fri May 15 20:57:36 1998 @@ -205,8 +205,8 @@ add_exclude(cvs_ignore_list[i]); if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) { - sprintf(fname,"%s/.cvsignore",p); - add_exclude_file(fname,0); + slprintf(fname,sizeof(fname)-1, "%s/.cvsignore",p); + add_exclude_file(fname,0); } add_exclude_line(getenv("CVSIGNORE")); diff -u -r --new-file --exclude=CVS rsync-2.0.3/flist.c rsync-2.0.4/flist.c --- rsync-2.0.3/flist.c Fri May 15 17:35:41 1998 +++ rsync-2.0.4/flist.c Fri May 15 20:57:36 1998 @@ -521,7 +521,7 @@ closedir(d); return; } - strcat(fname,"/"); + strlcat(fname,"/", MAXPATHLEN-1); l++; } p = fname + strlen(fname); @@ -585,7 +585,7 @@ l = strlen(fname); if (l != 1 && fname[l-1] == '/') { - strcat(fname,"."); + strlcat(fname,".",MAXPATHLEN-1); } if (link_stat(fname,&st) != 0) { @@ -616,7 +616,7 @@ thus getting their permissions right */ *p = 0; if (strcmp(lastpath,fname)) { - strcpy(lastpath, fname); + strlcpy(lastpath, fname, sizeof(lastpath)-1); *p = '/'; for (p=fname+1; (p=strchr(p,'/')); p++) { *p = 0; @@ -878,7 +878,7 @@ n = (n+1)%10; if (f->dirname) { - sprintf(p, "%s/%s", f->dirname, f->basename); + slprintf(p, MAXPATHLEN-1, "%s/%s", f->dirname, f->basename); } else { strlcpy(p, f->basename, MAXPATHLEN-1); } diff -u -r --new-file --exclude=CVS rsync-2.0.3/io.c rsync-2.0.4/io.c --- rsync-2.0.3/io.c Fri May 15 17:35:41 1998 +++ rsync-2.0.4/io.c Fri May 15 20:57:36 1998 @@ -521,13 +521,7 @@ int len; va_start(ap, format); - -#if HAVE_VSNPRINTF - len = vsnprintf(buf, sizeof(buf)-1, format, ap); -#else - vsprintf(buf, format, ap); - len = strlen(buf); -#endif + len = vslprintf(buf, sizeof(buf)-1, format, ap); va_end(ap); if (len < 0) exit_cleanup(1); diff -u -r --new-file --exclude=CVS rsync-2.0.3/loadparm.c rsync-2.0.4/loadparm.c --- rsync-2.0.3/loadparm.c Fri May 15 11:03:10 1998 +++ rsync-2.0.4/loadparm.c Fri May 15 20:57:36 1998 @@ -253,6 +253,7 @@ ***************************************************************************/ static void init_globals(void) { + memset(&Globals, 0, sizeof(Globals)); #ifdef LOG_DAEMON Globals.syslog_facility = LOG_DAEMON; #endif @@ -583,7 +584,7 @@ break; case P_GSTRING: - strcpy((char *)parm_ptr,parmvalue); + strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring)-1); break; case P_ENUM: @@ -664,26 +665,26 @@ Load the services array from the services file. Return True on success, False on failure. ***************************************************************************/ -BOOL lp_load(char *pszFname) +BOOL lp_load(char *pszFname, int globals_only) { - pstring n2; - BOOL bRetval; + pstring n2; + BOOL bRetval; - bRetval = False; + bRetval = False; - bInGlobalSection = True; + bInGlobalSection = True; - init_globals(); + init_globals(); - pstrcpy(n2,pszFname); + pstrcpy(n2,pszFname); - /* We get sections first, so have to start 'behind' to make up */ - iServiceIndex = -1; - bRetval = pm_process(n2, do_section, do_parameter); + /* We get sections first, so have to start 'behind' to make up */ + iServiceIndex = -1; + bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter); - bLoaded = True; + bLoaded = True; - return (bRetval); + return (bRetval); } diff -u -r --new-file --exclude=CVS rsync-2.0.3/log.c rsync-2.0.4/log.c --- rsync-2.0.3/log.c Wed May 13 23:48:25 1998 +++ rsync-2.0.4/log.c Fri May 15 20:57:36 1998 @@ -23,6 +23,31 @@ */ #include "rsync.h" + +void log_open(void) +{ + static int initialised; + int options = LOG_PID; + + if (initialised) return; + initialised = 1; + +#ifdef LOG_NDELAY + options |= LOG_NDELAY; +#endif + +#ifdef LOG_DAEMON + openlog("rsyncd", options, lp_syslog_facility()); +#else + openlog("rsyncd", options); +#endif + +#ifndef LOG_NDELAY + syslog(LOG_INFO,"rsyncd started\n"); +#endif +} + + /* this is the rsync debugging function. Call it with FINFO or FERROR */ void rprintf(int fd, const char *format, ...) { @@ -33,13 +58,7 @@ extern int am_daemon; va_start(ap, format); - -#if HAVE_VSNPRINTF - len = vsnprintf(buf, sizeof(buf)-1, format, ap); -#else - vsprintf(buf, format, ap); - len = strlen(buf); -#endif + len = vslprintf(buf, sizeof(buf)-1, format, ap); va_end(ap); if (len < 0) exit_cleanup(1); @@ -49,19 +68,10 @@ buf[len] = 0; if (am_daemon) { - static int initialised; int priority = LOG_INFO; if (fd == FERROR) priority = LOG_WARNING; - if (!initialised) { - initialised = 1; -#ifdef LOG_DAEMON - openlog("rsyncd", LOG_PID, lp_syslog_facility()); -#else - openlog("rsyncd", LOG_PID); -#endif - } - + log_open(); syslog(priority, "%s", buf); return; } diff -u -r --new-file --exclude=CVS rsync-2.0.3/main.c rsync-2.0.4/main.c --- rsync-2.0.3/main.c Thu May 14 17:07:51 1998 +++ rsync-2.0.4/main.c Fri May 15 20:57:36 1998 @@ -190,7 +190,6 @@ struct file_list *flist; char *dir = argv[0]; extern int relative_paths; - extern int am_daemon; extern int recurse; if (verbose > 2) diff -u -r --new-file --exclude=CVS rsync-2.0.3/params.c rsync-2.0.4/params.c --- rsync-2.0.3/params.c Sun May 10 00:00:55 1998 +++ rsync-2.0.4/params.c Fri May 15 20:57:36 1998 @@ -451,10 +451,11 @@ break; case '[': /* Section Header. */ - if( !Section( InFile, sfunc ) ) - return( False ); - c = EatWhitespace( InFile ); - break; + if (!sfunc) return True; + if( !Section( InFile, sfunc ) ) + return( False ); + c = EatWhitespace( InFile ); + break; case '\\': /* Bogus backslash. */ c = EatWhitespace( InFile ); @@ -558,3 +559,4 @@ } /* pm_process */ /* -------------------------------------------------------------------------- */ + diff -u -r --new-file --exclude=CVS rsync-2.0.3/proto.h rsync-2.0.4/proto.h --- rsync-2.0.3/proto.h Fri May 15 17:54:14 1998 +++ rsync-2.0.4/proto.h Fri May 15 20:57:36 1998 @@ -76,9 +76,10 @@ char *lp_secrets_file(int ); char *lp_exclude(int ); char *lp_exclude_from(int ); -BOOL lp_load(char *pszFname); +BOOL lp_load(char *pszFname, int globals_only); int lp_numservices(void); int lp_number(char *name); +void log_open(void); void rprintf(int fd, const char *format, ...); void rflush(int fd); void start_server(int f_in, int f_out, int argc, char *argv[]); @@ -161,9 +162,12 @@ pid_t do_fork(void); void kill_all(int sig); void strlcpy(char *d, char *s, int maxlen); +void strlcat(char *d, char *s, int maxlen); int name_to_uid(char *name, uid_t *uid); int name_to_gid(char *name, gid_t *gid); int process_exists(int pid); int lock_range(int fd, int offset, int len); -void glob_expand(char **argv, int *argc, int maxargs); +void glob_expand(char *base, char **argv, int *argc, int maxargs); void strlower(char *s); +int vslprintf(char *str, int n, const char *format, va_list ap); +int slprintf(char *str, int n, char *format, ...); diff -u -r --new-file --exclude=CVS rsync-2.0.3/rsync.c rsync-2.0.4/rsync.c --- rsync-2.0.3/rsync.c Thu May 14 17:07:51 1998 +++ rsync-2.0.4/rsync.c Fri May 15 20:57:36 1998 @@ -111,10 +111,7 @@ if (strcmp(dname,".")==0 || strcmp(dname,"..")==0) continue; - strlcpy(buf, fname, (MAXPATHLEN-strlen(dname))-2); - strcat(buf, "/"); - strcat(buf, dname); - buf[MAXPATHLEN-1] = 0; + slprintf(buf, sizeof(buf)-1, "%s/%s", fname, dname); if (verbose > 0) rprintf(FINFO,"deleting %s\n", buf); if (delete_file(buf) != 0) { @@ -831,7 +828,7 @@ close(fd1); continue; } - sprintf(fnametmp,"%s/.%s.XXXXXX",tmpdir,f); + slprintf(fnametmp,sizeof(fnametmp)-1, "%s/.%s.XXXXXX",tmpdir,f); } else { char *f = strrchr(fname,'/'); @@ -844,10 +841,10 @@ if (f) { *f = 0; - sprintf(fnametmp,"%s/.%s.XXXXXX",fname,f+1); + slprintf(fnametmp,sizeof(fnametmp)-1,"%s/.%s.XXXXXX",fname,f+1); *f = '/'; } else { - sprintf(fnametmp,".%s.XXXXXX",fname); + slprintf(fnametmp,sizeof(fnametmp)-1,".%s.XXXXXX",fname); } } if (NULL == do_mktemp(fnametmp)) { @@ -893,7 +890,7 @@ rprintf(FERROR,"backup filename too long\n"); continue; } - sprintf(fnamebak,"%s%s",fname,backup_suffix); + slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix); if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) { rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno)); continue; @@ -998,10 +995,10 @@ fname); return; } - strcat(fname,"/"); + strlcat(fname,"/",MAXPATHLEN-1); offset = strlen(file->basedir)+1; } - strncat(fname,f_name(file),MAXPATHLEN-strlen(fname)); + strlcat(fname,f_name(file),MAXPATHLEN-strlen(fname)); if (verbose > 2) rprintf(FINFO,"send_files(%d,%s)\n",i,fname); diff -u -r --new-file --exclude=CVS rsync-2.0.3/util.c rsync-2.0.4/util.c --- rsync-2.0.3/util.c Thu May 14 17:07:52 1998 +++ rsync-2.0.4/util.c Fri May 15 20:57:36 1998 @@ -456,6 +456,21 @@ d[len] = 0; } +/* like strncat but does not 0 fill the buffer and always null + terminates (thus it can use maxlen+1 space in d) */ +void strlcat(char *d, char *s, int maxlen) +{ + int len1 = strlen(d); + int len2 = strlen(s); + if (len1+len2 > maxlen) { + len2 = maxlen-len1; + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } +} + /* turn a user name into a uid */ int name_to_uid(char *name, uid_t *uid) { @@ -506,15 +521,21 @@ } -void glob_expand(char **argv, int *argc, int maxargs) +static void glob_expand_one(char *s, char **argv, int *argc, int maxargs) { #ifndef HAVE_GLOB + if (!*s) s = "."; + argv[*argc] = strdup(s); (*argc)++; return; #else glob_t globbuf; int i; + if (!*s) s = "."; + + argv[*argc] = strdup(s); + memset(&globbuf, 0, sizeof(globbuf)); glob(argv[*argc], 0, NULL, &globbuf); if (globbuf.gl_pathc == 0) { @@ -532,6 +553,36 @@ #endif } +void glob_expand(char *base, char **argv, int *argc, int maxargs) +{ + char *s = argv[*argc]; + char *p, *q; + + if (!s || !*s) return; + + if (strncmp(s, base, strlen(base)) == 0) { + s += strlen(base); + } + + s = strdup(s); + if (!s) out_of_memory("glob_expand"); + + q = s; + while ((p = strstr(q,base)) && ((*argc) < maxargs)) { + if (p != q && *(p-1) == ' ' && p[strlen(base)] == '/') { + /* split it at this point */ + *(p-1) = 0; + glob_expand_one(q, argv, argc, maxargs); + q = p+strlen(base)+1; + } else { + q++; + } + } + + if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs); + + free(s); +} /******************************************************************* convert a string to lower case @@ -542,4 +593,75 @@ if (isupper(*s)) *s = tolower(*s); s++; } +} + +/* this is like vsnprintf but the 'n' limit does not include + the terminating null. So if you have a 1024 byte buffer then + pass 1023 for n */ +int vslprintf(char *str, int n, const char *format, va_list ap) +{ +#ifdef HAVE_VSNPRINTF + int ret = vsnprintf(str, n, format, ap); + if (ret > n || ret < 0) { + str[n] = 0; + return -1; + } + str[ret] = 0; + return ret; +#else + static char *buf; + static int len=MAXPATHLEN*8; + int ret; + + /* this code is NOT a proper vsnprintf() implementation. It + relies on the fact that all calls to slprintf() in rsync + pass strings which have already been checked to be less + than MAXPATHLEN in length and never more than 2 strings are + concatenated. This means the above buffer is absolutely + ample and can never be overflowed. + + In the future we would like to replace this with a proper + vsnprintf() implementation but right now we need a solution + that is secure and portable. This is it. */ + + if (!buf) { + buf = malloc(len); + if (!buf) { + /* can't call debug or we would recurse */ + exit(1); + } + } + + ret = vsprintf(buf, format, ap); + + if (ret < 0) { + str[0] = 0; + return -1; + } + + if (ret < n) { + n = ret; + } else if (ret > n) { + ret = -1; + } + + buf[n] = 0; + + memcpy(str, buf, n+1); + + return ret; +#endif +} + + +/* like snprintf but always null terminates */ +int slprintf(char *str, int n, char *format, ...) +{ + va_list ap; + int ret; + + va_start(ap, format); + ret = vslprintf(str,n,format,ap); + va_end(ap); + return ret; } diff -u -r --new-file --exclude=CVS rsync-2.0.3/version.h rsync-2.0.4/version.h --- rsync-2.0.3/version.h Fri May 15 17:55:00 1998 +++ rsync-2.0.4/version.h Fri May 15 20:58:02 1998 @@ -1 +1 @@ -#define VERSION "2.0.3" +#define VERSION "2.0.4"