static void client_start_tls(struct client *client) { int fd_ssl; client_ref(client); if (!client_unref(&client) || client->destroyed) return; fd_ssl = ssl_proxy_alloc(client->fd, &client->ip, client->pool, client->set, client->ssl_set, &client->ssl_proxy); if (fd_ssl == -1) { client_notify_disconnect(client, CLIENT_DISCONNECT_INTERNAL_ERROR, "TLS initialization failed."); client_destroy(client, "Disconnected: TLS initialization failed."); return; } ssl_proxy_set_client(client->ssl_proxy, client); ssl_proxy_start(client->ssl_proxy); client->starttls = TRUE; client->tls = TRUE; client->secured = TRUE; login_refresh_proctitle(); client->fd = fd_ssl; client->io = io_add(client->fd, IO_READ, client_input, client); i_stream_unref(&client->input); o_stream_unref(&client->output); client_open_streams(client); client->v.starttls(client); }
bool client_unref(struct client **_client) { struct client *client = *_client; i_assert(client->refcount > 0); if (--client->refcount > 0) return TRUE; *_client = NULL; i_assert(client->destroyed); i_assert(client->ssl_proxy == NULL); i_assert(client->login_proxy == NULL); if (client->input != NULL) i_stream_unref(&client->input); if (client->output != NULL) o_stream_unref(&client->output); i_free(client->proxy_user); i_free(client->proxy_master_user); i_free(client->virtual_user); i_free(client->auth_mech_name); pool_unref(&client->pool); i_assert(clients_count > 0); clients_count--; master_service_client_connection_destroyed(master_service); login_refresh_proctitle(); return FALSE; }
struct client * client_create(int fd, bool ssl, pool_t pool, const struct login_settings *set, const struct master_service_ssl_settings *ssl_set, void **other_sets, const struct ip_addr *local_ip, const struct ip_addr *remote_ip) { struct client *client; i_assert(fd != -1); client = login_binary->client_vfuncs->alloc(pool); client->v = *login_binary->client_vfuncs; if (client->v.auth_send_challenge == NULL) client->v.auth_send_challenge = client_auth_send_challenge; if (client->v.auth_parse_response == NULL) client->v.auth_parse_response = client_auth_parse_response; client->created = ioloop_time; client->refcount = 1; client->pool = pool; client->set = set; client->ssl_set = ssl_set; client->real_local_ip = client->local_ip = *local_ip; client->real_remote_ip = client->ip = *remote_ip; client->fd = fd; client->tls = ssl; client->trusted = client_is_trusted(client); client->secured = ssl || client->trusted || net_ip_compare(remote_ip, local_ip); client->proxy_ttl = LOGIN_PROXY_TTL; if (last_client == NULL) last_client = client; DLLIST_PREPEND(&clients, client); clients_count++; client->to_disconnect = timeout_add(CLIENT_LOGIN_TIMEOUT_MSECS, client_idle_disconnect_timeout, client); client_open_streams(client); client->v.create(client, other_sets); if (auth_client_is_connected(auth_client)) client_notify_auth_ready(client); else client_set_auth_waiting(client); login_refresh_proctitle(); return client; }
void client_destroy(struct client *client, const char *reason) { if (client->destroyed) return; client->destroyed = TRUE; if (!client->login_success && reason != NULL) { reason = t_strconcat(reason, " ", client_get_extra_disconnect_reason(client), NULL); } if (reason != NULL) client_log(client, reason); if (last_client == client) last_client = client->prev; DLLIST_REMOVE(&clients, client); if (client->input != NULL) i_stream_close(client->input); if (client->output != NULL) o_stream_close(client->output); if (client->master_tag != 0) { i_assert(client->auth_request == NULL); i_assert(client->authenticating); i_assert(client->refcount > 1); client->authenticating = FALSE; master_auth_request_abort(master_auth, client->master_tag); client->refcount--; } else if (client->auth_request != NULL) { i_assert(client->authenticating); sasl_server_auth_abort(client); } else { i_assert(!client->authenticating); } if (client->io != NULL) io_remove(&client->io); if (client->to_disconnect != NULL) timeout_remove(&client->to_disconnect); if (client->to_auth_waiting != NULL) timeout_remove(&client->to_auth_waiting); if (client->auth_response != NULL) str_free(&client->auth_response); if (client->fd != -1) { net_disconnect(client->fd); client->fd = -1; } if (client->proxy_password != NULL) { safe_memset(client->proxy_password, 0, strlen(client->proxy_password)); i_free_and_null(client->proxy_password); } if (client->proxy_sasl_client != NULL) dsasl_client_free(&client->proxy_sasl_client); if (client->login_proxy != NULL) login_proxy_free(&client->login_proxy); if (client->v.destroy != NULL) client->v.destroy(client); if (client_unref(&client) && initial_service_count == 1) { /* as soon as this connection is done with proxying (or whatever), the process will die. there's no need for authentication anymore, so close the connection. do this only with initial service_count=1, in case there are other clients with pending authentications */ auth_client_disconnect(auth_client, "unnecessary connection"); } login_client_destroyed(); login_refresh_proctitle(); }