예제 #1
0
/**
 * network_desleep(handle):
 * Deregister the callback associated with the provided handle.  The
 * callback will be called with a status of NETWORK_STATUS_CANCEL.
 */
int
network_desleep(int handle)
{
	struct sleeper * sp;

	/* Sanity-check the handle. */
	if ((handle >= (int)sleepers_getsize(sleepers)) || (handle < 0)) {
		warn0("Invalid sleeper handle: %d", handle);
		goto err0;
	}

	/* Grab the relevant sleeper record. */
	sp = *sleepers_get(sleepers, (size_t)handle);

	/* If there is no timer, return silently. */
	if (sp->event_cookie == NULL)
		return (0);

	/* Cancel the timer. */
	events_timer_cancel(sp->event_cookie);
	sp->event_cookie = NULL;

	/* Invoke the callback. */
	return ((sp->callback)(sp->cookie, NETWORK_STATUS_CANCEL));

err0:
	/* Failure! */
	return (-1);
}
예제 #2
0
/**
 * crypto_keys_subr_export_RSA_priv(key, buf, buflen):
 * If buf != NULL, export the specified RSA private key.  Return the key
 * length in bytes.
 */
uint32_t
crypto_keys_subr_export_RSA_priv(RSA * key, uint8_t * buf, size_t buflen)
{
	uint32_t len = 0;

	if (key == NULL) {
		warn0("Cannot export a key which we don't have!");
		goto err0;
	}

	/* Each large integer gets exported. */
	if (export_BN(key->n, &buf, &buflen, &len))
		goto err0;
	if (export_BN(key->e, &buf, &buflen, &len))
		goto err0;
	if (export_BN(key->d, &buf, &buflen, &len))
		goto err0;
	if (export_BN(key->p, &buf, &buflen, &len))
		goto err0;
	if (export_BN(key->q, &buf, &buflen, &len))
		goto err0;
	if (export_BN(key->dmp1, &buf, &buflen, &len))
		goto err0;
	if (export_BN(key->dmq1, &buf, &buflen, &len))
		goto err0;
	if (export_BN(key->iqmp, &buf, &buflen, &len))
		goto err0;

	/* Success! */
	return (len);

err0:
	/* Failure! */
	return ((uint32_t)(-1));
}
예제 #3
0
/* Should we use AESNI? */
static int
useaesni(void)
{
	static int aesnigood = -1;
	uint8_t key[32];
	uint8_t ptext[16];
	size_t i;

	/* If we haven't decided which code to use yet, decide now. */
	while (aesnigood == -1) {
		/* Default to OpenSSL. */
		aesnigood = 0;

		/* If the CPU doesn't claim to support AESNI, stop here. */
		if (!cpusupport_x86_aesni())
			break;

		/* Test cases: key is 0x00010203..., ptext is 0x00112233... */
		for (i = 0; i < 16; i++)
			ptext[i] = 0x11 * i;
		for (i = 0; i < 32; i++)
			key[i] = i;

		/* Test that AESNI and OpenSSL produce the same results. */
		if (aesnitest(ptext, key, 16) || aesnitest(ptext, key, 32)) {
			warn0("Disabling AESNI due to failed self-test");
			break;
		}

		/* AESNI works; use it. */
		aesnigood = 1;
	}

	return (aesnigood);
}
예제 #4
0
/**
 * multitape_metadata_recrypt(obuf, obuflen, nbuf, nbuflen):
 * Decrypt and re-encrypt the provided metadata file.
 */
int
multitape_metadata_recrypt(uint8_t * obuf, size_t obuflen, uint8_t ** nbuf,
    size_t * nbuflen)
{
	struct tapemetadata mdat;

	/* Parse the metadata file. */
	switch (multitape_metadata_dec(&mdat, obuf, obuflen)) {
	case 1:
		warn0("Metadata file is corrupt");
		goto err0;
	case -1:
		warnp("Error parsing metadata file");
		goto err0;
	}

	/* Construct a new metadata file. */
	if (multitape_metadata_enc(&mdat, nbuf, nbuflen)) {
		warnp("Error constructing metadata file");
		goto err1;
	}

	/* Free the metadata we parsed. */
	multitape_metadata_free(&mdat);

	/* Success! */
	return (0);

err1:
	multitape_metadata_free(&mdat);
err0:
	/* Failure! */
	return (-1);
}
예제 #5
0
/**
 * crypto_keys_subr_import_RSA_pub(key, buf, buflen):
 * Import the specified RSA public key from the provided buffer.
 */
int
crypto_keys_subr_import_RSA_pub(RSA ** key, const uint8_t * buf, size_t buflen)
{

	/* Free any existing key. */
	if (*key != NULL)
		RSA_free(*key);

	/* Create a new key. */
	if ((*key = RSA_new()) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err0;
	}

	/* Load values. */
	if (import_BN(&(*key)->n, &buf, &buflen))
		goto err1;
	if (import_BN(&(*key)->e, &buf, &buflen))
		goto err1;

	/* We should have no unprocessed data left. */
	if (buflen)
		goto err1;

	/* Success! */
	return (0);

err1:
	RSA_free(*key);
	*key = NULL;
err0:
	/* Failure! */
	return (-1);
}
예제 #6
0
/**
 * netpacket_register_request(NPC, user, callback):
 * Construct and send a NETPACKET_REGISTER_REQUEST packet asking to register
 * a new machine belonging to the specified user.
 */
