int ct_regex_comp(regex_t *re, char **flist) { int i, rv; char *s, *q = NULL, error[1024]; for (i = 0; flist[i] != NULL; i++) { if (flist[i] == NULL) break; if (i == 0) e_asprintf(&s, "%s", flist[i]); else e_asprintf(&s, "%s|%s", q, flist[i]); if (q) e_free(&q); q = s; } if (q == NULL) return (0); if ((rv = regcomp(re, q, REG_EXTENDED | REG_NOSUB)) != 0) { regerror(rv, re, error, sizeof(error) - 1); CNDBG(CT_LOG_FILE, "regcomp failed: %s", error); e_free(&q); return (CTE_REGEX); } e_free(&q); return (0); }
/* * return the filename in the cache directory that a ctfile would have * if it extisted. */ char * ctfile_get_cachename(const char *ctfile, const char *cachedir) { char *cachename; /* cachedir was made sure to terminate with / earlier */ e_asprintf(&cachename, "%s%s", cachedir, ctfile); return cachename; }
/* * filenames passed in remote mode are opaque tags for the backup. * they are stored on the server and in remote mode in the form * YYYYMMDD-HHMMSS-<strnvis(mname)> */ void ctfile_find_for_extract(struct ct_global_state *state, struct ct_op *op) { struct ct_ctfile_find_args *ccfa = op->op_args; const char *ctfile = ccfa->ccfa_tag; struct ct_op *list_fakeop; struct ct_ctfile_list_args *ccla; if (state->ct_dying != 0) { /* nothing to clean up */ return; } /* cook the ctfile so we only search for the actual tag */ if ((ctfile = ctfile_cook_name(ctfile)) == NULL) { ct_fatal(state, ccfa->ccfa_tag, CTE_INVALID_CTFILE_NAME); return; } list_fakeop = e_calloc(1, sizeof(*list_fakeop)); ccla = e_calloc(1, sizeof(*ccla)); list_fakeop->op_args = ccla; ccla->ccla_search = e_calloc(2, sizeof(char **)); if (ctfile_is_fullname(ctfile)) { /* use list as stat() for now */ *ccla->ccla_search = e_strdup(ctfile); ccla->ccla_matchmode = CT_MATCH_GLOB; } else { e_asprintf(ccla->ccla_search, "^[[:digit:]]{8}-[[:digit:]]{6}-%s$", ctfile); ccla->ccla_matchmode = CT_MATCH_REGEX; /* * get the list of files matching this tag from the server. * list returns an empty list if it found * nothing and NULL upon failure. */ } e_free(&ctfile); CNDBG(CT_LOG_CTFILE, "looking for %s", ccla->ccla_search[0]); op->op_priv = list_fakeop; ctfile_list_start(state, list_fakeop); return; }
int ct_extract_complete_file_read(struct ct_global_state *state, struct ct_trans *trans) { int slot, ret; state->ct_stats->st_chunks_completed++; if (trans->tr_errno != 0) { char *errstr; char shat[SHA_DIGEST_STRING_LENGTH]; /* any other read failure is bad */ ct_sha1_encode(trans->tr_sha, shat); e_asprintf(&errstr, "Data missing on server: " "file %s, sha %s", trans->tr_fl_node ? trans->tr_fl_node->fn_fullname : "unknown", shat); ct_fatal(state, errstr, trans->tr_errno); free(errstr); return (0); } if (trans->tr_fl_node->fn_skip_file == 0) { slot = trans->tr_dataslot; ct_sha1_add(trans->tr_data[slot], &trans->tr_fl_node->fn_shactx, trans->tr_size[slot]); if ((ret = ct_file_extract_write(state->extract_state, trans->tr_fl_node, trans->tr_data[slot], trans->tr_size[slot])) != 0) { /* * XXX really this shouldn't be fatal, just make us skip * the file in future and CWARNX. */ ct_fatal(state, "Failed to write file", ret); return (0); } state->ct_stats->st_bytes_written += trans->tr_size[slot]; } return (0); }
int ct_get_cert_bundle(const char *user, const char *pass, char **xml, size_t *xml_sz) { CURL *c = NULL; int rv = -1; char *username = NULL, *password = NULL, *mode = NULL; char *login_post_data = NULL; long rc; char *ru; struct memdesc chunk; char *x = NULL; size_t xs = 0; long flags; /* init mem structure */ chunk.memory = NULL; chunk.size = 0; /* * Per the curl documentation, this function is not thread safe as it * calls initialization routines of other libraries; This most notably * causes issues with OpenSSL, so we rely on it having been initalized * before hand [assl]. */ flags = CURL_GLOBAL_ALL; #ifndef CT_CURL_INIT_SSL flags &= ~CURL_GLOBAL_SSL; #endif curl_global_init(flags); c = curl_easy_init(); if (c == NULL) goto done; #if 0 /* debug */ if (curl_easy_setopt(c, CURLOPT_VERBOSE, 1L)) { rv = -2; goto done; } #endif /* enable cookies in memory */ if (curl_easy_setopt(c, CURLOPT_COOKIEFILE, "")) { rv = -4; goto done; } /* verify cert */ curl_easy_setopt(c, CURLOPT_SSL_CTX_FUNCTION, sslctx_cb); if (curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 1L)) { rv = -5; goto done; } if (curl_easy_setopt(c, CURLOPT_SSL_VERIFYHOST, 2L)) { rv = -6; goto done; } /* write callback */ if (curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_mem_cb)) { rv = -7; goto done; } if (curl_easy_setopt(c, CURLOPT_WRITEDATA, (void *)&chunk)) { rv = -8; goto done; } /* login */ if ((username = curl_easy_escape(c, user, 0)) == NULL) { rv = -10; goto done; } if ((password = curl_easy_escape(c, pass, 0)) == NULL) { rv = -11; goto done; } if ((mode = curl_easy_escape(c, "login-process", 0)) == NULL) { rv = -12; goto done; } e_asprintf(&login_post_data, "username=%s&password=%s&do=%s", username, password, mode); curl_easy_setopt(c, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); curl_easy_setopt(c, CURLOPT_POSTFIELDS, login_post_data); if (curl_easy_setopt(c, CURLOPT_URL, URL LOGIN)) { rv = -13; goto done; } if (curl_easy_perform(c)) { rv = -14; goto done; } if (curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &rc)) { rv = -15; goto done; } if (curl_easy_getinfo(c, CURLINFO_REDIRECT_URL, &ru)) { rv = -16; goto done; } if (chunk.memory) { e_free(&chunk.memory); chunk.size = 0; } CDBG("login -> rc = %ld -> %s\n", rc, ru); if (strcmp(ru, URL ACCOUNT)) { rv = CT_CERT_BUNDLE_LOGIN_FAILED; goto done; } /* get certs */ curl_easy_setopt(c, CURLOPT_POSTFIELDS, NULL); curl_easy_setopt(c, CURLOPT_POST, 0L); if (curl_easy_setopt(c, CURLOPT_URL, URL ACCOUNT ACCOUNT_CERT)) { rv = -20; goto done; } if (curl_easy_perform(c)) { rv = -21; goto done; } if (curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &rc)) { rv = -22; goto done; } if (curl_easy_getinfo(c, CURLINFO_REDIRECT_URL, &ru)) { rv = -23; goto done; } CDBG("get certs: rc = %ld sz = %ld-> %s\n", rc, (long) chunk.size, ru); if (!(rc == 200 && ru == NULL)) { rv = -24; goto done; } xs = chunk.size; x = e_malloc(xs + 1); /* + nul */ x[xs] = '\0'; bcopy(chunk.memory, x, xs); /* logout */ if (curl_easy_setopt(c, CURLOPT_URL, URL LOGIN LOGIN_LOGOUT)) { rv = -30; goto done; } if (curl_easy_perform(c)) { rv = -31; goto done; } if (curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &rc)) { rv = -32; goto done; } if (curl_easy_getinfo(c, CURLINFO_REDIRECT_URL, &ru)) { rv = -33; goto done; } if (chunk.memory) { e_free(&chunk.memory); chunk.size = 0; } CDBG("logout: rc = %ld -> %s\n", rc, ru); if (strcmp(ru, URL INDEX)) { rv = -34; goto done; } rv = 0; done: if (chunk.memory) e_free(&chunk.memory); if (username) curl_free(username); if (password) curl_free(password); if (mode) curl_free(mode); if (login_post_data) e_free(&login_post_data); if (c) curl_easy_cleanup(c); curl_global_cleanup(); if (rv && x) e_free(&x); else { /* success */ *xml = x; *xml_sz = xs; } return (rv); }
int ctfile_nextop_archive(struct ct_global_state *state, char *basis, void *args) { struct ct_archive_args *caa = args; struct ct_ctfileop_args *cca; char *ctfile; char buf[TIMEDATA_LEN], *fullname, *cachename; time_t now; CNDBG(CT_LOG_CTFILE, "setting basisname %s", basis ? basis : "<none>"); caa->caa_basis = basis; /* * We now have the basis found for us, cook and prepare the tag * we wish to create then add the operation. */ if ((ctfile = ctfile_cook_name(caa->caa_tag)) == NULL) { CWARNX("%s: %s", caa->caa_tag, ct_strerror(CTE_INVALID_CTFILE_NAME)); return (CTE_INVALID_CTFILE_NAME); } if (ctfile_is_fullname(ctfile) != 0) { CWARNX("%s", ct_strerror(CTE_ARCHIVE_FULLNAME)); e_free(&ctfile); return (CTE_ARCHIVE_FULLNAME); } now = time(NULL); if (strftime(buf, TIMEDATA_LEN, "%Y%m%d-%H%M%S", localtime(&now)) == 0) CABORTX("can't format time"); e_asprintf(&fullname, "%s-%s", buf, ctfile); CNDBG(CT_LOG_CTFILE, "backup file is %s", fullname); /* check it isn't already in the cache */ cachename = ctfile_get_cachename(fullname, state->ct_config->ct_ctfile_cachedir); if (ctfile_in_cache(fullname, state->ct_config->ct_ctfile_cachedir)) { CWARNX("%s: %s", fullname, ct_strerror(CTE_BACKUP_ALREADY_EXISTS)); e_free(&ctfile); e_free(&fullname); e_free(&cachename); return (CTE_BACKUP_ALREADY_EXISTS); } e_free(&ctfile); e_free(&fullname); caa->caa_local_ctfile = cachename; ct_add_operation(state, ct_archive, NULL, caa); /* * set up an additional operation to upload the newly created * ctfile after the archive is completed. */ cca = e_calloc(1, sizeof(*cca)); cca->cca_localname = cachename; cca->cca_cleartext = 0; cca->cca_ctfile = 1; ct_add_operation(state, ctfile_archive, ctfile_nextop_archive_cleanup, cca); return (0); }