示例#1
0
文件: locks.c 项目: lavabit/magma
 /**
  * @brief	Acquire a named lock, with synchronization provided via memcached.
  * @see	cache_silent_add()
  * @note	The lock will be held for a maximum of 10 minutes, and failed locking attempts will be retried
  * 		periodically for a maxmimum of 1 minute before returing failure.
  * @param	key		a managed string containing the name of the lock to be acquired.
  * @return	-1 on general failure, 0 on memcached failure, or 1 on success.
  */
int_t lock_get(stringer_t *key) {

	uint64_t value;
	stringer_t *lock = MANAGEDBUF(128);
	int_t success, iterations = MAGMA_LOCK_TIMEOUT;
//	const struct timespec delay = { .tv_sec = 0, .tv_nsec = 1000000000 };
	const struct timespec delay = { .tv_sec = 1, .tv_nsec = 0 };

	// Build the key.
	if (st_empty(key) || st_sprint(lock, "%.*s.lock", st_length_int(key), st_char_get(key)) <= 0) {
		log_pedantic("Unable generate the accessor for the cluster lock.");
		return -1;
	}

	// Build the lock value.
	value = time(NULL);

	do {

		// Keep the lock for ten minutes.
		if ((success = cache_silent_add(lock, PLACER(&value, sizeof(uint64_t)), MAGMA_LOCK_EXPIRATION)) != 1) {
			nanosleep(&delay, NULL);
		}

	} while (success != 1 && iterations--);

#ifdef MAGMA_PEDANTIC
	if (success != 1) log_pedantic("Unable to obtain a cluster lock for %.*s.", st_length_int(lock), st_char_get(lock));
#endif

	return success;
}

/**
  * @brief	Release a named lock, with synchronization provided via memcached.
  * @see	cache_delete()
  * @note	The lock will be held for 10 seconds, and locking attempts will occur periodically for 60 seconds prior to failure.
  * @param	key		a managed string containing the name of the lock to be released.
  * @return	-1 on general failure, 0 on memcached failure, or 1 on success.
  */
void lock_release(stringer_t *key) {

	stringer_t *lock = MANAGEDBUF(128);

	// Build the key.
	if (st_empty(key) || st_sprint(lock, "%.*s.lock", st_length_int(key), st_char_get(key)) <= 0) {
		log_pedantic("Unable generate the accessor for the cluster lock.");
		return;
	}

	/// LOW: At some point we should add logic to check whether this cluster node even owns the lock before
	/// 	blindly deleting the lock.
	cache_delete(lock);
	return;
}
示例#2
0
文件: orgs.c 项目: lavabit/magma
/**
 * @brief	Derive an organizational signet from the corresponding private key structures.
 */
prime_org_signet_t * org_signet_generate(prime_org_key_t *org) {

	prime_org_signet_t *signet = NULL;
	stringer_t *signing = NULL, *encryption = NULL, *cryptographic = MANAGEDBUF(69);

	// Ensure the org structure contains the necessary private keys.
	if (!org || !org->encryption || !org->signing || org->signing->type != ED25519_PRIV) {
		return NULL;
	}
	else if (!(signet = mm_alloc(sizeof(prime_org_signet_t)))) {
		return NULL;
	}
	// Store the public singing, and encryption keys.
	else if (!(signing = ed25519_public_get(org->signing, NULL)) ||
		!(encryption = secp256k1_public_get(org->encryption, NULL))) {
		log_pedantic("PRIME organizational signet generation failed, the public keys could not be derived from the provided private keys.");
		org_signet_free(signet);
		st_cleanup(signing);
		return NULL;
	}

	// Generate a serialized signet with the cryptographic fields.
	else if (st_write(cryptographic, prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, signing, MANAGEDBUF(34)),
		prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, encryption, MANAGEDBUF(35))) != 69) {
		log_pedantic("PRIME organizational signet generation failed, the serialized cryptographic signet could not be derived.");
		org_signet_free(signet);
		st_free(encryption);
		st_free(signing);
		return NULL;
	}

	// Generate a signature using the serialized cryptographic fields.
	else if (!(signet->signature = ed25519_sign(org->signing, cryptographic, NULL))) {
		log_pedantic("PRIME organizational signet generation failed, the cryptographic signet signature could not be derived.");
		org_signet_free(signet);
		st_free(encryption);
		st_free(signing);
		return NULL;
	}

	// Finally, convert the serialized public keys into usable structures.
	else if (!(signet->signing = ed25519_public_set(signing)) || !(signet->encryption = secp256k1_public_set(encryption))) {
		log_pedantic("PRIME organizational signet generation failed, the serialized public keys could not be parsed.");
		org_signet_free(signet);
		st_free(encryption);
		st_free(signing);
		return NULL;
	}

	// We no longer need the serialized public keys.
	st_free(encryption);
	st_free(signing);

	return signet;
}
示例#3
0
文件: orgs.c 项目: lavabit/magma
stringer_t * org_signet_fingerprint(prime_org_signet_t *org, stringer_t *output) {

	stringer_t *holder = MANAGEDBUF(134);

	if (!org || !org->signing || !org->encryption || !org->signature || st_length_get(org->signature) != 64) {
		return false;
	}
	else if (st_write(holder, prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, ed25519_public_get(org->signing, MANAGEDBUF(32)), MANAGEDBUF(34)),
		prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, secp256k1_public_get(org->encryption, MANAGEDBUF(33)), MANAGEDBUF(35)),
		prime_field_write(PRIME_ORG_SIGNET, 4, ED25519_SIGNATURE_LEN, org->signature, MANAGEDBUF(65))) != 134) {
		return false;
	}

	return hash_sha512(holder, output);
}
示例#4
0
文件: crypto.c 项目: lavabit/magma
/**
 * @brief
 *  Serialize an EC public key to be shared.
 * @param
 *  key a pointer to the EC key pair to have its public key serialized.
 * @param
 *  outsize a pointer to a variable that will receive the length of the
 *  serialized key on success.
 * @return
 *  a pointer to the serialized EC public key on success, or NULL on failure.
 */
