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;
}
Esempio n. 2
0
S4Err  testZbase32()
{
    S4Err     err = kS4Err_NoErr;

    katvector kat_vector_array[] =
    {
        { 1,   (uint8_t*)"\x00",               "y"		},
        { 1,   (uint8_t*)"\x80",               "o"		},
        { 2,   (uint8_t*)"\x40",               "e"		},
        { 2,   (uint8_t*)"\xC0",               "a"		},
        { 10,  (uint8_t*)"\x00\x00",           "yy"	},
        { 10,  (uint8_t*)"\x80\x80",           "on"	},
        { 20,  (uint8_t*)"\x8B\x88\x80",       "tqre"	},

        { 24,  (uint8_t*)"\xF0\xBF\xC7",       "6n9hq"	},
        { 24,  (uint8_t*)"\xD4\x7A\x04",     	"4t7ye"	},

        { 30,  (uint8_t*)"\xF5\x57\xBD\x0C", "6im54d"	},  // the spec says "6im5sd" but I think it is wrong
        { 64,  (uint8_t*)"\x28\x6F\x20\x29\x28\x20\x6F\x29",               "fbz1ykjerbz11" },

        { 128,  (uint8_t*)"\x00\x01\x02\x03\x05\x06\x07\x08\x0A\x0B\x0C\x0D\x0F\x10\x11\x12",   "yyyoryafyadoonombogo6rytne" },
        {   160,  (uint8_t*) "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2\x6C"
            "\x9C\xD0\xD8\x9D",  "igcuhp18y4ysiqt6riazowgnp1qpbsr7"
        }
    };

    int i;

    for (i = 0; i < sizeof(kat_vector_array)/ sizeof(katvector) ; i++)
    {
        katvector* kat = &kat_vector_array[i];

        uint8_t  encoded[64]  = {0};
        uint8_t  decoded[64]  = {0};

        int len, len2;

        char* binString[128] = {0};

        bin_to_chars((uint8_t*)kat->base2, kat->bits, 24, (char*)binString);

        OPTESTLogVerbose("\t\t%4lu %2d %-30s %-32s\n",  kat->bits, INT_CEIL(kat->bits, 8), binString,  kat->zbase32);

        len = zbase32_encode((uint8_t*)encoded, (uint8_t*)kat->base2, kat->bits);

        /* check against encoded  */
        err = compareResults( kat->zbase32, encoded, len , kResultFormat_Byte, "Encoded");
        CKERR;

        len2 = zbase32_decode((uint8_t*) decoded, (uint8_t*)encoded, kat->bits);

        err = compareResults(decoded, kat->base2, len/8  , kResultFormat_Byte, "Decoded");
        CKERR;

    };
done:
    return err;

}
Esempio n. 3
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;
}