--- uac_crt.h.old 1998-07-01 10:29:00.000000000 +0200 +++ uac_crt.h 2005-02-14 00:48:35.000000000 +0100 @@ -4,7 +4,7 @@ #include "acestruc.h" -CHAR *ace_fname(CHAR * s, thead * head, INT nopath); +CHAR *ace_fname(CHAR * s, thead * head, INT nopath, unsigned int size); INT create_dest_file(CHAR * file, INT a); #ifdef UNIX --- uac_crt.c.old 1998-07-01 10:29:00.000000000 +0200 +++ uac_crt.c 2005-02-14 02:46:02.000000000 +0100 @@ -33,12 +33,15 @@ /* gets file name from header */ -CHAR *ace_fname(CHAR * s, thead * head, INT nopath) +CHAR *ace_fname(CHAR * s, thead * head, INT nopath, unsigned int size) { - INT i; + unsigned int i; char *cp; - strncpy(s, (*(tfhead *) head).FNAME, i = (*(tfhead *) head).FNAME_SIZE); + i = (*(tfhead *) head).FNAME_SIZE; + if (i > (size - 1)) + i = size - 1; + strncpy(s, (*(tfhead *) head).FNAME, i); s[i] = 0; if (nopath) @@ -56,22 +59,72 @@ CHAR *ace_fname(CHAR * s, thead * head, } #endif + cp = s; + while (*cp == '/') cp++; + if (cp != s) + memmove(s, cp, strlen(cp) + 1); + return s; } +int is_directory_traversal(char *str) +{ + unsigned int mode, countdots; + /* mode 0 = fresh, 1 = just dots, 2 = not just dots */ + char ch; + + mode = countdots = 0; + + while (ch = *str++) + { + if ((ch == '/') && (mode == 1) && (countdots > 1)) + return 1; + + if (ch == '/') + { + mode = countdots = 0; + continue; + } + + if (ch == '.') + { + if (mode == 0) + mode = 1; + + countdots++; + } + else + mode = 2; + } + + if ((mode == 1) && (countdots > 1)) + return 1; + + return 0; +} + void check_ext_dir(CHAR * f) // checks/creates path of file { CHAR *cp, d[PATH_MAX]; - INT i; + unsigned int i; d[0] = 0; + if (is_directory_traversal(f)) + { + f_err = ERR_WRITE; + printf("\n Directory traversal attempt: %s\n", f); + return; + } + for (;;) { if ((cp = (CHAR *) strchr(&f[strlen(d) + 1], DIRSEP))!=NULL) { i = cp - f; + if (i > (PATH_MAX - 1)) + i = PATH_MAX - 1; strncpy(d, f, i); d[i] = 0; } --- unace.c.old 1998-07-01 10:29:00.000000000 +0200 +++ unace.c 2005-02-14 01:43:28.000000000 +0100 @@ -240,6 +240,7 @@ INT read_arc_head(void) // searc INT open_archive(INT print_err) // opens archive (or volume) { CHAR av_str[80]; + unsigned int copylen; archan = open(aname, O_RDONLY | O_BINARY); // open file @@ -263,8 +264,11 @@ INT open_archive(INT print_err) sprintf(av_str, "\ncreated on %d.%d.%d by ", ts_day(adat.time_cr), ts_month(adat.time_cr), ts_year(adat.time_cr)); printf(av_str); - strncpy(av_str, mhead.AV, mhead.AV_SIZE); - av_str[mhead.AV_SIZE] = 0; + copylen = mhead.AV_SIZE; + if (copylen > 79) + copylen = 79; + strncpy(av_str, mhead.AV, copylen); + av_str[copylen] = 0; printf("%s\n\n", av_str); } comment_out("Main comment:"); // print main comment @@ -300,7 +304,7 @@ void get_next_volname(void) INT proc_vol(void) // opens volume { INT i; - CHAR s[80]; + CHAR s[PATH_MAX + 80]; // if f_allvol_pr is 2 we have -y and should never ask if ((!fileexists_insense(aname) && f_allvol_pr != 2) || !f_allvol_pr) @@ -428,7 +432,7 @@ void extract_files(int nopath, int test) if (head.HEAD_TYPE == FILE_BLK) { comment_out("File comment:"); // show file comment - ace_fname(file, &head, nopath); // get file name + ace_fname(file, &head, nopath, sizeof(file)); // get file name printf("\n%s", file); flush; dcpr_init_file(); // initialize decompression of file @@ -496,7 +500,7 @@ void list_files(int verbose) if (head.HEAD_TYPE == FILE_BLK) { ULONG ti=fhead.FTIME; - ace_fname(file, &head, verbose ? 0 : 1); // get file name + ace_fname(file, &head, verbose ? 0 : 1, sizeof(file)); // get file name size += fhead.SIZE; psize += @@ -588,7 +592,8 @@ int main(INT argc, CHAR * argv[]) init_unace(); // initialize unace - strcpy(aname, argv[arg_cnt]); // get archive name + strncpy(aname, argv[arg_cnt], sizeof(aname) - 4); // get archive name + aname[sizeof(aname) - 5] = '\0'; if (!(s = (CHAR *) strrchr(aname, DIRSEP))) s = aname; if (!strrchr(s, '.'))