コード例 #1
25
int
ct_compare_secrets(struct ct_global_state *state, struct ct_op *op)
{
	struct ct_ctfileop_args		*cca = op->op_args;
	FILE				*f, *tf;
	char				 temp_path[PATH_MAX];
	struct stat			 sb, tsb;
	char				 buf[1024], tbuf[1024];
	size_t				 rsz;
	off_t				 sz;
	int				 ret = 0, s_errno = 0;

	/* cachedir is '/' terminated */
	strlcpy(temp_path, cca->cca_tdir, sizeof(temp_path));
	strlcat(temp_path, cca->cca_localname, sizeof(temp_path));
	if (stat(state->ct_config->ct_crypto_secrets, &sb) != 0) {
		s_errno = errno;
		ret = CTE_ERRNO;
		CWARNX("\"%s\": %s", state->ct_config->ct_crypto_secrets,
		    ct_strerror(ret));
		goto free;
	}
	if (stat(temp_path, &tsb) != 0) {
		s_errno = errno;
		ret = CTE_ERRNO;
		CWARNX("\"%s\": %s", temp_path, ct_strerror(ret));
		goto free;
	}

	/* Compare size first */
	if (tsb.st_size != sb.st_size) {
		ret = CTE_SECRETS_FILE_SIZE_MISMATCH;
		CWARNX("%" PRId64 " vs %" PRId64 ": %s", (int64_t)tsb.st_size,
		    (int64_t)sb.st_size, ct_strerror(ret));
		goto free;
	}

	if ((f = ct_fopen(state->ct_config->ct_crypto_secrets, "rb")) == NULL) {
		s_errno = errno;
		ret = CTE_ERRNO;
		CWARNX("\"%s\": %s", state->ct_config->ct_crypto_secrets,
		    ct_strerror(ret));
		goto free;
	}
	if ((tf = ct_fopen(temp_path, "rb")) == NULL) {
		s_errno = errno;
		ret = CTE_ERRNO;
		CWARNX("temp_path: %s", ct_strerror(ret));
		goto close_current;
	}
	/* read then throw away */
	unlink(temp_path);
	while (sb.st_size > 0) {
		sz = sb.st_size;
		if (sz > 1024)
			sz = 1024;
		sb.st_size -= sz;
		CNDBG(CT_LOG_FILE, "sz = %" PRId64 " remaining = %" PRId64,
		    (int64_t)sz, (int64_t)sb.st_size);
		if ((rsz = fread(buf, 1, sz, f)) != sz) {
			CNDBG(CT_LOG_CRYPTO, "short read on secrets file (%"
			    PRId64 " %" PRId64 ")", (int64_t)sz, (int64_t)rsz);
			ret = CTE_SECRETS_FILE_SHORT_READ;
			CWARNX("%s: %s", state->ct_config->ct_crypto_secrets,
			    ct_strerror(ret));
			goto out;
		}
		if ((rsz = fread(tbuf, 1, sz, tf)) != sz) {
			CNDBG(CT_LOG_CRYPTO, "short read on temporary secrets "
			    "file (%" PRId64 " %" PRId64 ")", (int64_t)sz,
			    (int64_t)rsz);
			ret = CTE_SECRETS_FILE_SHORT_READ;
			CWARNX("%s: %s", temp_path, ct_strerror(ret));
			goto out;
		}

		if (memcmp(buf, tbuf, sz) != 0) {
			ret = CTE_SECRETS_FILE_DIFFERS;
			goto out;
		}
	}
out:
	fclose(f);
close_current:
	fclose(tf);
free:
	e_free(&cca);

	if (ret == CTE_ERRNO)
		errno = s_errno;
	return (ret);
}
コード例 #2
0
static int
openct_reader_connect(sc_reader_t *reader,
			sc_slot_info_t *slot)
{
	struct driver_data *data = (struct driver_data *) reader->drv_data;
	int rc;

	SC_FUNC_CALLED(reader->ctx, 1);

	if (data->h)
		ct_reader_disconnect(data->h);

	if (!(data->h = ct_reader_connect(data->num))) {
		sc_error(reader->ctx, "ct_reader_connect socket failed\n");
		return SC_ERROR_CARD_NOT_PRESENT;
	}

	rc = ct_card_request(data->h, slot->id, 0, NULL,
				slot->atr, sizeof(slot->atr));
	if (rc < 0) {
		sc_error(reader->ctx,
				"openct_reader_connect read failed: %s\n",
				ct_strerror(rc));
		return SC_ERROR_CARD_NOT_PRESENT;
	}

	if (rc == 0) {
		sc_error(reader->ctx, "openct_reader_connect recved no data\n");
		return SC_ERROR_READER;
	}

	slot->atr_len = rc;
	return SC_NO_ERROR;
}
コード例 #3
0
ファイル: ct_util.c プロジェクト: carriercomm/cyphertite
int
ct_init(struct ct_global_state **statep, struct ct_config *conf,
    int flags, void (*info_cb)(evutil_socket_t, short, void *))
{
	struct ct_global_state *state = NULL;
	extern void		ct_reconnect(evutil_socket_t, short, void *);
	struct stat		sb;
	int			ret = 0;

	/* Run with restricted umask as we create numerous sensitive files. */
	umask(S_IRWXG|S_IRWXO);
	if ((ret = ct_check_expired_certs(conf)) != 0) {
		CNDBG(CT_LOG_NET, "can't updated expired certificates: %s",
		    ct_strerror(ret));
		goto fail;
	}

	if ((ret = ct_setup_state(&state, conf)) != 0)
		goto fail;

	/* set defaults */
	if ((ret = ct_set_log_fns(state, NULL, NULL, NULL, NULL, NULL,
	    NULL)) != 0)
		goto fail;

	if ((flags & CT_NEED_SECRETS) != 0) {
		if (stat(conf->ct_crypto_secrets, &sb) == -1) {
			ret = CTE_NO_SECRETS_FILE;
			goto fail;
		}
		/* we got crypto */
		if ((ret = ct_unlock_secrets(conf->ct_crypto_passphrase,
		    conf->ct_crypto_secrets,
		    state->ct_crypto_key, sizeof(state->ct_crypto_key),
		    state->ct_iv, sizeof(state->ct_iv))) != 0) {
			goto fail;
		}
	}

	if ((ret = ct_init_eventloop(state, info_cb, flags)) != 0)
		goto fail;

	*statep = state;
	return (0);

fail:
	if (state != NULL) {
		e_free(&state->ct_stats);
		e_free(&state);
	}
	return (ret);
}
コード例 #4
0
ファイル: reader-openct.c プロジェクト: PhoenixBaymax/OpenSC
static int
openct_reader_connect(sc_reader_t *reader)
{
	struct driver_data *data = (struct driver_data *) reader->drv_data;
	int rc;

	SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE);

	if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE)
		return SC_ERROR_NOT_ALLOWED;

	if (data->h)
		ct_reader_disconnect(data->h);

	if (!(data->h = ct_reader_connect(data->num))) {
		sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "ct_reader_connect socket failed\n");
		return SC_ERROR_CARD_NOT_PRESENT;
	}

	rc = ct_card_request(data->h, data->slot, 0, NULL,
				reader->atr.value, sizeof(reader->atr.value));
	if (rc < 0) {
		sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL,
				"openct_reader_connect read failed: %s\n",
				ct_strerror(rc));
		return SC_ERROR_CARD_NOT_PRESENT;
	}

	if (rc == 0) {
		sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "openct_reader_connect recved no data\n");
		return SC_ERROR_READER;
	}

	reader->atr.len = rc;
	return SC_SUCCESS;
}
コード例 #5
0
ファイル: ct_version_tree.c プロジェクト: Bluerise/cyphertite
int
ct_version_tree_build(const char *filename, const char *ctfile_basedir,
                      struct ct_version_tree **version_tree)
{
    struct ct_version_tree		*tree = NULL;
    struct ct_extract_head		 extract_head;
    struct ctfile_parse_state	 parse_state;
    struct ct_vertree_dnode_cache	 dnode_cache;
    struct ct_vertree_dnode		*dnode_entry;
    struct ct_vertree_ctfile	*ctfile = NULL;
    struct ct_vertree_dir		*root_dir;
    struct ct_vertree_ver		*root_version;
    off_t				 offset;
    int				 allfiles;
    int				 rv = 0;