int
netpacket_register_request(NETPACKET_CONNECTION * NPC,
    const char * user, handlepacket_callback * callback)
{

	/* Make sure user name is a sane length. */
	if (strlen(user) > 255) {
		warn0("User name too long: %s", user);
		goto err0;
	}

	/* Send the packet. */
	if (netproto_writepacket(NPC->NC, NETPACKET_REGISTER_REQUEST,
	    (const uint8_t *)user, strlen(user),
	    netpacket_op_packetsent, NPC))
		goto err0;

	/* Set callback for handling a response. */
	NPC->pending_current->handlepacket = callback;

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
예제 #7
0
/**
 * netproto_sleep(C, secs, callback, cookie):
 * Call the provided callback after ${secs} seconds.
 */
int
netproto_sleep(NETPROTO_CONNECTION * C, int secs,
    network_callback * callback, void * cookie)
{
	struct timeval timeo;

	/* Set timeout. */
	timeo.tv_sec = secs;
	timeo.tv_usec = 0;

	/* Make sure this connection isn't already sleeping. */
	if (C->sleepcookie.handle != -1) {
		warn0("Connection is already sleeping!");
		goto err0;
	}

	/* Record callback parameters. */
	C->sleepcookie.callback = callback;
	C->sleepcookie.cookie = cookie;

	/* Ask for a wake-up call. */
	if ((C->sleepcookie.handle =
	    network_sleep(&timeo, callback_sleep, C)) == -1)
		goto err0;

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
예제 #8
0
/**
 * crypto_MGF1(seed, seedlen, buf, buflen):
 * The MGF1 mask generation function, as specified in RFC 3447.
 */
void
crypto_MGF1(uint8_t * seed, size_t seedlen, uint8_t * buf, size_t buflen)
{
	uint8_t hbuf[32];
	size_t pos;
	uint32_t i;
	uint8_t C[4];

	/* Sanity check for I2OSP function. */
	assert(((buflen - 1) / 32) <= UINT32_MAX);

	/* Iterate through the buffer. */
	for (pos = 0; pos < buflen; pos += 32) {
		/* The ith block starts at position i * 32. */
		i = (uint32_t)(pos / 32);

		/* Convert counter to big-endian format. */
		be32enc(C, i);

		/* Compute the hash of (seed || C). */
		if (crypto_hash_data_2(CRYPTO_KEY_HMAC_SHA256, seed, seedlen,
		    C, 4, hbuf)) {
			warn0("Programmer error: "
			    "SHA256 should never fail");
			abort();
		}

		/* Copy as much data as needed. */
		if (buflen - pos > 32)
			memcpy(buf + pos, hbuf, 32);
		else
			memcpy(buf + pos, hbuf, buflen - pos);
	}
}
예제 #9
0
파일: crypto_dh.c 프로젝트: e6/pkg-spiped
/**
 * crypto_dh_compute(pub, priv, key):
 * In the Diffie-Hellman group #14, compute ${pub}^(2^258 + ${priv}) and
 * write the result into ${key}.  All values are big-endian.  Note that the
 * value ${pub} is the public key produced by the call to crypto_dh_generate
 * made by the *other* participant in the key exchange.
 */
int
crypto_dh_compute(const uint8_t pub[CRYPTO_DH_PUBLEN],
    const uint8_t priv[CRYPTO_DH_PRIVLEN], uint8_t key[CRYPTO_DH_KEYLEN])
{
	BIGNUM * a;

	/* Convert ${pub} into BN representation. */
	if ((a = BN_bin2bn(pub, CRYPTO_DH_PUBLEN, NULL)) == NULL) {
		warn0("%s", ERR_error_string(ERR_get_error(), NULL));
		goto err0;
	}

	/* Compute key = pub^(2^258 + priv). */
	if (blinded_modexp(key, a, priv))
		goto err1;

	/* Free storage allocated by BN_bin2bn. */
	BN_free(a);

	/* Success! */
	return (0);

err1:
	BN_free(a);
err0:
	/* Failure! */
	return (-1);
}
예제 #10
0
파일: main.c 프로젝트: Tarsnap/kivaloo
int
main(int argc, char * argv[])
{
	struct sock_addr ** sas;
	uintmax_t N;
	int s;
	struct wire_requestqueue * Q;

	WARNP_INIT;

	/* Check number of arguments. */
	if (argc != 3) {
		fprintf(stderr, "usage: hotspot_read %s N\n", "<socketname>");
		exit(1);
	}

	/* Parse N. */
	if ((N = strtoumax(argv[2], NULL, 0)) == 0) {
		warnp("Invalid value for N: %s", argv[2]);
		exit(1);
	}

	/* Resolve the socket address and connect. */
	if ((sas = sock_resolve(argv[1])) == NULL) {
		warnp("Error resolving socket address: %s", argv[1]);
		exit(1);
	}
	if (sas[0] == NULL) {
		warn0("No addresses found for %s", argv[1]);
		exit(1);
	}
	if ((s = sock_connect(sas)) == -1)
		exit(1);

	/* Create a request queue. */
	if ((Q = wire_requestqueue_init(s)) == NULL) {
		warnp("Cannot create packet write queue");
		exit(1);
	}

	/* Start issuing hotspot read requests. */
	if (hotspotread(Q, N))
		exit(1);

	/* Free the request queue. */
	wire_requestqueue_destroy(Q);
	wire_requestqueue_free(Q);

	/* Free socket addresses. */
	sock_addr_freelist(sas);

	/* Shut down the event subsystem. */
	events_shutdown();

	/* Success! */
	exit(0);
}
예제 #11
0
/**
 * callback_file(cookie, buf, buflen):
 * Handle a chunk ${buf} of length ${buflen} from a file which is being
 * written to the tape associated with the multitape write cookie ${cookie}.
 */
static int
callback_file(void * cookie, uint8_t * buf, size_t buflen)
{
	struct multitape_write_internal * d = cookie;
	struct chunkheader ch;

	/* Data is being passed out by c_file. */
	d->c_file_out += buflen;

	/* Anything under MINCHUNK bytes belongs in the trailer stream. */
	if (buflen < MINCHUNK) {
		/* There shouldn't be any trailer yet. */
		if (d->tlen != 0) {
			warn0("Archive entry has two trailers?");
			goto err0;
		}

		/* Write to the trailer stream. */
		if (chunkify_write(d->t.c, buf, buflen))
			goto err0;

		/* Record the trailer length. */
		d->tlen = buflen;

		/* Call the trailer callback, if one exists. */
		if ((d->callback_trailer != NULL) &&
		    (d->callback_trailer)(d->callback_cookie, buf, buflen))
			goto err0;
	} else {
		/* Store the chunk. */
		if (store_chunk(buf, buflen, &ch, d->C))
			goto err0;

		/* Write chunk header to chunk index stream. */
		if (chunkify_write(d->c.c, (uint8_t *)(&ch),
		    sizeof(struct chunkheader)))
			goto err0;

		/* Record the chunkified data length. */
		d->clen += buflen;

		/* Call the chunk callback, if one exists. */
		if ((d->callback_chunk != NULL) &&
		    (d->callback_chunk)(d->callback_cookie, &ch))
			goto err0;
	}

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
예제 #12
0
파일: main.c 프로젝트: Tarsnap/kivaloo
int
main(int argc, char * argv[])
{
	struct sock_addr ** sas;
	int s;
	struct wire_requestqueue * Q;

	WARNP_INIT;

	/* Check number of arguments. */
	if (argc != 2) {
		fprintf(stderr, "usage: bulk_insert %s\n", "<socketname>");
		exit(1);
	}

	/* Resolve the socket address and connect. */
	if ((sas = sock_resolve(argv[1])) == NULL) {
		warnp("Error resolving socket address: %s", argv[1]);
		exit(1);
	}
	if (sas[0] == NULL) {
		warn0("No addresses found for %s", argv[1]);
		exit(1);
	}
	if ((s = sock_connect(sas)) == -1)
		exit(1);

	/* Create a request queue. */
	if ((Q = wire_requestqueue_init(s)) == NULL) {
		warnp("Cannot create packet write queue");
		exit(1);
	}

	/* Start bulk inserting. */
	if (bulkinsert(Q, stdin))
		exit(1);

	/* Free the request queue. */
	wire_requestqueue_destroy(Q);
	wire_requestqueue_free(Q);

	/* Free socket addresses. */
	sock_addr_freelist(sas);

	/* Shut down the event subsystem. */
	events_shutdown();

	/* Success! */
	exit(0);
}
예제 #13
0
/**
 * tsnetwork_read(fd, buf, buflen, to0, to1, callback, cookie):
 * Asynchronously fill the provided buffer with data from ${fd}, and call
 * callback(cookie, status) where status is a NETWORK_STATUS_* value.  Time
 * out if no data can be read for a period of time to0, or if the complete
 * buffer has not been read after time to1.  Note that ${buflen} must be
 * non-zero, since otherwise deadlock would result.
 */
int
tsnetwork_read(int fd, uint8_t * buf, size_t buflen,
    struct timeval * to0, struct timeval * to1,
    network_callback * callback, void * cookie)
{

	/* Make sure buflen is non-zero. */
	if (buflen == 0) {
		warn0("Cannot read zero-byte buffer");
		return (-1);
	}

	return (network_buf(fd, buf, buflen, to0, to1, callback, cookie,
	    recv, NETWORK_OP_READ, 0));
}
예제 #14
0
/**
 * callback_print(cookie, ch):
 * Call chunks_stats_addchunk on the chunk stats cookie ${cookie} and the
 * chunk header ${ch}.
 */
static int
callback_print(void * cookie, struct chunkheader * ch)
{
	CHUNKS_S * C = cookie;
	size_t len, zlen;
	int rc;

	/* Decode chunk header. */
	len = le32dec(ch->len);
	zlen = le32dec(ch->zlen);
	if ((rc = chunks_stats_addchunk(C, ch->hash, len, zlen)) == 1) {
		warn0("Directory is not consistent with archive: Run --fsck");
		rc = -1;
	}

	/* Return status. */
	return (rc);
}
예제 #15
0
bool random_get(uint8_t *buffer, size_t buffer_len) {
    FILE *frand = fopen(CANDADO_RANDOM_DEV, "r");
    if (!frand) {
        warn0("%s", CANDADO_RANDOM_DEV);
        goto err0;
    }

    if (fread(buffer, 1, buffer_len, frand) < buffer_len)
        goto err1;

    fclose(frand);
    return true;

err1:
    fclose(frand);
err0:
    return false;
}
예제 #16
0
/**
 * storage_util_unlock(S):
 * Release the lock on the storage state ${S}.
 */
int
storage_util_unlock(struct storage_state * S)
{
	int rc;

	/* Try to release the lock. */
	if ((rc = pthread_rwlock_unlock(&S->lck)) != 0) {
		warn0("pthread_rwlock_unlock: %s", strerror(rc));
		goto err0;
	}

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
예제 #17
0
파일: main.c 프로젝트: FauxFaux/spiped
static int
found(void * cookie, struct sock_addr ** sas)
{
	char * addr;
	int i;

	(void)cookie;	/* UNUSED */

	/* Sanity check. */
	if (sas == NULL)
		goto err0;

	/* Print each address. */
	for (i = 0; i < MAX_ADDRS; i++) {
		if (sas[i] == NULL)
			break;

		/* Extract address and print it. */
		if ((addr = sock_addr_prettyprint(sas[i])) == NULL) {
			warn0("sock_addr_prettyprint()");
			goto err1;
		}
		printf("%s\n", addr);

		/* Clean up. */
		free(addr);
	}

	/* Clean up. */
	sock_addr_freelist(sas);

	/* Quit event loop. */
	doneloop = 1;

	/* Success! */
	return (0);

err1:
	sock_addr_freelist(sas);
err0:
	/* Failure! */
	return (-1);
}
예제 #18
0
static int
callback_reconnect(void * cookie, int status)
{
    struct netpacket_internal * NPC = cookie;
    uint64_t in, out, queued;

    /* If we're being cancelled, return. */
    if (status == NETWORK_STATUS_CANCEL)
        goto done;

    /* The status should be NETWORK_STATUS_TIMEOUT. */
    if (status != NETWORK_STATUS_TIMEOUT) {
        warn0("Bad status in callback_reconnect: %d", status);
        goto err0;
    }

    /* Add the bandwidth used by the connection to our running totals. */
    netproto_getstats(NPC->NC, &in, &out, &queued);
    NPC->bytesin += in;
    NPC->bytesout += out;

    /* Close the (dead) connection. */
    if (netproto_close(NPC->NC))
        goto err1;
    NPC->NC = NULL;

    /* Open a new connection. */
    if ((NPC->NC = netproto_connect(NPC->useragent,
                                    callback_connect, NPC)) == NULL)
        goto err0;

done:
    /* Success! */
    return (0);

err1:
    NPC->NC = NULL;
err0:
    /* Failure! */
    return (-1);
}
예제 #19
0
파일: sock.c 프로젝트: brainwater/spiped
/**
 * sock_connect(sas):
 * Iterate through the addresses in ${sas}, attempting to create a socket and
 * connect (blockingly).  Once connected, stop iterating, mark the socket as
 * non-blocking, and return it.
 */
int
sock_connect(struct sock_addr * const * sas)
{
	int s = -1;

	/* Iterate through the addresses provided. */
	for (; sas[0] != NULL; sas++) {
		/* Create a socket. */
		if ((s = socket(sas[0]->ai_family,
		    sas[0]->ai_socktype, 0)) == -1)
			continue;

		/* Attempt to connect. */
		if (connect(s, sas[0]->name, sas[0]->namelen) == 0)
			break;

		/* Close the socket; this address didn't work. */
		close(s);
	}

	/* Did we manage to connect? */
	if (sas[0] == NULL) {
		warn0("Could not connect");
		goto err0;
	}

	/* Mark the socket as non-blocking. */
	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
		warnp("Cannot make connection non-blocking");
		goto err1;
	}

	/* Success! */
	return (s);

err1:
	close(s);
err0:
	/* Failure! */
	return (-1);
}
예제 #20
0
/**
 * crypto_keys_subr_import_HMAC(key, buf, buflen):
 * Import the specified HMAC key from the provided buffer.
 */
int
crypto_keys_subr_import_HMAC(struct crypto_hmac_key ** key,
    const uint8_t * buf, size_t buflen)
{

	/* Free any existing key. */
	if (*key != NULL) {
		free((*key)->key);
		free(*key);
	}

	/* Make sure the buffer is the right length. */
	if (buflen != 32) {
		warn0("Incorrect HMAC key size: %zu", buflen);
		goto err0;
	}

	/* Allocate key structure. */
	if ((*key = malloc(sizeof(struct crypto_hmac_key))) == NULL)
		goto err0;

	/* Allocate key buffer. */
	if (((*key)->key = malloc(buflen)) == NULL)
		goto err1;

	/* Copy key data and length. */
	(*key)->len = buflen;
	memcpy((*key)->key, buf, buflen);

	/* Success! */
	return (0);

err1:
	free(*key);
	*key = NULL;
err0:
	/* Failure! */
	return (-1);
}
예제 #21
0
/**
 * tapepresent(S, fmt, s):
 * Return 1 if an archive exists with the name sprintf(fmt, s), or 0
 * otherwise.
 */
static int
tapepresent(STORAGE_W * S, const char * fmt, const char * s)
{
	char * tapename;

	/* Generate name. */
	if (asprintf(&tapename, fmt, s) == -1)
		goto err0;

	/* Make sure that there isn't already a tape with this name. */
	switch (multitape_metadata_ispresent(S, tapename)) {
	case 1:
		/* File exists. */
		warn0("An archive already exists with the name \"%s\"",
		    tapename);
		goto eexist;
	case -1:
		/* Something went wrong. */
		goto err1;
	}

	/* Free string allocated by asprintf. */
	free(tapename);

	/* Nothing is in the way. */
	return (0);

eexist:
	free(tapename);

	/* Something is in the way. */
	return (1);

err1:
	free(tapename);
err0:
	/* Failure! */
	return (-1);
}
예제 #22
0
/**
 * writetape_setmode(d, mode):
 * Set the tape mode to 0 (HEADER) or 1 (DATA).
 */
int
writetape_setmode(TAPE_W * d, int mode)
{

	if (mode == d->mode)
		goto done;

	/* If we were in DATA mode, end the current file chunk. */
	if (d->mode == 1) {
		if (chunkify_end(d->c_file))
			goto err0;
	}

	/* If we have written an archive trailer, we can't change the mode. */
	if (d->mode == 3) {
		warn0("Programmer error: "
		    "Archive entry occurs after archive trailer.");
		goto err0;
	}

	/* If the entry is ending, write to the header stream. */
	if (mode == 2) {
		if (endentry(d))
			goto err0;
	}

	/* Record the new mode. */
	d->mode = mode;

done:
	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
예제 #23
0
/* Callback for btree_sync when write is complete. */
static int
callback_append(void * cookie, int failed, int status, uint64_t blkno)
{
	struct write_cookie * WC = cookie;
	struct btree * T = WC->T;

	/* Throw a fit if we didn't manage to write the pages. */
	if (failed)
		goto err1;
	if (status) {
		warn0("Failed to write dirty nodes to backing store");
		goto err1;
	}

	/* Record the next available block number. */
	T->nextblk = blkno;

	/* Mark the nodes in the dirty tree as clean. */
	makeclean(T, T->root_dirty);

	/*
	 * Make sure no callbacks are pending on the shadow tree before we
	 * garbage collect it.
	 */
	if (!events_immediate_register(callback_unshadow, WC, 1))
		goto err1;

	/* Success! */
	return (0);

err1:
	free(WC);

	/* Failure! */
	return (-1);
}
예제 #24
0
/**
 * crypto_aes_key_expand_aesni(key, len):
 * Expand the ${len}-byte AES key ${key} into a structure which can be passed
 * to crypto_aes_encrypt_block_aesni.  The length must be 16 or 32.  This
 * implementation uses x86 AESNI instructions, and should only be used if
 * CPUSUPPORT_X86_AESNI is defined and cpusupport_x86_aesni() returns nonzero.
 */
void *
crypto_aes_key_expand_aesni(const uint8_t * key, size_t len)
{
	struct crypto_aes_key_aesni * kexp;
	size_t rkey_offset;

	/* Allocate structure. */
	if ((kexp = malloc(sizeof(struct crypto_aes_key_aesni))) == NULL)
		goto err0;

	/* Figure out where to put the round keys. */
	rkey_offset = (uintptr_t)(&kexp->rkeys_buf[0]) % sizeof(__m128i);
	rkey_offset = (sizeof(__m128i) - rkey_offset) % sizeof(__m128i);
	kexp->rkeys = (void *)&kexp->rkeys_buf[rkey_offset];

	/* Compute round keys. */
	if (len == 16) {
		kexp->nr = 10;
		crypto_aes_key_expand_128_aesni(key, kexp->rkeys);
	} else if (len == 32) {
		kexp->nr = 14;
		crypto_aes_key_expand_256_aesni(key, kexp->rkeys);
	} else {
		warn0("Unsupported AES key length: %zu bytes", len);
		goto err1;
	}

	/* Success! */
	return (kexp);

err1:
	free(kexp);
err0:
	/* Failure! */
	return (NULL);
}
예제 #25
0
/**
 * storage_done(S):
 * Free the storage state data ${S}.
 */
int
storage_done(struct storage_state * S)
{
	int rc;

	/* Destroy the lock on the storage state. */
	if ((rc = pthread_rwlock_destroy(&S->lck)) != 0) {
		warn0("pthread_rwlock_destroy: %s", strerror(rc));
		goto err0;
	}

	/* Free the queue of file state structures. */
	elasticqueue_free(S->files);

	/* Free the storage state. */
	free(S);

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
예제 #26
0
/**
 * events_network_cancel(s, op):
 * Cancel the event registered for the socket/operation pair ${s}/${op}.  If
 * there is no such registration, errno will be set to ENOENT and the
 * function will fail.
 */
int
events_network_cancel(int s, int op)
{
	struct eventrec ** r;

	/* Initialize if necessary. */
	if (initsocketlist())
		goto err0;

	/* Sanity-check socket number. */
	if ((s < 0) || (s >= (int)FD_SETSIZE)) {
		warn0("Invalid file descriptor for network event: %d", s);
		goto err0;
	}

	/* Sanity-check operation. */
	if ((op != EVENTS_NETWORK_OP_READ) &&
	    (op != EVENTS_NETWORK_OP_WRITE)) {
		warn0("Invalid operation for network event: %d", op);
		goto err0;
	}

	/* We have no events registered beyond the end of the array. */
	if ((size_t)(s) >= socketlist_getsize(S)) {
		errno = ENOENT;
		goto err0;
	}

	/* Look up the relevant event pointer. */
	if (op == EVENTS_NETWORK_OP_READ)
		r = &socketlist_get(S, s)->reader;
	else
		r = &socketlist_get(S, s)->writer;

	/* Check if we have an event. */
	if (*r == NULL) {
		errno = ENOENT;
		goto err0;
	}

	/* Free the event. */
	events_freerec(*r);
	*r = NULL;

	/*
	 * Since there is no longer an event registered for this socket /
	 * operation pair, it doesn't make any sense for it to be ready.
	 */
	if (op == EVENTS_NETWORK_OP_READ)
		FD_CLR(s, &readfds);
	else
		FD_CLR(s, &writefds);

	/*
	 * Decrement events-registered counter; and if it is becoming zero,
	 * stop the inter-select duration clock.
	 */
	if (--nev == 0)
		events_network_selectstats_stopclock();

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
예제 #27
0
/**
 * chunks_directory_read(cachepath, dir, stats_unique, stats_all, stats_extra,
 *     mustexist, statstape):
 * Read stats_extra statistics (statistics on non-chunks which are stored)
 * and the chunk directory (if present) from "${cachepath}/directory" into
 * memory allocated and assigned to ${*dir}; and return a hash table
 * populated with struct chunkdata records.  Populate stats_all with
 * statistics for all the chunks listed in the directory (counting
 * multiplicity) and populate stats_unique with statistics reflecting the
 * unique chunks.  If ${mustexist}, error out if the directory does not exist.
 * If ${statstape}, allocate struct chunkdata_statstape records instead.
 */
RWHASHTAB *
chunks_directory_read(const char * cachepath, void ** dir,
    struct chunkstats * stats_unique, struct chunkstats * stats_all,
    struct chunkstats * stats_extra, int mustexist, int statstape)
{
	struct chunkdata_external che;
	struct chunkstats_external cse;
	struct stat sb;
	RWHASHTAB * HT;
	char * s;
	struct chunkdata * p = NULL;
	struct chunkdata_statstape * ps = NULL;
	FILE * f;
	size_t numchunks;

	/* Zero statistics. */
	chunks_stats_zero(stats_unique);
	chunks_stats_zero(stats_all);
	chunks_stats_zero(stats_extra);

	/* Create a hash table to hold the chunkdata structures. */
	HT = rwhashtab_init(offsetof(struct chunkdata, hash), 32);
	if (HT == NULL)
		goto err0;

	/* Construct the string "${cachepath}/directory". */
	if (asprintf(&s, "%s/directory", cachepath) == -1) {
		warnp("asprintf");
		goto err1;
	}
	if (stat(s, &sb)) {
		/* Could not stat ${cachepath}/directory.  Error? */
		if (errno != ENOENT) {
			warnp("stat(%s)", s);
			goto err2;
		}

		/* The directory doesn't exist; complain if mustexist != 0. */
		if (mustexist) {
			warn0("Error reading cache directory from %s",
			    cachepath);
			goto err2;
		}

		/*
		 * ${cachepath}/directory does not exist; set ${*dir} to NULL
		 * and return the empty hash table.
		 */
		free(s);
		*dir = NULL;
		return (HT);
	}

	/*
	 * Make sure the directory file isn't too large or too small, in
	 * order to avoid any possibility of integer overflows.
	 */
	if ((sb.st_size < 0) ||
	    ((sizeof(off_t) > sizeof(size_t)) && (sb.st_size > SIZE_MAX))) {
		warn0("on-disk directory has insane size (%jd bytes): %s",
		    (intmax_t)(sb.st_size), s);
		goto err2;
	}

	/* Make sure the number of chunks is an integer. */
	if ((size_t)(sb.st_size - sizeof(struct chunkstats_external)) %
	    (sizeof(struct chunkdata_external))) {
		warn0("on-disk directory is corrupt: %s", s);
		goto err2;
	}

	/* Compute the number of on-disk chunks. */
	numchunks =
	    (size_t)(sb.st_size - sizeof(struct chunkstats_external)) /
	    sizeof(struct chunkdata_external);

	/* Make sure we don't get an integer overflow. */
	if (numchunks >= SIZE_MAX / sizeof(struct chunkdata_statstape)) {
		warn0("on-disk directory is too large: %s", s);
		goto err2;
	}

	/*
	 * Allocate memory to ${*dir} large enough to store a struct
	 * chunkdata or struct chunkdata_statstape for each struct
	 * chunkdata_external in ${cachepath}/directory.
	 */
	if (statstape) {
		ps = malloc(numchunks * sizeof(struct chunkdata_statstape));
		*dir = ps;
	} else {
		p = malloc(numchunks * sizeof(struct chunkdata));
		*dir = p;
	}
	if (*dir == NULL)
		goto err2;

	/* Open the directory file. */
	if ((f = fopen(s, "r")) == NULL) {
		warnp("fopen(%s)", s);
		goto err3;
	}

	/* Read the extra files statistics. */
	if (fread(&cse, sizeof(cse), 1, f) != 1) {
		warnp("fread(%s)", s);
		goto err4;
	}
	stats_extra->nchunks = le64dec(cse.nchunks);
	stats_extra->s_len = le64dec(cse.s_len);
	stats_extra->s_zlen = le64dec(cse.s_zlen);

	/* Read the chunk structures. */
	for (; numchunks != 0; numchunks--) {
		/* Set p to point at the struct chunkdata. */
		if (statstape)
			p = &ps->d;

		/* Read the file one record at a time... */
		if (fread(&che, sizeof(che), 1, f) != 1) {
			warnp("fread(%s)", s);
			goto err4;
		}

		/* ... creating struct chunkdata records... */
		memcpy(p->hash, che.hash, 32);
		p->len = le32dec(che.len);
		p->zlen_flags = le32dec(che.zlen);
		p->nrefs = le32dec(che.nrefs);
		p->ncopies = le32dec(che.ncopies);

		/* ... inserting them into the hash table... */
		if (rwhashtab_insert(HT, p))
			goto err4;

		/* ... and updating the statistics. */
		chunks_stats_add(stats_unique, p->len, p->zlen_flags, 1);
		chunks_stats_add(stats_all, p->len, p->zlen_flags, p->ncopies);

		/* Sanity check. */
		if ((p->len == 0) || (p->zlen_flags == 0) || (p->nrefs == 0)) {
			warn0("on-disk directory is corrupt: %s", s);
			goto err4;
		}

		/* Move to next record. */
		if (statstape)
			ps++;
		else
			p++;
	}
	if (fclose(f)) {
		warnp("fclose(%s)", s);
		goto err3;
	}

	/* Free string allocated by asprintf. */
	free(s);

	/* Success! */
	return (HT);

err4:
	fclose(f);
err3:
	free(*dir);
err2:
	free(s);
err1:
	rwhashtab_free(HT);
err0:
	/* Failure! */
	return (NULL);
}
예제 #28
0
/**
 * archive_multitape_copy(ina, read_cookie, a, write_cookie)
 * Copy the data for an entry from one archive to another.
 */
int
archive_multitape_copy(struct archive * ina, void * read_cookie,
    struct archive * a, void * write_cookie)
{
	char	buff[64*1024];
	struct chunkheader * ch;
	ssize_t lenread;
	ssize_t writelen;
	off_t entrylen;
	ssize_t backloglen;

	/* Compute the entry size. */
	if ((entrylen = archive_read_get_entryleft(ina)) < 0) {
		archive_set_error(ina, ENOSYS,
		    "read_get_entryleft not supported");
		return (-2);
	}

	/* Copy data. */
	while (entrylen > 0) {
		/* Is there data buffered by libarchive? */
		if ((backloglen = archive_read_get_backlog(ina)) < 0) {
			warn0("Error reading libarchive data backlog");
			return (-2);
		}
		if (backloglen > 0) {
			/* Drain some data from libarchive. */
			if ((size_t)backloglen > sizeof(buff))
				lenread = sizeof(buff);
			else
				lenread = backloglen;
			lenread = archive_read_data(ina, buff, lenread);
			if (lenread == 0) {
				warn0("libarchive claims data backlog,"
				    " but no data can be read?");
				return (-2);
			}
			if (lenread < 0)
				return (-2);

			/* Write it out to the new archive. */
			writelen = archive_write_data(a, buff, lenread);
			if (writelen < lenread)
				return (-1);

			/* Adjust the remaining entry length and continue. */
			entrylen -= lenread;
			continue;
		}

		/* Attempt to read a chunk for fast-pathing. */
		lenread = readtape_readchunk(read_cookie, &ch);
		if (lenread < 0)
			return (-2);
		if (lenread > entrylen) {
			warn0("readchunk returned chunk beyond end"
			    " of archive entry?");
			return (-2);
		}
		if (lenread == 0)
			goto nochunk;

		/* Attempt to write the chunk via the fast path. */
		writelen = writetape_writechunk(write_cookie, ch);
		if (writelen < 0)
			return (-1);
		if (writelen == 0)
			goto nochunk;
		if (writelen != lenread) {
			warn0("chunk write size != chunk read size?");
			return (-1);
		}

		/*
		 * Advance libarchive pointers.  Do the write pointer
		 * first since a failure there is fatal.
		 */
		if (archive_write_skip(a, writelen))
			return (-1);
		if (archive_read_advance(ina, lenread))
			return (-2);

		/* We don't need to see this chunk again. */
		if (readtape_skip(read_cookie, lenread) != lenread) {
			warn0("could not skip read data?");
			return (-2);
		}

		/* We've done part of the entry. */
		entrylen -= lenread;
		continue;

nochunk:
		/*
		 * We have no data buffered in libarchive, and we can't copy
		 * an intact chunk.  We need to read some data, but we have
		 * no idea how much the multitape layer wants to provide to
		 * libarchive next; and we don't want to read too much data
		 * since we might waste time reading and writing chunked data
		 * which could be fast-pathed.  Simple solution: Read and
		 * write one byte.  Libarchive will almost certainly get more
		 * than one byte from the multitape layer, but when we return
		 * to the start of this loop and handle backlogged data we
		 * will pick up the rest of the data.  (Also, this is always
		 * where we end up when we hit the end of an archive entry,
		 * in which case archive_read_data returns 0 and we exit the
		 * loop.)
		 */
		lenread = archive_read_data(ina, buff, 1);
		if (lenread == 0)
			break;
		if (lenread < 0)
			return (-2);
		writelen = archive_write_data(a, buff, 1);
		if (writelen < 1)
			return (-1);
	};

	return (0);
}
예제 #29
0
파일: main.c 프로젝트: carriercomm/scrypt
int
main(int argc, char *argv[])
{
	FILE * infile;
	FILE * outfile;
	int dec = 0;
	size_t maxmem = 0;
	double maxmemfrac = 0.5;
	double maxtime = 300.0;
	const char * ch;
	char * passwd;
	int rc;
	int verbose = 0;

	WARNP_INIT;

	/* We should have "enc" or "dec" first. */
	if (argc < 2)
		usage();
	if (strcmp(argv[1], "enc") == 0) {
		maxmem = 0;
		maxmemfrac = 0.125;
		maxtime = 5.0;
	} else if (strcmp(argv[1], "dec") == 0) {
		dec = 1;
	} else
		usage();
	argc--;
	argv++;

	/* Parse arguments. */
	while ((ch = GETOPT(argc, argv)) != NULL) {
		GETOPT_SWITCH(ch) {
		GETOPT_OPTARG("-M"):
			maxmem = strtoumax(optarg, NULL, 0);
			break;
		GETOPT_OPTARG("-m"):
			maxmemfrac = strtod(optarg, NULL);
			break;
		GETOPT_OPTARG("-t"):
			maxtime = strtod(optarg, NULL);
			break;
		GETOPT_OPT("-v"):
			verbose = 1;
			break;
		GETOPT_MISSING_ARG:
			warn0("Missing argument to %s\n", ch);
			/* FALLTHROUGH */
		GETOPT_DEFAULT:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	/* We must have one or two parameters left. */
	if ((argc < 1) || (argc > 2))
		usage();

	/* If the input isn't stdin, open the file. */
	if (strcmp(argv[0], "-")) {
		if ((infile = fopen(argv[0], "rb")) == NULL) {
			warnp("Cannot open input file: %s", argv[0]);
			exit(1);
		}
	} else {
		infile = stdin;
	}

	/* If we have an output file, open it. */
	if (argc > 1) {
		if ((outfile = fopen(argv[1], "wb")) == NULL) {
			warnp("Cannot open output file: %s", argv[1]);
			exit(1);
		}
	} else {
		outfile = stdout;
	}

	/* Prompt for a password. */
	if (readpass(&passwd, "Please enter passphrase",
	    dec ? NULL : "Please confirm passphrase", 1))
		exit(1);

	/* Encrypt or decrypt. */
	if (dec)
		rc = scryptdec_file(infile, outfile, (uint8_t *)passwd,
		    strlen(passwd), maxmem, maxmemfrac, maxtime, verbose);
	else
		rc = scryptenc_file(infile, outfile, (uint8_t *)passwd,
		    strlen(passwd), maxmem, maxmemfrac, maxtime, verbose);

	/* Zero and free the password. */
	insecure_memzero(passwd, strlen(passwd));
	free(passwd);

	/* Close any files we opened. */
	if (infile != stdin)
		fclose(infile);
	if (outfile != stdout)
		fclose(outfile);

	/* If we failed, print the right error message and exit. */
	if (rc != 0) {
		switch (rc) {
		case 1:
			warnp("Error determining amount of available memory");
			break;
		case 2:
			warnp("Error reading clocks");
			break;
		case 3:
			warnp("Error computing derived key");
			break;
		case 4:
			warnp("Error reading salt");
			break;
		case 5:
			warnp("OpenSSL error");
			break;
		case 6:
			warnp("Error allocating memory");
			break;
		case 7:
			warn0("Input is not valid scrypt-encrypted block");
			break;
		case 8:
			warn0("Unrecognized scrypt format version");
			break;
		case 9:
			warn0("Decrypting file would require too much memory");
			break;
		case 10:
			warn0("Decrypting file would take too much CPU time");
			break;
		case 11:
			warn0("Passphrase is incorrect");
			break;
		case 12:
			warnp("Error writing file: %s",
			    (argc > 1) ? argv[1] : "standard output");
			break;
		case 13:
			warnp("Error reading file: %s", argv[0]);
			break;
		}
		exit(1);
	}

	return (0);
}
예제 #30
0
static int
multitape_metadata_get(STORAGE_R * S, CHUNKS_S * C,
    struct tapemetadata * mdat,
    const uint8_t tapehash[32], const char * tapename, int quiet)
{
	uint8_t hbuf[32];
	uint8_t * mbuf;
	size_t mdlen;

	/* Read the tape metadata. */
	switch (storage_read_file_alloc(S, &mbuf, &mdlen, 'm', tapehash)) {
	case -1:
		/* Internal error. */
		goto err1;
	case 1:
		/* ENOENT. */
		goto notpresent;
	case 2:
		/* Corrupt metadata file. */
		goto corrupt;
	}

	/* Adjust chunk statistics. */
	if (C != NULL)
		chunks_stats_extrastats(C, mdlen);

	/* Parse the tape metadata. */
	switch (multitape_metadata_dec(mdat, mbuf, mdlen)) {
	case 1:
		/* Metadata is corrupt. */
		goto corrupt1;
	case -1:
		/* Error. */
		goto err2;
	}

	/* Store metadata length. */
	mdat->metadatalen = mdlen;

	/* Free tape metadata. */
	free(mbuf);

	/*
	 * Make sure the name stored in the archive metadata matches the
	 * name of the metadata file.
	 */
	if (crypto_hash_data(CRYPTO_KEY_HMAC_NAME,
	    (uint8_t *)mdat->name, strlen(mdat->name), hbuf))
		goto err0;
	if (crypto_verify_bytes(tapehash, hbuf, 32))
		goto corrupt;

	/* Success! */
	return (0);

corrupt1:
	free(mbuf);
corrupt:
	if (quiet == 0) {
		if (tapename)
			warn0("Archive metadata is corrupt: %s", tapename);
		else
			warn0("Archive metadata file is corrupt");
	}

	/* File is corrupt. */
	return (2);

notpresent:
	if (quiet == 0) {
		if (tapename)
			warn0("Archive does not exist: %s", tapename);
		else
			warn0("Cannot read archive metadata file");
	}

	/* ENOENT. */
	return (1);

err2:
	free(mbuf);
err1:
	warnp("Error reading archive metadata");
err0:
	/* Failure! */
	return (-1);
}