/*!
 * \brief Check authentication using Digest scheme
 *
 * This function will check an incoming message against configured authentication
 * options. If \b any of the incoming Authorization headers result in successful
 * authentication, then authentication is considered successful.
 *
 * \see ast_sip_check_authentication
 */
static enum ast_sip_check_auth_result digest_check_auth(struct ast_sip_endpoint *endpoint,
		pjsip_rx_data *rdata, pjsip_tx_data *tdata)
{
	struct ast_sip_auth **auths;
	enum digest_verify_result *verify_res;
	enum ast_sip_check_auth_result res;
	int i;
	int failures = 0;
	size_t auth_size;

	RAII_VAR(struct ast_sip_endpoint *, artificial_endpoint,
		 ast_sip_get_artificial_endpoint(), ao2_cleanup);

	auth_size = AST_VECTOR_SIZE(&endpoint->inbound_auths);

	auths = ast_alloca(auth_size * sizeof(*auths));
	verify_res = ast_alloca(auth_size * sizeof(*verify_res));

	if (!auths) {
		return AST_SIP_AUTHENTICATION_ERROR;
	}

	if (endpoint == artificial_endpoint) {
		auths[0] = ast_sip_get_artificial_auth();
	} else if (ast_sip_retrieve_auths(&endpoint->inbound_auths, auths)) {
		res = AST_SIP_AUTHENTICATION_ERROR;
		goto cleanup;
	}

	for (i = 0; i < auth_size; ++i) {
		if (ast_strlen_zero(auths[i]->realm)) {
			ast_string_field_set(auths[i], realm, "asterisk");
		}
		verify_res[i] = verify(auths[i], rdata, tdata->pool);
		if (verify_res[i] == AUTH_SUCCESS) {
			res = AST_SIP_AUTHENTICATION_SUCCESS;
			goto cleanup;
		}
		if (verify_res[i] == AUTH_FAIL) {
			failures++;
		}
	}

	for (i = 0; i < auth_size; ++i) {
		challenge(auths[i]->realm, tdata, rdata, verify_res[i] == AUTH_STALE);
	}

	if (failures == auth_size) {
		res = AST_SIP_AUTHENTICATION_FAILED;
	} else {
		res = AST_SIP_AUTHENTICATION_CHALLENGE;
	}

cleanup:
	ast_sip_cleanup_auths(auths, auth_size);
	return res;
}
示例#2
0
static void global_loaded(const char *object_type)
{
	char default_realm[MAX_REALM_LENGTH + 1];
	struct ast_sip_auth *fake_auth;
	char *identifier_order;

	/* Update using_auth_username */
	identifier_order = ast_sip_get_endpoint_identifier_order();
	if (identifier_order) {
		char *identify_method;
		char *io_copy = ast_strdupa(identifier_order);
		int new_using = 0;

		ast_free(identifier_order);
		while ((identify_method = ast_strip(strsep(&io_copy, ",")))) {
			if (!strcmp(identify_method, "auth_username")) {
				new_using = 1;
				break;
			}
		}
		using_auth_username = new_using;
	}

	/* Update default_realm of artificial_auth */
	ast_sip_get_default_realm(default_realm, sizeof(default_realm));
	fake_auth = ast_sip_get_artificial_auth();
	if (!fake_auth || strcmp(fake_auth->realm, default_realm)) {
		ao2_cleanup(fake_auth);

		fake_auth = alloc_artificial_auth(default_realm);
		if (fake_auth) {
			ao2_global_obj_replace_unref(artificial_auth, fake_auth);
		}
	}
	ao2_cleanup(fake_auth);

	ast_sip_get_unidentified_request_thresholds(&unidentified_count, &unidentified_period, &unidentified_prune_interval);

	/* Clean out the old task, if any */
	ast_sched_clean_by_callback(prune_context, prune_task, clean_task);
	/* Have to do something with the return value to shut up the stupid compiler. */
	if (ast_sched_add_variable(prune_context, unidentified_prune_interval * 1000, prune_task, NULL, 1) < 0) {
		return;
	}
}