    TAILQ_INIT(&extract_head);
    TAILQ_INIT(&dnode_cache.cache);
    dnode_cache.root_dnode = NULL;

    if ((rv = ct_extract_setup(&extract_head, &parse_state, filename,
                               ctfile_basedir, &allfiles))) {
        CNDBG(CT_LOG_VERTREE,
              "failed to setup extract for filename %s: %s",
              filename, ct_strerror(rv));
        goto out;
    }


    /* Create and init ctfile cache */
    tree = e_calloc(1, sizeof(*tree));
    TAILQ_INIT(&tree->cvt_ctfiles);
    TAILQ_INIT(&tree->cvt_head.cve_versions);
    RB_INIT(&tree->cvt_head.cve_children);
    tree->cvt_head.cve_name = e_strdup("/");

nextfile:
    root_dir = e_calloc(1, sizeof(*root_dir));
    root_version = &root_dir->cvd_base;
    root_version->cvv_type = C_TY_DIR;
    root_version->cvv_uid = 0;
    root_version->cvv_gid = 0;
    root_version->cvv_mode = 0777;
    root_version->cvv_atime = parse_state.xs_gh.cmg_created;
    root_version->cvv_mtime = parse_state.xs_gh.cmg_created;
    TAILQ_INSERT_HEAD(&tree->cvt_head.cve_versions, root_version, cvv_link);