unsigned char * _serialize_ec_pubkey(EC_KEY *key, size_t *outsize) {
	unsigned char *buf = NULL;

	if (!key || !outsize) {
		RET_ERROR_PTR(ERR_BAD_PARAM, NULL);
	}

	stringer_t *pub;
	if (!(pub = secp256k1_public_get(key, MANAGEDBUF(33)))) {
		PUSH_ERROR_OPENSSL();
		RET_ERROR_PTR(ERR_UNSPEC, "unable to serialize EC public key");
	}

	buf = mm_alloc(33);
	memmove(buf, st_data_get(pub), st_length_get(pub));

	*outsize = st_length_get(pub);

//    EC_KEY_set_conv_form_d(key, POINT_CONVERSION_COMPRESSED);
//    if ((bsize = i2o_ECPublicKey_d(key, &buf)) < 0) {
//        PUSH_ERROR_OPENSSL();
//        RET_ERROR_PTR(ERR_UNSPEC, "unable to serialize EC public key");
//    }

//    *outsize = bsize;

	return buf;
}
示例#5
0
bool_t check_string_write(void) {

	stringer_t *output = MANAGEDBUF(1024), *strings[3] = { MANAGEDBUF(32), MANAGEDBUF(64), MANAGEDBUF(128) };

	for (int i = 0; i < 3; i++) {
		rand_write(strings[i]);
	}

	if (st_write(NULL, strings[0], strings[1], strings[2]) != 224) {
		return false;
	}

	if (st_write(output, strings[0], strings[1], strings[2]) != 224) {
		return false;
	}

	return true;

}
示例#6
0
文件: locks.c 项目: lavabit/magma
 /**
  * @brief	Acquire a lock in the magma.user keyspace.
  * @param	usernum		the numerical id of the user for whom the lock will be acquired.
  * @return	-1 on general failure, 0 on memcached failure, or 1 on success.
  */
int_t user_lock(uint64_t usernum) {

	stringer_t *key = MANAGEDBUF(128);

	if (st_sprint(key, "magma.user.%lu", usernum) <= 0) {
		return -1;
	}

	return lock_get(key);
}
示例#7
0
文件: orgs.c 项目: lavabit/magma
stringer_t * org_signet_get(prime_org_signet_t *org, stringer_t *output) {

	size_t length;
	int_t written = 0;
	stringer_t *result = NULL;

	if (!org || !(length = org_signet_length(org))) {
		log_pedantic("An invalid org signet was supplied for serialization.");
		return NULL;
	}

	// See if we have a valid output buffer, or if output is NULL, allocate a buffer to hold the output.
	else if (output && (!st_valid_destination(st_opt_get(output)) || st_avail_get(output) < length)) {
		log_pedantic("An output string was supplied but it does not represent a buffer capable of holding the output.");
		return NULL;
	}
	else if (!output && !(result = st_alloc(length))) {
		log_pedantic("Could not allocate a buffer large enough to hold encoded result. { requested = %zu }", length);
		return NULL;
	}
	else if (!output) {
		output = result;
	}

	st_wipe(output);

	// Calculate the size, by writing out all the fields (minus the header) using a NULL output.
	length = st_write(NULL, prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, ed25519_public_get(org->signing, MANAGEDBUF(32)), MANAGEDBUF(34)),
		prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, secp256k1_public_get(org->encryption, MANAGEDBUF(33)), MANAGEDBUF(35)),
		prime_field_write(PRIME_ORG_SIGNET, 4, ED25519_SIGNATURE_LEN, org->signature, MANAGEDBUF(65)));

	// Then output them again into the actual output buffer, but this time include the header. This is very primitive serialization logic.
	if ((written = st_write(output, prime_header_org_signet_write(length, MANAGEDBUF(5)),
		prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, ed25519_public_get(org->signing, MANAGEDBUF(32)), MANAGEDBUF(34)),
		prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, secp256k1_public_get(org->encryption, MANAGEDBUF(33)), MANAGEDBUF(35)),
		prime_field_write(PRIME_ORG_SIGNET, 4, ED25519_SIGNATURE_LEN, org->signature, MANAGEDBUF(65)))) != (length + 5)) {
		log_pedantic("The organizational signet didn't serialize to the expected length. { written = %i }", written);
		st_cleanup(result);
		return NULL;
	}

	return output;
}
示例#8
0
/**
 * @brief	Increment the contact abuse history counter for an IP address.
 * @param	con		a pointer to the connection object of the remote host making the contact request.
 * @return	This function returns no value.
 */
void contact_abuse_increment_history(connection_t *con) {

	stringer_t *key = MANAGEDBUF(64), *ip = NULL;

	// Build the key.
	if (!(ip = con_addr_presentation(con, ip)) && st_sprint(key, "magma.web.contact.history.%.*s", st_length_int(ip), st_char_get(ip)) > 0) {
		cache_increment(key, 1, 1, 86400);
	}

	return;
}
示例#9
0
文件: locks.c 项目: lavabit/magma
/**
 * @brief	Unlock a lock in the magma.user keyspace.
 * @param	usernum		the numerical id of the user for whom the lock will be unlocked.
 * @return	This function returns no value.
 */
void user_unlock(uint64_t usernum) {

	stringer_t *key = MANAGEDBUF(128);

	if (st_sprint(key, "magma.user.%lu", usernum) <= 0) {
		return;
	}

	lock_release(key);

	return;
}
示例#10
0
END_TEST

START_TEST (check_mail_headers_s) {

	log_disable();
	bool_t result = true;
	stringer_t *errmsg = MANAGEDBUF(1024);

	if (status()) result = check_mail_headers_sthread(errmsg);

	log_test("MAIL / HEADERS / SINGLE THREADED:", errmsg);
	ck_assert_msg(result, st_char_get(errmsg));
}
示例#11
0
/**
 * @brief	Check to see that a client from a given IP address hasn't exceeded its daily quota of contact requests.
 * @note	Each IP address will be limited to at most 2 contact requests in any 24-hour period.
 * @param	con		a pointer to the connection object of the remote host making the contact request.
 * @param	branch	a null-terminated string specifying where the contact request was directed ("Abuse" or "Contact").
 * @return	true if the specified connection failed the abuse check or false if it did not.
 */
bool_t contact_abuse_checks(connection_t *con, chr_t *branch) {

	stringer_t *key = MANAGEDBUF(64), *ip = NULL;

	// Build the key.
	if (!(ip = con_addr_presentation(con, ip)) && st_sprint(key, "magma.web.contact.history.%.*s", st_length_int(ip), st_char_get(ip)) > 0 && cache_get_u64(key) >= 2) {
		contact_print_message(con, branch, "To prevent abuse, our system only allows you to submit two letters to our team in a twenty-four hour period. If you need "
			"to submit another message please return in twenty-four hours and try again");
		return true;
	}

	return false;
}
示例#12
0
END_TEST

