[dovecot-cvs]
dovecot/src/lib-auth .cvsignore,NONE,1.1 Makefile.am,NONE,1.1
auth-client.c,NONE,1.1 auth-client.h,NONE,1.1
auth-server-connection.c,NONE,1.1 auth-server-connection.h,NONE,1.1
auth-server-request.c,NONE,1.1 auth-server-request.h,NONE,1.1
cras at procontrol.fi
cras at procontrol.fi
Fri Aug 22 06:42:15 EEST 2003
- Previous message: [dovecot-cvs] dovecot/src/pop3-login Makefile.am,1.2,1.3
client-authenticate.c,1.9,1.10 client.c,1.13,1.14 client.h,1.4,1.5
common.h,1.1,NONE
- Next message: [dovecot-cvs] dovecot/src/master auth-process.c,1.48,1.49
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/dovecot/src/lib-auth
In directory danu:/tmp/cvs-serv8684/src/lib-auth
Added Files:
.cvsignore Makefile.am auth-client.c auth-client.h
auth-server-connection.c auth-server-connection.h
auth-server-request.c auth-server-request.h
Log Message:
Moved client side code for auth process handling to lib-auth. Some other login process cleanups.
--- NEW FILE: .cvsignore ---
*.la
*.lo
*.o
.deps
.libs
Makefile
Makefile.in
so_locations
--- NEW FILE: Makefile.am ---
noinst_LIBRARIES = libauth.a
INCLUDES = \
-I$(top_srcdir)/src/lib
libauth_a_SOURCES = \
auth-client.c \
auth-server-connection.c \
auth-server-request.c
noinst_HEADERS = \
auth-client.h
--- NEW FILE: auth-client.c ---
/* Copyright (C) 2003 Timo Sirainen */
#include "lib.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)
{
struct auth_client *client;
client = i_new(struct auth_client, 1);
client->pid = client_pid;
auth_client_connect_missing_servers(client);
return client;
}
void auth_client_free(struct auth_client *client)
{
struct auth_server_connection *next;
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);
}
enum auth_mech auth_client_get_available_mechs(struct auth_client *client)
{
return client->available_auth_mechs;
}
int auth_client_is_connected(struct auth_client *client)
{
return client->to_reconnect == NULL &&
client->conn_waiting_handshake_count == 0;
}
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);
}
void auth_client_connect_missing_servers(struct auth_client *client)
{
DIR *dirp;
struct dirent *dp;
struct stat st;
int reconnect;
/* we're chrooted into */
dirp = opendir(".");
if (dirp == NULL) {
i_fatal("opendir(.) failed when trying to get list of "
"authentication servers: %m");
}
reconnect = FALSE;
while ((dp = readdir(dirp)) != NULL) {
if (dp->d_name[0] == '.')
continue;
if (auth_server_connection_find_path(client, dp->d_name) != NULL) {
/* already connected */
continue;
}
if (stat(dp->d_name, &st) == 0 && S_ISSOCK(st.st_mode)) {
if (auth_server_connection_new(client,
dp->d_name) == NULL)
reconnect = TRUE;
}
}
if (closedir(dirp) < 0)
i_error("closedir() failed: %m");
if (reconnect || client->connections == NULL) {
if (client->to_reconnect == NULL) {
client->to_reconnect =
timeout_add(5000, reconnect_timeout, client);
}
} else if (client->to_reconnect != NULL) {
timeout_remove(client->to_reconnect);
client->to_reconnect = NULL;
}
client->connect_notify_callback(client,
auth_client_is_connected(client),
client->connect_notify_context);
}
--- NEW FILE: auth-client.h ---
#ifndef __AUTH_CLIENT_H
#define __AUTH_CLIENT_H
#include "../auth/auth-client-interface.h"
struct auth_client;
struct auth_request;
/* reply is NULL if auth connection died */
typedef void auth_request_callback_t(struct auth_request *request,
struct auth_client_request_reply *reply,
const unsigned char *data, void *context);
typedef void auth_connect_notify_callback_t(struct auth_client *client,
int connected, void *context);
/* Create new authentication client. */
struct auth_client *auth_client_new(unsigned int client_pid);
void auth_client_free(struct auth_client *client);
int auth_client_is_connected(struct auth_client *client);
void auth_client_set_connect_notify(struct auth_client *client,
auth_connect_notify_callback_t *callback,
void *context);
enum auth_mech auth_client_get_available_mechs(struct auth_client *client);
void auth_client_connect_missing_servers(struct auth_client *client);
/* Create a new authentication request. callback is called whenever something
happens for the request. */
struct auth_request *
auth_client_request_new(struct auth_client *client,
enum auth_mech mech, enum auth_protocol protocol,
auth_request_callback_t *callback, void *context,
const char **error_r);
/* Continue authentication. Call when
reply->result == AUTH_CLIENT_REQUEST_CONTINUE */
void auth_client_request_continue(struct auth_request *request,
const unsigned char *data, size_t data_size);
/* Abort ongoing authentication request. */
void auth_client_request_abort(struct auth_request *request);
/* Return ID of this request. */
unsigned int auth_client_request_get_id(struct auth_request *request);
/* Return the PID of the server that handled this request. */
unsigned int auth_client_request_get_server_pid(struct auth_request *request);
#endif
--- NEW FILE: auth-server-connection.c ---
/* Copyright (C) 2003 Timo Sirainen */
#include "lib.h"
#include "hash.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "network.h"
#include "auth-client.h"
#include "auth-server-connection.h"
#include "auth-server-request.h"
#include <unistd.h>
/* Maximum size for an auth reply. 50kB should be more than enough. */
#define MAX_INBUF_SIZE (1024*50)
#define MAX_OUTBUF_SIZE \
(sizeof(struct auth_client_request_continue) + \
AUTH_CLIENT_MAX_REQUEST_DATA_SIZE)
static void update_available_auth_mechs(struct auth_client *client)
{
struct auth_server_connection *conn;
client->available_auth_mechs = 0;
for (conn = client->connections; conn != NULL; conn = conn->next)
client->available_auth_mechs |= conn->available_auth_mechs;
}
static void auth_handle_handshake(struct auth_server_connection *conn,
struct auth_client_handshake_reply *handshake)
{
if (handshake->server_pid == 0) {
i_error("BUG: Auth server said it's PID 0");
auth_server_connection_destroy(conn, FALSE);
return;
}
conn->pid = handshake->server_pid;
conn->available_auth_mechs = handshake->auth_mechanisms;
conn->handshake_received = TRUE;
conn->client->conn_waiting_handshake_count--;
update_available_auth_mechs(conn->client);
if (auth_client_is_connected(conn->client)) {
conn->client->connect_notify_callback(conn->client, TRUE,
conn->client->connect_notify_context);
}
}
static void auth_client_input(void *context)
{
struct auth_server_connection *conn = context;
struct auth_client_handshake_reply handshake;
const unsigned char *data;
size_t size;
switch (i_stream_read(conn->input)) {
case 0:
return;
case -1:
/* disconnected */
auth_server_connection_destroy(conn, TRUE);
return;
case -2:
/* buffer full - can't happen unless auth is buggy */
i_error("BUG: Auth server sent us more than %d bytes of data",
MAX_INBUF_SIZE);
auth_server_connection_destroy(conn, FALSE);
return;
}
if (!conn->handshake_received) {
data = i_stream_get_data(conn->input, &size);
if (size == sizeof(handshake)) {
memcpy(&handshake, data, sizeof(handshake));
i_stream_skip(conn->input, sizeof(handshake));
auth_handle_handshake(conn, &handshake);
} else if (size > sizeof(handshake)) {
i_error("BUG: Auth server sent us too large handshake "
"(%"PRIuSIZE_T " vs %"PRIuSIZE_T")", size,
sizeof(handshake));
auth_server_connection_destroy(conn, FALSE);
}
return;
}
if (!conn->reply_received) {
data = i_stream_get_data(conn->input, &size);
if (size < sizeof(conn->reply))
return;
memcpy(&conn->reply, data, sizeof(conn->reply));
i_stream_skip(conn->input, sizeof(conn->reply));
conn->reply_received = TRUE;
}
data = i_stream_get_data(conn->input, &size);
if (size < conn->reply.data_size)
return;
/* we've got a full reply */
conn->reply_received = FALSE;
auth_server_request_handle_reply(conn, &conn->reply, data);
i_stream_skip(conn->input, conn->reply.data_size);
}
struct auth_server_connection *
auth_server_connection_new(struct auth_client *client, const char *path)
{
struct auth_server_connection *conn;
struct auth_client_handshake_request handshake;
pool_t pool;
int fd;
fd = net_connect_unix(path);
if (fd == -1) {
i_error("Can't connect to auth server at %s: %m", path);
return NULL;
}
/* use blocking connection since we depend on auth server -
if it's slow, just wait */
pool = pool_alloconly_create("Auth connection", 1024);
conn = p_new(pool, struct auth_server_connection, 1);
conn->pool = pool;
conn->client = client;
conn->path = p_strdup(pool, path);
conn->fd = fd;
conn->io = io_add(fd, IO_READ, auth_client_input, conn);
conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
FALSE);
conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
FALSE);
conn->requests = hash_create(default_pool, pool, 100, NULL, NULL);
conn->next = client->connections;
client->connections = conn;
/* send our handshake */
memset(&handshake, 0, sizeof(handshake));
handshake.client_pid = client->pid;
client->conn_waiting_handshake_count++;
if (o_stream_send(conn->output, &handshake, sizeof(handshake)) < 0) {
errno = conn->output->stream_errno;
i_warning("Error sending handshake to auth server: %m");
auth_server_connection_destroy(conn, TRUE);
return NULL;
}
return conn;
}
void auth_server_connection_destroy(struct auth_server_connection *conn,
int reconnect)
{
struct auth_client *client = conn->client;
struct auth_server_connection **pos;
pos = &conn->client->connections;
for (; *pos != NULL; pos = &(*pos)->next) {
if (*pos == conn) {
*pos = conn->next;
break;
}
}
if (!conn->handshake_received)
client->conn_waiting_handshake_count--;
io_remove(conn->io);
if (close(conn->fd) < 0)
i_error("close(auth) failed: %m");
conn->fd = -1;
auth_server_requests_remove_all(conn);
hash_destroy(conn->requests);
i_stream_unref(conn->input);
o_stream_unref(conn->output);
pool_unref(conn->pool);
if (reconnect)
auth_client_connect_missing_servers(client);
else {
client->connect_notify_callback(client,
auth_client_is_connected(client),
client->connect_notify_context);
}
}
struct auth_server_connection *
auth_server_connection_find_path(struct auth_client *client, const char *path)
{
struct auth_server_connection *conn;
for (conn = client->connections; conn != NULL; conn = conn->next) {
if (strcmp(conn->path, path) == 0)
return conn;
}
return NULL;
}
struct auth_server_connection *
auth_server_connection_find_mech(struct auth_client *client,
enum auth_mech mech, const char **error_r)
{
struct auth_server_connection *conn;
for (conn = client->connections; conn != NULL; conn = conn->next) {
if ((conn->available_auth_mechs & mech))
return conn;
}
if ((client->available_auth_mechs & mech) == 0)
*error_r = "Unsupported authentication mechanism";
else {
*error_r = "Authentication server isn't connected, "
"try again later..";
}
return NULL;
}
--- NEW FILE: auth-server-connection.h ---
#ifndef __AUTH_SERVER_CONNECTION_H
#define __AUTH_SERVER_CONNECTION_H
struct auth_client {
unsigned int pid;
struct auth_server_connection *connections;
struct timeout *to_reconnect;
unsigned int conn_waiting_handshake_count;
enum auth_mech available_auth_mechs;
unsigned int request_id_counter;
auth_connect_notify_callback_t *connect_notify_callback;
void *connect_notify_context;
};
struct auth_server_connection {
struct auth_server_connection *next;
pool_t pool;
struct auth_client *client;
const char *path;
int fd;
struct io *io;
struct istream *input;
struct ostream *output;
unsigned int pid;
enum auth_mech available_auth_mechs;
struct auth_client_request_reply reply;
struct hash_table *requests;
unsigned int handshake_received:1;
unsigned int reply_received:1;
};
struct auth_server_connection *
auth_server_connection_new(struct auth_client *client, const char *path);
void auth_server_connection_destroy(struct auth_server_connection *conn,
int reconnect);
struct auth_server_connection *
auth_server_connection_find_path(struct auth_client *client, const char *path);
struct auth_server_connection *
auth_server_connection_find_mech(struct auth_client *client,
enum auth_mech mech, const char **error_r);
#endif
--- NEW FILE: auth-server-request.c ---
/* Copyright (C) 2003 Timo Sirainen */
#include "lib.h"
#include "hash.h"
#include "ostream.h"
#include "auth-client.h"
#include "auth-server-connection.h"
#include "auth-server-request.h"
struct auth_request {
enum auth_mech mech;
struct auth_server_connection *conn;
unsigned int id;
auth_request_callback_t *callback;
void *context;
unsigned int init_sent:1;
};
void auth_server_request_handle_reply(struct auth_server_connection *conn,
struct auth_client_request_reply *reply,
const unsigned char *data)
{
struct auth_request *request;
request = hash_lookup(conn->requests, POINTER_CAST(reply->id));
if (request == NULL) {
i_error("BUG: Auth server sent us reply with unknown ID %u",
reply->id);
return;
}
request->callback(request, reply, data, request->context);
if (reply->result != AUTH_CLIENT_RESULT_CONTINUE) {
hash_remove(conn->requests, POINTER_CAST(request->id));
i_free(request);
}
}
static void request_hash_remove(void *key __attr_unused__, void *value,
void *context __attr_unused__)
{
struct auth_request *request = value;
request->callback(request, NULL, NULL, request->context);
request->conn = NULL;
}
void auth_server_requests_remove_all(struct auth_server_connection *conn)
{
hash_foreach(conn->requests, request_hash_remove, NULL);
}
struct auth_request *
auth_client_request_new(struct auth_client *client,
enum auth_mech mech, enum auth_protocol protocol,
auth_request_callback_t *callback, void *context,
const char **error_r)
{
struct auth_server_connection *conn;
struct auth_request *request;
struct auth_client_request_new auth_request;
conn = auth_server_connection_find_mech(client, mech, error_r);
if (conn == NULL)
return NULL;
request = i_new(struct auth_request, 1);
request->mech = mech;
request->conn = conn;
request->id = ++client->request_id_counter;
if (request->id == 0) {
/* wrapped - ID 0 not allowed */
request->id = ++client->request_id_counter;
}
request->callback = callback;
request->context = context;
hash_insert(conn->requests, POINTER_CAST(request->id), request);
/* send request to auth */
auth_request.type = AUTH_CLIENT_REQUEST_NEW;
auth_request.id = request->id;
auth_request.protocol = protocol;
auth_request.mech = request->mech;
if (o_stream_send(request->conn->output, &auth_request,
sizeof(auth_request)) < 0) {
errno = request->conn->output->stream_errno;
i_warning("Error sending request to auth process: %m");
auth_server_connection_destroy(request->conn, TRUE);
}
return request;
}
void auth_client_request_continue(struct auth_request *request,
const unsigned char *data, size_t data_size)
{
struct auth_client_request_continue auth_request;
/* send continued request to auth */
auth_request.type = AUTH_CLIENT_REQUEST_CONTINUE;
auth_request.id = request->id;
auth_request.data_size = data_size;
if (o_stream_send(request->conn->output, &auth_request,
sizeof(auth_request)) < 0 ||
o_stream_send(request->conn->output, data, data_size) < 0) {
errno = request->conn->output->stream_errno;
i_warning("Error sending continue request to auth process: %m");
auth_server_connection_destroy(request->conn, TRUE);
}
}
void auth_client_request_abort(struct auth_request *request)
{
void *id = POINTER_CAST(request->id);
if (hash_lookup(request->conn->requests, id) != NULL)
hash_remove(request->conn->requests, id);
i_free(request);
}
unsigned int auth_client_request_get_id(struct auth_request *request)
{
return request->id;
}
unsigned int auth_client_request_get_server_pid(struct auth_request *request)
{
return request->conn->pid;
}
--- NEW FILE: auth-server-request.h ---
#ifndef __AUTH_SERVER_REQUEST_H
#define __AUTH_SERVER_REQUEST_H
void auth_server_request_handle_reply(struct auth_server_connection *conn,
struct auth_client_request_reply *reply,
const unsigned char *data);
void auth_server_requests_remove_all(struct auth_server_connection *conn);
#endif
- Previous message: [dovecot-cvs] dovecot/src/pop3-login Makefile.am,1.2,1.3
client-authenticate.c,1.9,1.10 client.c,1.13,1.14 client.h,1.4,1.5
common.h,1.1,NONE
- Next message: [dovecot-cvs] dovecot/src/master auth-process.c,1.48,1.49
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list