    /*
     * Create only one struct for each ctfile.  Each entry in the version
     * tree references the appropriate one.  These are added to a cache list
     * so they can be freed during tree cleanup.
     */
    ctfile = e_calloc(1, sizeof(*ctfile));
    strlcpy(ctfile->cvc_path, parse_state.xs_filename,
            sizeof(ctfile->cvc_path));
    offset = ctfile_parse_tell(&parse_state);
    TAILQ_INSERT_TAIL(&tree->cvt_ctfiles, ctfile, cvc_link);

    while (((rv = ctfile_parse(&parse_state)) != XS_RET_EOF) &&
            (rv != XS_RET_FAIL)) {
        switch(rv) {
        case XS_RET_FILE:
            if ((rv = ct_vertree_add(&dnode_cache, &tree->cvt_head,
                                     &parse_state, ctfile, offset, allfiles)) != 0) {
                goto out;
            }
            break;
        case XS_RET_FILE_END:
            break;
        case XS_RET_SHA:
            if ((rv = ctfile_parse_seek(&parse_state))) {
                goto out;
            }
            break;
        default:
            rv = CTE_CTFILE_CORRUPT;
            goto out;
        }
        offset = ctfile_parse_tell(&parse_state);
    }
    if (rv == XS_RET_EOF) {
        ctfile_parse_close(&parse_state);
        if (!TAILQ_EMPTY(&extract_head)) {
            /* XXX do we need to zero root dnode? */
            ct_extract_open_next(&extract_head, &parse_state);
            goto nextfile;
        }
        rv = 0;
        /* free state */
    } else {
        rv = CTE_CTFILE_CORRUPT;
        goto out;
    }

    *version_tree = tree;

out:
    /* Free dnode_cache entries. */
    while ((dnode_entry = TAILQ_FIRST(&dnode_cache.cache)) != NULL) {
        TAILQ_REMOVE(&dnode_cache.cache, dnode_entry, cvd_link);
        if (dnode_entry->cvd_dnode.d_name != NULL)
            e_free(&dnode_entry->cvd_dnode.d_name);
        e_free(&dnode_entry);
    }

