[dovecot-cvs] dovecot/src/master auth-process.c, 1.61,
1.62 auth-process.h, 1.8, 1.9 common.h, 1.19,
1.20 login-process.c, 1.59, 1.60 mail-process.c, 1.60,
1.61 mail-process.h, 1.6, 1.7
cras at dovecot.org
cras at dovecot.org
Wed Oct 13 19:38:38 EEST 2004
Update of /var/lib/cvs/dovecot/src/master
In directory talvi:/tmp/cvs-serv8894/master
Modified Files:
auth-process.c auth-process.h common.h login-process.c
mail-process.c mail-process.h
Log Message:
Changed dovecot-auth protocol to ASCII based. Should be easier now to write
replacement server if needed by someone. Also cleaned up/made more
consistent auth code. The new code could still use some cleaning though..
Index: auth-process.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/auth-process.c,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -d -r1.61 -r1.62
--- auth-process.c 10 Oct 2004 13:55:13 -0000 1.61
+++ auth-process.c 13 Oct 2004 16:38:35 -0000 1.62
@@ -7,6 +7,7 @@
#include "network.h"
#include "istream.h"
#include "ostream.h"
+#include "str.h"
#include "restrict-access.h"
#include "restrict-process-size.h"
#include "auth-process.h"
@@ -18,8 +19,8 @@
#include <syslog.h>
#include <sys/stat.h>
-#define MAX_INBUF_SIZE \
- (sizeof(struct auth_master_reply) + AUTH_MASTER_MAX_REPLY_DATA_SIZE)
+#define MAX_INBUF_SIZE 8192
+#define MAX_OUTBUF_SIZE 65536
struct auth_process_group {
struct auth_process_group *next;
@@ -41,8 +42,6 @@
struct istream *input;
struct ostream *output;
- struct auth_master_reply auth_reply;
-
struct hash_table *requests;
unsigned int external:1;
@@ -56,145 +55,171 @@
static void auth_process_destroy(struct auth_process *p);
-static int handle_reply(struct auth_process *process,
- struct auth_master_reply *reply,
- const unsigned char *data)
+void auth_process_request(struct auth_process *process, unsigned int login_pid,
+ unsigned int login_id, void *context)
+{
+ string_t *str;
+ ssize_t ret;
+
+ t_push();
+ str = t_str_new(256);
+ str_printfa(str, "REQUEST\t%u\t%u\t%u\n",
+ ++auth_tag, login_pid, login_id);
+
+ ret = o_stream_send(process->output, str_data(str), str_len(str));
+ if (ret != (ssize_t)str_len(str)) {
+ if (ret >= 0) {
+ /* FIXME: well .. I'm not sure if it'd be better to
+ just block here. I don't think this condition should
+ happen often, so this could mean that the auth
+ process is stuck. Or that the computer is just
+ too heavily loaded. Possibility to block infinitely
+ is annoying though, so for now don't do it. */
+ i_warning("Auth process %s transmit buffer full, "
+ "killing..", dec2str(process->pid));
+ }
+ auth_process_destroy(process);
+ } else {
+ hash_insert(process->requests, POINTER_CAST(auth_tag), context);
+ }
+ t_pop();
+}
+
+static int
+auth_process_input_user(struct auth_process *process, const char *args)
{
- size_t nul_pos;
void *context;
+ const char *const *list;
+ unsigned int id;
- context = hash_lookup(process->requests, POINTER_CAST(reply->tag));
+ /* <id> <userid> [..] */
+
+ list = t_strsplit(args, "\t");
+ if (list[0] == NULL || list[1] == NULL) {
+ i_error("BUG: Auth process %s sent corrupted USER line",
+ dec2str(process->pid));
+ return FALSE;
+ }
+ id = (unsigned int)strtoul(list[0], NULL, 10);
+
+ context = hash_lookup(process->requests, POINTER_CAST(id));
if (context == NULL) {
- i_error("Auth process %s sent unrequested reply with tag %u",
- dec2str(process->pid), reply->tag);
- return TRUE;
+ i_error("BUG: Auth process %s sent unrequested reply with ID "
+ "%u", dec2str(process->pid), id);
+ return FALSE;
}
- /* make sure the reply looks OK */
- if (reply->data_size == 0) {
- nul_pos = 0;
- data = (const unsigned char *) "";
- } else {
- nul_pos = reply->data_size-1;
+ auth_master_callback(list[1], list + 2, context);
+ hash_remove(process->requests, POINTER_CAST(id));
+ return TRUE;
+}
+
+static int
+auth_process_input_notfound(struct auth_process *process, const char *args)
+{
+ void *context;
+ unsigned int id;
+
+ id = (unsigned int)strtoul(args, NULL, 10);
+
+ context = hash_lookup(process->requests, POINTER_CAST(id));
+ if (context == NULL) {
+ i_error("BUG: Auth process %s sent unrequested reply with ID "
+ "%u", dec2str(process->pid), id);
+ return FALSE;
}
- if (data[nul_pos] != '\0') {
- i_error("Auth process %s sent invalid reply",
- dec2str(process->pid));
+ auth_master_callback(NULL, NULL, context);
+ hash_remove(process->requests, POINTER_CAST(id));
+ return TRUE;
+}
+
+static int
+auth_process_input_spid(struct auth_process *process, const char *args)
+{
+ unsigned int pid;
+
+ if (process->initialized) {
+ i_error("BUG: Authentication server re-handshaking");
return FALSE;
}
- /* fix the request so that all the values point to \0 terminated
- strings */
- if (reply->system_user_idx >= reply->data_size)
- reply->system_user_idx = nul_pos;
- if (reply->virtual_user_idx >= reply->data_size)
- reply->virtual_user_idx = nul_pos;
- if (reply->home_idx >= reply->data_size)
- reply->home_idx = nul_pos;
- if (reply->chroot_idx >= reply->data_size)
- reply->chroot_idx = nul_pos;
- if (reply->mail_idx >= reply->data_size)
- reply->mail_idx = nul_pos;
+ pid = (unsigned int)strtoul(args, NULL, 10);
+ if (pid == 0) {
+ i_error("BUG: Authentication server said it's PID 0");
+ return FALSE;
+ }
- auth_master_callback(reply, data, context);
- hash_remove(process->requests, POINTER_CAST(reply->tag));
+ process->pid = pid;
+ process->initialized = TRUE;
return TRUE;
}
-void auth_process_request(struct auth_process *process, unsigned int login_pid,
- unsigned int login_id, void *context)
+static int
+auth_process_input_fail(struct auth_process *process, const char *args)
{
- struct auth_master_request req;
- ssize_t ret;
+ void *context;
+ const char *error;
+ unsigned int id;
- req.tag = ++auth_tag;
- req.id = login_id;
- req.client_pid = login_pid;
+ error = strchr(args, '\t');
+ if (error != NULL)
+ error++;
- ret = o_stream_send(process->output, &req, sizeof(req));
- if ((size_t)ret != sizeof(req)) {
- if (ret >= 0) {
- /* FIXME: well .. I'm not sure if it'd be better to
- just block here. I don't think this condition should
- happen often, so this could mean that the auth
- process is stuck. Or that the computer is just
- too heavily loaded. Possibility to block infinitely
- is annoying though, so for now don't do it. */
- i_warning("Auth process %s transmit buffer full, "
- "killing..", dec2str(process->pid));
- }
- auth_process_destroy(process);
- return;
+ id = (unsigned int)strtoul(args, NULL, 10);
+
+ context = hash_lookup(process->requests, POINTER_CAST(id));
+ if (context == NULL) {
+ i_error("BUG: Auth process %s sent unrequested reply with ID "
+ "%u", dec2str(process->pid), id);
+ return FALSE;
}
- hash_insert(process->requests, POINTER_CAST(req.tag), context);
+ auth_master_callback(NULL, NULL, context);
+ hash_remove(process->requests, POINTER_CAST(id));
+ return TRUE;
}
static void auth_process_input(void *context)
{
- struct auth_process *p = context;
- const unsigned char *data;
- size_t size;
+ struct auth_process *process = context;
+ const char *line;
+ int ret;
- switch (i_stream_read(p->input)) {
+ switch (i_stream_read(process->input)) {
case 0:
return;
case -1:
/* disconnected */
- auth_process_destroy(p);
+ auth_process_destroy(process);
return;
case -2:
/* buffer full */
i_error("BUG: Auth process %s sent us more than %d "
- "bytes of data", dec2str(p->pid), (int)MAX_INBUF_SIZE);
- auth_process_destroy(p);
+ "bytes of data", dec2str(process->pid),
+ (int)MAX_INBUF_SIZE);
+ auth_process_destroy(process);
return;
}
- if (!p->initialized) {
- struct auth_master_handshake_reply rec;
-
- data = i_stream_get_data(p->input, &size);
- if (size < sizeof(rec))
- return;
-
- memcpy(&rec, data, sizeof(rec));
- i_stream_skip(p->input, sizeof(rec));
-
- if (rec.server_pid == 0) {
- i_fatal("Auth process sent invalid initialization "
- "notification");
- }
-
- p->pid = rec.server_pid;
- p->initialized = TRUE;
- }
-
- for (;;) {
- if (!p->in_auth_reply) {
- data = i_stream_get_data(p->input, &size);
- if (size < sizeof(p->auth_reply))
- break;
-
- p->in_auth_reply = TRUE;
- memcpy(&p->auth_reply, data, sizeof(p->auth_reply));
-
- i_stream_skip(p->input, sizeof(p->auth_reply));
- }
-
- data = i_stream_get_data(p->input, &size);
- if (size < p->auth_reply.data_size)
- break;
+ while ((line = i_stream_next_line(process->input)) != NULL) {
+ t_push();
+ if (strncmp(line, "USER\t", 5) == 0)
+ ret = auth_process_input_user(process, line + 5);
+ else if (strncmp(line, "NOTFOUND\t", 9) == 0)
+ ret = auth_process_input_notfound(process, line + 9);
+ else if (strncmp(line, "FAIL\t", 5) == 0)
+ ret = auth_process_input_fail(process, line + 5);
+ else if (strncmp(line, "SPID\t", 5) == 0)
+ ret = auth_process_input_spid(process, line + 5);
+ else
+ ret = TRUE;
- /* reply is now read */
- if (!handle_reply(p, &p->auth_reply, data)) {
- auth_process_destroy(p);
+ if (!ret) {
+ auth_process_destroy(process);
break;
}
-
- p->in_auth_reply = FALSE;
- i_stream_skip(p->input, p->auth_reply.data_size);
+ t_pop();
}
}
@@ -213,8 +238,7 @@
p->io = io_add(fd, IO_READ, auth_process_input, p);
p->input = i_stream_create_file(fd, default_pool,
MAX_INBUF_SIZE, FALSE);
- p->output = o_stream_create_file(fd, default_pool,
- sizeof(struct auth_master_request)*100,
+ p->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
FALSE);
p->requests = hash_create(default_pool, default_pool, 0, NULL, NULL);
Index: auth-process.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/auth-process.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- auth-process.h 27 Jan 2003 01:33:40 -0000 1.8
+++ auth-process.h 13 Oct 2004 16:38:35 -0000 1.9
@@ -1,8 +1,8 @@
#ifndef __AUTH_PROCESS_H
#define __AUTH_PROCESS_H
-void auth_master_callback(struct auth_master_reply *reply,
- const unsigned char *data, void *context);
+void auth_master_callback(const char *user, const char *const *args,
+ void *context);
/* Find process for given id */
struct auth_process *auth_process_find(unsigned int pid);
Index: common.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/common.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- common.h 24 May 2004 22:33:51 -0000 1.19
+++ common.h 13 Oct 2004 16:38:35 -0000 1.20
@@ -7,8 +7,6 @@
#include "hash.h"
#include "master-settings.h"
-#include "../auth/auth-master-interface.h"
-
enum process_type {
PROCESS_TYPE_UNKNOWN,
PROCESS_TYPE_AUTH,
Index: login-process.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/login-process.c,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -d -r1.59 -r1.60
--- login-process.c 5 Oct 2004 16:00:18 -0000 1.59
+++ login-process.c 13 Oct 2004 16:38:36 -0000 1.60
@@ -71,14 +71,14 @@
i_free(group);
}
-void auth_master_callback(struct auth_master_reply *reply,
- const unsigned char *data, void *context)
+void auth_master_callback(const char *user, const char *const *args,
+ void *context)
{
struct login_auth_request *request = context;
struct master_login_reply master_reply;
ssize_t ret;
- if (reply == NULL || !reply->success)
+ if (user == NULL)
master_reply.success = FALSE;
else {
struct login_group *group = request->process->group;
@@ -87,8 +87,7 @@
master_reply.success =
create_mail_process(group, request->fd,
&request->local_ip,
- &request->remote_ip,
- reply, (const char *) data);
+ &request->remote_ip, user, args);
t_pop();
}
Index: mail-process.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/mail-process.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -d -r1.60 -r1.61
--- mail-process.c 10 Oct 2004 17:25:45 -0000 1.60
+++ mail-process.c 13 Oct 2004 16:38:36 -0000 1.61
@@ -312,15 +312,18 @@
int create_mail_process(struct login_group *group, int socket,
const struct ip_addr *local_ip,
const struct ip_addr *remote_ip,
- struct auth_master_reply *reply, const char *data)
+ const char *user, const char *const *args)
{
struct settings *set = group->set;
const struct var_expand_table *var_expand_table;
- const char *addr, *mail, *user, *chroot_dir, *home_dir, *full_home_dir;
+ const char *addr, *mail, *chroot_dir, *home_dir, *full_home_dir;
+ const char *system_user;
char title[1024];
struct log_io *log;
string_t *str;
pid_t pid;
+ uid_t uid;
+ gid_t gid;
int i, err, ret, log_fd;
// FIXME: per-group
@@ -329,14 +332,25 @@
return FALSE;
}
- if (!validate_uid_gid(set, reply->uid, reply->gid,
- data + reply->virtual_user_idx))
- return FALSE;
+ mail = home_dir = chroot_dir = system_user = "";
+ uid = gid = 0;
+ for (; *args != NULL; args++) {
+ if (strncmp(*args, "home=", 5) == 0)
+ home_dir = *args + 5;
+ else if (strncmp(*args, "mail=", 5) == 0)
+ mail = *args + 5;
+ else if (strncmp(*args, "chroot=", 7) == 0)
+ chroot_dir = *args + 7;
+ else if (strncmp(*args, "system_user=", 12) == 0)
+ system_user = *args + 12;
+ else if (strncmp(*args, "uid=", 4) == 0)
+ uid = (uid_t)strtoul(*args + 4, NULL, 10);
+ else if (strncmp(*args, "gid=", 4) == 0)
+ gid = (gid_t)strtoul(*args + 4, NULL, 10);
+ }
- user = data + reply->virtual_user_idx;
- mail = data + reply->mail_idx;
- home_dir = data + reply->home_idx;
- chroot_dir = data + reply->chroot_idx;
+ if (!validate_uid_gid(set, uid, gid, user))
+ return FALSE;
if (*chroot_dir == '\0' && set->mail_chroot != NULL)
chroot_dir = set->mail_chroot;
@@ -395,8 +409,7 @@
/* setup environment - set the most important environment first
(paranoia about filling up environment without noticing) */
- restrict_access_set_env(data + reply->system_user_idx,
- reply->uid, reply->gid, chroot_dir,
+ restrict_access_set_env(system_user, uid, gid, chroot_dir,
set->first_valid_gid, set->last_valid_gid,
set->mail_extra_groups);
@@ -410,10 +423,10 @@
/* NOTE: if home directory is NFS-mounted, we might not
have access to it as root. Change the effective UID
temporarily to make it work. */
- if (reply->uid != master_uid && seteuid(reply->uid) < 0)
- i_fatal("seteuid(%s) failed: %m", dec2str(reply->uid));
+ if (uid != master_uid && seteuid(uid) < 0)
+ i_fatal("seteuid(%s) failed: %m", dec2str(uid));
ret = chdir(full_home_dir);
- if (reply->uid != master_uid && seteuid(master_uid) < 0)
+ if (uid != master_uid && seteuid(master_uid) < 0)
i_fatal("seteuid(%s) failed: %m", dec2str(master_uid));
/* If user's home directory doesn't exist and we're not
@@ -421,7 +434,7 @@
could be stored elsewhere. */
if (ret < 0 && (errno != ENOENT || *chroot_dir != '\0')) {
i_fatal("chdir(%s) failed with uid %s: %m",
- full_home_dir, dec2str(reply->uid));
+ full_home_dir, dec2str(uid));
}
}
if (ret < 0) {
@@ -435,7 +448,7 @@
env_put("LOGGED_IN=1");
env_put(t_strconcat("HOME=", home_dir, NULL));
- env_put(t_strconcat("USER=", data + reply->virtual_user_idx, NULL));
+ env_put(t_strconcat("USER=", user, NULL));
addr = net_ip2addr(remote_ip);
env_put(t_strconcat("IP=", addr, NULL));
@@ -446,8 +459,7 @@
if (addr == NULL)
addr = "??";
- i_snprintf(title, sizeof(title), "[%s %s]",
- data + reply->virtual_user_idx, addr);
+ i_snprintf(title, sizeof(title), "[%s %s]", user, addr);
}
/* make sure we don't leak syslog fd, but do it last so that
Index: mail-process.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/master/mail-process.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mail-process.h 9 Jul 2004 19:59:02 -0000 1.6
+++ mail-process.h 13 Oct 2004 16:38:36 -0000 1.7
@@ -9,7 +9,7 @@
int create_mail_process(struct login_group *group, int socket,
const struct ip_addr *local_ip,
const struct ip_addr *remote_ip,
- struct auth_master_reply *reply, const char *data);
+ const char *user, const char *const *args);
void mail_process_destroyed(pid_t pid);
More information about the dovecot-cvs
mailing list