Beispiel #1
0
bool_t check_bitwise_determinism(void) {

	stringer_t *a = NULL, *b = NULL, *res1 = NULL, *res2 = NULL;

	unsigned char a_buf[] = {0x00, 0x33, 0x80, 0x04, 0x20};
	unsigned char b_buf[] = {0x11, 0xCC, 0x78, 0x4B, 0x1E};

	a = PLACER(a_buf, 5);
	b = PLACER(b_buf, 5);

	if(!(res1 = st_xor(a, b, NULL)) || !(res2 = st_xor(a, b, NULL))) {
		st_cleanup(res1, res2);
		return false;
	}
	else if(st_cmp_cs_eq(res1, res2)) {
		st_cleanup(res1, res2);
		return false;
	}

	st_cleanup(res1, res2);
	res1 = res2 = NULL;

	if(!(res1 = st_and(a, b, NULL)) || !(res2 = st_and(a, b, NULL))) {
		st_cleanup(res1, res2);
		return false;
	}
	else if(st_cmp_cs_eq(res1, res2)) {
		st_cleanup(res1, res2);
		return false;
	}

	st_cleanup(res1, res2);
	res1 = res2 = NULL;

	if(!(res1 = st_or(a, b, NULL)) || !(res2 = st_or(a, b, NULL))) {
		st_cleanup(res1, res2);
		return false;
	}
	else if(st_cmp_cs_eq(res1, res2)) {
		st_cleanup(res1, res2);
		return false;
	}

	st_cleanup(res1, res2);
	res1 = res2 = NULL;

	if(!(res1 = st_not(a, NULL)) || !(res2 = st_not(a, NULL))) {
		st_cleanup(res1, res2);
		return false;
	}
	else if(st_cmp_cs_eq(res1, res2)) {
		st_cleanup(res1, res2);
		return false;
	}

	st_cleanup(res1, res2);
	return true;
}
/* modeled closely after args_parse() */
void check_args_parse(int argc, char *argv[]) {

	int_t i = 1;

	while (i < argc) {

		if (!st_cmp_cs_eq(NULLER(argv[i]), PLACER("-v", 2))) {

			if (!(virus_check_data_path = check_next_opt(argv, &i, argc))) {
				do_virus_check = false;
			}

		}
		else if (!st_cmp_cs_eq(NULLER(argv[i]), PLACER("-t", 2))) {

			if (!(tank_check_data_path = check_next_opt(argv, &i, argc))) {
				do_tank_check = false;
			}

		}
		else if (!st_cmp_cs_eq(NULLER(argv[i]), PLACER("-d", 2))) {

			if (!(dspam_check_data_path = check_next_opt(argv, &i, argc))) {
				do_dspam_check = false;
			}

		}
		else if (!st_cmp_cs_eq(NULLER(argv[i]), PLACER("-s", 2))) {
			do_spf_check = false;
			i++;
		}
		// See if it's an illegal parameter beginning with "-"
		else if (!mm_cmp_cs_eq(argv[i], "-", 1)) {
			check_display_usage(argv[0]);
		}
		// Otherwise it's the config file
		else if (i == (argc-1)) {
			snprintf(magma.config.file, MAGMA_FILEPATH_MAX, "%s", argv[i]);
			i++;
		}
		else {
			check_display_usage(argv[0]);
		}

	}

	return;
}
bool_t check_encoding_zbase32(void) {

	stringer_t *zb32, *binary;
	byte_t buffer[ZBASE32_CHECK_SIZE];

	for (uint64_t i = 0; status() && i < ZBASE32_CHECK_ITERATIONS; i++) {

		// Fill the buffer with random data and convert the buffer to hex.
		if (rand_write(PLACER(buffer, ZBASE32_CHECK_SIZE)) != ZBASE32_CHECK_SIZE) {
			return false;
		}
		else if (!(zb32 = zbase32_encode(PLACER(buffer, ZBASE32_CHECK_SIZE)))) {
			return false;
		}

		//log_pedantic("zb32 = %.*s", st_length_int(zb32), st_char_get(zb32));

		// Convert the buffer back to binary and compare it with the original array.
		if (!(binary = zbase32_decode(zb32))) {
			st_free(zb32);
			return false;
		}
		else if (st_cmp_cs_eq(binary, PLACER(buffer, ZBASE32_CHECK_SIZE))) {
			st_free(binary);
			st_free(zb32);
			return false;
		}

		st_free(binary);
		st_free(zb32);
	}

	return true;
}
Beispiel #4
0
bool_t check_encoding_qp(void) {

	stringer_t *qp, *binary;
	byte_t buffer[QP_CHECK_SIZE];

	for (uint64_t i = 0; status() && i < QP_CHECK_ITERATIONS; i++) {

		// Fill the buffer with random data and convert the buffer to hex.
		if (rand_write(PLACER(buffer, QP_CHECK_SIZE)) != QP_CHECK_SIZE) {
			return false;
		}
		else if (!(qp = qp_encode(PLACER(buffer, QP_CHECK_SIZE)))) {
			return false;
		}

		//log_pedantic("qp = %.*s", st_length_int(qp), st_char_get(qp));

		// Convert the buffer back to binary and compare it with the original array.
		if (!(binary = qp_decode(qp))) {
			st_free(qp);
			return false;
		}
		else if (st_cmp_cs_eq(binary, PLACER(buffer, QP_CHECK_SIZE))) {
			st_free(binary);
			st_free(qp);
			return false;
		}

		st_free(binary);
		st_free(qp);
	}

	return true;
}
Beispiel #5
0
bool_t check_bitwise_simple(void) {

	stringer_t *a, *b, *outcome, *check;
	unsigned char    a_buf[] = {0x00, 0xFF, 0x88, 0x44, 0x22};
	unsigned char    b_buf[] = {0x11, 0x33, 0xF0, 0x0F, 0x3C};
	unsigned char  xor_buf[] = {0x11, 0xCC, 0x78, 0x4B, 0x1E};
	unsigned char  and_buf[] = {0x00, 0x33, 0x80, 0x04, 0x20};
	unsigned char   or_buf[] = {0x11, 0xFF, 0xF8, 0x4F, 0x3E};
	unsigned char nota_buf[] = {0xFF, 0x00, 0x77, 0xBB, 0xDD};

	a = PLACER(a_buf, 5);
	b = PLACER(b_buf, 5);
	check = PLACER(xor_buf, 5);

	if(!(outcome = st_xor(a, b, NULL)) || st_cmp_cs_eq(outcome, check)) {
		st_cleanup(outcome);
		return false;
	}

	check = PLACER(and_buf, 5);
	st_free(outcome);

	if(!(outcome = st_and(a, b, NULL)) || st_cmp_cs_eq(outcome, check)) {
		st_cleanup(outcome);
		return false;
	}

	check = PLACER(or_buf, 5);
	st_free(outcome);

	if(!(outcome = st_or(a, b, NULL)) || st_cmp_cs_eq(outcome, check)) {
		st_cleanup(outcome);
		return false;
	}

	check = PLACER(nota_buf, 5);
	st_free(outcome);

	if(!(outcome = st_not(a, NULL)) || st_cmp_cs_eq(outcome,check)) {
		st_cleanup(outcome);
		return false;
	}

	st_free(outcome);

	return true;
}
Beispiel #6
0
/**
 * @brief	Provide the SSL/TLS/DTLS version as a string constant.
 * @see		SSL_get_version()
 */