    return rv;
}
コード例 #6
0
ファイル: ct_main.c プロジェクト: finid/cyphertite
int
ct_main(int argc, char **argv)
{
	struct ct_extract_args		 cea;
	struct ct_archive_args		 caa;
	struct ct_ctfileop_args 	 cca;
	struct ct_ctfile_list_args	 ccla;
	struct ct_ctfile_delete_args	 ccda;
	struct ct_global_state		*state = NULL;
	struct ct_config		*conf;
	char				*ct_tdir = NULL;
	char				*ct_basisbackup = NULL;
	char				*ctfile = NULL;
	char				*ct_includefile = NULL;
	char				*ct_excludefile = NULL;
	char				*configfile = NULL, *config_file = NULL;
	char				*basisfile = NULL;
	char				*debugstring = NULL;
	char				**excludelist = NULL;
	char				**includelist = NULL;
	uint64_t			 debug_mask = 0;
	uint32_t			 cflags = CLOG_F_ENABLE | CLOG_F_STDERR;
	int				 ct_metadata = 0;
	int				 ct_match_mode = CT_MATCH_GLOB;
	int				 c;
	int				 ret = 0;
	int				 level0 = 0;
	int				 freeincludes = 0;
	int				 no_cross_mounts = 0;
	int				 strip_slash = 1;
	int				 follow_root_symlink = 0;
	int				 follow_symlinks = 0;
	int				 attr = 0;
	int				 verbose_ratios = 0;
	int				 ct_flags = 0;

	while ((c = getopt(argc, argv,
	    "AB:C:D:E:F:HI:PRVXacdef:hmprtvx0")) != -1) {
		switch (c) {
		case 'A':
			/* noop, deprecated */
			break;
		case 'B':
			basisfile = optarg;
			break;
		case 'C':
			ct_tdir = optarg;
			break;
		case 'D':
			if (debugstring != NULL)
				CFATALX("only one -D argument is valid");
			debugstring = optarg;
			break;
		case 'E':
			ct_excludefile = optarg;
			break;
		case 'F':
			configfile = optarg;
			break;
		case 'H':
			follow_root_symlink = 1;
			break;
		case 'I':
			ct_includefile = optarg;
			break;
		case 'P':
			strip_slash = 0;
			break;
		case 'R':
			verbose_ratios = 1;
			break;
		case 'V':
			show_version();
			exit(0);
			break;
		case 'X':
			no_cross_mounts = 1;
			break;
		case 'a':
			/* noop, deprecated */
			break;
		case 'c':
			if (ct_action)
				CFATALX("cannot mix operations, -c -e -t -x");
			ct_action = CT_A_ARCHIVE;
			break;
		case 'e':
			if (ct_action)
				CFATALX("cannot mix operations, -c -e -t -x");
			ct_action = CT_A_ERASE;
			break;
		case 'f': /* metadata file */
			ctfile = optarg;
			break;
		case 'h':
			follow_symlinks = 1;
			break;
		case 'm': /* metadata processing - XXX temporary? */
			ct_metadata = 1;
			break;
		case 'r':
			ct_match_mode = CT_MATCH_REGEX;
			break;
		case 'p':
			attr = 1;
			break;
		case 't':
			if (ct_action)
				CFATALX("cannot mix operations, -c -e -t -x");
			ct_action = CT_A_LIST;
			break;
		case 'v':
			ct_verbose++;
			break;
		case 'x':
			if (ct_action)
				CFATALX("cannot mix operations, -c -e -t -x");
			ct_action = CT_A_EXTRACT;
			break;
		case '0':
			level0 = 1;
			break;
		default:
			ct_usage();
			/* NOTREACHED */
		}
	}

	argc -= optind;
	argv += optind;

	if (debugstring) {
		cflags |= CLOG_F_DBGENABLE | CLOG_F_FILE | CLOG_F_FUNC |
		    CLOG_F_LINE | CLOG_F_DTIME;
		exude_enable(CT_LOG_EXUDE);
#if CT_ENABLE_THREADS
		exude_enable_threads();
#endif
		debug_mask |= ct_get_debugmask(debugstring);
	}

	/* please don't delete this line AGAIN! --mp */
	if (clog_set_flags(cflags))
		errx(1, "illegal clog flags");
	clog_set_mask(debug_mask);

	/* We can allocate these now that we've decided if we need exude */
	if (configfile)
		config_file = e_strdup(configfile);
	if (basisfile)
		ct_basisbackup = e_strdup(basisfile);

	if (ct_includefile != NULL) {
		int nentries;

		if ((ct_action == CT_A_LIST || ct_action == CT_A_EXTRACT) &&
		    argc != 0)
			CFATALX("-I is invalid when a pattern is "
			    "provided on the command line");
		includelist = ct_matchlist_fromfile(ct_includefile,
		    &nentries);
		if (nentries == -1)
			CFATAL("can't get includelist from %s",
			    ct_includefile);

		freeincludes = 1;
	} else if ((ct_action == CT_A_LIST || ct_action == CT_A_EXTRACT)) {
		includelist = argv;
	}
	if (ct_excludefile != NULL) {
		int	nentries;
		excludelist = ct_matchlist_fromfile(ct_excludefile, &nentries);
		if (nentries == -1)
			CFATAL("can't get excludelsit from %s", ct_excludefile);
	}


	if ((ret = ct_load_config(&conf, &config_file)) != 0) {
		CFATALX("%s", ct_strerror(ret));
	}

	if (!(ct_metadata && (ct_action == CT_A_LIST ||
	    ct_action == CT_A_ERASE))) {
		if (ctfile == NULL) {
			CWARNX("ctfile is required");
			ct_usage();
		}

		if (conf->ct_ctfile_mode == CT_MDMODE_REMOTE &&
		    ctfile_verify_name(ctfile))
			CFATALX("invalid ctfile: %s", ctfile);
	}

	/*
	 * !metadata extract with no args extracts everything.
	 * and all lists show everything if not filtered
	 */
	if (((ct_metadata == 0 && ct_action == CT_A_EXTRACT) ||
	    ct_action == CT_A_LIST) && argc == 0)
		ct_match_mode = CT_MATCH_EVERYTHING;

	if (level0)
		conf->ct_auto_incremental = 0; /* force incremental off */

	if (conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ct_metadata == 0 &&
	    ct_basisbackup != NULL)
		CFATALX("incremental basis in remote mode");

	/* Don't bother starting a connection if just listing local files. */
	if (ct_action == CT_A_LIST &&
	    conf->ct_ctfile_mode == CT_MDMODE_LOCAL &&
	    ct_metadata == 0 ) {
		ret = ct_list(ctfile, includelist, excludelist,
		    ct_match_mode, NULL, strip_slash, ct_verbose);
		goto out;
	}

	ct_prompt_for_login_password(conf);

	if (ct_action == CT_A_EXTRACT ||
	    ct_action == CT_A_ARCHIVE || (ct_action == CT_A_LIST &&
	    conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ct_metadata == 0) ||
	    ct_action == CT_A_ERASE)
		ct_flags |= CT_NEED_SECRETS;
	if (ct_action == CT_A_ARCHIVE)
		ct_flags |= CT_NEED_DB;


	if ((ret = ct_init(&state, conf, ct_flags, ct_info_sig)) != 0)
		CFATALX("failed to initialise cyphertite: %s",
		    ct_strerror(ret));

#if defined(CT_EXT_INIT)
	CT_EXT_INIT(state);
#endif

	if (conf->ct_crypto_passphrase != NULL &&
	    conf->ct_secrets_upload != 0) {
		ct_add_operation(state, ctfile_list_start,
		    ct_check_secrets_extract, conf->ct_crypto_secrets);
	}

	if (ct_action == CT_A_EXTRACT)
		ct_set_log_fns(state, &ct_verbose, ct_print_ctfile_info,
		    ct_print_file_start, ct_print_file_end,
		    ct_print_traverse_start, ct_print_traverse_end);
	else if (ct_action == CT_A_ARCHIVE)
		ct_set_log_fns(state, &ct_verbose, ct_print_ctfile_info,
		    ct_pr_fmt_file, ct_pr_fmt_file_end,
		    ct_print_traverse_start, ct_print_traverse_end);

	if (conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ct_metadata == 0) {
		switch (ct_action) {
		case CT_A_EXTRACT:
		case CT_A_LIST:
			cea.cea_local_ctfile = NULL; /* to be found */
			cea.cea_filelist = includelist;
			cea.cea_excllist = excludelist;
			cea.cea_matchmode = ct_match_mode;
			cea.cea_ctfile_basedir = conf->ct_ctfile_cachedir;
			cea.cea_tdir = ct_tdir;
			cea.cea_strip_slash = strip_slash;
			cea.cea_attr = attr;
			cea.cea_follow_symlinks = follow_symlinks;
			cea.cea_log_state = &ct_verbose;
			cea.cea_log_chown_failed =
			    ct_print_extract_chown_failed;
			ctfile_find_for_operation(state, ctfile,
			    ((ct_action == CT_A_EXTRACT)  ?
			    ctfile_nextop_extract : ctfile_nextop_list),
			    &cea, 1, 0);
			break;
		case CT_A_ARCHIVE:
			ct_normalize_filelist(argv);
			caa.caa_filelist = argv;
			caa.caa_excllist = excludelist;
			caa.caa_matchmode = ct_match_mode;
			caa.caa_includelist = includelist;
			caa.caa_tdir = ct_tdir;
			caa.caa_tag = ctfile;
			caa.caa_ctfile_basedir = conf->ct_ctfile_cachedir;
			/* we want to encrypt as long as we have keys */
			caa.caa_no_cross_mounts = no_cross_mounts;
			caa.caa_strip_slash = strip_slash;
			caa.caa_follow_root_symlink = follow_root_symlink;
			caa.caa_follow_symlinks = follow_symlinks;
			caa.caa_max_incrementals = conf->ct_max_incrementals;
			if (conf->ct_auto_incremental)
				/*
				 * Need to work out basis filename and
				 * download it if necessary
				 */
				ctfile_find_for_operation(state, ctfile,
				    ctfile_nextop_archive, &caa, 0, 1);
			else   {
				/* No basis, just start the op */
				ctfile_nextop_archive(state, NULL, &caa);
			}
			break;
		default:
			CWARNX("invalid action");
			ct_usage();
			/* NOTREACHED */
			break;
		}
	} else if (ct_metadata != 0) {
		if (ct_action == CT_A_ARCHIVE || ct_action == CT_A_EXTRACT) {
			cca.cca_localname = ctfile;
			cca.cca_remotename = NULL;
			cca.cca_tdir = ct_tdir;
			cca.cca_cleartext = 0;
			cca.cca_ctfile = 1;
			/* only matters for archive */
			ct_add_operation(state,
			    ((ct_action == CT_A_ARCHIVE) ?
			    ctfile_archive : ctfile_extract),
			    ctfile_op_cleanup, &cca);
		} else if (ct_action == CT_A_ERASE) {
			if (ctfile != NULL)
				CFATALX("-f is not permitted with -me operation");
			if (argc == 0)
				CFATALX("no files specified");
			ccda.ccda_pattern = argv;
			ccda.ccda_matchmode = ct_match_mode;
			ccda.ccda_callback = ct_print_delete;
			ct_add_operation(state, ctfile_list_start,
			    ctfile_process_delete, &ccda);
		} else if (ct_action == CT_A_LIST) {
			ccla.ccla_search = includelist;
			ccla.ccla_exclude = excludelist;
			ccla.ccla_matchmode = ct_match_mode;
			ct_add_operation(state, ctfile_list_start,
			    ctfile_list_print, &ccla);
		} else {
			CWARNX("must specify action");
			ct_usage();
			/* NOTREACHED */
		}
	} else {
		/* list is handled above */
		if (ct_action == CT_A_ARCHIVE) {
			caa.caa_local_ctfile = ctfile;
			ct_normalize_filelist(argv);
			caa.caa_filelist = argv;
			caa.caa_excllist = excludelist;
			caa.caa_matchmode = ct_match_mode;
			caa.caa_includelist = includelist;
			caa.caa_tdir = ct_tdir;
			caa.caa_tag = ctfile;
			caa.caa_ctfile_basedir = NULL;
			/* we want to encrypt as long as we have keys */
			caa.caa_no_cross_mounts = no_cross_mounts;
			caa.caa_strip_slash = strip_slash;
			caa.caa_follow_root_symlink = follow_root_symlink;
			caa.caa_follow_symlinks = follow_symlinks;
			caa.caa_max_incrementals = 0; /* unlimited */
			caa.caa_basis = ct_basisbackup;

			ct_add_operation(state, ct_archive, NULL, &caa);
		} else if (ct_action == CT_A_EXTRACT) {
			cea.cea_local_ctfile = ctfile;
			cea.cea_filelist = includelist;
			cea.cea_excllist = excludelist;
			cea.cea_matchmode = ct_match_mode;
			cea.cea_ctfile_basedir = NULL;
			cea.cea_tdir = ct_tdir;
			cea.cea_strip_slash = strip_slash;
			cea.cea_attr = attr;
			cea.cea_follow_symlinks = follow_symlinks;
			cea.cea_log_state = &ct_verbose;
			cea.cea_log_chown_failed =
			    ct_print_extract_chown_failed;
			ct_add_operation(state, ct_extract, NULL, &cea);
		} else {
			CWARNX("must specify action");
			ct_usage();
			/* NOTREACHED */
		}
	}

	ct_wakeup_file(state->event_state);

	if ((ret = ct_run_eventloop(state)) != 0) {
		if (state->ct_errmsg[0] != '\0')
			CWARNX("%s: %s", state->ct_errmsg,
			    ct_strerror(ret));
		else
			CWARNX("%s", ct_strerror(ret));
		return (ret);
	}

	if (verbose_ratios)
		ct_dump_stats(state, stdout);
	ct_cleanup_login_cache();
	ct_cleanup(state);
out:
	if (includelist && freeincludes == 1)
		ct_matchlist_free(includelist);
	if (excludelist)
		ct_matchlist_free(excludelist);
	if (conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ct_metadata == 0)
		ctfile_trim_cache(conf->ct_ctfile_cachedir,
		    conf->ct_ctfile_max_cachesize);

	ct_unload_config(config_file, conf);
#if CT_CHECK_MEMORY
	e_check_memory();
#endif
	exude_cleanup();

	return (ret);
}
コード例 #7
0
ファイル: ct_main.c プロジェクト: finid/cyphertite
int
ct_list(const char *file, char **flist, char **excludelist, int match_mode,
    const char *ctfile_basedir, int strip_slash, int verbose)
{
	struct ct_extract_state		*ces;
	struct ctfile_parse_state	 xs_ctx;
	struct fnode			 fnodestore;
	uint64_t			 reduction;
	struct fnode			*fnode = &fnodestore;
	struct ct_match			*match, *ex_match = NULL;
	char				*ct_next_filename;
	char				*sign;
	int				 state;
	int				 doprint = 0;
	int				 ret;
	int				 s_errno = 0, ct_errno = 0;
	char				 shat[SHA_DIGEST_STRING_LENGTH];
	char				 cshat[SHA_DIGEST_STRING_LENGTH];
	char				 iv[CT_IV_LEN*2+1];

	if ((ret = ct_file_extract_init(&ces, NULL, 1, 1, 0, NULL, NULL)) != 0)
		CFATALX("failed to initialise extract state: %s",
		    ct_strerror(ret));
	if ((ret = ct_match_compile(&match, match_mode, flist)) != 0)
		CFATALX("failed to compile match pattern: %s",
		    ct_strerror(ret));
	if (excludelist != NULL && (ret = ct_match_compile(&ex_match,
	    match_mode, excludelist)) != 0)
		CFATALX("failed to compile exclude pattern: %s",
		    ct_strerror(ret));

	verbose++;	/* by default print something. */

	ct_next_filename = NULL;
next_file:
	ret = ctfile_parse_init(&xs_ctx, file, ctfile_basedir);
	if (ret)
		CFATALX("failed to open %s: %s", file, ct_strerror(ret));
	ct_print_ctfile_info(&verbose, file, &xs_ctx.xs_gh);

	if (ct_next_filename)
		e_free(&ct_next_filename);

	if (xs_ctx.xs_gh.cmg_prevlvl_filename) {
		CNDBG(CT_LOG_CTFILE, "previous backup file %s\n",
		    xs_ctx.xs_gh.cmg_prevlvl_filename);
		ct_next_filename = e_strdup(xs_ctx.xs_gh.cmg_prevlvl_filename);
	}
	bzero(&fnodestore, sizeof(fnodestore));

	do {
		ret = ctfile_parse(&xs_ctx);
		switch (ret) {
		case XS_RET_FILE:
			ct_populate_fnode(ces, &xs_ctx, fnode, &state,
			    xs_ctx.xs_gh.cmg_flags & CT_MD_MLB_ALLFILES,
			    strip_slash);
			doprint = !ct_match(match, fnode->fn_fullname);
			if (doprint && ex_match != NULL &&
			    !ct_match(ex_match, fnode->fn_fullname))
				doprint = 0;
			if (doprint) {
				ct_pr_fmt_file(&verbose, fnode);
				if (!C_ISREG(xs_ctx.xs_hdr.cmh_type) ||
				    verbose > 2)
					printf("\n");
			}
			if (fnode->fn_hlname)
				e_free(&fnode->fn_hlname);
			if (fnode->fn_fullname)
				e_free(&fnode->fn_fullname);
			break;
		case XS_RET_FILE_END:
			sign = " ";
			if (xs_ctx.xs_trl.cmt_comp_size == 0)
				reduction = 100;
			else {
				uint64_t orig, comp;
				orig = xs_ctx.xs_trl.cmt_orig_size;
				comp = xs_ctx.xs_trl.cmt_comp_size;

				if (comp <= orig) {
					reduction = 100 * (orig - comp) / orig;
				} else  {
					reduction = 100 * (comp - orig) / orig;
					if (reduction != 0)
						sign = "-";
				}
			}
			if (doprint && verbose > 1)
				printf(" sz: %" PRIu64 " shas: %" PRIu64
				    " reduction: %s%" PRIu64 "%%\n",
				    xs_ctx.xs_trl.cmt_orig_size,
				    xs_ctx.xs_hdr.cmh_nr_shas,
				    sign, reduction);
			else if (doprint)
				printf("\n");
			break;
		case XS_RET_SHA:
			if (!(doprint && verbose > 2)) {
				if (ctfile_parse_seek(&xs_ctx)) {
					CFATALX("seek failed");
				}
			} else {
				int i;
				ct_sha1_encode(xs_ctx.xs_sha, shat);
				switch (xs_ctx.xs_gh.cmg_flags & CT_MD_CRYPTO) {
				case 0:
					printf(" sha %s\n", shat);
					break;
				case CT_MD_CRYPTO:
					ct_sha1_encode(xs_ctx.xs_csha, cshat);
					for (i = 0; i < CT_IV_LEN; i++)
						snprintf(&iv[i * 2], 3, "%02x",
						    xs_ctx.xs_iv[i]);

					printf(" sha %s csha %s iv %s\n",
					    shat, cshat, iv);
				}
			}
			break;
		case XS_RET_EOF:
			break;
		case XS_RET_FAIL:
			s_errno = errno;
			ct_errno = xs_ctx.xs_errno;
			;
		}

	} while (ret != XS_RET_EOF && ret != XS_RET_FAIL);

	ctfile_parse_close(&xs_ctx);

	if (ret != XS_RET_EOF) {
		errno = s_errno;
		CWARNX("corrupt ctfile: %s", ct_strerror(ct_errno));
	} else {
		if (ct_next_filename) {
			file = ct_next_filename;
			goto next_file;
		}
	}
	ct_match_unwind(match);
	ct_file_extract_cleanup(ces);
	return (0);
}
コード例 #8
0
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);
}
コード例 #9
0
/*
 * Download all dependent ctfiles of the current ctfile.
 * (called repeatedly until all are fetched).
 */