START_TEST (check_mail_store_s) {

	log_disable();
	bool_t result = true;
	stringer_t *errmsg = MANAGEDBUF(1024);

	if (status()) result = check_mail_store_plaintext_sthread(errmsg);
	if (status() && result) result = check_mail_store_encrypted_sthread(errmsg);

	log_test("MAIL / STORE / SINGLE THREADED:", errmsg);
	ck_assert_msg(result, st_char_get(errmsg));
}
示例#13
0
文件: orgs.c 项目: lavabit/magma
bool_t org_signet_verify(prime_org_signet_t *org) {

	stringer_t *holder = MANAGEDBUF(69);

	if (!org || !org->signing || !org->encryption || !org->signature || st_length_get(org->signature) != 64) {
		return false;
	}
	else if (st_write(holder, prime_field_write(PRIME_ORG_SIGNET, 1, ED25519_KEY_PUB_LEN, ed25519_public_get(org->signing, MANAGEDBUF(32)), MANAGEDBUF(34)),
		prime_field_write(PRIME_ORG_SIGNET, 3, SECP256K1_KEY_PUB_LEN, secp256k1_public_get(org->encryption, MANAGEDBUF(33)), MANAGEDBUF(35))) != 69) {
		return false;
	}
	else if (ed25519_verify(org->signing, holder, org->signature)) {
		return false;
	}

	return true;
}
示例#14
0
bool_t check_prime_signets_user_sthread(stringer_t *errmsg) {

	prime_t *org = NULL, *verify = NULL, *user1 = NULL, *user2 = NULL, *request1 = NULL, *request2 = NULL,
		*signet1 = NULL, *signet2 = NULL, *signet3 = NULL, *signet4 = NULL;
	stringer_t *fingerprint = NULL, *binary = NULL, *armored = NULL;


	// Create an org key.
	if (!(org = prime_key_generate(PRIME_ORG_KEY, NONE)) || !(verify = prime_signet_generate(org))) {
		st_sprint(errmsg, "Organizational signet/key for user signing failed.");
		prime_cleanup(org);
		return false;
	}

	// Create a user key and then generate the corresponding signing request.
	else if (!(user1 = prime_key_generate(PRIME_USER_KEY, NONE)) || !(request1 = prime_request_generate(user1, NULL))) {
		st_sprint(errmsg, "User key/signing request creation failed.");
		prime_cleanup(user1);
		prime_free(verify);
		prime_free(org);
		return false;
	}

	// Sign the user request.
	else if (!(signet1 = prime_request_sign(request1, org))) {
		st_sprint(errmsg, "User key/signing request signing failed.");
		prime_free(request1);
		prime_free(verify);
		prime_free(user1);
		prime_free(org);
		return false;
	}


	// Serialize the user signet.
	else if (!(binary = prime_get(signet1, BINARY, MANAGEDBUF(512)))) {
		st_sprint(errmsg, "User signet serialization failed.");
		prime_free(request1);
		prime_free(signet1);
		prime_free(verify);
		prime_free(user1);
		prime_free(org);
		return false;
	}

	// Serialize and armor the user signet.
	else if (!(armored = prime_get(signet1, ARMORED, MANAGEDBUF(512)))) {
		st_sprint(errmsg, "User signet armoring failed.");
		prime_free(request1);
		prime_free(signet1);
		prime_free(verify);
		prime_free(user1);
		prime_free(org);
		return false;
	}

	else if (!(user2 = prime_key_generate(PRIME_USER_KEY, NONE)) || !(request2 = prime_request_generate(user2, user1)) ||
		!(signet2 = prime_request_sign(request2, org))) {
		st_sprint(errmsg, "User signet/key rotation failed.");
		prime_cleanup(request2);
		prime_cleanup(user2);
		prime_free(request1);
		prime_free(signet1);
		prime_free(verify);
		prime_free(user1);
		prime_free(org);
		return false;
	}

	else if (!(signet3 = prime_set(binary, BINARY,  NONE)) || !(signet4 = prime_set(armored, ARMORED,  NONE))) {
		st_sprint(errmsg, "User signet parsing failed.");
		prime_cleanup(signet3);
		prime_free(request2);
		prime_free(request1);
		prime_free(signet2);
		prime_free(signet1);
		prime_free(verify);
		prime_free(user2);
		prime_free(user1);
		prime_free(org);
		return false;
	}

	// Ensure we can generate cryptographic fingerprints.
	else if (!prime_signet_validate(request1, NULL) || !prime_signet_validate(signet1, NULL) || !prime_signet_validate(request2, NULL) ||
		!prime_signet_validate(signet2, NULL) || !prime_signet_validate(signet1, verify) || !prime_signet_validate(signet2, verify) ||
		!prime_signet_validate(request2, signet1) || !prime_signet_validate(signet2, signet1)) {
		st_sprint(errmsg, "User signet validation failed.");
		prime_free(request2);
		prime_free(request1);
		prime_free(signet4);
		prime_free(signet3);
		prime_free(signet2);
		prime_free(signet1);
		prime_free(verify);
		prime_free(user2);
		prime_free(user1);
		prime_free(org);
		return false;
	}

	// Ensure we can generate cryptographic fingerprints.
	else if (!(fingerprint = prime_signet_fingerprint(signet1, MANAGEDBUF(64))) || !(fingerprint = prime_signet_fingerprint(signet2, MANAGEDBUF(64)))) {
		st_sprint(errmsg, "User signet fingerprinting failed.");
		prime_free(request2);
		prime_free(request1);
		prime_free(signet4);
		prime_free(signet3);
		prime_free(signet2);
		prime_free(signet1);
		prime_free(verify);
		prime_free(user2);
		prime_free(user1);
		prime_free(org);
		return false;
	}

	prime_free(request2);
	prime_free(request1);
	prime_free(signet4);
	prime_free(signet3);
	prime_free(signet2);
	prime_free(signet1);
	prime_free(verify);
	prime_free(user2);
	prime_free(user1);
	prime_free(org);

	return true;
}
示例#15
0
bool_t check_prime_keys_org_sthread(stringer_t *errmsg) {

	prime_t *holder = NULL;
	stringer_t *packed = NULL, *key = MANAGEDBUF(64);

	// Create a STACIE realm key.
	rand_write(key);

	// Allocate an org key.
	if (!(holder = prime_alloc(PRIME_ORG_KEY, NONE))) {
		st_sprint(errmsg, "Organizational key allocation failed.");
		return false;
	}

	prime_free(holder);

	// Generate an org key.
	if (!(holder = prime_key_generate(PRIME_ORG_KEY, NONE))) {
		st_sprint(errmsg, "Organizational key generation failed.");
		return false;
	}

	// Serialize the org key.
	else if (!(packed = prime_get(holder, BINARY, MANAGEDBUF(256)))) {
		st_sprint(errmsg, "Organizational key serialization failed.");
		prime_free(holder);
		return false;
	}

	prime_free(holder);

	// Unpack the serialized org key.
	if (!(holder = prime_set(packed, BINARY, NONE))) {
		st_sprint(errmsg, "Organizational key parsing failed.");
		return false;
	}

	// Encrypt the org key.
	else if (!(packed = prime_key_encrypt(key, holder, BINARY, MANAGEDBUF(256)))) {
		st_sprint(errmsg, "Organizational key encryption failed.");
		prime_free(holder);
		return false;
	}

	prime_free(holder);

	// Decrypt the org key.
	if (!(holder = prime_key_decrypt(key, packed, BINARY, NONE))) {
		st_sprint(errmsg, "Encrypted organizational key parsing failed.");
		return false;
	}

	prime_free(holder);

	// Perform the same checks, but this time make the functions
	// allocate memory for the output. Generate an org key.
	if (!(holder = prime_key_generate(PRIME_ORG_KEY, NONE))) {
		st_sprint(errmsg, "Organizational key generation failed.");
		return false;
	}

	// Serialize the org key.
	else if (!(packed = prime_get(holder, BINARY, NULL))) {
		st_sprint(errmsg, "Organizational key serialization failed.");
		prime_free(holder);
		return false;
	}

	prime_free(holder);

	// Unpack the serialized org key.
	if (!(holder = prime_set(packed, BINARY, NONE))) {
		st_sprint(errmsg, "Organizational key parsing failed.");
		st_free(packed);
		return false;
	}

	st_free(packed);

	// Encrypt the org key.
	if (!(packed = prime_key_encrypt(key, holder, BINARY, NULL))) {
		st_sprint(errmsg, "Organizational key encryption failed.");
		prime_free(holder);
		return false;
	}

	prime_free(holder);

	// Decrypt the org key.
	if (!(holder = prime_key_decrypt(key, packed, BINARY, NONE))) {
		st_sprint(errmsg, "Encrypted organizational key parsing failed.");
		st_free(packed);
		return false;
	}

	prime_free(holder);
	st_free(packed);

	return true;
}
示例#16
0
/**
 * @brief	Send the contents of a user-submitted contact or abuse form to the magma-configured contact email address.
 * @param	con		the connection of the web client making the request.
 * @param	branch	a null-terminated string containing the destination of the contact form: either "Abuse" or "Contact".
 * @return	This function returns no value.
 */