chr_t * tls_version(TLS *tls) {

	chr_t *version = NULL;
	SSL_CIPHER *cipher = NULL;

	if (!tls || !(cipher = SSL_get_current_cipher_d(tls)) || !(version = (chr_t *)SSL_get_version_d(tls))) {
		return NULL ;
	}

	return (st_cmp_cs_eq(NULLER(version), PLACER("TLSv1", 5)) ? version : "TLSv1.0");
 }
Beispiel #7
0
int check_bsearch_months(int num, char *name) {

	struct check_mi_t *res, key;

	key.name = name;

	qsort(months, (sizeof(months) / sizeof(months[0])), sizeof(struct check_mi_t), check_bsearch_compare);
	res = bsearch(&key, months, (sizeof(months) / sizeof(months[0])), sizeof(struct check_mi_t), check_bsearch_compare);
	if (res == NULL || res->nr != num || st_cmp_cs_eq(NULLER(res->name), NULLER(name))) {
		return false;
	}
	return true;
}
} END_TEST

START_TEST (check_credential_auth_creation_s) {

	credential_t *cred;
	char *errmsg = NULL;

	log_unit("%-64.64s", "OBJECTS / USERS / CREDENTIALS / AUTH CREATION / SINGLE THREADED:");

	if (!(cred = credential_alloc_auth(CONSTANT("ladar"), CONSTANT("test")))) {
		errmsg = "Credential creation failed.";
	}
	else if (st_cmp_cs_eq(cred->auth.password, CONSTANT("46c3c0f5c777aacbdb0c25b14d6889b98efa62fa0ae551ec067d7aa126392805e3e3a2ce07d36" \
		"df7e715e24f35c88105fff5a9eebff0532f990644cf07a4751f"))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
		cred = NULL;
	}

	if (!errmsg && !(cred = credential_alloc_auth(CONSTANT("*****@*****.**"), CONSTANT("test")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && st_cmp_cs_eq(cred->auth.password, CONSTANT("46c3c0f5c777aacbdb0c25b14d6889b98efa62fa0ae551ec067d7aa126392805e3e3a2ce07d36" \
		"df7e715e24f35c88105fff5a9eebff0532f990644cf07a4751f"))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	log_unit("%10.10s\n", (!status() ? "SKIPPED" : !errmsg ? "PASSED" : "FAILED"));
	fail_unless(!errmsg, errmsg);
} END_TEST
Beispiel #9
0
/**
 * @brief	Free all loaded magma configuration options.
 * @note	First all magma config keys will be freed, then the cache servers, relay servers, and magma servers.
 * @return	This function returns no value.
 */
void config_free(void) {

	for (uint64_t i = 0; i < sizeof(magma_keys) / sizeof(magma_keys_t); i++) {
		switch (magma_keys[i].norm.type) {

		case (M_TYPE_BLOCK):
			if (*((void **)(magma_keys[i].store))) {
				mm_free(*((void **)(magma_keys[i].store)));
			}
			break;
		case (M_TYPE_NULLER):
			if (*((char **)(magma_keys[i].store))) {
				ns_free(*((char **)(magma_keys[i].store)));
			}
			break;
		case (M_TYPE_STRINGER):

			// Intercept the blacklist config key.
			if (!st_cmp_cs_eq(NULLER(magma_keys[i].name), PLACER("magma.smtp.blacklist", 20))) {
				for (uint32_t j = 0; j < magma.smtp.blacklists.count; j++) {
					st_free(magma.smtp.blacklists.domain[j]);
				}
			}
			else if (*((stringer_t **)(magma_keys[i].store))) {
				st_free(*((stringer_t **)(magma_keys[i].store)));
			}
			break;
		default:
#ifdef MAGMA_PEDANTIC
			if (magma_keys[i].norm.type != M_TYPE_BOOLEAN && magma_keys[i].norm.type != M_TYPE_DOUBLE && magma_keys[i].norm.type != M_TYPE_FLOAT &&
					magma_keys[i].norm.type != M_TYPE_INT16 && magma_keys[i].norm.type != M_TYPE_INT32 && magma_keys[i].norm.type != M_TYPE_INT64 &&
					magma_keys[i].norm.type != M_TYPE_INT8 && magma_keys[i].norm.type != M_TYPE_UINT8 && magma_keys[i].norm.type != M_TYPE_UINT16 &&
					magma_keys[i].norm.type != M_TYPE_UINT32 && magma_keys[i].norm.type != M_TYPE_UINT64 && magma_keys[i].norm.type != M_TYPE_ENUM) {
				log_pedantic("Unexpected type. {type = %s = %u}", type(magma_keys[i].norm.type), magma_keys[i].norm.type);
			}
#endif
			break;
		}
	}

	cache_free();
	relay_free();
	servers_free();
	return;
}
Beispiel #10
0
bool_t check_hash_simple(void) {

	digest_t *digest;
	stringer_t *hash, *hex;
	chr_t *digest_list[] = {
		"MD4", "MD5", "SHA", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "RIPEMD160"
	}, *result_list[] = {
		"66f1f59819d52476f328839e34101d0f",
		"7215ee9c7d9dc229d2921a40e899ec5f",
		"bce965d4e985f27d988262331c0427909417cd90",
		"b858cb282617fb0956d960215c8e84d1ccf909c6",
		"ca17734c016e36b898af29c1aeb142e774abf4b70bac55ec98a27ba8",
		"36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a430aac59f84ef3cbfab6145068",
		"588016eb10045dd85834d67d187d6b97858f38c58c690320c4a64e0c2f92eebd9f1bd74de256e8268815905159449566",
		"f90ddd77e400dfe6a3fcf479b00b1ee29e7015c5bb8cd70f5f15b4886cc339275ff553fc8a053f8ddc7324f45168cffaf81f8c3ac93996f6536eef38e5e40768",
		"ac53a3aea6835b5ec12054e12d41d392e9d57b72"
	};

	// Loop through and hash a single space using each digest method. Then check whether we got what we expected.
	for (uint64_t i = 0; status() && i < (sizeof(digest_list) / sizeof(chr_t *)); i++) {

		if (!(digest = digest_name(NULLER(digest_list[i]))) || !(hash = hash_digest(digest, PLACER(" ", 1), NULL))) {
			return false;
		}
		else if (!(hex = hex_encode_st(hash, NULL))) {
			st_free(hash);
			return false;
		}
		else if (st_cmp_cs_eq(hex, NULLER(result_list[i]) )) {
			st_free(hash);
			st_free(hex);
			return false;
		}

		st_free(hash);
		st_free(hex);
	}

	return true;
}
END_TEST

START_TEST(check_parser_header) {

	dmime_common_headers_t *header1, *header2;
	int res = 0;
	size_t outsize;
	unsigned char *formatted;

	header1 = dime_prsr_headers_create();
	header1->headers[HEADER_TYPE_DATE] = st_import("11:34:12 AM March 12, 2004", 26);
	header1->headers[HEADER_TYPE_TO] = st_import("*****@*****.**", 13);
	header1->headers[HEADER_TYPE_CC] = st_import("*****@*****.**", 16);
	header1->headers[HEADER_TYPE_FROM] = st_import("*****@*****.**", 22);
	header1->headers[HEADER_TYPE_ORGANIZATION] = st_import("Cool people organization", 24);
	header1->headers[HEADER_TYPE_SUBJECT] = st_import("here's stuff", 12);

	formatted = dime_prsr_headers_format(header1, &outsize);
	ck_assert_msg(formatted != NULL, "Failed to format common headers.\n");

	header2 = dime_prsr_headers_parse(formatted, outsize);
	ck_assert_msg(header2 != NULL, "Failed to parse common headers.\n");

	res = st_cmp_cs_eq(header1->headers[HEADER_TYPE_DATE], header2->headers[HEADER_TYPE_DATE]);
	ck_assert_msg(res == 0, "Date header was corrupted.\n");

	res = st_cmp_cs_eq(header1->headers[HEADER_TYPE_TO], header2->headers[HEADER_TYPE_TO]);
	ck_assert_msg(res == 0, "To header was corrupted.\n");

	res = st_cmp_cs_eq(header1->headers[HEADER_TYPE_CC], header2->headers[HEADER_TYPE_CC]);
	ck_assert_msg(res == 0, "CC header was corrupted.\n");

	res = st_cmp_cs_eq(header1->headers[HEADER_TYPE_FROM], header2->headers[HEADER_TYPE_FROM]);
	ck_assert_msg(res == 0, "From header was corrupted.\n");

	res = st_cmp_cs_eq(header1->headers[HEADER_TYPE_ORGANIZATION], header2->headers[HEADER_TYPE_ORGANIZATION]);
	ck_assert_msg(res == 0, "Organization header was corrupted.\n");

	res = st_cmp_cs_eq(header1->headers[HEADER_TYPE_SUBJECT], header2->headers[HEADER_TYPE_SUBJECT]);
	ck_assert_msg(res == 0, "Subject header was corrupted.\n");

	dime_prsr_headers_destroy(header1);
	dime_prsr_headers_destroy(header2);
	free(formatted);

	fprintf(stderr, "DMIME common header parsing complete.\n");
}
Beispiel #12
0
bool_t check_encoding_url(void) {

	bool_t result = true;
	stringer_t *url, *binary;
	byte_t buffer[URL_CHECK_SIZE];

	for (uint64_t i = 0; status() && result && i < URL_CHECK_ITERATIONS; i++) {

		// Fill the buffer with random data and convert the buffer to hex.
		if (rand_write(PLACER(buffer, URL_CHECK_SIZE)) != URL_CHECK_SIZE) {
			return false;
		}
		else if (!(url = url_encode(PLACER(buffer, URL_CHECK_SIZE)))) {
			return false;
		}
		else if (!url_valid_st(url)) {
			return false;
		}

		// Convert the buffer back to binary and compare it with the original array.
		if (!(binary = url_decode(url))) {
			st_free(url);
			return false;
		}
		else if (st_cmp_cs_eq(binary, PLACER(buffer, URL_CHECK_SIZE))) {
			result = false;
		}

		//log_pedantic("%-15.15s = %.*s", "plain", URL_CHECK_SIZE, buffer);
		//log_pedantic("%-15.15s = %.*s", "url", st_length_int(url), st_char_get(url));
		//log_pedantic("%-15.15s = %.*s", "decoded", st_length_int(binary), st_char_get(binary));

		st_free(binary);
		st_free(url);
	}

	return result;
}
Beispiel #13
0
/**
 * @brief	Return the name of the TLS cipher suite assoicated with a connection.
 * @see		SSL_CIPHER_get_name()
 * @param 	tls the TLS connection being inspected.
 * @param	output	a managed string to receive the encoded output; if passed as NULL, an output buffer will be allocated
 *				which must be freed by the caller.
 * @return	a pointer to the result, or NULL if an error occurs.
 */
 stringer_t * tls_cipher(TLS *tls, stringer_t *output) {

	 SSL_CIPHER *cipher = NULL;
	 stringer_t *result = NULL;
	 chr_t *version = NULL, *name = NULL;

	 if (!(cipher = SSL_get_current_cipher_d(tls))) {
		 return NULL;
	 }
	 else if (!(version = (chr_t *)SSL_get_version_d(tls))) {
		 return NULL;
	 }
	 else if (!(name = (chr_t *)SSL_CIPHER_get_name_d(cipher))) {
		 return NULL;
	 }
	 else if (!(result = st_output(output, 128))) {
		 return NULL;
	 }

	 st_sprint(result, "version = %s / suite = %s", (st_cmp_cs_eq(NULLER(version), PLACER("TLSv1", 5)) ? version : "TLSv1.0"), name);

	 return result;
 }
Beispiel #14
0
/**
 * @brief	Return the contact/abuse page with a marked error indicator for the user in the event of a user submission error.
 * @param	branch		a null-terminated string containing the source  of the error: "Abuse" or "Contact"
 * @param	xpath		a null-terminated string containing the xpath of the element in the returned page that should be colored red.
 * @param	id			a null-terminated string containing the id of the error text <span> element to be added to the document.
 * @param	message		a null-terminated string containing the actual error message text to be displayed to the user.
 * @return	NULL on failure, or a pointer to the processed contact page with error message on success.
 */
http_page_t * contact_business_add_error(chr_t *branch, uchr_t *xpath, uchr_t *id, uchr_t *message) {

	http_page_t *page = NULL;
	xmlNodePtr node, error;
	xmlXPathObjectPtr xpath_obj;

	// We are here either for the contact or abuse page.
	if (!st_cmp_cs_eq(NULLER(branch), PLACER("Abuse", 5)) && !((page = http_page_get("contact/abuse")))) {
		return NULL;
	}
	else if (!page && !(page = http_page_get("contact/contact"))) {
		return NULL;
	}

	if ((xpath_obj = xml_xpath_eval(xpath, page->xpath_ctx)) && xpath_obj->nodesetval &&
		xpath_obj->nodesetval->nodeNr && xpath_obj->nodesetval->nodeTab[0]) {

		node = (xmlNodePtr)xpath_obj->nodesetval->nodeTab[0];

		// Make the field red.
		xml_node_set_property(node, (uchr_t *)"class", (uchr_t *)"red");

		// Add the error message.
		if ((error = xml_node_new((uchr_t *)"span"))) {
			xml_node_set_property(error, (uchr_t *)"id", id);
			xml_node_set_content(error, message);

			if (!(xml_node_add_sibling(node, error))) {
				xml_node_free(error);
			}

		}
	}

	return page;
}
Beispiel #15
0
/**
 * @brief	Create a new session for a given web connection.
 * @note	The session stores the following data points: remote IP address, request path, application name, the specified http hostname,
 * 			the remote client's user agent string, the server's host number, a unique session id, the server's current timestamp, a randomly-
 * 			generated session key for authentication, and an encrypted token for the session returned to the user as a cookie.
 * @param	con			a pointer to the connection underlying the web session.
 * @param	path		a pointer to a managed string containing the pathname of the generating request (should be "/portal/camel").
 * @param	application	a pointer to a managed string containing the name of the parent application of the session (should be "portal").
 * @return	NULL on failure or a pointer to a newly allocated session object for the specified connection.
 */
session_t *sess_create(connection_t *con, stringer_t *path, stringer_t *application) {

	session_t *output;
	multi_t key = { .type = M_TYPE_UINT64, .val.u64 = 0 };

	if (!(output = mm_alloc(sizeof(session_t)))) {
		log_pedantic("Unable to allocate %zu bytes for a session context.", sizeof(session_t));
		return NULL;
	}
	else if (pthread_mutex_init(&(output->lock), NULL) != 0) {
		log_pedantic("Unable to initialize reference lock for new user session.");
		mm_free(output);
		return NULL;
	} else if (!(output->compositions = inx_alloc(M_INX_LINKED, &sess_release_composition))) {
		log_pedantic("Unable to allocate space for user session's compositions.");
		mm_free(output);
		return NULL;
	}

	if (!(ip_copy(&(output->warden.ip), con_addr(con, MEMORYBUF(64)))) ||
		(path && !(output->request.path = st_dupe_opts(MANAGED_T | HEAP | CONTIGUOUS, path))) ||
		(application && !(output->request.application = st_dupe_opts(MANAGED_T | HEAP | CONTIGUOUS, application))) ||
		(con->http.host && !(output->request.host = st_dupe_opts(MANAGED_T | HEAP | CONTIGUOUS, con->http.host))) ||
		(con->http.agent && !(output->warden.agent = st_dupe_opts(MANAGED_T | HEAP | CONTIGUOUS, con->http.agent))) ||
		!(output->warden.host = magma.host.number) || !(key.val.u64 = output->warden.number = sess_number()) ||
		!(output->warden.stamp = time(NULL)) || !(output->warden.key = sess_key()) || !(output->warden.token = sess_token(output))) {
		log_pedantic("Unable to initialize the session warden context.");
		sess_destroy(output);
		return NULL;
	}

	output->request.httponly = true;
	output->request.secure = (con_secure(con) == 1 ? true : false);

	sess_ref_add(output);

	if (inx_insert(objects.sessions, key, output) != 1) {
		log_pedantic("Unable to insert the session into the global context.");
		sess_ref_dec(output);
		sess_destroy(output);
		return NULL;
	}

	return output;
}

/**
 * @brief	Try to retrieve the session associated with a client connection's supplied cookie.
 * @param	con				a pointer to the connection object sending the cookie.
 * @param	application		a managed string containing the application associated with the session.
 * @param	path			a managed string containing the path associated with the session.
 * @param	token			the encrypted user token retrieved from the supplied http cookie.
 * @return	1 if the cookie was found and valid, or one of the following values on failure:
 * 			 0 = Session not found.
 *			-1 = Server error.
 *			-2 = Invalid token.
 *			-3 = Security violation / incorrect user-agent.
 *			-4 = Security violation / incorrect session key.
 *			-5 = Security violation / incorrect source address.
 *			-6 = Session terminated by logout.
 *			-7 = Session timed out.
 */
int_t sess_get(connection_t *con, stringer_t *application, stringer_t *path, stringer_t *token) {

	uint64_t *numbers;
	scramble_t *scramble;
	stringer_t *binary, *encrypted;
	multi_t key = { .type = M_TYPE_UINT64, .val.u64 = 0 };
	int_t result = 1;

	/// Most session attributes need simple equality comparison, except for timeout checking. Make sure not to validate against a stale session that should have already timed out (which will have to be determined dynamically).
	encrypted = zbase32_decode(token);
	scramble = scramble_import(encrypted);
	binary = scramble_decrypt(magma.secure.sessions, scramble);

	st_cleanup(encrypted);

	if (!binary) {
		return 0;
	}

	numbers = st_data_get(binary);

	// QUESTION: Is this necessary? doesn't inx_find() lock the inx?
	inx_lock_read(objects.sessions);

	key.val.u64 = *(numbers + 2);

	if ((con->http.session = inx_find(objects.sessions, key))) {
		sess_ref_add(con->http.session);
	}

	inx_unlock(objects.sessions);
	st_free(binary);

	// Return if we didn't find the session or user.
	if (!con->http.session || !con->http.session->user) {
		return 0;
	}

	// We need to do full validation against the cookie and associated session.
	// First, the cookie.
	if ((*numbers != con->http.session->warden.host) || (*(numbers + 1) != con->http.session->warden.stamp) ||
			(*(numbers + 2) != con->http.session->warden.number)) {
		log_error("Received mismatched cookie for authenticated session { user = %s }", st_char_get(con->http.session->user->username));
		result = -2;
	} else if (*(numbers + 3) != con->http.session->warden.key) {
		log_error("Cookie contained an incorrect session key { user = %s }", st_char_get(con->http.session->user->username));
		result = -4;
	} else if (st_cmp_cs_eq(application, con->http.session->request.application)) {
		log_error("Cookie did not match session's application { user = %s }", st_char_get(con->http.session->user->username));
		result = -2;
	} else if (st_cmp_cs_eq(path, con->http.session->request.path)) {
		log_error("Cookie did not match session's path { user = %s }", st_char_get(con->http.session->user->username));
		result = -2;
	} else if (st_cmp_cs_eq(con->http.agent, con->http.session->warden.agent)) {
		log_error("Cookie contained a mismatched user agent { user = %s }", st_char_get(con->http.session->user->username));
		result = -3;
	} else if (con->http.session->request.secure != (con_secure(con) ? 1 : 0)) {
		log_error("Cookie was submitted from a mismatched transport layer { user = %s }", st_char_get(con->http.session->user->username));
		result = -5;
	} else if (!ip_address_equal(&(con->http.session->warden.ip), (ip_t *)con_addr(con, MEMORYBUF(64)))) {
		log_error("Cookie was submitted from a mismatched IP address { user = %s }", st_char_get(con->http.session->user->username));
		result = -5;
	}

	// Finally, do comparisons to see that we haven't timed out.
	/* Did we expire? */
	if (magma.http.session_timeout <= (time(NULL) - con->http.session->warden.stamp)) {
		log_pedantic("User submitted expired or invalidated cookie; marking for deletion { user = %s }", st_char_get(con->http.session->user->username));
		result = -7;
	}

	// QUESTION: This destruction needs a second look.
	if (result < 0) {

		if (!inx_delete(objects.sessions, key)) {
			log_pedantic("Unexpected error occurred attempting to delete expired cookie { user = %s }", st_char_get(con->http.session->user->username));
		}

		sess_ref_dec(con->http.session);
		//sess_destroy(con->http.session);
		con->http.session = NULL;
	}
	// Otherwise, if the last session status update is more than 10 minutes ago, check now to see if things are current.
	// QUESTION: Why is it 600 here and 120 elsewhere?
	else if ((time(NULL) - sess_refresh_stamp(con->http.session)) > 600) {
		sess_update(con->http.session);
	}

	return result;
}
} END_TEST

START_TEST (check_credential_mail_creation_s) {

	credential_t *cred;
	char *errmsg = NULL;

	log_unit("%-64.64s", "OBJECTS / USERS / CREDENTIALS / MAIL CREATION / SINGLE THREADED:");

	if ((cred = credential_alloc_mail(CONSTANT("ladar")))) {
		errmsg = "Credential creation should have failed but didn't.";
	}

	if (cred) {
		credential_free(cred);
		cred = NULL;
	}

	if ((cred = credential_alloc_mail(CONSTANT("ladar@")))) {
		errmsg = "Credential creation should have failed but didn't.";
	}

	if (cred) {
		credential_free(cred);
		cred = NULL;
	}

	if ((cred = credential_alloc_mail(CONSTANT("@lavabit.com")))) {
		errmsg = "Credential creation should have failed but didn't.";
	}

	if (cred) {
		credential_free(cred);
		cred = NULL;
	}

	if (!errmsg && !(cred = credential_alloc_mail(CONSTANT("*****@*****.**")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && (st_cmp_cs_eq(cred->mail.address, CONSTANT("*****@*****.**")) || st_cmp_cs_eq(cred->mail.domain, CONSTANT("lavabit.com")))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	if (!errmsg && !(cred = credential_alloc_mail(CONSTANT("*****@*****.**")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && (st_cmp_cs_eq(cred->mail.address, CONSTANT("*****@*****.**")) || st_cmp_cs_eq(cred->mail.domain, CONSTANT("lavabit.com")))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	if (!errmsg && !(cred = credential_alloc_mail(CONSTANT("*****@*****.**")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && (st_cmp_cs_eq(cred->mail.address, CONSTANT("*****@*****.**")) || st_cmp_cs_eq(cred->mail.domain, CONSTANT("nerdshack.com")))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	if (!errmsg && !(cred = credential_alloc_mail(CONSTANT("*****@*****.**")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && (st_cmp_cs_eq(cred->mail.address, CONSTANT("*****@*****.**")) || st_cmp_cs_eq(cred->mail.domain, CONSTANT("nerdshack.com")))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	if (!errmsg && !(cred = credential_alloc_mail(CONSTANT("*****@*****.**")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && (st_cmp_cs_eq(cred->mail.address, CONSTANT("*****@*****.**")) || st_cmp_cs_eq(cred->mail.domain, CONSTANT("mailshack.com")))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	if (!errmsg && !(cred = credential_alloc_mail(CONSTANT("*****@*****.**")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && (st_cmp_cs_eq(cred->mail.address, CONSTANT("*****@*****.**")) || st_cmp_cs_eq(cred->mail.domain, CONSTANT("mailshack.com")))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	if (!errmsg && !(cred = credential_alloc_mail(CONSTANT("*****@*****.**")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && (st_cmp_cs_eq(cred->mail.address, CONSTANT("*****@*****.**")) || st_cmp_cs_eq(cred->mail.domain, CONSTANT("domain.com")))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	if (!errmsg && !(cred = credential_alloc_mail(CONSTANT("*****@*****.**")))) {
		errmsg = "Credential creation failed.";
	}
	else if (!errmsg && (st_cmp_cs_eq(cred->mail.address, CONSTANT("*****@*****.**")) || st_cmp_cs_eq(cred->mail.domain, CONSTANT("domain.com")))) {
		errmsg = "The credential password hash doesn't match the expected value.";
	}

	if (cred) {
		credential_free(cred);
	}

	log_unit("%10.10s\n", (!status() ? "SKIPPED" : !errmsg ? "PASSED" : "FAILED"));
	fail_unless(!errmsg, errmsg);
} END_TEST
Beispiel #17
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;
}
Beispiel #18
0
/**
 * @brief	Lookup user and return their meta user object.
 *
 * @note	If the user is not found in the local session cache, the session will be constructed using the database, and then cached.
 *
 * @param 	usernum			the numeric identifier for the user account.
 * @param 	username		the official username stored in the database.
 * @param	salt			the user specific salt value.
 * @param	master			the user account's master encryption key which will be used to unlock the private storage key.
 * @param 	verification	the verification token.
 * @param	protocol			a set of protocol specifying the protocol used by the calling function. Values can be META_PROT_NONE,
 * 							META_PROT_SMTP, META_PROT_POP, META_PROT_IMAP, META_PROT_WEB, or META_PROT_GENERIC.
 * @param	get				a set of protocol specifying the data to be retrieved (META_GET_NONE, META_GET_MESSAGES,
 * 							META_GET_FOLDERS, or META_GET_CONTACTS)
 * @param	output			the address of a meta user object that will store a pointer to the result of the lookup.
 *
 * @return	-1 on error, 0 on success, 1 for an authentication issue.
 */
int_t meta_get(uint64_t usernum, stringer_t *username, stringer_t *salt, stringer_t *master, stringer_t *verification, META_PROTOCOL protocol, META_GET get, meta_user_t **output) {

	int_t state;
	meta_user_t *user = NULL;

	// If the auth structure is empty, or the usernum is invalid, return an error immediately.
	if (!usernum || !st_populated(username, master, verification)) {
		log_pedantic("Invalid parameters were used to get the meta data object.");
		return -1;
	}

	// Pull the user context using the usernum, or add an empty context if it doesn't exist.
	if (!(user = meta_inx_find(usernum, protocol))) {
		log_pedantic("Could not find an existing user object, nor could we create one.");
		return -1;
	}

	meta_user_wlock(user);

	// Pull the user information.
	if ((state = meta_update_user(user, META_LOCKED)) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return state;
	}

	// The auth_t object should have checked the verification token already, but we check here just to be sure.
	else if (st_empty(user->verification) || st_cmp_cs_eq(verification, user->verification)) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return 1;
	}

	// Are we supposed to get the realm keys.
	if ((get & META_GET_KEYS) && meta_update_realms(user, salt, master, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	// Are we supposed to get the mailbox keys.
	if ((get & META_GET_KEYS) && meta_update_keys(user, META_LOCKED) < 0) {

		// If key decryption fails, then the master key is likely invalid, so we need to ensure we don't cache an invalid
		// realm key as a result.
		st_cleanup(user->realm.mail);
		user->realm.mail = NULL;
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

 	 // Are we supposed to get the mailbox aliases.
	if ((get & META_GET_ALIASES) && meta_update_aliases(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	// Are we supposed to get the messages.
	if ((get & META_GET_MESSAGES) && meta_messages_update(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	if ((get & META_GET_FOLDERS) && meta_update_message_folders(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	// Are we supposed to update the folders.
	if ((get & META_GET_FOLDERS) && meta_update_folders(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	// Are we supposed to update the folders.
	if ((get & META_GET_CONTACTS) && meta_update_contacts(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	*output = user;
	meta_user_unlock(user);

	return 0;
}
Beispiel #19
0
/**
 * @brief	Output a key name and value in a generic way.
 * @param	prefix		a pointer to a null-terminated string containing an optional prefix to be printed before the supplied key name.
 * @param	name		a pointer to a null-terminated string containing the name of the key being output.
 * @param	type		an M_TYPE value specifying the multi-type of the key value.
 * @param	val			a void pointer to the value of the specified key, which will be printed in accordance with the supplied multi-type.
 * @param	required	a boolean value specifying whether the specified key is a required configuration option.
 * @return	This function returns no value.
 */
void config_output_value_generic(chr_t *prefix, chr_t *name, M_TYPE type, void *val, bool_t required) {

	chr_t *reqstr = "";

	if (!prefix) {
		prefix = "";
	}

	if (required) {
		reqstr = "*";
	}

	switch (type) {
	case (M_TYPE_NULLER):
		if (ns_empty(*((char **)(val))))
			log_info("%s%s%s = NULL", prefix, name, reqstr);
		else
			log_info("%s%s%s = %s", prefix, name, reqstr, *((char **)(val)));
		break;

	case (M_TYPE_STRINGER):
		// Intercept the blacklist config key->
		if (!st_cmp_cs_eq(NULLER(name), PLACER("magma.smtp.blacklist", 20))) {

			if (!magma.smtp.blacklists.count) {
				log_info("%s%s%s = NULL", prefix, name, reqstr);
			}

			for (uint32_t j = 0; j < magma.smtp.blacklists.count; j++) {
				log_info("%s%s%s = %.*s", prefix, name, reqstr, st_length_int(magma.smtp.blacklists.domain[j]), st_char_get(magma.smtp.blacklists.domain[j]));
			}
		}

		else if (st_empty(*((stringer_t **)(val))))
			log_info("%s%s%s = NULL", prefix, name, reqstr);
		else
			log_info("%s%s%s = %.*s", prefix, name, reqstr, st_length_int(*((stringer_t **)(val))), st_char_get(*((stringer_t **)(val))));
		break;

	case (M_TYPE_ENUM):

			if (!st_cmp_cs_eq(NULLER(name), CONSTANT(".protocol"))) {
				if (*((M_PROTOCOL *)((char *)val)) == MOLTEN)
					log_info("%s%s%s = MOLTEN", prefix, name, reqstr);
				else if (*((M_PROTOCOL *)((char *)val)) == HTTP)
					log_info("%s%s%s = HTTP", prefix, name, reqstr);
				else if (*((M_PROTOCOL *)((char *)val)) == POP)
					log_info("%s%s%s = POP", prefix, name, reqstr);
				else if (*((M_PROTOCOL *)((char *)val)) == IMAP)
					log_info("%s%s%s = IMAP", prefix, name, reqstr);
				else if (*((M_PROTOCOL *)((char *)val)) == SMTP)
					log_info("%s%s%s = SMTP", prefix, name, reqstr);
				else if (*((M_PROTOCOL *)((char *)val)) == SUBMISSION)
					log_info("%s%s%s = SUBMISSION", prefix, name, reqstr);
				else if (*((M_PROTOCOL *)((char *)val)) == EMPTY)
						log_info("%s%s%s = EMPTY", prefix, name, reqstr);
				else
					log_info("%s%s%s = [UNKNOWN]", prefix, name, reqstr);
			} else if (!st_cmp_cs_eq(NULLER(name), CONSTANT(".network.type"))) {
				if (*((M_PORT *)((char *)val)) == TCP_PORT)
					log_info("%s%s%s = TCP", prefix, name, reqstr);
				else if (*((M_PORT *)((char *)val)) == SSL_PORT)
					log_info("%s%s%s = SSL", prefix, name, reqstr);
				else
					log_info("%s%s%s = [UNKNOWN]", prefix, name, reqstr);
			}
		break;

	case (M_TYPE_BOOLEAN):
		log_info("%s%s%s = %s", prefix, name, reqstr, (*((bool_t *)(val)) ? "true" : "false"));
		break;

	case (M_TYPE_INT8):
		log_info("%s%s%s = %hhi", prefix, name, reqstr, *((int8_t *)(val)));
		break;
	case (M_TYPE_INT16):
		log_info("%s%s%s = %hi", prefix, name, reqstr, *((int16_t *)(val)));
		break;

	case (M_TYPE_INT32):
		log_info("%s%s%s = %i", prefix, name, reqstr, *((int32_t *)(val)));
		break;

	case (M_TYPE_INT64):
		log_info("%s%s%s = %li", prefix, name, reqstr, *((int64_t *)(val)));
		break;

	case (M_TYPE_UINT8):
		log_info("%s%s%s = %hhu", prefix, name, reqstr, *((uint8_t *)(val)));
		break;
	case (M_TYPE_UINT16):
		log_info("%s%s%s = %hu", prefix, name, reqstr, *((uint16_t *)(val)));
		break;
	case (M_TYPE_UINT32):
		log_info("%s%s%s = %u", prefix, name, reqstr, *((uint32_t *)(val)));
		break;
	case (M_TYPE_UINT64):
		log_info("%s%s%s = %lu", prefix, name, reqstr, *((uint64_t *)(val)));
		break;
	default:
		log_pedantic("Unexpected type. {type = %u}", type);
		break;
	}

	return;
}
Beispiel #20
0
/**
 * @brief	Set the value of a global config key.
 * @note	This function will also free the value of the global config key if it has already previously been set.
 * @param	setting		a pointer to the global key to have its value adjusted.
 * @param	value		a managed string containing the new key value, or if NULL, the key's default value will be used.
 * @return	true if the specified key's value was set successfully, or false on failure.
 */
bool_t config_value_set(magma_keys_t *setting, stringer_t *value) {

	bool_t result = true;

	/// LOW: Realtime blacklist domains are handled using custom code because we don't yet have a generic type to store lists.
	if (!st_cmp_cs_eq(NULLER(setting->name), PLACER("magma.smtp.blacklist", 20))) {

		// When the default values are assigned an empty string is passed in. Returning false then tricks the system into
		// thinking the default value is wrong, so we just return true to avoid the issue.
		if (st_empty(value)) {
			return true;
		}

		// Were using a fixed array, so if we run out of room we have to reject config.
		if (magma.smtp.blacklists.count >= MAGMA_BLACKLIST_INSTANCES) {
			log_critical("magma.smtp.blacklist is limited to %u %s and the configuration currently contains more than %u %s.",
				MAGMA_BLACKLIST_INSTANCES, MAGMA_BLACKLIST_INSTANCES == 1 ? "domain" : "domains", MAGMA_BLACKLIST_INSTANCES,
				MAGMA_BLACKLIST_INSTANCES == 1 ? "domain" : "domains");
			return false;
		}

		// Make sure the targeted array slot is empty, and the string passed to us has data in it. If so duplicate the value and
		// and store it in the array. If anything fails, return false.
		else if (magma.smtp.blacklists.domain[magma.smtp.blacklists.count] || !(magma.smtp.blacklists.domain[magma.smtp.blacklists.count] =
			st_dupe_opts(MANAGED_T | CONTIGUOUS | HEAP, value))) {
			return false;
		}

		// Track the number of blacklist domains we have.
		magma.smtp.blacklists.count++;

		// Return true so the switch statement below doesn't corrupt the array.
		return true;
	}
	else if (!st_cmp_cs_eq(NULLER(setting->name), NULLER("magma.smtp.bypass_addr"))) {

			// When the default values are assigned an empty string is passed in. Returning false then tricks the system into
			// thinking the default value is wrong, so we just return true to avoid the issue.
			if (st_empty(value)) {
				return true;
			}

			if (!smtp_add_bypass_entry(value)) {
				log_critical("Unable to add smtp bypass entry { entry = %s }", st_char_get(value));
				return false;
			}

			// Return true so the switch statement below doesn't corrupt the array.
			return true;
		}


	switch (setting->norm.type) {

	// Strings
	case (M_TYPE_NULLER):
		if (!ns_empty(*((char **)(setting->store)))) {
			ns_free(*((char **)(setting->store)));
			*((char **)(setting->store)) = NULL;
		}
		if (!st_empty(value))
			*((char **)(setting->store)) = ns_import(st_char_get(value), st_length_get(value));
		else if (!ns_empty(setting->norm.val.ns))
			*((char **)(setting->store)) = ns_dupe(setting->norm.val.ns);
		break;

	case (M_TYPE_STRINGER):
		if (!st_empty(*((stringer_t **)(setting->store)))) {
			st_free(*((stringer_t **)(setting->store)));
			*((stringer_t **)(setting->store)) = NULL;
		}
		if (!st_empty(value))
			*((stringer_t **)(setting->store)) = st_dupe_opts(MANAGED_T | CONTIGUOUS | HEAP, value);
		else if (!st_empty(setting->norm.val.st))
			*((stringer_t **)(setting->store)) = st_dupe_opts(MANAGED_T | CONTIGUOUS | HEAP, setting->norm.val.st);
		break;

		// Booleans
	case (M_TYPE_BOOLEAN):
		if (!st_empty(value)) {
			if (!st_cmp_ci_eq(value, CONSTANT("true")))
				*((bool_t *)(setting->store)) = true;
			else if (!st_cmp_ci_eq(value, CONSTANT("false")))
				*((bool_t *)(setting->store)) = false;
			else {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((bool_t *)(setting->store)) = setting->norm.val.binary;
		break;

		// Integers
	case (M_TYPE_INT8):
		if (!st_empty(value)) {
			if (!int8_conv_st(value, (int8_t *)(setting->store))) {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((int8_t *)(setting->store)) = setting->norm.val.i8;
		break;

	case (M_TYPE_INT16):
		if (!st_empty(value)) {
			if (!uint16_conv_st(value, (uint16_t *)(setting->store))) {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((int16_t *)(setting->store)) = setting->norm.val.u16;
		break;

	case (M_TYPE_INT32):
		if (!st_empty(value)) {
			if (!int32_conv_st(value, (int32_t *)(setting->store))) {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((int32_t *)(setting->store)) = setting->norm.val.i32;
		break;

	case (M_TYPE_INT64):
		if (!st_empty(value)) {
			if (!int64_conv_st(value, (int64_t *)(setting->store))) {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((int64_t *)(setting->store)) = setting->norm.val.i64;
		break;

		// Unsigned Integers
	case (M_TYPE_UINT8):
		if (!st_empty(value)) {
			if (!uint8_conv_st(value, (uint8_t *)(setting->store))) {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((uint8_t *)(setting->store)) = setting->norm.val.u8;
		break;

	case (M_TYPE_UINT16):
		if (!st_empty(value)) {
			if (!uint16_conv_st(value, (uint16_t *)(setting->store))) {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((uint16_t *)(setting->store)) = setting->norm.val.u16;
		break;

	case (M_TYPE_UINT32):
		if (!st_empty(value)) {
			if (!uint32_conv_st(value, (uint32_t *)(setting->store))) {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((uint32_t *)(setting->store)) = setting->norm.val.u32;
		break;

	case (M_TYPE_UINT64):
		if (!st_empty(value)) {
			if (!uint64_conv_st(value, (uint64_t *)(setting->store))) {
				log_critical("Invalid value for %s.", setting->name);
				result = false;
			}
		} else
			*((uint64_t *)(setting->store)) = setting->norm.val.u64;
		break;

	default:
		log_critical("The %s setting definition is using an invalid type.", setting->name);
		result = false;
		break;
	}
	return result;
}
Beispiel #21
0
/**
 * @brief	Perform a series of system-wide sanity checks at process startup.
 * @note	This function ensures that the standard data types are their expected data sizes, and performs other
 * 			checks, such as data primitive maximum values.
 * @return	true if the system environment passed all checks and should function correctly, or false if any checks failed.
 */
bool_t sanity_check(void) {

	stringer_t *st;
	size_t sz[2] = { 0, 0 };
	int64_t i64[2] = { 0, 0 };
	ssize_t ssz[2] = { 0, 0 };
	uint64_t ui64[2] = { 0, 0 };

	// Make sure the standard types are what we expect.
	if (sizeof(char) != 1 || sizeof(short) != 2 || sizeof(int) != 4 || sizeof(long) != 8) {
		return false;
	}

	// Check on the standard integer sizes in use.
	if (sizeof(int8_t) != 1 || sizeof(int16_t) != 2 || sizeof(int32_t) != 4 || sizeof(int64_t) != 8) {
		return false;
	}

	if (sizeof(uint8_t) != 1 || sizeof(uint16_t) != 2 || sizeof(uint32_t) != 4 || sizeof(uint64_t) != 8) {
		return false;
	}

	// Check the system specific typedefs we use.
	if (sizeof(bool_t) != 1 || sizeof(time_t) != 8 || sizeof(size_t) != 8) {
		return false;
	}

	// Check on the different types of pointers.
	if (sizeof(char *) != 8 || sizeof(void *) != 8) {
		return false;
	}

	// Ensure the type aliases are properly sized.
	if (sizeof(byte_t) != 1 || sizeof(uchr_t) != 1 || sizeof(chr_t) != 1) {
		return false;
	}

	if (sizeof(float_t) != 4 || sizeof(double_t) != 8) {
		return false;
	}

	// That strings are properly formed and sized.
	if (sizeof(stringer_t) != 1 || sizeof(stringer_t *) != 8) {
		return false;
	}

	// That IP addresses are properly formed and sized.
	if (sizeof(octet_t) != 2 || sizeof(segment_t) != 4 || sizeof(struct in_addr) != 4 || sizeof(struct in6_addr) != 16) {
			return false;
		}


	// Should be the size of a size variable, plus a pointer.
	if (sizeof(placer_t) != 20 || sizeof(placer_t) != (sizeof(size_t) + sizeof(void *) + sizeof(uint32_t))) {
		return false;
	}

	// Setup the min/max values.
	sz[0] = SIZE_MAX + 1;
	sz[1] = SIZE_MAX;
	ssz[0] = (SIZE_MAX / 2) + 1;
	ssz[1] = (SIZE_MAX / 2);
	i64[0] = INT64_MIN;
	i64[1] = INT64_MAX;
	ui64[0] = UINT64_MAX + 1;
	ui64[1] = UINT64_MAX;

	// The functions used to convert character strings into size_t and ssize_t are aliases for uint64_t and int64_t. Aliases are also used by the serialization
	// functions. The following test uses the min/max values calculated above to ensure the aliases used remain accurate.
	if (sizeof(size_t) != sizeof(uint64_t) || sz[0] != ui64[0] || sz[1] != ui64[1] ||	sizeof(ssize_t) != sizeof(int64_t) || ssz[0] != i64[0] || ssz[1] != i64[1] ||
			sz[1] != SIZE_MAX || i64[0] != INT64_MIN || i64[1] != INT64_MAX || ui64[1] != UINT64_MAX) {
		return false;
	}

	// We are using a semaphore to block access to our connection pools,
	// so our max is limited by the semaphore max value.
	if (MAGMA_CORE_POOL_OBJECTS_LIMIT > SEM_VALUE_MAX) {
		return false;
	}

	// The pool counters are unsigned 32 bit ints, so make sure the max is below their limit.
	if (MAGMA_CORE_POOL_OBJECTS_LIMIT > UINT32_MAX || MAGMA_CORE_POOL_TIMEOUT_LIMIT > UINT32_MAX) {
		return false;
	}

	// This tuple must evaluate correctly or the comparison functions will not function correctly.
	if (((100 < 200) ? -1 : 100 > 200) != -1 || ((100 < 100) ? -1 : 100 > 100) != 0 || ((200 < 100) ? -1 : 200 > 100) != 1) {
		return false;
	}

	// The tank interface uses the memory that initially holds a the object heading to store the two size_t variables need for a compress_t block. If
	// the size of two size_t variables is greater than the length of of a record_t, the math being used to cause data to be written before the actual
	// starting address of the buffer. So to keep this from happening we have a sanity check in place.
	if ((sizeof(size_t) + sizeof(size_t)) > sizeof(record_t)) {
	 return false;
	}

	// We also need to make sure the stringer_t format doesn't change in a way that would break the implementation.
	if (!(st = st_alloc(1))) {
		return false;
	}	else if ((size_t)((st_data_get(st) + st_avail_get(st)) - (void *)(st)) != (sizeof(uint32_t) + sizeof(size_t) + sizeof(size_t) + sizeof(void *) + 1)) {
		st_free(st);
		return false;
	} else {
		st_free(st);
	}

	// We assume the select_domains query is the points to the beginning of the prepared statement structure. If the order is changed the code will need to be
	// updated or the statement variables won't be pointed at the correct SQL query. This affects the functions stmt_start(), stmt_rebuild(), and stmt_stop().
	if (st_cmp_cs_eq(NULLER(queries[0]), CONSTANT(SELECT_DOMAINS))) {
		return false;
	}

	return true;
}
Beispiel #22
0
/**
 * @brief	Log the contents of a magma configuration option.
 * @param	key		a pointer to the magma configuration key to be dumped.
 * @return	This function returns no value.
 */
void config_output_value(magma_keys_t *key) {

	switch (key->norm.type) {
	case (M_TYPE_NULLER):
		if (ns_empty(*((char **)(key->store))))
			log_info("%s = NULL", key->name);
		else
			log_info("%s = %s", key->name, *((char **)(key->store)));
		break;

	case (M_TYPE_STRINGER):
		// Intercept the blacklist config key->
		if (!st_cmp_cs_eq(NULLER(key->name), PLACER("magma.smtp.blacklist", 20))) {

			if (!magma.smtp.blacklists.count) {
				log_info("%s = NULL",key->name);
			}

			for (uint32_t j = 0; j < magma.smtp.blacklists.count; j++) {
				log_info("%s = %.*s",key->name, st_length_int(magma.smtp.blacklists.domain[j]), st_char_get(magma.smtp.blacklists.domain[j]));
			}
		}

		else if (st_empty(*((stringer_t **)(key->store))))
			log_info("%s = NULL", key->name);
		else
			log_info("%s = %.*s", key->name, st_length_int(*((stringer_t **)(key->store))), st_char_get(*((stringer_t **)(key->store))));
		break;

	case (M_TYPE_BOOLEAN):
		log_info("%s = %s", key->name, (*((bool_t *)(key->store)) ? "true" : "false"));
		break;

	case (M_TYPE_INT8):
		log_info("%s = %hhi", key->name, *((int8_t *)(key->store)));
		break;
	case (M_TYPE_INT16):
		log_info("%s = %hi", key->name, *((int16_t *)(key->store)));
		break;

	case (M_TYPE_INT32):
		log_info("%s = %i", key->name, *((int32_t *)(key->store)));
		break;

	case (M_TYPE_INT64):
		log_info("%s = %li", key->name, *((int64_t *)(key->store)));
		break;

	case (M_TYPE_UINT8):
		log_info("%s = %hhu", key->name, *((uint8_t *)(key->store)));
		break;
	case (M_TYPE_UINT16):
		log_info("%s = %hu", key->name, *((uint16_t *)(key->store)));
		break;
	case (M_TYPE_UINT32):
		log_info("%s = %u", key->name, *((uint32_t *)(key->store)));
		break;
	case (M_TYPE_UINT64):
		log_info("%s = %lu", key->name, *((uint64_t *)(key->store)));
		break;
	default:
		log_pedantic("Unexpected type. {type = %u}", key->norm.type);
		break;
	}

	return;
}