int
ctfile_download_next(struct ct_global_state *state, struct ct_op *op)
{
	struct ct_ctfileop_args	*cca = op->op_args, *nextcca;
	const char		*ctfile = cca->cca_localname;
	const char		*rfile = cca->cca_remotename;
	char			*prevfile;
	char			*cookedname;
	int			 ret = 0;

again:
	CNDBG(CT_LOG_CTFILE, "ctfile %s", ctfile);

	if ((ret = ctfile_get_previous(ctfile, cca->cca_tdir, 
	    &prevfile)) != 0) {
		CWARNX("can not get previous filename for %s", ctfile);
		/* error output will happen when even loop returns */
		goto out;
	}
	if (prevfile == NULL) /* done with this chain */
		goto out;

	if (prevfile[0] != '\0') {
		if ((cookedname = ctfile_cook_name(prevfile)) == NULL) {
			CWARNX("%s: %s", prevfile,
			    ct_strerror(CTE_INVALID_CTFILE_NAME));
			ret = CTE_INVALID_CTFILE_NAME;
			e_free(&prevfile);
			goto out;
		}
		CNDBG(CT_LOG_CTFILE, "prev file %s cookedname %s", prevfile,
		    cookedname);
		if (!ctfile_in_cache(cookedname, cca->cca_tdir)) {
			nextcca = e_calloc(1, sizeof(*nextcca));
			nextcca->cca_localname = cookedname;
			nextcca->cca_remotename = e_strdup(cookedname);
			nextcca->cca_tdir = cca->cca_tdir;
			nextcca->cca_ctfile = 1;
			ct_add_operation_after(state, op, ctfile_extract,
			    ctfile_download_next, nextcca);
		} else {
			if (ctfile)
				e_free(&ctfile);
			if (rfile)
				e_free(&rfile);
			e_free(&cookedname);
			ctfile = prevfile;
			goto again;
		}
	} else
		e_free(&prevfile);

out:
	if (ctfile)
		e_free(&ctfile);
	if (rfile)
		e_free(&rfile);
	e_free(&cca);

	return (ret);
}
コード例 #10
0
/*
 * List has completed.
 *
 * Select the best filename for download, and download it if missing.
 */