void contact_business(connection_t *con, chr_t *branch) {

	stringer_t *composed, *ip, *daddr;
	http_data_t *name, *email, *message;
	bool_t is_contact;

	// A contact form submission by default
	if (!st_cmp_cs_eq(NULLER(branch), PLACER("Abuse", 5))) {
		is_contact = false;
		daddr = magma.admin.abuse;
	} else {
		is_contact = true;
		daddr = magma.admin.contact;
	}

	// One last sanity check, just in case.
	if (is_contact && !daddr) {
		contact_print_message(con, branch, "An unexpected error occurred while trying to process your request. This server does not have a contact address configured.");
		log_error("Contact form routine was reached but no contact address was configured.");
		return;
	}
	else if (!is_contact && !daddr) {
		contact_print_message(con, branch, "An unexpected error occurred while trying to process your request. This server does not have an abuse address configured.");
		log_error("Abuse form routine was reached but no abuse address was configured.");
		return;
	}

	// If either the name, email, or message fields are omitted from the post, spit out an error message.
	if (!(name = http_data_get(con, HTTP_DATA_POST, "your_name")) || !name->value) {
		contact_print_form(con, branch, contact_business_add_error(branch, (uchr_t *)"//xhtml:input[@id='your_name']", (uchr_t *)"your_name_msg", (uchr_t *)"Please enter your name."));
		return;
	}
	else if (!(email = http_data_get(con, HTTP_DATA_POST, "your_email")) || !email->value || !contact_business_valid_email(email->value)) {
		contact_print_form(con, branch, contact_business_add_error(branch,  (uchr_t *)"//xhtml:input[@id='your_email']",  (uchr_t *)"your_email_msg",  (uchr_t *)"A valid e-mail address is required."));
		return;
	}
	else if (!(message = http_data_get(con, HTTP_DATA_POST, "your_message")) || !message->value) {
		contact_print_form(con, branch, contact_business_add_error(branch,  (uchr_t *)"//xhtml:textarea[@id='your_message']",  (uchr_t *)"your_message_msg",  (uchr_t *)"Please enter your message."));
		return;
	}

	// Build the IP string.
	ip = con_addr_presentation(con, MANAGEDBUF(64));

	if ((composed = st_merge("nnnsnsnsnsnsnsnsn", "Subject: ", (is_contact ? "* Contact Form Submission *" : "*Abuse Form Submission*"),
		"\r\nFrom: ", magma.admin.contact, "\r\nTo: ", magma.admin.contact, "\r\nReply-To: ",
		email->value, "\r\n\r\nip = ", ip, "\r\nname = ", name->value, "\r\nemail = ", email->value, "\r\n------------\r\n\r\n ", message->value, "\r\n"))) {

		// Dotstuff the message. Just to prevent SMTP injection attacks.
		st_replace(&composed, PLACER("\n.",2), PLACER("\n..", 3));

		// Send the message.
		if (smtp_send_message(daddr, daddr, composed) != 1) {
			contact_print_message(con, branch, "An error occurred while trying to process your request. Please try again in a few minutes.");
			st_free(composed);
			return;
		}

		// Increment our abuse counters.
		contact_abuse_increment_history(con);
		st_free(composed);
	}

	contact_print_message(con, branch, "Your message has been submitted. We'll review your message-typically within one business day-and get back to you. However "
		"during certain busy periods our team can take up to three business days to respond.");

	return;
}
示例#17
0
文件: read.c 项目: lavabit/magma
/**
 * @brief	Read a line of input from a network client session.
 * @return	-1 on general failure, -2 if the connection was reset, or the length of the current line of input, including the trailing new line character.
 */
