void client_proxy_failed(struct client *client, bool send_line) { if (send_line) { client_proxy_error(client, PROXY_FAILURE_MSG); } login_proxy_free(&client->login_proxy); proxy_free_password(client); i_free_and_null(client->proxy_user); i_free_and_null(client->proxy_master_user); /* call this last - it may destroy the client */ client_auth_failed(client); }
static void sasl_callback(struct client *client, enum sasl_server_reply sasl_reply, const char *data, const char *const *args) { struct client_auth_reply reply; i_assert(!client->destroyed || sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED || sasl_reply == SASL_SERVER_REPLY_MASTER_FAILED); switch (sasl_reply) { case SASL_SERVER_REPLY_SUCCESS: if (client->to_auth_waiting != NULL) timeout_remove(&client->to_auth_waiting); if (args != NULL) { client_auth_parse_args(client, args, &reply); if (client_auth_handle_reply(client, &reply, TRUE)) break; } client_auth_result(client, CLIENT_AUTH_RESULT_SUCCESS, NULL, NULL); client_destroy_success(client, "Login"); break; case SASL_SERVER_REPLY_AUTH_FAILED: case SASL_SERVER_REPLY_AUTH_ABORTED: if (client->to_auth_waiting != NULL) timeout_remove(&client->to_auth_waiting); if (args != NULL) { client_auth_parse_args(client, args, &reply); reply.nologin = TRUE; if (client_auth_handle_reply(client, &reply, FALSE)) break; } if (sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED) { client_auth_result(client, CLIENT_AUTH_RESULT_ABORTED, NULL, "Authentication aborted by client."); } else if (data == NULL) { client_auth_result(client, CLIENT_AUTH_RESULT_AUTHFAILED, NULL, AUTH_FAILED_MSG); } else { client_auth_result(client, CLIENT_AUTH_RESULT_AUTHFAILED_REASON, NULL, data); } if (!client->destroyed) client_auth_failed(client); break; case SASL_SERVER_REPLY_MASTER_FAILED: if (data != NULL) { /* authentication itself succeeded, we just hit some internal failure. */ client_auth_result(client, CLIENT_AUTH_RESULT_TEMPFAIL, NULL, data); } /* the fd may still be hanging somewhere in kernel or another process. make sure the client gets disconnected. */ if (shutdown(client->fd, SHUT_RDWR) < 0 && errno != ENOTCONN) i_error("shutdown() failed: %m"); if (data == NULL) client_destroy_internal_failure(client); else client_destroy_success(client, data); break; case SASL_SERVER_REPLY_CONTINUE: i_assert(client->v.auth_send_challenge != NULL); client->v.auth_send_challenge(client, data); if (client->to_auth_waiting != NULL) timeout_remove(&client->to_auth_waiting); if (client->auth_response != NULL) str_truncate(client->auth_response, 0); i_assert(client->io == NULL); client->auth_waiting = TRUE; client->io = io_add(client->fd, IO_READ, client_auth_input, client); client_auth_input(client); return; } client_unref(&client); }
static bool client_auth_handle_reply(struct client *client, const struct client_auth_reply *reply, bool success) { if (reply->proxy) { /* we want to proxy the connection to another server. don't do this unless authentication succeeded. with master user proxying we can get FAIL with proxy still set. proxy host=.. [port=..] [destuser=..] pass=.. */ if (!success) return FALSE; if (proxy_start(client, reply) < 0) client_auth_failed(client); return TRUE; } if (reply->host != NULL) { const char *reason; if (reply->reason != NULL) reason = reply->reason; else if (reply->nologin) reason = "Try this server instead."; else reason = "Logged in, but you should use this server instead."; if (reply->nologin) { client_auth_result(client, CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN, reply, reason); } else { client_auth_result(client, CLIENT_AUTH_RESULT_REFERRAL_SUCCESS, reply, reason); return TRUE; } } else if (reply->nologin) { /* Authentication went ok, but for some reason user isn't allowed to log in. Shouldn't probably happen. */ if (reply->reason != NULL) { client_auth_result(client, CLIENT_AUTH_RESULT_AUTHFAILED_REASON, reply, reply->reason); } else if (reply->temp) { const char *timestamp, *msg; timestamp = t_strflocaltime("%Y-%m-%d %H:%M:%S", ioloop_time); msg = t_strdup_printf(AUTH_TEMP_FAILED_MSG" [%s:%s]", my_hostname, timestamp); client_auth_result(client, CLIENT_AUTH_RESULT_TEMPFAIL, reply, msg); } else if (reply->authz_failure) { client_auth_result(client, CLIENT_AUTH_RESULT_AUTHZFAILED, reply, "Authorization failed"); } else { client_auth_result(client, CLIENT_AUTH_RESULT_AUTHFAILED, reply, AUTH_FAILED_MSG); } } else { /* normal login/failure */ return FALSE; } i_assert(reply->nologin); if (!client->destroyed) client_auth_failed(client); return TRUE; }