int restore_sbuf_protocol1(struct asfd *asfd, struct sbuf *sb, struct bu *bu, enum action act, struct sdirs *sdirs, enum cntr_status cntr_status, struct conf **cconfs) { if((sb->protocol1->datapth.buf && asfd->write(asfd, &(sb->protocol1->datapth))) || asfd->write(asfd, &sb->attr)) return -1; else if(sbuf_is_filedata(sb) || sbuf_is_vssdata(sb)) { if(!sb->protocol1->datapth.buf) { logw(asfd, get_cntr(cconfs), "Got filedata entry with no datapth: %c:%s\n", sb->path.cmd, sb->path.buf); return 0; } return restore_file(asfd, bu, sb, act, sdirs, cconfs); } else { if(asfd->write(asfd, &sb->path)) return -1; // If it is a link, send what // it points to. else if(sbuf_is_link(sb) && asfd->write(asfd, &sb->link)) return -1; cntr_add(get_cntr(cconfs), sb->path.cmd, 0); } return 0; }
static int restore_sbuf(struct sbuf *sb, struct bu *arr, int a, int i, const char *tmppath1, const char *tmppath2, enum action act, const char *client, char status, struct cntr *p1cntr, struct cntr *cntr, struct config *cconf) { //logp("%s: %s\n", act==ACTION_RESTORE?"restore":"verify", sb->path); write_status(client, status, sb->path, p1cntr, cntr); if((sb->datapth && async_write(CMD_DATAPTH, sb->datapth, strlen(sb->datapth))) || async_write(CMD_STAT, sb->statbuf, sb->slen)) return -1; else if(sb->cmd==CMD_FILE || sb->cmd==CMD_ENC_FILE || sb->cmd==CMD_METADATA || sb->cmd==CMD_ENC_METADATA || sb->cmd==CMD_EFS_FILE) { return restore_file(arr, a, i, sb->datapth, sb->path, tmppath1, tmppath2, act, sb->endfile, sb->cmd, sb->winattr, cntr, cconf); } else { if(async_write(sb->cmd, sb->path, sb->plen)) return -1; // If it is a link, send what // it points to. else if(sbuf_is_link(sb)) { if(async_write(sb->cmd, sb->linkto, sb->llen)) return -1; } do_filecounter(cntr, sb->cmd, 0); } return 0; }
static int do_sbufl_fill_from_file(struct sbuf *sb, FILE *fp, gzFile zp, int phase1, struct cntr *cntr) { int ars; struct iobuf rbuf; //free_sbufl(sb); iobuf_init(&rbuf); if((ars=read_stat(NULL /* no async */, &rbuf, fp, zp, sb, cntr))) return ars; if((ars=read_fp(fp, zp, &rbuf))) return ars; iobuf_copy(&sb->path, &rbuf); if(sbuf_is_link(sb)) { if((ars=read_fp(fp, zp, &rbuf))) return ars; iobuf_copy(&sb->link, &rbuf); if(!cmd_is_link(rbuf.cmd)) return unexpected(&rbuf, __func__); } else if(!phase1 && sbuf_is_filedata(sb)) { if((ars=read_fp(fp, zp, &rbuf))) return ars; iobuf_copy(&(sb->burp1->endfile), &rbuf); if(!cmd_is_endfile(rbuf.cmd)) return unexpected(&rbuf, __func__); } return 0; }
END_TEST static void setup_proto2_some_things(struct asfd *asfd, struct slist *slist) { struct sbuf *s; struct stat statp_dir; struct stat statp_file; int r=0; int w=0; fail_unless(!lstat(BASE, &statp_dir)); fail_unless(!lstat(BASE "/burp.conf", &statp_file)); asfd_assert_write(asfd, &w, 0, CMD_GEN, "restore :"); asfd_mock_read(asfd, &r, 0, CMD_GEN, "ok"); asfd_mock_read(asfd, &r, 0, CMD_GEN, "restore_stream"); asfd_assert_write(asfd, &w, 0, CMD_GEN, "restore_stream_ok"); for(s=slist->head; s; s=s->next) { s->winattr=0; s->compression=0; if(s->path.cmd==CMD_DIRECTORY) { memcpy(&s->statp, &statp_dir, sizeof(statp_dir)); attribs_encode(s); } if(sbuf_is_link(s)) { char path[256]; if(s->path.cmd==CMD_HARD_LINK) snprintf(path, sizeof(path), "%s", s->link.buf); else { char *cp; snprintf(path, sizeof(path), "%s", s->path.buf); fail_unless((cp=strrchr(path, '/'))!=NULL); cp++; snprintf(cp, strlen(s->link.buf)+1, "%s", s->link.buf); } build_file(path, NULL); memcpy(&s->statp, &statp_file, sizeof(statp_file)); attribs_encode(s); asfd_mock_read_iobuf(asfd, &r, 0, &s->attr); asfd_mock_read_iobuf(asfd, &r, 0, &s->path); asfd_mock_read_iobuf(asfd, &r, 0, &s->link); } else if(sbuf_is_filedata(s)) { memcpy(&s->statp, &statp_file, sizeof(statp_file)); attribs_encode(s); asfd_mock_read_iobuf(asfd, &r, 0, &s->attr); asfd_mock_read_iobuf(asfd, &r, 0, &s->path); asfd_mock_read(asfd, &r, 0, CMD_DATA, "data"); } } asfd_mock_read(asfd, &r, 0, CMD_GEN, "restoreend"); asfd_assert_write(asfd, &w, 0, CMD_GEN, "restoreend ok"); }
static void setup_asfds_proto1_stuff(struct asfd *asfd, struct slist *slist) { int r=0; int w=0; struct sbuf *s; for(s=slist->head; s; s=s->next) { if(sbuf_is_link(s)) { asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); asfd_assert_write_iobuf(asfd, &w, 0, &s->link); } else if(sbuf_is_filedata(s)) { struct iobuf wbuf; // The string "data" gzipped. unsigned char gzipped_data1[10] = { 0x1f, 0x8b, 0x08, 0, 0, 0, 0, 0, 0x02, 0x03 }; unsigned char gzipped_data2[14] = { 0x4b, 0x49, 0x2c, 0x49, 0x04, 0x00, 0x63, 0xf3, 0xf3, 0xad, 0x04, 0x00, 0x00, 0x00 }; asfd_assert_write_iobuf(asfd, &w, 0, &s->protocol1->datapth); asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); if(sbuf_is_encrypted(s)) { // Encrypted files get sent as is. asfd_assert_write(asfd, &w, 0, CMD_APPEND, "data"); asfd_assert_write(asfd, &w, 0, CMD_END_FILE, "4:8d777f385d3dfec8815d20f7496026dc"); continue; } // Protocol1 always sends it gzipped. iobuf_set(&wbuf, CMD_APPEND, (char *)gzipped_data1, sizeof(gzipped_data1)); asfd_assert_write_iobuf(asfd, &w, 0, &wbuf); iobuf_set(&wbuf, CMD_APPEND, (char *)gzipped_data2, sizeof(gzipped_data2)); asfd_assert_write_iobuf(asfd, &w, 0, &wbuf); asfd_assert_write(asfd, &w, 0, CMD_END_FILE, "4:8d777f385d3dfec8815d20f7496026dc"); } else { asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); } } asfd_assert_write(asfd, &w, 0, CMD_GEN, "restoreend"); asfd_mock_read_no_op(asfd, &r, 100); asfd_mock_read(asfd, &r, 0, CMD_GEN, "restoreend_ok"); }
static void setup_asfds_proto2_interrupt(struct asfd *asfd, struct slist *slist) { int r=0; int w=0; struct sbuf *s; int count=0; asfd_assert_write(asfd, &w, 0, CMD_GEN, "restore_stream"); asfd_mock_read(asfd, &r, 0, CMD_GEN, "restore_stream_ok"); for(s=slist->head; s; s=s->next) { if(sbuf_is_link(s)) { asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); asfd_assert_write_iobuf(asfd, &w, 0, &s->link); asfd_mock_read_no_op(asfd, &r, 1); } else if(sbuf_is_filedata(s)) { struct blk *b; asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); asfd_mock_read_no_op(asfd, &r, 1); if(count++==1) { asfd_assert_write(asfd, &w, 0, CMD_DATA, "data"); asfd_assert_write(asfd, &w, 0, CMD_DATA, "data"); asfd_mock_read_no_op(asfd, &r, 2); asfd_mock_read(asfd, &r, 0, CMD_INTERRUPT, s->path.buf); asfd_assert_write(asfd, &w, 0, CMD_END_FILE, "0:0"); continue; } for(b=s->protocol2->bstart; b && b!=s->protocol2->bend; b=b->next) { asfd_assert_write(asfd, &w, 0, CMD_DATA, "data"); asfd_mock_read_no_op(asfd, &r, 1); } asfd_assert_write(asfd, &w, 0, CMD_END_FILE, "0:0"); asfd_mock_read_no_op(asfd, &r, 1); } else { asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); asfd_mock_read_no_op(asfd, &r, 1); } } asfd_assert_write(asfd, &w, 0, CMD_GEN, "restoreend"); asfd_mock_read_no_op(asfd, &r, 200); asfd_mock_read(asfd, &r, 0, CMD_GEN, "restoreend_ok"); }
static int restore_sbuf(struct asfd *asfd, struct sbuf *sb, enum action act, enum cstat_status status, struct conf *conf, int *need_data) { //logp("%s: %s\n", act==ACTION_RESTORE?"restore":"verify", sb->path.buf); if(write_status(status, sb->path.buf, conf)) return -1; if(asfd->write(asfd, &sb->attr) || asfd->write(asfd, &sb->path)) return -1; if(sbuf_is_link(sb) && asfd->write(asfd, &sb->link)) return -1; if(sb->burp2->bstart) { // This will restore directory data on Windows. struct blk *b=NULL; struct blk *n=NULL; b=sb->burp2->bstart; while(b) { struct iobuf wbuf; iobuf_set(&wbuf, CMD_DATA, b->data, b->length); if(asfd->write(asfd, &wbuf)) return -1; n=b->next; blk_free(&b); b=n; } sb->burp2->bstart=sb->burp2->bend=NULL; } switch(sb->path.cmd) { case CMD_FILE: case CMD_ENC_FILE: case CMD_METADATA: case CMD_ENC_METADATA: case CMD_EFS_FILE: *need_data=1; return 0; default: cntr_add(conf->cntr, sb->path.cmd, 0); return 0; } }
static int do_sbufl_fill_from_net(struct sbuf *sb, struct asfd *asfd, struct cntr *cntr) { int ars; static struct iobuf *rbuf=NULL; rbuf=asfd->rbuf; iobuf_free_content(rbuf); if((ars=read_stat(asfd, rbuf, NULL, NULL, sb, cntr)) || (ars=asfd->read(asfd))) return ars; iobuf_copy(&sb->path, rbuf); rbuf->buf=NULL; if(sbuf_is_link(sb)) { if((ars=asfd->read(asfd))) return ars; iobuf_copy(&sb->link, rbuf); rbuf->buf=NULL; if(!cmd_is_link(rbuf->cmd)) return unexpected(rbuf, __func__); } return 0; }
int restore_sbuf_protocol2(struct asfd *asfd, struct sbuf *sb, enum action act, struct cntr *cntr, struct sbuf *need_data) { if(asfd->write(asfd, &sb->attr) || asfd->write(asfd, &sb->path)) return -1; if(sbuf_is_link(sb) && asfd->write(asfd, &sb->link)) return -1; if(sb->protocol2->bstart) { // This will restore directory data on Windows. struct blk *b=NULL; struct blk *n=NULL; b=sb->protocol2->bstart; while(b) { if(send_data(asfd, b, act, need_data, cntr)) return -1; n=b->next; blk_free(&b); b=n; } sb->protocol2->bstart=sb->protocol2->bend=NULL; } if(sbuf_is_filedata(sb)) { if(need_data) { iobuf_copy(&need_data->path, &sb->path); sb->path.buf=NULL; } } else cntr_add(cntr, sb->path.cmd, 0); return 0; }
END_TEST static void setup_asfds_proto2_stuff(struct asfd *asfd, struct slist *slist) { int r=0; int w=0; struct sbuf *s; asfd_assert_write(asfd, &w, 0, CMD_GEN, "restore_stream"); asfd_mock_read(asfd, &r, 0, CMD_GEN, "restore_stream_ok"); for(s=slist->head; s; s=s->next) { if(sbuf_is_link(s)) { asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); asfd_assert_write_iobuf(asfd, &w, 0, &s->link); } else if(sbuf_is_filedata(s)) { struct blk *b; asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); for(b=s->protocol2->bstart; b && b!=s->protocol2->bend; b=b->next) asfd_assert_write(asfd, &w, 0, CMD_DATA, "data"); asfd_assert_write(asfd, &w, 0, CMD_END_FILE, "0:0"); } else { asfd_assert_write_iobuf(asfd, &w, 0, &s->attr); asfd_assert_write_iobuf(asfd, &w, 0, &s->path); } } asfd_assert_write(asfd, &w, 0, CMD_GEN, "restoreend"); asfd_mock_read_no_op(asfd, &r, 300); asfd_mock_read(asfd, &r, 0, CMD_GEN, "restoreend_ok"); }
static void setup_proto1_some_things(struct asfd *asfd, struct slist *slist) { struct sbuf *s; struct stat statp_dir; struct stat statp_file; int r=0; int w=0; fail_unless(!lstat(BASE, &statp_dir)); fail_unless(!lstat(BASE "/burp.conf", &statp_file)); asfd_assert_write(asfd, &w, 0, CMD_GEN, "restore :"); asfd_mock_read(asfd, &r, 0, CMD_GEN, "ok"); for(s=slist->head; s; s=s->next) { s->winattr=0; s->compression=0; if(s->path.cmd==CMD_DIRECTORY) { memcpy(&s->statp, &statp_dir, sizeof(statp_dir)); attribs_encode(s); } if(sbuf_is_link(s)) { char path[256]; if(s->path.cmd==CMD_HARD_LINK) snprintf(path, sizeof(path), "%s", s->link.buf); else { char *cp; snprintf(path, sizeof(path), "%s", s->path.buf); fail_unless((cp=strrchr(path, '/'))!=NULL); cp++; snprintf(cp, strlen(s->link.buf)+1, "%s", s->link.buf); } build_file(path, NULL); memcpy(&s->statp, &statp_file, sizeof(statp_file)); attribs_encode(s); asfd_mock_read_iobuf(asfd, &r, 0, &s->attr); asfd_mock_read_iobuf(asfd, &r, 0, &s->path); asfd_mock_read_iobuf(asfd, &r, 0, &s->link); } else if(sbuf_is_filedata(s)) { struct iobuf rbuf; // The string "data" gzipped. unsigned char gzipped_data[27] = { 0x1f, 0x8b, 0x08, 0x08, 0xb4, 0x1e, 0x7f, 0x56, 0x00, 0x03, 0x79, 0x00, 0x4b, 0x49, 0x2c, 0x49, 0xe4, 0x02, 0x00, 0x82, 0xc5, 0xc1, 0xe6, 0x05, 0x00, 0x00, 0x00 }; memcpy(&s->statp, &statp_file, sizeof(statp_file)); attribs_encode(s); asfd_mock_read(asfd, &r, 0, CMD_DATAPTH, s->path.buf); asfd_mock_read_iobuf(asfd, &r, 0, &s->attr); asfd_mock_read_iobuf(asfd, &r, 0, &s->path); // Protocol1 always sends it gzipped. iobuf_set(&rbuf, CMD_APPEND, (char *)gzipped_data, sizeof(gzipped_data)); asfd_mock_read_iobuf(asfd, &r, 0, &rbuf); asfd_mock_read(asfd, &r, 0, CMD_END_FILE, "0:19201273128"); } } asfd_mock_read(asfd, &r, 0, CMD_GEN, "restoreend"); asfd_assert_write(asfd, &w, 0, CMD_GEN, "restoreend ok"); }
static int list_manifest(struct asfd *asfd, const char *fullpath, regex_t *regex, const char *browsedir, struct conf *conf) { int ars=0; int ret=0; struct sbuf *sb=NULL; struct manio *manio=NULL; char *manifest_dir=NULL; char *last_bd_match=NULL; size_t bdlen=0; if(!(manifest_dir=prepend_s(fullpath, conf->protocol==PROTO_BURP1?"manifest.gz":"manifest")) || !(manio=manio_alloc()) || manio_init_read(manio, manifest_dir) || !(sb=sbuf_alloc(conf))) { log_and_send_oom(asfd, __func__); goto error; } manio_set_protocol(manio, conf->protocol); if(browsedir) bdlen=strlen(browsedir); while(1) { int show=0; if((ars=manio_sbuf_fill(manio, asfd, sb, NULL, NULL, conf))<0) goto error; else if(ars>0) goto end; // Finished OK. if(write_status(STATUS_LISTING, sb->path.buf, conf)) goto error; if(browsedir) { int r; if((r=check_browsedir(browsedir, &sb->path.buf, bdlen, &last_bd_match))<0) goto error; if(!r) continue; show++; } else { if(check_regex(regex, sb->path.buf)) show++; } if(show) { if(write_wrapper(asfd, &sb->attr) || write_wrapper(asfd, &sb->path)) goto error; if(sbuf_is_link(sb) && write_wrapper(asfd, &sb->link)) goto error; } sbuf_free_content(sb); } error: ret=-1; end: sbuf_free(&sb); free_w(&manifest_dir); manio_free(&manio); free_w(&last_bd_match); return ret; }
static int list_manifest(const char *fullpath, regex_t *regex, const char *browsedir, const char *client, struct cntr *p1cntr, struct cntr *cntr) { int ars=0; int ret=0; int quit=0; gzFile zp=NULL; struct sbuf mb; char *manifest=NULL; size_t bdlen=0; init_sbuf(&mb); if(!(manifest=prepend_s(fullpath, "manifest.gz", strlen("manifest.gz")))) { log_and_send_oom(__FUNCTION__); return -1; } if(!(zp=gzopen_file(manifest, "rb"))) { log_and_send("could not open manifest"); free(manifest); return -1; } free(manifest); if(browsedir) bdlen=strlen(browsedir); while(!quit) { int show=0; //logp("list manifest loop\n"); // Need to parse while sending, to take note of the regex. free_sbuf(&mb); if((ars=sbuf_fill(NULL, zp, &mb, cntr))) { if(ars<0) ret=-1; // ars==1 means it ended ok. break; } if(mb.cmd!=CMD_DIRECTORY && mb.cmd!=CMD_FILE && mb.cmd!=CMD_ENC_FILE && mb.cmd!=CMD_EFS_FILE && mb.cmd!=CMD_SPECIAL && !cmd_is_link(mb.cmd)) continue; //if(mb.path[mb.plen]=='\n') mb.path[mb.plen]='\0'; write_status(client, STATUS_LISTING, mb.path, p1cntr, cntr); if(browsedir) { int r; if((r=check_browsedir(browsedir, &(mb.path), bdlen))<0) { quit++; ret=-1; } if(!r) continue; show++; } else { if(check_regex(regex, mb.path)) show++; } if(show) { if(async_write(CMD_STAT, mb.statbuf, mb.slen) || async_write(mb.cmd, mb.path, mb.plen)) { quit++; ret=-1; } else if(sbuf_is_link(&mb) && async_write(mb.cmd, mb.linkto, mb.llen)) { quit++; ret=-1; } } } gzclose_fp(&zp); free_sbuf(&mb); return ret; }
static int list_manifest(const char *fullpath) { int ret=0; struct sbuf *sb=NULL; struct manio *manio=NULL; char *manifest_dir=NULL; char *last_bd_match=NULL; size_t bdlen=0; if(!(manifest_dir=prepend_s(fullpath, protocol==PROTO_1?"manifest.gz":"manifest")) || !(manio=manio_open(manifest_dir, "rb", protocol)) || !(sb=sbuf_alloc(protocol))) { log_and_send_oom(asfd); goto error; } if(browsedir) bdlen=strlen(browsedir); while(1) { sbuf_free_content(sb); switch(manio_read(manio, sb)) { case 0: break; case 1: if(browsedir && *browsedir && !last_bd_match) asfd_write_wrapper_str(asfd, CMD_ERROR, "directory not found"); goto end; // Finished OK. default: goto error; } if(protocol==PROTO_2 && sb->endfile.buf) continue; if(sbuf_is_metadata(sb)) continue; if(write_status(CNTR_STATUS_LISTING, sb->path.buf, cntr)) goto error; if(browsedir) { int r; if((r=check_browsedir(browsedir, sb, bdlen, &last_bd_match))<0) goto error; if(!r) continue; } if(regex && !regex_check(regex, sb->path.buf)) continue; if(asfd_write_wrapper(asfd, &sb->attr) || asfd_write_wrapper(asfd, &sb->path)) goto error; if(sbuf_is_link(sb) && asfd_write_wrapper(asfd, &sb->link)) goto error; } error: ret=-1; end: sbuf_free(&sb); free_w(&manifest_dir); manio_close(&manio); free_w(&last_bd_match); return ret; }