int64_t client_read_line(client_t *client) {

	ssize_t bytes = 0;
	int_t counter = 0;
	stringer_t *error = NULL;
	bool_t blocking = true, line = false;

#ifdef MAGMA_PEDANTIC
	int_t local = 0;
	stringer_t *ip = NULL, *cipher = NULL;
#endif

	if (!client || client->sockd == -1) {
		if (client) client->status = 1;
		return -1;
	}

	// Check for data past the current line buffer.
	else if (pl_length_get(client->line) && st_length_get(client->buffer) > pl_length_get(client->line)) {

		// Move the unused data to the front of the buffer.
		mm_move(st_data_get(client->buffer), st_data_get(client->buffer) + pl_length_get(client->line), st_length_get(client->buffer) - pl_length_get(client->line));

		// Update the length.
		st_length_set(client->buffer, st_length_get(client->buffer) - pl_length_get(client->line));

		// Check whether the data we just moved contains a complete line.
		if (!pl_empty((client->line = line_pl_st(client->buffer, 0)))) {
			client->status = 1;
			return pl_length_get(client->line);
		}
	}
	// Otherwise reset the buffer and line lengths to zero.
	else {
		st_length_set(client->buffer, 0);
		client->line = pl_null();
	}

	// Loop until we get a complete line, an error, or the buffer is filled.
	do {

		// Read bytes off the network. Skip past any existing data in the buffer.
		if (client->tls) {

			// If bytes is zero or below and the library isn't asking for another read, then an error occurred.
			bytes = tls_read(client->tls, st_char_get(client->buffer) + st_length_get(client->buffer),
				st_avail_get(client->buffer) - st_length_get(client->buffer), blocking);

			// If zero bytes were read, or a negative value was returned to indicate an error, call tls_erorr(), which will return
			// NULL if the error can be safely ignored. Otherwise log the output for debug purposes.
			if (bytes <= 0 && (error = tls_error(client->tls, bytes, MANAGEDBUF(512)))) {
#ifdef MAGMA_PEDANTIC
				cipher = tls_cipher(client->tls, MANAGEDBUF(128));
				ip = ip_presentation(client->ip, MANAGEDBUF(INET6_ADDRSTRLEN));

				log_pedantic("TLS client read operation failed. { ip = %.*s / %.*s / result = %zi%s%.*s }",
					st_length_int(ip), st_char_get(ip), st_length_int(cipher), st_char_get(cipher),
					bytes, (error ? " / " : ""), st_length_int(error), st_char_get(error));
#endif
				client->status = -1;
				return -1;
			}
			// This will occur when the read operation results in a 0, or negative value, but TLS error returns NULL to
			// indicate it was a transient error. For transient errors we simply set bytes equal to 0 so the read call gets retried.
			else if (bytes <= 0) {
				bytes = 0;
			}
		}
		else {

			errno = 0;

			bytes = recv(client->sockd, st_char_get(client->buffer) + st_length_get(client->buffer),
				st_avail_get(client->buffer) - st_length_get(client->buffer), (blocking ? 0 : MSG_DONTWAIT));

			// Check for errors on non-SSL reads in the traditional way.
			if (bytes <= 0 && tcp_status(client->sockd)) {
#ifdef MAGMA_PEDANTIC
				local = errno;
				ip = ip_presentation(client->ip, MANAGEDBUF(INET6_ADDRSTRLEN));

				log_pedantic("TCP client read operation failed. { ip = %.*s / result = %zi / error = %i / message = %s }",
					st_length_int(ip), st_char_get(ip), bytes, local, strerror_r(local, MEMORYBUF(1024), 1024));
#endif
				client->status = -1;
				return -1;
			}

		}

		// We actually read in data, so we need to update the buffer to reflect the amount of data it currently holds.
		if (bytes > 0) {
			st_length_set(client->buffer, st_length_get(client->buffer) + bytes);
		}

		// Check whether we have a complete line before checking whether the connection was closed.
		if (!st_empty(client->buffer) && !pl_empty((client->line = line_pl_st(client->buffer, 0)))) {
			line = true;
		}

	} while (!line && counter++ < 128 && st_length_get(client->buffer) != st_avail_get(client->buffer) && status());

	if (st_length_get(client->buffer) > 0) {
		client->status = 1;
	}

	return pl_length_get(client->line);
}
示例#18
0
/**
 * @brief	Accept and verify a password for POP3 authentication.
 * @note	This command is only allowed for sessions which have not yet been authenticated, but which have already supplied a username.
 *			If the username/password combo was validated, the account information is retrieved and checked to see if it is locked.
 *			After successful authentication, this function will prohibit insecure connections for any user configured to use SSL only,
 *			and enforce the existence of only one POP3 session at a time.
 *			Finally, the database Log table for this user's POP3 access is updated, and all the user's messages are retrieved.
 * @param	con		the POP3 client connection issuing the command.
 * @return	This function returns no value.
 */
