int tar_extract_glob(TAR *t, char *globname, char *prefix) { char *filename; char buf[MAXPATHLEN]; int i; while ((i = th_read(t)) == 0) { filename = th_get_pathname(t); if (fnmatch(globname, filename, FNM_PATHNAME | FNM_PERIOD)) { if (TH_ISREG(t) && tar_skip_regfile(t)) return -1; continue; } if (t->options & TAR_VERBOSE) th_print_long_ls(t); if (prefix != NULL) snprintf(buf, sizeof(buf), "%s/%s", prefix, filename); else strlcpy(buf, filename, sizeof(buf)); if (tar_extract_file(t, filename) != 0) return -1; } return (i == 1 ? 0 : -1); }
static int list(char *tarfile) { TAR *t; int i; if (tar_open(&t, tarfile, #ifdef HAVE_LIBZ (use_zlib ? &gztype : NULL), #else NULL, #endif O_RDONLY, 0, (verbose ? TAR_VERBOSE : 0) | (use_gnu ? TAR_GNU : 0)) == -1) { fprintf(stderr, "tar_open(): %s\n", strerror(errno)); return -1; } while ((i = th_read(t)) == 0) { th_print_long_ls(t); #ifdef DEBUG th_print(t); #endif if (TH_ISREG(t) && tar_skip_regfile(t) != 0) { fprintf(stderr, "tar_skip_regfile(): %s\n", strerror(errno)); return -1; } } #ifdef DEBUG printf("th_read() returned %d\n", i); printf("EOF mark encountered after %ld bytes\n", # ifdef HAVE_LIBZ (use_zlib ? gzseek((gzFile) t->fd, 0, SEEK_CUR) : # endif lseek(t->fd, 0, SEEK_CUR) # ifdef HAVE_LIBZ ) # endif ); #endif if (tar_close(t) != 0) { fprintf(stderr, "tar_close(): %s\n", strerror(errno)); return -1; } (void)i; return 0; }
/* \internal Checks whether a tar file is valid. A valid tar file does not contains files that start with ./ or contain .. This is intended to prevent malicious packages placing binaries outside of the sandbox directory */ bool check_tar_valid( const QString &tarfile ) { TAR *tarHandle = get_tar_ptr( tarfile ); bool ret=true; QString filename; int i; while ( (i = th_read(tarHandle)) == 0) { filename = th_get_pathname( tarHandle ); if ( !filename.startsWith("./") || filename.contains( "..") ) { ret = false; qWarning() << "check_tar_valid:- tar contains invalid file path: " << filename << "\nAll paths must begin with ./ and not contain .." ; break; } else if ( TH_ISBLK(tarHandle) || TH_ISCHR(tarHandle) ) { ret = false; qWarning() << "check_tar_valid:-tar invalid, contains device special file:" << filename; break; } else if ( TH_ISLNK(tarHandle) ) { ret = false; qWarning() << "check_tar_valid:-tar invalid, contains hard link:" << filename; break; } else if (TH_ISSYM(tarHandle) ) { QString target; if ((tarHandle->options & TAR_GNU) && tarHandle->th_buf.gnu_longlink != NULL) target = tarHandle->th_buf.gnu_longlink; else target = tarHandle->th_buf.linkname; if ( target.startsWith("/") || target.contains( "..") ) { ret = false; qWarning() << "check_tar_valid:tar invalid, contains symlink whose target" << (target.startsWith("/")?"is an absolute path.":"references " "a parent directory.") << "Link:" << filename << "Target:" << target; break; } } if( TH_ISREG(tarHandle) ) tar_skip_regfile(tarHandle); } tar_close( tarHandle ); return ret; }
qlonglong targz_archive_size( const QString &tarfile ) { TAR *tarHandle = get_tar_ptr( tarfile ); qlonglong size = 0; int i; while ((i = th_read(tarHandle)) == 0) { size += th_get_size(tarHandle); if( TH_ISREG(tarHandle) ) tar_skip_regfile(tarHandle); } tar_close( tarHandle ); return size; }
static int sandbox_attr(void *fpctx,void *handle,const char *attr,glite_jp_attrval_t **attrval) { glite_jp_error_t err; glite_jp_context_t ctx = fpctx; glite_jp_attrval_t *out = NULL; int i,nout = 0, count = 0; sb_handle *h = handle; printf("sandbox_attr() called\n"); memset(&err,0,sizeof err); err.source = __FUNCTION__; glite_jp_clear_error(ctx); *attrval = NULL; if (!strcmp(attr, GLITE_JP_ATTR_ISB_FILENAME)) { while ((i = th_read(h->t)) == 0) { printf("-- %s\n", th_get_pathname(h->t)); if ( !(count % ALLOC_CHUNK) ) { *attrval = realloc(*attrval, (count + ALLOC_CHUNK + 1) * sizeof(**attrval) ); memset( (*attrval) + count, 0, (ALLOC_CHUNK + 1) * sizeof(**attrval)); } (*attrval)[count].name = strdup(GLITE_JP_ATTR_ISB_FILENAME); (*attrval)[count].value = strdup(th_get_pathname(h->t)); (*attrval)[count].origin = GLITE_JP_ATTR_ORIG_FILE; (*attrval)[count].timestamp = th_get_mtime(h->t); count++; if (TH_ISREG(h->t) && tar_skip_regfile(h->t) != 0) { err.code = EIO; err.desc = "tar_skip_regfile"; return glite_jp_stack_error(ctx,&err); } } } else if (!strcmp(attr, GLITE_JP_ATTR_OSB_FILENAME)) { printf("Namespace %s not implemented yet\n", GLITE_JP_ATTR_OSB_FILENAME); } else if (strstr(attr,GLITE_JP_OSB_CONTENT_NS)) { printf("Namespace %s not implemented yet\n", GLITE_JP_OSB_CONTENT_NS); } else if (strstr(attr,GLITE_JP_ISB_CONTENT_NS)) { char *fileName = (char *) attr + sizeof(GLITE_JP_ISB_CONTENT_NS); printf("untaring file: %s\n", fileName); while (th_read(h->t) == 0) { if ( !strcmp(fileName, th_get_pathname(h->t)) ) { /* extract the file */ int k; size_t size; char buf[T_BLOCKSIZE]; char *value; if (!TH_ISREG(h->t)) assert(0); // not a regular file size = th_get_size(h->t); value = (char *) malloc(size * sizeof(char) + 1); memset( value, 0, size * sizeof(char) + 1); for (i = 0; i < size; i += T_BLOCKSIZE) { k = tar_block_read(h->t, buf); if (k == -1) { err.code = errno; err.desc = "tar_block_read"; return glite_jp_stack_error(ctx,&err); } // tar_block_read calls glite_jppsbe_pread, which usually // returns whole block (read from the middle of uploaded // tar file // so cut k in order to the last chunk had correct size if (i + T_BLOCKSIZE > size) { k = size - i; } strncpy(value + i, buf, k); } *attrval = malloc(2 * sizeof(**attrval) ); memset( (*attrval), 0, 2 * sizeof(**attrval)); (*attrval)[0].name = strdup(attr); (*attrval)[0].value = value; (*attrval)[0].origin = GLITE_JP_ATTR_ORIG_FILE; (*attrval)[0].timestamp = th_get_mtime(h->t); } else if (TH_ISREG(h->t) && tar_skip_regfile(h->t) != 0) { err.code = EIO; err.desc = "tar_skip_regfile"; return glite_jp_stack_error(ctx,&err); } } } return glite_jp_stack_error(ctx,&err); }