Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-auth/auth-client.c @ 4891:6ab2712f1a93 HEAD
Only imap binary was actually working.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 10 Dec 2006 14:35:02 +0200 |
parents | 1a35d53c18fc |
children | 204d7edc7cdc |
line wrap: on
line source
/* Copyright (C) 2003 Timo Sirainen */ #include "lib.h" #include "buffer.h" #include "ioloop.h" #include "hash.h" #include "auth-client.h" #include "auth-server-connection.h" #include <dirent.h> #include <sys/stat.h> struct auth_client *auth_client_new(unsigned int client_pid) { return auth_client_new_external(client_pid, NULL, NULL, NULL); } struct auth_client *auth_client_new_external(unsigned int client_pid, const char *socket_paths, input_func_add_t *add_func, input_func_remove_t *remove_func) { struct auth_client *client; client = i_new(struct auth_client, 1); client->pid = client_pid; client->socket_paths = i_strdup(socket_paths); client->available_auth_mechs = buffer_create_dynamic(default_pool, 128); client->ext_input_add = add_func; client->ext_input_remove = remove_func; auth_client_connect_missing_servers(client); return client; } void auth_client_free(struct auth_client **_client) { struct auth_client *client = *_client; struct auth_server_connection *next; struct auth_mech_desc *mech; size_t i, size; *_client = NULL; mech = buffer_get_modifiable_data(client->available_auth_mechs, &size); size /= sizeof(*mech); for (i = 0; i < size; i++) i_free(mech[i].name); buffer_free(client->available_auth_mechs); while (client->connections != NULL) { next = client->connections->next; auth_server_connection_destroy(&client->connections, FALSE); client->connections = next; } if (client->to_reconnect != NULL) timeout_remove(&client->to_reconnect); i_free(client->socket_paths); i_free(client); } const struct auth_mech_desc * auth_client_get_available_mechs(struct auth_client *client, unsigned int *mech_count) { const struct auth_mech_desc *mechs; size_t size; mechs = buffer_get_data(client->available_auth_mechs, &size); *mech_count = size / sizeof(*mechs); return mechs; } const struct auth_mech_desc * auth_client_find_mech(struct auth_client *client, const char *name) { const struct auth_mech_desc *mech; size_t i, size; mech = buffer_get_data(client->available_auth_mechs, &size); size /= sizeof(*mech); for (i = 0; i < size; i++) { if (strcasecmp(mech[i].name, name) == 0) return &mech[i]; } return NULL; } bool auth_client_reserve_connection(struct auth_client *client, const char *mech, struct auth_connect_id *id_r) { struct auth_server_connection *conn; const char *error; conn = auth_server_connection_find_mech(client, mech, &error); if (conn == NULL) return FALSE; id_r->server_pid = conn->server_pid; id_r->connect_uid = conn->connect_uid; return TRUE; } bool auth_client_is_connected(struct auth_client *client) { return !client->reconnect && client->conn_waiting_handshake_count == 0 && client->connections != NULL; } void auth_client_set_connect_notify(struct auth_client *client, auth_connect_notify_callback_t *callback, void *context) { client->connect_notify_callback = callback; client->connect_notify_context = context; } static void reconnect_timeout(void *context) { struct auth_client *client = context; auth_client_connect_missing_servers(client); } static void auth_client_connect_missing_servers_list(struct auth_client *client, const char *list) { const char *const *path; client->reconnect = FALSE; t_push(); path = t_strsplit(list, ":"); for (; *path != NULL; path++) { if (auth_server_connection_find_path(client, *path) == NULL) { if (auth_server_connection_new(client, *path) == NULL) client->reconnect = TRUE; } } t_pop(); } void auth_client_connect_missing_servers(struct auth_client *client) { DIR *dirp; struct dirent *dp; struct stat st; if (client->socket_paths != NULL) { auth_client_connect_missing_servers_list(client, client->socket_paths); } else { /* we're chrooted */ dirp = opendir("."); if (dirp == NULL) { i_fatal("opendir(.) failed when trying to get list of " "authentication servers: %m"); } client->reconnect = FALSE; while ((dp = readdir(dirp)) != NULL) { const char *name = dp->d_name; if (name[0] == '.') continue; if (auth_server_connection_find_path(client, name) != NULL) { /* already connected */ continue; } /* Normally they're sockets, but in UnixWare they're created as fifos. */ if (stat(name, &st) == 0 && (S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode))) { if (auth_server_connection_new(client, name) == NULL) client->reconnect = TRUE; } } if (closedir(dirp) < 0) i_error("closedir() failed: %m"); } if (client->reconnect || client->connections == NULL) { if (client->to_reconnect == NULL && client->ext_input_add == NULL) { client->to_reconnect = timeout_add(5000, reconnect_timeout, client); } } else if (client->to_reconnect != NULL) timeout_remove(&client->to_reconnect); if (client->connect_notify_callback != NULL) { client->connect_notify_callback(client, auth_client_is_connected(client), client->connect_notify_context); } }