int
ctfile_find_for_extract_complete(struct ct_global_state *state,
    struct ct_op *op)
{
	struct ct_ctfile_find_args		*ccfa = op->op_args;
	struct ct_ctfile_find_fileop_args	*ccffa;
	struct ct_op				*list_fakeop = op->op_priv;
	struct ct_ctfile_list_args		*ccla = list_fakeop->op_args;
	struct ctfile_list_tree			 result;
	struct ctfile_list_file			*tmp;
	char	 				*best = NULL;
	int					 ret = 0;

	RB_INIT(&result);
	ctfile_list_complete(&state->ctfile_list_files, ccla->ccla_matchmode,
	    ccla->ccla_search, ccla->ccla_exclude, &result);
	e_free(ccla->ccla_search);
	e_free(&ccla->ccla_search);
	e_free(&ccla);
	e_free(&list_fakeop);

	/*
	 * Prepare arguments for next operation.
	 * either we'll download the next file, or skip straight to
	 * the callback for after the download, either way we need the nextop
	 */
	ccffa = e_calloc(1, sizeof(*ccffa));
	ccffa->ccffa_nextop = ccfa->ccfa_nextop;
	ccffa->ccffa_nextop_args = ccfa->ccfa_nextop_args;
	ccffa->ccffa_download_chain = ccfa->ccfa_download_chain;

