string_t *auth_response;
time_t auth_first_started, auth_finished;
const char *sasl_final_resp;
+ const char *sasl_final_delayed_resp;
+ enum sasl_server_reply delayed_final_reply;
+ const char *const *final_args;
const char *const *auth_passdb_args;
struct anvil_query *anvil_query;
struct anvil_request *anvil_request;
bool ssl_servername_settings_read:1;
bool banner_sent:1;
bool authenticating:1;
+ bool auth_client_continue_pending:1;
bool auth_try_aborted:1;
bool auth_initializing:1;
bool auth_process_comm_fail:1;
bool notified_auth_ready:1;
bool notified_disconnect:1;
bool fd_proxying:1;
+ bool final_response:1;
/* ... */
};
/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
#include "login-common.h"
+#include "array.h"
+#include "md5.h"
+#include "sasl-server.h"
#include "str.h"
#include "base64.h"
#include "buffer.h"
#include "hex-binary.h"
#include "ioloop.h"
#include "istream.h"
+#include "strfuncs.h"
#include "write-full.h"
#include "strescape.h"
#include "str-sanitize.h"
t_strdup_until(key, value),
value+1);
}
- } else if (str_begins(args[i], "resp=") &&
- login_binary->sasl_support_final_reply) {
- client->sasl_final_resp =
- p_strdup(client->pool, args[i] + 5);
+ } else if (str_begins(args[i], "resp=")) {
+ client->sasl_final_delayed_resp =
+ p_strdup(client->pool, args[i]+5);
}
}
if (args != NULL) {
/* parse our username if it's there */
- for (i = 0; args[i] != NULL; i++)
- (void)args_parse_user(client, args[i]);
+ for (i = 0; args[i] != NULL; i++) {
+ if (args_parse_user(client, args[i]))
+ continue;
+ if (str_begins(args[i], "resp=")) {
+ client->sasl_final_delayed_resp =
+ p_strdup(client->preproxy_pool,
+ t_strdup(args[i]+5));
+ }
+ }
}
- client->authenticating = FALSE;
- call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
- NULL, args);
+ if (client->sasl_final_delayed_resp != NULL &&
+ !login_binary->sasl_support_final_reply) {
+ client->final_response = TRUE;
+ client->final_args = p_strarray_dup(client->preproxy_pool, args);
+ client->delayed_final_reply = SASL_SERVER_REPLY_AUTH_FAILED;
+ client->sasl_callback(client, SASL_SERVER_REPLY_CONTINUE,
+ client->sasl_final_delayed_resp, NULL);
+ } else {
+ client->authenticating = FALSE;
+ call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
+ NULL, args);
+ }
break;
}
}
}
sasl_server_auth_cancel(client, NULL, NULL, SASL_SERVER_REPLY_AUTH_ABORTED);
}
+
+void sasl_server_auth_delayed_final(struct client *client)
+{
+ client->final_response = FALSE;
+ client->authenticating = FALSE;
+ client->auth_client_continue_pending = FALSE;
+ call_client_callback(client, client->delayed_final_reply, NULL, client->final_args);
+}