Files
rsync/exclude.c
Andrew Tridgell 13a1f7929e some people are now using rsync as a public server, using various
patches or wrappers. One problem with this is that rsync was not
written with this in mind and wasn't very careful about possible stack
overflows etc which could lead to security breaches. This wasn't a
problem when run in the traditional way as any user that can run rsync
can login anyway and cause much more damage that way.
This patch attempts to close possible stack overflow problems. I've
checked for all strcpy(), strcat(), sprintf() and memcpy()
overflows. I would appreciate it if someone else with a devious mind
could also go through the rsync source code and see if there are any
other stack overflows possible. Let me know if you do.
1997-12-15 21:35:37 +00:00

202 lines
4.2 KiB
C

/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
a lot of this stuff was derived from GNU tar
*/
#include "rsync.h"
extern int verbose;
static char **exclude_list = NULL;
static int is_regex(char *str)
{
return strchr(str, '*') || strchr(str, '[') || strchr(str, '?');
}
static int check_one_exclude(char *name,char *pattern)
{
char *p;
if (!strchr(pattern,'/') && (p=strrchr(name,'/')))
name = p+1;
if (!name[0]) return 0;
if (is_regex(pattern)) {
if (fnmatch(pattern, name, 0) == 0)
return 1;
} else {
int l1 = strlen(name);
int l2 = strlen(pattern);
if (l2 <= l1 &&
strcmp(name+(l1-l2),pattern) == 0 &&
(l1==l2 || name[l1-(l2+1)] == '/'))
return 1;
}
return 0;
}
int check_exclude(char *name,char **local_exclude_list)
{
int n;
if (exclude_list) {
for (n=0; exclude_list[n]; n++)
if (check_one_exclude(name,exclude_list[n]))
return 1;
}
if (local_exclude_list) {
for (n=0; local_exclude_list[n]; n++)
if (check_one_exclude(name,local_exclude_list[n]))
return 1;
}
return 0;
}
void add_exclude_list(char *pattern,char ***list)
{
int len=0;
if (list && *list)
for (; (*list)[len]; len++) ;
if (strcmp(pattern,"!") == 0) {
if (verbose > 2)
fprintf(FERROR,"clearing exclude list\n");
while ((len)--)
free((*list)[len]);
free((*list));
*list = NULL;
return;
}
if (!*list) {
*list = (char **)malloc(sizeof(char *)*2);
} else {
*list = (char **)realloc(*list,sizeof(char *)*(len+2));
}
if (!*list || !((*list)[len] = strdup(pattern)))
out_of_memory("add_exclude");
if (verbose > 2)
fprintf(FERROR,"add_exclude(%s)\n",pattern);
(*list)[len+1] = NULL;
}
void add_exclude(char *pattern)
{
add_exclude_list(pattern,&exclude_list);
}
char **make_exclude_list(char *fname,char **list1,int fatal)
{
char **list=list1;
FILE *f = fopen(fname,"r");
char line[MAXPATHLEN];
if (!f) {
if (fatal) {
fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
exit_cleanup(1);
}
return list;
}
while (fgets(line,MAXPATHLEN,f)) {
int l = strlen(line);
if (l && line[l-1] == '\n') l--;
line[l] = 0;
if (line[0]) add_exclude_list(line,&list);
}
fclose(f);
return list;
}
void add_exclude_file(char *fname,int fatal)
{
exclude_list = make_exclude_list(fname,exclude_list,fatal);
}
void send_exclude_list(int f)
{
int i;
if (exclude_list)
for (i=0;exclude_list[i];i++) {
int l = strlen(exclude_list[i]);
if (l == 0) continue;
write_int(f,l);
write_buf(f,exclude_list[i],l);
}
write_int(f,0);
}
void recv_exclude_list(int f)
{
char line[MAXPATHLEN];
int l;
while ((l=read_int(f))) {
read_buf(f,line,l);
line[l] = 0;
add_exclude(line);
}
}
static char *cvs_ignore_list[] = {
"RCS","SCCS","CVS","CVS.adm","RCSLOG","cvslog.*",
"tags","TAGS",".make.state",".nse_depinfo",
"*~", "#*", ".#*", ",*", "*.old", "*.bak", "*.BAK", "*.orig",
"*.rej", ".del-*", "*.a", "*.o", "*.obj", "*.so", "*.Z", "*.elc", "*.ln",
"core",NULL};
void add_cvs_excludes(void)
{
char fname[MAXPATHLEN];
char *p;
int i;
for (i=0; cvs_ignore_list[i]; i++)
add_exclude(cvs_ignore_list[i]);
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
sprintf(fname,"%s/.cvsignore",p);
add_exclude_file(fname,0);
}
if ((p=getenv("CVSIGNORE"))) {
char *tok;
for (tok=strtok(p," "); tok; tok=strtok(NULL," "))
add_exclude(tok);
}
}