void pop_pass(connection_t *con) {

	int_t state;
	credential_t *cred;
	stringer_t *password, *username;

	if (con->pop.session_state != 0) {
		pop_invalid(con);
		return;
	}

	// The user must come before the PASS command.
	if (st_empty(con->pop.username)) {
		con_write_bl(con, "-ERR You must supply a username first.\r\n", 40);
		return;
	}

	// If they didn't pass in a valid password.
	if (!(password = pop_pass_parse(con))) {
		con_write_bl(con, "-ERR Invalid PASS command.\r\n", 28);
		return;
	}

	// Hash the password.
	// First we need to get the regular username from the fully qualified one.
	if (!(username = credential_username(con->pop.username))) {
		con_write_bl(con, "-ERR Internal server error. Please try again later.\r\n", 53);
		st_wipe(password);
		st_free(password);
	}

	st_free(con->pop.username);
	con->pop.username = username;

	if (!(cred = credential_alloc_auth(con->pop.username, password))) {
		con_write_bl(con, "-ERR Internal server error. Please try again later.\r\n", 53);
		st_wipe(password);
		st_free(password);
		return;
	}

	st_wipe(password);
	st_free(password);

	// Pull the user info out.
	state = meta_get(con->pop.username, cred->auth.domain, cred->auth.password, cred->auth.key, META_PROT_POP, META_GET_MESSAGES, &(con->pop.user));

	// Securely delete this information, as these are the keys to the castle.
	credential_free(cred);

	// Not found, or invalid password.
	if (state == 0) {
		con_write_bl(con,  "-ERR The username and password combination is invalid.\r\n", 56);
		return;
	}
	// Internal error.
	else if (state < 0 || !con->pop.user) {
		con_write_bl(con, "-ERR [SYS/TEMP] Internal server error. Please try again later.\r\n", 64);
		return;
	}

	// Locks
	else if (con->pop.user->lock_status != 0) {
		// What type of lock is it.
		if (con->pop.user->lock_status == 1) {
			con_write_bl(con, "-ERR [SYS/PERM] This account has been administratively locked.\r\n", 64);
		}
		else if (con->pop.user->lock_status == 2) {
			con_write_bl(con, "-ERR [SYS/PERM] This account has been locked for inactivity.\r\n", 62);
		}
		else if (con->pop.user->lock_status == 3) {
			con_write_bl(con, "-ERR [SYS/PERM] This account has been locked on suspicion of abuse.\r\n", 69);
		}
		else if (con->pop.user->lock_status == 4) {
			con_write_bl(con, "-ERR [SYS/PERM] This account has been locked at the request of the user.\r\n", 74);
		}
		else {
			con_write_bl(con, "-ERR [SYS/PERM] This account has been locked.\r\n", 47);
		}

		con->pop.user = NULL;
		meta_remove(con->pop.username, META_PROT_POP);
		return;
	}

	// SSL check.
	else if ((con->pop.user->flags & META_USER_SSL) == META_USER_SSL && con_secure(con) != 1) {
		con->pop.user = NULL;
		meta_remove(con->pop.username, META_PROT_POP);
		con_write_bl(con, "-ERR [SYS/PERM] This user account is configured to require that all POP sessions be connected over SSL.\r\n", 105);
		return;
	}

	// Single session check.
	else if (con->pop.user->refs.pop != 1) {
		con->pop.user = NULL;
		meta_remove(con->pop.username, META_PROT_POP);
		con_write_bl(con, "-ERR [IN-USE] This account is being used by another session. Please try again in a few minutes.\r\n", 97);
		return;
	}

	// Debug logging.
	log_pedantic("User %.*s logged in from %s via POP. {poprefs = %lu, imaprefs = %lu, messages = %lu}",
		st_length_int(con->pop.username), st_char_get(con->pop.username), st_char_get(con_addr_presentation(con, MANAGEDBUF(256))),
		con->pop.user->refs.pop, con->pop.user->refs.imap, con->pop.user->messages ? inx_count(con->pop.user->messages) : 0);

	// Update the log and unlock the session.
	meta_data_update_log(con->pop.user, META_PROT_POP);

	meta_user_wlock(con->pop.user);
	meta_messages_login_update(con->pop.user, META_LOCKED);
	meta_user_unlock(con->pop.user);

	// Update session state.
	con->pop.session_state = 1;

	// Tell the client everything worked.
	con_write_bl(con, "+OK Password accepted.\r\n", 24);

	return;
}
示例#19
0
文件: legacy.c 项目: lavabit/magma
/**
 * @brief	Calculates the legacy symmetric encryption key and authentication token.
 * @param	username	a managed string holding the sanitzed username.
 * @param	password	a managed string holding the plain text user password.
 * @return	an auth_legacy_t structure is returned upon success, and NULL upon failure.
 **/
auth_legacy_t * auth_legacy(stringer_t *username, stringer_t *password) {

	auth_legacy_t *legacy = NULL;
	stringer_t *input = NULL, *intermediate = MANAGEDBUF(64);

	// Make sure all three required inputs are valid pointers and hold at least one character.
	if (st_empty(username) || st_empty(password) || st_empty(magma.secure.salt)) {
		log_error("A variable needed to calculate the legacy authentication and encryption values was invalid.");
		return NULL;
	}
	else if (!(legacy = auth_legacy_alloc())) {
		log_error("We were unable to allocate a buffer to hold the legacy hash values.");
		return NULL;
	}

	// Combine the three inputs into a single buffer.
	else if (!(input = st_merge("sss", username, magma.secure.salt, password))) {
		log_error("Unable to combine the three input values needed to calculate the legacy authentication and encryption values.");
		auth_legacy_free(legacy);
		return NULL;
	}

	// Hash the inputs together and we'll get the legacy symmetric encryption key.
	else if (!(legacy->key = st_alloc_opts(MANAGED_T | CONTIGUOUS | SECURE, 64)) || !(hash_sha512(input, legacy->key))) {
		log_error("Unable to calculate the legacy hash values.");
		auth_legacy_free(legacy);
		st_free(input);
		return NULL;
	}

	// Free and reuse the holder variable.
	st_free(input);

	// Prepare the inputs for the intermediary hash.
	if (!(input = st_merge("ss", password, legacy->key))) {
		log_error("Failed to merge the legacy authentication inputs for the intermediate hash round.");
		auth_legacy_free(legacy);
		return NULL;
	}

	// Hash the password with the output of the first round. Note that if the hash function returns NULL and overwrites
	// the intermediate string pointer, the buffer will be freed automatically because it was allocated off the stack.
	else if (!(hash_sha512(input, intermediate))) {
		log_error("Unable to calculate the legacy hash values.");
		auth_legacy_free(legacy);
		st_free(input);
		return NULL;
	}

	// Free and reuse the holder variable.
	st_free(input);

	// Prepare the inputs for the intermediary hash.
	if (!(input = st_merge("ss", password, intermediate))) {
		log_error("Failed to merge the legacy authentication inputs for the final hash round.");
		auth_legacy_free(legacy);
		return NULL;
	}

	// Hash the inputs together and we'll get the legacy authentication token.
	if (!(legacy->token = st_alloc(64)) || !(hash_sha512(input, legacy->token))) {
		log_error("Failed to merge the legacy authentication inputs for the final hash round.");
		auth_legacy_free(legacy);
		st_free(input);
		return NULL;
	}

	// Free the inputs.
	st_free(input);

	// And return success.
	return legacy;
}
示例#20
0
文件: read.c 项目: lavabit/magma
/**
 * @brief	Read data from a network connection, and store the data in the connection context buffer.
 * @return	-1 on general failure, -2 if the connection was reset, or the amount of data that was read.
 */
