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; }
static int do_browse_manifest(struct asfd *srfd, struct manio *manio, struct sbuf *sb, const char *browse) { int ret=-1; int ars=0; //char ls[1024]=""; //struct cntr cntr; size_t blen=0; char *last_bd_match=NULL; if(browse) blen=strlen(browse); while(1) { int r; sbuf_free_content(sb); if((ars=manio_read(manio, sb))) { if(ars<0) goto end; // ars==1 means it ended ok. break; } if(manio->protocol==PROTO_2 && sb->endfile.buf) continue; if(sb->path.cmd!=CMD_DIRECTORY && sb->path.cmd!=CMD_FILE && sb->path.cmd!=CMD_ENC_FILE && sb->path.cmd!=CMD_EFS_FILE && sb->path.cmd!=CMD_SPECIAL && !cmd_is_link(sb->path.cmd)) continue; if((r=check_browsedir(browse, sb, blen, &last_bd_match))<0) goto end; if(!r) continue; if(json_from_statp(sb->path.buf, &sb->statp)) goto end; } ret=0; end: free_w(&last_bd_match); return ret; }
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 do_list_client(struct asfd *asfd, struct conf *conf, enum action act, int json) { int ret=-1; char msg[512]=""; char *dpth=NULL; struct sbuf *sb=NULL; int json_started=0; struct iobuf *rbuf=asfd->rbuf; //logp("in do_list\n"); if(conf->browsedir) snprintf(msg, sizeof(msg), "listb %s:%s", conf->backup?conf->backup:"", conf->browsedir); else snprintf(msg, sizeof(msg), "list %s:%s", conf->backup?conf->backup:"", conf->regex?conf->regex:""); if(asfd->write_str(asfd, CMD_GEN, msg) || asfd->read_expect(asfd, CMD_GEN, "ok")) goto end; if(!(sb=sbuf_alloc(conf))) goto end; iobuf_init(&sb->path); iobuf_init(&sb->link); iobuf_init(&sb->attr); if(json) { open_tag(0, NULL); open_tag(1, "backups"); json_started++; } // This should probably should use the sbuf stuff. while(1) { sbuf_free_content(sb); iobuf_free_content(rbuf); if(asfd->read(asfd)) break; if(rbuf->cmd==CMD_TIMESTAMP) { // A backup timestamp, just print it. if(json) json_backup(rbuf->buf, conf); else { printf("Backup: %s\n", rbuf->buf); if(conf->browsedir) printf("Listing directory: %s\n", conf->browsedir); if(conf->regex) printf("With regex: %s\n", conf->regex); } continue; } else if(rbuf->cmd!=CMD_ATTRIBS) { iobuf_log_unexpected(rbuf, __func__); goto end; } iobuf_copy(&sb->attr, rbuf); iobuf_init(rbuf); attribs_decode(sb); if(asfd->read(asfd)) { logp("got stat without an object\n"); goto end; } iobuf_copy(&sb->path, rbuf); iobuf_init(rbuf); if(sb->path.cmd==CMD_DIRECTORY || sb->path.cmd==CMD_FILE || sb->path.cmd==CMD_ENC_FILE || sb->path.cmd==CMD_EFS_FILE || sb->path.cmd==CMD_SPECIAL) { list_item(json, act, sb); } else if(cmd_is_link(sb->path.cmd)) // symlink or hardlink { if(asfd->read(asfd) || rbuf->cmd!=sb->path.cmd) { logp("could not get link %c:%s\n", sb->path.cmd, sb->path.buf); goto end; } iobuf_copy(&sb->link, rbuf); iobuf_init(rbuf); list_item(json, act, sb); } else { fprintf(stderr, "unlistable %c:%s\n", sb->path.cmd, sb->path.buf?sb->path.buf:""); } } ret=0; end: if(json && json_started) close_tag(0); printf("\n"); iobuf_free_content(&sb->path); iobuf_free_content(&sb->link); iobuf_free_content(&sb->attr); if(dpth) free(dpth); sbuf_free(&sb); if(!ret) logp("List finished ok\n"); return ret; }
int do_list_client(struct config *conf, enum action act, int json) { int ret=0; size_t slen=0; char msg[512]=""; char scmd=0; struct stat statp; char *statbuf=NULL; char ls[2048]=""; char *dpth=NULL; int first_entry=1; // format long list as JSON int emit_json = (act==ACTION_LONG_LIST && conf->backup && json); //logp("in do_list\n"); if(conf->browsedir) snprintf(msg, sizeof(msg), "listb %s:%s", conf->backup?conf->backup:"", conf->browsedir); else snprintf(msg, sizeof(msg), "list %s:%s", conf->backup?conf->backup:"", conf->regex?conf->regex:""); if(async_write_str(CMD_GEN, msg) || async_read_expect(CMD_GEN, "ok")) return -1; if(emit_json) { printf("{\n"); } // This should probably should use the sbuf stuff. while(1) { char fcmd=0; size_t flen=0; int64_t winattr=0; int compression=-1; char *fname=NULL; if(async_read(&scmd, &statbuf, &slen)) { //ret=-1; break; break; } if(scmd==CMD_TIMESTAMP) { // A backup timestamp, just print it. if(emit_json) { printf("\t\"backup\":\n" "\t\t{\n" "\t\t\t\"timestamp\": \"%s\",\n" "\t\t\t\"directory\": \"%s\",\n" "\t\t\t\"regex\": \"%s\"\n" "\t\t},\n", statbuf, conf->browsedir? conf->browsedir:"", conf->regex? conf->regex:""); } else { printf("Backup: %s\n", statbuf); if(conf->browsedir) printf("Listing directory: %s\n", conf->browsedir); if(conf->regex) printf("With regex: %s\n", conf->regex); } if(statbuf) { free(statbuf); statbuf=NULL; } continue; } else if(scmd==CMD_DATAPTH) { if(statbuf) { free(statbuf); statbuf=NULL; } continue; } else if(scmd!=CMD_STAT) { logp("expected %c cmd - got %c:%s\n", CMD_STAT, scmd, statbuf); ret=-1; break; } decode_stat(statbuf, &statp, &winattr, &compression); if(async_read(&fcmd, &fname, &flen)) { logp("got stat without an object\n"); ret=-1; break; } else if(fcmd==CMD_DIRECTORY || fcmd==CMD_FILE || fcmd==CMD_ENC_FILE || fcmd==CMD_EFS_FILE || fcmd==CMD_SPECIAL) { *ls='\0'; if(act==ACTION_LONG_LIST) { if(emit_json) { char *esc_fname = NULL; ls_output_json(ls, sizeof(ls), first_entry, fcmd, fname, &esc_fname, NULL, NULL, &statp); printf(ls, esc_fname? esc_fname:"", ""); if(esc_fname) free(esc_fname); } else { ls_output(ls, fname, &statp); printf("%s\n", ls); } } else { printf("%s\n", fname); } if (first_entry) { first_entry = 0; } } else if(cmd_is_link(fcmd)) // symlink or hardlink { char lcmd=0; size_t llen=0; char *lname=NULL; if(async_read(&lcmd, &lname, &llen) || lcmd!=fcmd) { logp("could not get second part of link %c:%s\n", fcmd, fname); ret=-1; } else { if(act==ACTION_LONG_LIST) { *ls='\0'; if(emit_json) { char *esc_fname = NULL; char *esc_lname = NULL; ls_output_json(ls, sizeof(ls), first_entry, fcmd, fname, &esc_fname, lname, &esc_lname, &statp); printf(ls, esc_fname? esc_fname:"", esc_lname? esc_lname:""); if(esc_fname) free(esc_fname); if(esc_lname) free(esc_lname); } else { ls_output(ls, fname, &statp); printf("%s -> %s\n", ls, lname); } } else { printf("%s\n", fname); } if (first_entry) { first_entry = 0; } } if(lname) free(lname); } else { fprintf(stderr, "unlistable %c:%s\n", fcmd, fname?:""); } if(fname) free(fname); if(statbuf) { free(statbuf); statbuf=NULL; } } if(statbuf) free(statbuf); if(dpth) free(dpth); if(emit_json) { if(!first_entry) { printf("\t\t]\n"); } printf("}\n"); } if(!ret) logp("List finished ok\n"); return ret; }
int iobuf_is_link(struct iobuf *iobuf) { return cmd_is_link(iobuf->cmd); }
int do_list_client(struct asfd *asfd, enum action act, struct conf **confs) { int ret=-1; char msg[512]=""; struct sbuf *sb=NULL; struct iobuf *rbuf=asfd->rbuf; const char *backup=get_string(confs[OPT_BACKUP]); const char *backup2=get_string(confs[OPT_BACKUP2]); const char *browsedir=get_string(confs[OPT_BROWSEDIR]); const char *regex=get_string(confs[OPT_REGEX]); //logp("in do_list\n"); switch(act) { case ACTION_LIST: case ACTION_LIST_LONG: if(browsedir && regex) { logp("You cannot specify both a directory and a regular expression when listing.\n"); goto end; } if(browsedir) snprintf(msg, sizeof(msg), "listb %s:%s", backup?backup:"", browsedir); else snprintf(msg, sizeof(msg), "list %s:%s", backup?backup:"", regex?regex:""); break; case ACTION_DIFF: case ACTION_DIFF_LONG: snprintf(msg, sizeof(msg), "diff %s:%s", backup?backup:"", backup2?backup2:""); break; default: logp("unknown action %d\n", act); goto end; } if(asfd->write_str(asfd, CMD_GEN, msg) || asfd_read_expect(asfd, CMD_GEN, "ok")) goto end; if(!(sb=sbuf_alloc(get_protocol(confs)))) goto end; iobuf_init(&sb->path); iobuf_init(&sb->link); iobuf_init(&sb->attr); // This should probably should use the sbuf stuff. while(1) { sbuf_free_content(sb); iobuf_free_content(rbuf); if(asfd->read(asfd)) break; if(rbuf->cmd==CMD_MESSAGE) { printf("%s\n", rbuf->buf); if(!strcmp(rbuf->buf, "no backups")) ret=0; goto end; } else if(rbuf->cmd==CMD_TIMESTAMP) { // A backup timestamp, just print it. printf("Backup: %s\n", rbuf->buf); if(browsedir) printf("Listing directory: %s\n", browsedir); if(regex) printf("With regex: %s\n", regex); continue; } else if(rbuf->cmd!=CMD_ATTRIBS) { iobuf_log_unexpected(rbuf, __func__); goto end; } iobuf_copy(&sb->attr, rbuf); iobuf_init(rbuf); attribs_decode(sb); if(asfd->read(asfd)) { logp("got stat without an object\n"); goto end; } iobuf_copy(&sb->path, rbuf); iobuf_init(rbuf); if(sb->path.cmd==CMD_DIRECTORY || sb->path.cmd==CMD_FILE || sb->path.cmd==CMD_ENC_FILE || sb->path.cmd==CMD_EFS_FILE || sb->path.cmd==CMD_SPECIAL) { list_item(act, sb); } else if(cmd_is_link(sb->path.cmd)) // symlink or hardlink { if(asfd->read(asfd) || rbuf->cmd!=sb->path.cmd) { logp("could not get link %s\n", iobuf_to_printable(&sb->path)); goto end; } iobuf_copy(&sb->link, rbuf); iobuf_init(rbuf); list_item(act, sb); } else { logp("unlistable %s\n", iobuf_to_printable(&sb->path)); } } ret=0; end: sbuf_free(&sb); if(!ret) logp("List finished ok\n"); 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 enum parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd, struct iobuf *rbuf, struct blk *blk, struct cntr *cntr) { switch(rbuf->cmd) { case CMD_ATTRIBS: if(sb->protocol2) sbuf_free_content(sb); else { if(sb->protocol1->datapth.buf) // protocol 1 phase 2+ file data // starts with datapth. iobuf_free_content(&sb->attr); else // protocol 1 phase 1 or non file data // starts with attribs sbuf_free_content(sb); } iobuf_move(&sb->attr, rbuf); attribs_decode(sb); return PARSE_RET_NEED_MORE; case CMD_FILE: case CMD_DIRECTORY: case CMD_SOFT_LINK: case CMD_HARD_LINK: case CMD_SPECIAL: // Stuff not currently supported in burp-2, but OK // to find in burp-1. case CMD_ENC_FILE: case CMD_METADATA: case CMD_ENC_METADATA: case CMD_EFS_FILE: case CMD_VSS: case CMD_ENC_VSS: case CMD_VSS_T: case CMD_ENC_VSS_T: if(!sb->attr.buf) { log_and_send(asfd, "read cmd with no attribs"); return PARSE_RET_ERROR; } if(sb->flags & SBUF_NEED_LINK) { if(cmd_is_link(rbuf->cmd)) { iobuf_free_content(&sb->link); iobuf_move(&sb->link, rbuf); sb->flags &= ~SBUF_NEED_LINK; return PARSE_RET_COMPLETE; } else { log_and_send(asfd, "got non-link after link in manifest"); return PARSE_RET_NEED_MORE; } } else { iobuf_free_content(&sb->path); iobuf_move(&sb->path, rbuf); if(cmd_is_link(rbuf->cmd)) { sb->flags |= SBUF_NEED_LINK; return PARSE_RET_NEED_MORE; } else if(sb->protocol1 && sb->protocol1->datapth.buf) { // Protocol1 client restore reads // CMD_APPEND and CMD_END_FILE in the // calling function, so pretend it is // complete if we have the hack flag. if(sb->flags & SBUF_CLIENT_RESTORE_HACK) return PARSE_RET_COMPLETE; return PARSE_RET_NEED_MORE; } return PARSE_RET_COMPLETE; } #ifndef HAVE_WIN32 case CMD_SIG: // Fill in the sig/block, if the caller provided // a pointer for one. Server only. if(!blk) return PARSE_RET_NEED_MORE; // Just fill in the sig details. if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf)) return PARSE_RET_ERROR; blk->got_save_path=1; iobuf_free_content(rbuf); return PARSE_RET_COMPLETE; #endif case CMD_DATA: // Need to write the block to disk. // Client only. if(!blk) return PARSE_RET_NEED_MORE; blk->data=rbuf->buf; blk->length=rbuf->len; rbuf->buf=NULL; return PARSE_RET_COMPLETE; case CMD_MESSAGE: case CMD_WARNING: log_recvd(rbuf, cntr, 1); return PARSE_RET_NEED_MORE; case CMD_GEN: if(!strcmp(rbuf->buf, "restoreend") || !strcmp(rbuf->buf, "phase1end") || !strcmp(rbuf->buf, "backupphase2") // Think these are protocol1 things. || !strcmp(rbuf->buf, "backupend") || !strcmp(rbuf->buf, "estimateend")) return PARSE_RET_FINISHED; iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; case CMD_FINGERPRINT: if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf)) return PARSE_RET_ERROR; // Fall through. case CMD_MANIFEST: iobuf_free_content(&sb->path); iobuf_move(&sb->path, rbuf); return PARSE_RET_COMPLETE; case CMD_ERROR: logp("got error: %s\n", rbuf->buf); return PARSE_RET_ERROR; case CMD_DATAPTH: if(!sb->protocol1) { iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; } if(sb->flags & SBUF_CLIENT_RESTORE_HACK) { sbuf_free_content(sb); sb->flags |= SBUF_CLIENT_RESTORE_HACK; } else sbuf_free_content(sb); iobuf_move(&sb->protocol1->datapth, rbuf); return PARSE_RET_NEED_MORE; case CMD_END_FILE: iobuf_free_content(&sb->endfile); iobuf_move(&sb->endfile, rbuf); if(sb->protocol1) { if(!sb->attr.buf || !sb->protocol1->datapth.buf || (!sbuf_is_filedata(sb) && !sbuf_is_vssdata(sb))) { logp("got unexpected cmd_endfile"); return PARSE_RET_ERROR; } } return PARSE_RET_COMPLETE; default: iobuf_log_unexpected(rbuf, __func__); return PARSE_RET_ERROR; } logp("Fell out of switch unexpectedly in %s()\n", __func__); return PARSE_RET_ERROR; }