Example #1
0
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;
}
Example #4
0
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);
}
Example #5
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);
}