int64_t client_read(client_t *client) {

	int_t counter = 0;
	ssize_t bytes = 0;
	bool_t blocking = true;
	stringer_t *error = NULL;

#ifdef MAGMA_PEDANTIC
	int_t local = 0;
	stringer_t *ip = NULL, *cipher = NULL;
#endif

	if (!client || client->sockd == -1 || client_status(client) < 0) {
		return -1;
	}

	// Check for data past the current line buffer.
	else if (pl_length_get(client->line) && st_length_get(client->buffer) > pl_length_get(client->line)) {

		// Move the unused data to the front of the buffer.
		mm_move(st_data_get(client->buffer), st_data_get(client->buffer) + pl_length_get(client->line), st_length_get(client->buffer) - pl_length_get(client->line));

		// Update the length.
		st_length_set(client->buffer, st_length_get(client->buffer) - pl_length_get(client->line));

		// Clear the line buffer.
		client->line = pl_null();
	}
	// Otherwise reset the buffer and line lengths to zero.
	else {
		st_length_set(client->buffer, 0);
		client->line = pl_null();
	}

	// Loop until the buffer has data or we get an error.
	do {
		blocking = st_length_get(client->buffer) ? false : true;

		// Read bytes off the network. If data is already in the buffer this should be a non-blocking read operation so we can
		// return the already buffered data without delay.
		if (client->tls) {

			// If bytes is zero or below and the library isn't asking for another read, then an error occurred.
			bytes = tls_read(client->tls, st_char_get(client->buffer) + st_length_get(client->buffer),
				st_avail_get(client->buffer) - st_length_get(client->buffer), blocking);

			// If zero bytes were read, or a negative value was returned to indicate an error, call tls_erorr(), which will return
			// NULL if the error can be safely ignored. Otherwise log the output for debug purposes.
			if (bytes <= 0 && (error = tls_error(client->tls, bytes, MANAGEDBUF(512)))) {
#ifdef MAGMA_PEDANTIC
				cipher = tls_cipher(client->tls, MANAGEDBUF(128));
				ip = ip_presentation(client->ip, MANAGEDBUF(INET6_ADDRSTRLEN));

				log_pedantic("TLS client read operation failed. { ip = %.*s / %.*s / result = %zi%s%.*s }",
					st_length_int(ip), st_char_get(ip), st_length_int(cipher), st_char_get(cipher),
					bytes, (error ? " / " : ""), st_length_int(error), st_char_get(error));
#endif
				client->status = -1;
				return -1;
			}
			// This will occur when the read operation results in a 0, or negative value, but TLS error returns NULL to
			// indicate it was a transient error. For transient errors we simply set bytes equal to 0 so the read call gets retried.
			else if (bytes <= 0) {
				bytes = 0;
			}
		}
		else {

			errno = 0;

			bytes = recv(client->sockd, st_char_get(client->buffer) + st_length_get(client->buffer),
				st_avail_get(client->buffer) - st_length_get(client->buffer), (blocking ? 0 : MSG_DONTWAIT));

			// Check for errors on non-SSL reads in the traditional way.
			if (bytes <= 0 && tcp_status(client->sockd)) {
#ifdef MAGMA_PEDANTIC
				local = errno;
				ip = ip_presentation(client->ip, MANAGEDBUF(INET6_ADDRSTRLEN));

				log_pedantic("TCP client read operation failed. { ip = %.*s / result = %zi / error = %i / message = %s }",
					st_length_int(ip), st_char_get(ip), bytes, local, strerror_r(local, MEMORYBUF(1024), 1024));
#endif
				client->status = -1;
				return -1;
			}

		}

		// We actually read in data, so we need to update the buffer to reflect the amount of data it currently holds.
		if (bytes > 0) {
			st_length_set(client->buffer, st_length_get(client->buffer) + bytes);
		}

	} while (blocking && counter++ < 128 && !st_length_get(client->buffer) && status());

	// If there is data in the buffer process it. Otherwise if the buffer is empty and the connection appears to be closed
	// (as indicated by a return value of 0), then return -1 to let the caller know the connection is dead.
	if (st_length_get(client->buffer)) {
		client->status = 1;
	}
	else if (!bytes) {
		client->status = 2;
		return -2;
	}

	return st_length_get(client->buffer);
}
示例#21
0
bool_t check_prime_signets_org_sthread(stringer_t *errmsg) {

	prime_t *org = NULL, *signet = NULL;
	stringer_t *fingerprint = NULL, *binary = NULL, *armored = NULL, *signet2 = NULL, *signet3 = NULL;

	// Create an org key and then generate the corresponding signet.
	if (!(org = prime_key_generate(PRIME_ORG_KEY, NONE)) || !(signet = prime_signet_generate(org))) {
		st_sprint(errmsg, "Organizational signet/key creation failed.");
		prime_cleanup(org);
		return false;
	}

	// Serialize the org signet.
	else if (!(binary = prime_get(signet, BINARY, MANAGEDBUF(256)))) {
		st_sprint(errmsg, "Organizational signet serialization failed.");
		prime_free(signet);
		prime_free(org);
		return false;
	}

	// Serialize and armor the org signet.
	else if (!(armored = prime_get(signet, ARMORED, MANAGEDBUF(512)))) {
		st_sprint(errmsg, "Organizational signet armoring failed.");
		prime_free(signet);
		prime_free(org);
		return false;
	}
	else if (!(signet2 = prime_set(binary, BINARY,  NONE)) || !(signet3 = prime_set(armored, ARMORED,  NONE))) {
		st_sprint(errmsg, "Organizational signet parsing failed.");
		prime_cleanup(signet2);
		prime_free(signet);
		prime_free(org);
		return false;
	}

	// Validate the org signet.
	else if (!prime_signet_validate(signet, NULL)) {
		st_sprint(errmsg, "Organizational signet validation failed.");
		prime_free(signet3);
		prime_free(signet2);
		prime_free(signet);
		prime_free(org);
		return false;
	}

	// Fingerprint the org signet.
	else if (!(fingerprint = prime_signet_fingerprint(signet, MANAGEDBUF(64)))) {
		st_sprint(errmsg, "Organizational signet fingerprinting failed.");
		prime_free(signet3);
		prime_free(signet2);
		prime_free(signet);
		prime_free(org);
		return false;
	}

	// Hack to easily generate a new org identity.

//	log_enable();
//	log_pedantic("%.*s", st_length_int(armored), st_char_get(armored));
//	fingerprint = prime_get(org, ARMORED, MANAGEDBUF(1024));
//	log_pedantic("%.*s", st_length_int(fingerprint), st_char_get(fingerprint));
//	log_disable();

	prime_free(signet3);
	prime_free(signet2);
	prime_free(signet);
	prime_free(org);

	return true;
}
示例#22
0
bool_t check_prime_signets_parameters_sthread(stringer_t *errmsg) {

	stringer_t *holder = NULL, *rand1 = MANAGEDBUF(32), *rand2 = MANAGEDBUF(128), *rand3 = MANAGEDBUF(64),
		*encrypted_key = NULL;
	prime_t *org_key = NULL, *org_signet = NULL, *user_key = NULL, *user_request = NULL, *user_signet = NULL,
		*rotation_key = NULL, *rotation_request = NULL, *rotation_signet = NULL, *check = NULL;

	// Create various PRIME types for use below.
	if (rand_write(rand1) != 32 || rand_write(rand2) != 128 || rand_write(rand3) != 64 ||
		!(org_key = prime_key_generate(PRIME_ORG_KEY, NONE)) || !(org_signet = prime_signet_generate(org_key)) ||
		!(user_key = prime_key_generate(PRIME_USER_KEY, NONE)) || !(user_request = prime_request_generate(user_key, NULL)) ||
		!(user_signet = prime_request_sign(user_request, org_key)) || !(rotation_key = prime_key_generate(PRIME_USER_KEY, NONE)) ||
		!(rotation_request = prime_request_generate(rotation_key, user_key)) || !(rotation_signet = prime_request_sign(rotation_request, org_key)) ||
		!(encrypted_key = prime_key_encrypt(rand3, user_key, ARMORED, MANAGEDBUF(512)))) {
		st_sprint(errmsg, "Signet/key creation for parameter testing failed.");
		prime_cleanup(org_key);
		prime_cleanup(org_signet);
		prime_cleanup(user_key);
		prime_cleanup(user_request);
		prime_cleanup(user_signet);
		prime_cleanup(rotation_key);
		prime_cleanup(rotation_request);
		prime_cleanup(rotation_signet);
		return false;
	}

	else if ((check = prime_signet_generate(user_key)) || (check = prime_signet_generate(user_request)) || (check = prime_signet_generate(user_signet)) ||
		(check = prime_request_generate(org_key, NULL)) || (check = prime_request_generate(org_signet, NULL)) || (check = prime_request_generate(user_request, NULL)) ||
		(check = prime_request_generate(user_signet, NULL)) || (check = prime_request_sign(org_key, user_key)) || (check = prime_request_sign(org_key, user_request)) ||
		(check = prime_request_sign(org_key, user_signet)) || (check = prime_request_sign(org_key, org_signet)) || (check = prime_request_sign(user_key, org_key)) ||
		(check = prime_request_sign(user_signet, org_key)) || prime_signet_validate(user_key, NULL) || prime_signet_validate(org_key, NULL) ||
		prime_signet_validate(org_signet, org_key) || prime_signet_validate(rotation_request, org_key) || prime_signet_validate(rotation_request, user_key) ||
		prime_signet_validate(org_signet, user_key) || prime_signet_validate(org_signet, user_signet) || prime_signet_validate(user_request, org_key) ||
		prime_signet_validate(user_request, user_key) || prime_signet_validate(user_request, org_signet) || prime_signet_validate(user_request, rotation_key) ||
		prime_signet_validate(user_signet, org_key) || prime_signet_validate(user_signet, user_key) || prime_signet_validate(user_signet, rotation_signet) ||
		prime_signet_validate(user_signet, user_request) || (check = prime_key_generate(PRIME_USER_SIGNET, NONE)) || (check = prime_key_generate(PRIME_ORG_SIGNET, NONE)) ||
		(check = prime_key_generate(PRIME_USER_SIGNING_REQUEST, NONE)) || (check = prime_get(NULL, BINARY, NULL)) ||
		(check = prime_get(NULL, BINARY, MANAGEDBUF(512))) || (check = prime_set(NULL, BINARY, NONE)) || (check = prime_set(NULL, ARMORED, NONE)) ||
		(holder = prime_signet_fingerprint(org_key, MANAGEDBUF(64))) || (holder = prime_signet_fingerprint(user_key, MANAGEDBUF(64))) ||
		(holder = prime_signet_fingerprint(user_request, MANAGEDBUF(64))) || (holder = prime_signet_fingerprint(org_signet, CONSTANT("TEST"))) ||
		(holder = prime_key_encrypt(NULL, org_key, BINARY, MANAGEDBUF(512))) || (holder = prime_key_encrypt(rand1, org_key, BINARY, MANAGEDBUF(512))) ||
		(holder = prime_key_encrypt(rand2, org_key, BINARY, MANAGEDBUF(512))) || (holder = prime_key_encrypt(rand3, org_signet, BINARY, MANAGEDBUF(512))) ||
		(holder = prime_key_encrypt(rand3, NULL, BINARY, MANAGEDBUF(512))) || (holder = prime_key_decrypt(NULL, encrypted_key, ARMORED, NONE)) ||
		(holder = prime_key_decrypt(rand3, NULL, ARMORED, NONE)) || (holder = prime_key_decrypt(rand1, encrypted_key, ARMORED, NONE)) ||
		(holder = prime_key_decrypt(rand2, encrypted_key, ARMORED, NONE)) || (holder = prime_key_decrypt(rand3, encrypted_key, BINARY, NONE)) ||
		(holder = prime_key_decrypt(rand3, prime_get(org_signet, BINARY, MANAGEDBUF(512)), BINARY, NONE)) ||
		(holder = prime_key_decrypt(rand3, prime_get(user_request, BINARY, MANAGEDBUF(512)), BINARY, NONE)) ||
		(holder = prime_key_decrypt(rand3, prime_get(user_signet, BINARY, MANAGEDBUF(512)), BINARY, NONE))) {

		st_sprint(errmsg, "Signet/key parameter checks failed.");
		prime_cleanup(check);
		prime_free(org_key);
		prime_free(org_signet);
		prime_free(user_key);
		prime_free(user_request);
		prime_free(user_signet);
		prime_free(rotation_key);
		prime_free(rotation_request);
		prime_free(rotation_signet);
	}

	prime_free(org_key);
	prime_free(org_signet);
	prime_free(user_key);
	prime_free(user_request);
	prime_free(user_signet);
	prime_free(rotation_key);
	prime_free(rotation_request);
	prime_free(rotation_signet);

	return true;
}