/*
* Send auth failed message from server to client.
+ *
+ * Does nothing if an exit is already scheduled
*/
void
send_auth_failed(struct context *c, const char *client_reason)
{
+ if (event_timeout_defined(&c->c2.scheduled_exit))
+ {
+ msg(D_TLS_DEBUG, "exit already scheduled for context");
+ return;
+ }
+
struct gc_arena gc = gc_new();
static const char auth_failed[] = "AUTH_FAILED";
size_t len;
{
int ret = PUSH_MSG_ERROR;
- if (tls_authentication_status(c->c2.tls_multi, 0) == TLS_AUTHENTICATION_FAILED
+
+ if (tls_authentication_status(c->c2.tls_multi, TLS_MULTI_AUTH_STATUS_INTERVAL) == TLS_AUTHENTICATION_FAILED
|| c->c2.tls_multi->multi_state == CAS_FAILED)
{
const char *client_reason = tls_client_reason(c->c2.tls_multi);
unsigned int auth_control_status;
};
+/* key_state_test_auth_control_file return values, these specify the
+ * current status of a deferred authentication */
+enum auth_deferred_result {
+ ACF_PENDING, /**< deferred auth still pending */
+ ACF_SUCCEEDED, /**< deferred auth has suceeded */
+ ACF_DISABLED, /**< deferred auth is not used */
+ ACF_FAILED /**< deferred auth has failed */
+};
+
/**
* Security parameter state of one TLS and data channel %key session.
* @ingroup control_processor
#ifdef ENABLE_MANAGEMENT
unsigned int mda_key_id;
- unsigned int mda_status;
+ enum auth_deferred_result mda_status;
#endif
time_t acf_last_mod;
char *locked_username;
struct cert_hash_set *locked_cert_hash_set;
- /* Time of last call to tls_authentication_status */
- time_t tas_last;
+ /* Time of last when we updated the cached state of
+ * tls_authentication_status deferred files */
+ time_t tas_cache_last_update;
/*
* An error message to send to client on AUTH_FAILED
* user/password authentication.
*************************************************************************** */
-/* key_state_test_auth_control_file return values,
- * NOTE: acf_merge indexing depends on these values */
-#define ACF_UNDEFINED 0
-#define ACF_SUCCEEDED 1
-#define ACF_DISABLED 2
-#define ACF_FAILED 3
-
void
auth_set_client_reason(struct tls_multi *multi, const char *client_reason)
{
#ifdef ENABLE_MANAGEMENT
-static inline unsigned int
+static inline enum auth_deferred_result
man_def_auth_test(const struct key_state *ks)
{
if (management_enable_def_auth(management))
return (acf && apf);
}
-static unsigned int
-key_state_test_auth_control_file(struct auth_deferred_status *ads)
+/**
+ * Checks the auth control status from a file. The function will try
+ * to read and update the cached status if the status is still pending
+ * and the parameter cached is false.
+ * The function returns the most recent known status.
+ *
+ * @param ads deferred status control structure
+ * @param cached Return only cached status
+ * @return ACF_* as per enum
+ */
+static enum auth_deferred_result
+key_state_test_auth_control_file(struct auth_deferred_status *ads, bool cached)
{
if (ads->auth_control_file)
{
unsigned int ret = ads->auth_control_status;
- if (ret == ACF_UNDEFINED)
+ if (ret == ACF_PENDING && !cached)
{
FILE *fp = fopen(ads->auth_control_file, "r");
if (fp)
/* at least one key already failed authentication */
bool failed_auth = false;
- if (latency && multi->tas_last + latency >= now)
- {
- return TLS_AUTHENTICATION_UNDEFINED;
- }
- multi->tas_last = now;
+ bool cached = multi->tas_cache_last_update + latency >= now;
for (int i = 0; i < KEY_SCAN_SIZE; ++i)
{
}
else
{
- unsigned int auth_plugin = ACF_DISABLED;
- unsigned int auth_script = ACF_DISABLED;
- unsigned int auth_man = ACF_DISABLED;
- auth_plugin = key_state_test_auth_control_file(&ks->plugin_auth);
- auth_script = key_state_test_auth_control_file(&ks->script_auth);
+ enum auth_deferred_result auth_plugin = ACF_DISABLED;
+ enum auth_deferred_result auth_script = ACF_DISABLED;
+ enum auth_deferred_result auth_man = ACF_DISABLED;
+ auth_plugin = key_state_test_auth_control_file(&ks->plugin_auth, cached);
+ auth_script = key_state_test_auth_control_file(&ks->script_auth, cached);
#ifdef ENABLE_MANAGEMENT
auth_man = man_def_auth_test(ks);
#endif
ks->authenticated = KS_AUTH_FALSE;
failed_auth = true;
}
- else if (auth_plugin == ACF_UNDEFINED
- || auth_script == ACF_UNDEFINED
- || auth_man == ACF_UNDEFINED)
+ else if (auth_plugin == ACF_PENDING
+ || auth_script == ACF_PENDING
+ || auth_man == ACF_PENDING)
{
if (now < ks->auth_deferred_expire)
{
}
}
+ /* we did not rely on a cached result, remember the cache update time */
+ if (!cached)
+ {
+ multi->tas_cache_last_update = now;
+ }
+
#if 0
dmsg(D_TLS_ERRORS, "TAS: a=%d s=%d d=%d f=%d", active, success, deferred, failed_auth);
#endif
{
TLS_AUTHENTICATION_SUCCEEDED=0,
TLS_AUTHENTICATION_FAILED=1,
- TLS_AUTHENTICATION_DEFERRED=2,
- TLS_AUTHENTICATION_UNDEFINED=3
+ TLS_AUTHENTICATION_DEFERRED=2
};
/**
* from KS_AUTH_DEFERRED to KS_AUTH_FALSE/KS_AUTH_TRUE if the deferred
* authentication has succeeded after last call.
*
- * @param latency if not null, return TLS_AUTHENTICATION_UNDEFINED if
- * the last call for this multi struct has been less
- * than latency seconds ago
+ * @param latency if not null, return a cached result from the last
+ * call if the last call for this multi struct has
+ * been less than latency seconds ago
* @param multi the tls_multi struct to operate on
*
* @return Current authentication status of the tls_multi