	/* grab the newest one */
	if ((tmp = RB_MAX(ctfile_list_tree, &result)) == NULL) {
		if (ccfa->ccfa_empty_ok)
			goto do_operation;
		else {
			CWARNX("%s: %s", ccfa->ccfa_tag,
			    ct_strerror(CTE_NO_SUCH_BACKUP));
			ret = CTE_NO_SUCH_BACKUP;
			e_free(&ccffa);
			goto out;
		}
	}

	/* pick the newest one */
	best = e_strdup(tmp->mlf_name);
	CNDBG(CT_LOG_CTFILE, "backup file is %s", best);

	while ((tmp = RB_ROOT(&result)) != NULL) {
		RB_REMOVE(ctfile_list_tree, &result, tmp);
		e_free(&tmp);
	}

	/*
	 * if the metadata file is not in the cache directory then we
	 * need to download it first. if we need to recursively download
	 * an incremental chain then that code will handle scheduling
	 * those operations too. If we have it, we still need to check
	 * that all others in the chain exist, however.
	 */
	if (!ctfile_in_cache(best, ccfa->ccfa_cachedir)) {
		ccffa->ccffa_base.cca_localname = best;
		ccffa->ccffa_base.cca_tdir = ccfa->ccfa_cachedir;
		ccffa->ccffa_base.cca_remotename = e_strdup(best);
		ccffa->ccffa_base.cca_ctfile = 1;
		ct_add_operation(state, ctfile_extract, ctfile_extract_nextop,
		    ccffa);
	} else {
do_operation:
		/*
		 * No download needed, fake the next operation callback
		 * to see if we need anymore.
		 */
		ccffa->ccffa_base.cca_localname = best;
		ccffa->ccffa_base.cca_tdir = ccfa->ccfa_cachedir;
		ccffa->ccffa_base.cca_ctfile = 1;
		op->op_args = ccffa;
		ctfile_extract_nextop(state, op);
	}
out:
	e_free(&ccfa);

	return (ret);
}