123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- /* Copyright (c) 2003-2017 Dovecot authors, see the included COPYING file */
- #include "lib.h"
- #include "str.h"
- #include "strescape.h"
- #include "ostream.h"
- #include "auth-client-private.h"
- #include "auth-server-connection.h"
- #include "auth-client-request.h"
- struct auth_client_request {
- pool_t pool;
- struct auth_server_connection *conn;
- unsigned int id;
- time_t created;
- struct auth_request_info request_info;
- auth_request_callback_t *callback;
- void *context;
- };
- static void auth_server_send_new_request(struct auth_server_connection *conn,
- struct auth_client_request *request)
- {
- struct auth_request_info *info = &request->request_info;
- string_t *str;
- str = t_str_new(512);
- str_printfa(str, "AUTH\t%u\t", request->id);
- str_append_tabescaped(str, info->mech);
- str_append(str, "\tservice=");
- str_append_tabescaped(str, info->service);
- if ((info->flags & AUTH_REQUEST_FLAG_SUPPORT_FINAL_RESP) != 0)
- str_append(str, "\tfinal-resp-ok");
- if ((info->flags & AUTH_REQUEST_FLAG_SECURED) != 0)
- str_append(str, "\tsecured");
- if ((info->flags & AUTH_REQUEST_FLAG_NO_PENALTY) != 0)
- str_append(str, "\tno-penalty");
- if ((info->flags & AUTH_REQUEST_FLAG_VALID_CLIENT_CERT) != 0)
- str_append(str, "\tvalid-client-cert");
- if ((info->flags & AUTH_REQUEST_FLAG_DEBUG) != 0)
- str_append(str, "\tdebug");
- if (info->session_id != NULL) {
- str_append(str, "\tsession=");
- str_append_tabescaped(str, info->session_id);
- }
- if (info->cert_username != NULL) {
- str_append(str, "\tcert_username=");
- str_append_tabescaped(str, info->cert_username);
- }
- if (info->local_ip.family != 0)
- str_printfa(str, "\tlip=%s", net_ip2addr(&info->local_ip));
- if (info->remote_ip.family != 0)
- str_printfa(str, "\trip=%s", net_ip2addr(&info->remote_ip));
- if (info->local_port != 0)
- str_printfa(str, "\tlport=%u", info->local_port);
- if (info->remote_port != 0)
- str_printfa(str, "\trport=%u", info->remote_port);
- /* send the real_* variants only when they differ from the unreal
- ones */
- if (info->real_local_ip.family != 0 &&
- !net_ip_compare(&info->real_local_ip, &info->local_ip)) {
- str_printfa(str, "\treal_lip=%s",
- net_ip2addr(&info->real_local_ip));
- }
- if (info->real_remote_ip.family != 0 &&
- !net_ip_compare(&info->real_remote_ip, &info->remote_ip)) {
- str_printfa(str, "\treal_rip=%s",
- net_ip2addr(&info->real_remote_ip));
- }
- if (info->real_local_port != 0 &&
- info->real_local_port != info->local_port)
- str_printfa(str, "\treal_lport=%u", info->real_local_port);
- if (info->real_remote_port != 0 &&
- info->real_remote_port != info->remote_port)
- str_printfa(str, "\treal_rport=%u", info->real_remote_port);
- if (info->local_name != NULL &&
- *info->local_name != '\0') {
- str_append(str, "\tlocal_name=");
- str_append_tabescaped(str, info->local_name);
- }
- if (info->client_id != NULL &&
- *info->client_id != '\0') {
- str_append(str, "\tclient_id=");
- str_append_tabescaped(str, info->client_id);
- }
- if (info->forward_fields != NULL &&
- *info->forward_fields != '\0') {
- str_append(str, "\tforward_fields=");
- str_append_tabescaped(str, info->forward_fields);
- }
- if (info->initial_resp_base64 != NULL) {
- str_append(str, "\tresp=");
- str_append_tabescaped(str, info->initial_resp_base64);
- }
- str_append_c(str, '\n');
- if (o_stream_send(conn->output, str_data(str), str_len(str)) < 0)
- i_error("Error sending request to auth server: %m");
- }
- struct auth_client_request *
- auth_client_request_new(struct auth_client *client,
- const struct auth_request_info *request_info,
- auth_request_callback_t *callback, void *context)
- {
- struct auth_client_request *request;
- pool_t pool;
- pool = pool_alloconly_create("auth client request", 512);
- request = p_new(pool, struct auth_client_request, 1);
- request->pool = pool;
- request->conn = client->conn;
- request->request_info = *request_info;
- request->request_info.mech = p_strdup(pool, request_info->mech);
- request->request_info.service = p_strdup(pool, request_info->service);
- request->request_info.session_id =
- p_strdup_empty(pool, request_info->session_id);
- request->request_info.cert_username =
- p_strdup_empty(pool, request_info->cert_username);
- request->request_info.initial_resp_base64 =
- p_strdup_empty(pool, request_info->initial_resp_base64);
-
- request->callback = callback;
- request->context = context;
- request->id =
- auth_server_connection_add_request(request->conn, request);
- request->created = ioloop_time;
- T_BEGIN {
- auth_server_send_new_request(request->conn, request);
- } T_END;
- return request;
- }
- void auth_client_request_continue(struct auth_client_request *request,
- const char *data_base64)
- {
- struct const_iovec iov[3];
- const char *prefix;
- prefix = t_strdup_printf("CONT\t%u\t", request->id);
- iov[0].iov_base = prefix;
- iov[0].iov_len = strlen(prefix);
- iov[1].iov_base = data_base64;
- iov[1].iov_len = strlen(data_base64);
- iov[2].iov_base = "\n";
- iov[2].iov_len = 1;
- if (o_stream_sendv(request->conn->output, iov, 3) < 0)
- i_error("Error sending continue request to auth server: %m");
- }
- static void ATTR_NULL(3, 4)
- call_callback(struct auth_client_request *request,
- enum auth_request_status status,
- const char *data_base64,
- const char *const *args)
- {
- auth_request_callback_t *callback = request->callback;
- if (status != AUTH_REQUEST_STATUS_CONTINUE)
- request->callback = NULL;
- callback(request, status, data_base64, args, request->context);
- }
- void auth_client_request_abort(struct auth_client_request **_request)
- {
- struct auth_client_request *request = *_request;
- *_request = NULL;
- auth_client_send_cancel(request->conn->client, request->id);
- call_callback(request, AUTH_REQUEST_STATUS_ABORT, NULL, NULL);
- auth_server_connection_remove_request(request->conn, request->id);
- pool_unref(&request->pool);
- }
- unsigned int auth_client_request_get_id(struct auth_client_request *request)
- {
- return request->id;
- }
- unsigned int
- auth_client_request_get_server_pid(struct auth_client_request *request)
- {
- return request->conn->server_pid;
- }
- const char *auth_client_request_get_cookie(struct auth_client_request *request)
- {
- return request->conn->cookie;
- }
- bool auth_client_request_is_aborted(struct auth_client_request *request)
- {
- return request->callback == NULL;
- }
- time_t auth_client_request_get_create_time(struct auth_client_request *request)
- {
- return request->created;
- }
- void auth_client_request_server_input(struct auth_client_request *request,
- enum auth_request_status status,
- const char *const *args)
- {
- const char *const *tmp, *base64_data = NULL;
- if (request->callback == NULL) {
- /* aborted already */
- return;
- }
- switch (status) {
- case AUTH_REQUEST_STATUS_OK:
- for (tmp = args; *tmp != NULL; tmp++) {
- if (strncmp(*tmp, "resp=", 5) == 0) {
- base64_data = *tmp + 5;
- break;
- }
- }
- break;
- case AUTH_REQUEST_STATUS_CONTINUE:
- base64_data = args[0];
- args = NULL;
- break;
- case AUTH_REQUEST_STATUS_FAIL:
- case AUTH_REQUEST_STATUS_INTERNAL_FAIL:
- case AUTH_REQUEST_STATUS_ABORT:
- break;
- }
- call_callback(request, status, base64_data, args);
- if (status != AUTH_REQUEST_STATUS_CONTINUE)
- pool_unref(&request->pool);
- }
- void auth_client_send_cancel(struct auth_client *client, unsigned int id)
- {
- const char *str = t_strdup_printf("CANCEL\t%u\n", id);
- if (o_stream_send_str(client->conn->output, str) < 0)
- i_error("Error sending request to auth server: %m");
- }
|