[dovecot-cvs] dovecot/src/master auth-process.c, 1.57, 1.58 master-settings.c, 1.55, 1.56 master-settings.h, 1.35, 1.36

cras at procontrol.fi cras at procontrol.fi
Wed Jun 23 20:50:46 EEST 2004


Update of /home/cvs/dovecot/src/master
In directory talvi:/tmp/cvs-serv5259/src/master

Modified Files:
	auth-process.c master-settings.c master-settings.h 
Log Message:
Dovecot can now connect to externally running dovecot-auth.



Index: auth-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/auth-process.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -d -r1.57 -r1.58
--- auth-process.c	23 Jun 2004 14:50:47 -0000	1.57
+++ auth-process.c	23 Jun 2004 17:50:44 -0000	1.58
@@ -45,6 +45,7 @@
 
 	struct hash_table *requests;
 
+	unsigned int external:1;
 	unsigned int initialized:1;
 	unsigned int in_auth_reply:1;
 };
@@ -152,16 +153,21 @@
 	}
 
 	if (!p->initialized) {
+		struct auth_master_handshake_reply rec;
+
 		data = i_stream_get_data(p->input, &size);
-		i_assert(size > 0);
+		if (size < sizeof(rec))
+			return;
 
-		if (data[0] != 'O') {
+		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");
 		}
 
-		i_stream_skip(p->input, 1);
-
+		p->pid = rec.server_pid;
 		p->initialized = TRUE;
 	}
 
@@ -197,7 +203,8 @@
 {
 	struct auth_process *p;
 
-	PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_AUTH);
+	if (pid != 0)
+		PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_AUTH);
 
 	p = i_new(struct auth_process, 1);
 	p->group = group;
@@ -223,7 +230,7 @@
 	void *key, *value;
 	struct auth_process **pos;
 
-	if (!p->initialized && io_loop_is_running(ioloop)) {
+	if (!p->initialized && io_loop_is_running(ioloop) && !p->external) {
 		i_error("Auth process died too early - shutting down");
 		io_loop_stop(ioloop);
 	}
@@ -250,14 +257,54 @@
 	i_free(p);
 }
 
-static pid_t create_auth_process(struct auth_process_group *group)
+static void
+socket_settings_env_put(const char *env_base, struct socket_settings *set)
+{
+	if (env_base == NULL)
+		return;
+
+	env_put(t_strdup_printf("%s_PATH=%s", env_base, set->path));
+	if (set->mode != 0)
+		env_put(t_strdup_printf("%s_MODE=%u", env_base, set->mode));
+	if (set->user != NULL)
+		env_put(t_strdup_printf("%s_USER=%s", env_base, set->user));
+	if (set->group != NULL)
+		env_put(t_strdup_printf("%s_GROUP=%s", env_base, set->group));
+}
+
+static int connect_auth_socket(struct auth_process_group *group,
+			       const char *path)
+{
+	struct auth_process *auth;
+	int fd;
+
+	fd = net_connect_unix(path);
+	if (fd == -1) {
+		i_error("net_connect_unix(%s) failed: %m", path);
+		return -1;
+	}
+
+	net_set_nonblock(fd, TRUE);
+	fd_close_on_exec(fd, TRUE);
+	auth = auth_process_new(0, fd, group);
+	auth->external = TRUE;
+	return 0;
+}
+
+static int create_auth_process(struct auth_process_group *group)
 {
 	static char *argv[] = { NULL, NULL };
-	const char *prefix;
+	struct auth_socket_settings *as;
+	const char *prefix, *str;
 	struct log_io *log;
 	pid_t pid;
 	int fd[2], log_fd, i;
 
+	/* see if this is a connect socket */
+	as = group->set->sockets;
+	if (as != NULL && strcmp(as->type, "connect") == 0)
+		return connect_auth_socket(group, as->master.path);
+
 	/* create communication to process with a socket pair */
 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
 		i_error("socketpair() failed: %m");
@@ -290,7 +337,7 @@
 		auth_process_new(pid, fd[0], group);
 		(void)close(fd[1]);
 		(void)close(log_fd);
-		return pid;
+		return 0;
 	}
 
 	prefix = t_strdup_printf("master-auth(%s): ", group->set->name);
@@ -337,7 +384,16 @@
 	env_put(t_strconcat("USERNAME_CHARS=", group->set->username_chars, NULL));
 	env_put(t_strconcat("ANONYMOUS_USERNAME=",
 			    group->set->anonymous_username, NULL));
-	env_put(t_strconcat("AUTH_SOCKETS=", group->set->extra_sockets));
+
+	for (as = group->set->sockets, i = 1; as != NULL; as = as->next, i++) {
+		if (strcmp(as->type, "listen") != 0)
+			continue;
+
+		str = t_strdup_printf("AUTH_%u", i);
+		socket_settings_env_put(str, &as->client);
+		socket_settings_env_put(t_strconcat(str, "_MASTER", NULL),
+					&as->master);
+	}
 
 	if (group->set->use_cyrus_sasl)
 		env_put("USE_CYRUS_SASL=1");
@@ -390,6 +446,13 @@
 	group = i_new(struct auth_process_group, 1);
 	group->set = auth_set;
 
+	group->next = process_groups;
+	process_groups = group;
+
+	if (auth_set->sockets != NULL &&
+	    strcmp(auth_set->sockets->type, "connect") == 0)
+		return;
+
 	/* create socket for listening auth requests from login */
 	path = t_strconcat(auth_set->parent->defaults->login_dir, "/",
 			   auth_set->name, NULL);
@@ -410,9 +473,6 @@
 			path, dec2str(master_uid),
 			dec2str(auth_set->parent->login_gid));
 	}
-
-	group->next = process_groups;
-	process_groups = group;
 }
 
 static void auth_process_group_destroy(struct auth_process_group *group)

Index: master-settings.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/master-settings.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -d -r1.55 -r1.56
--- master-settings.c	16 Jun 2004 02:04:02 -0000	1.55
+++ master-settings.c	23 Jun 2004 17:50:44 -0000	1.56
@@ -16,7 +16,9 @@
 	SETTINGS_TYPE_ROOT,
 	SETTINGS_TYPE_SERVER,
 	SETTINGS_TYPE_AUTH,
-        SETTINGS_TYPE_NAMESPACE
+	SETTINGS_TYPE_AUTH_SOCKET,
+        SETTINGS_TYPE_NAMESPACE,
+	SETTINGS_TYPE_SOCKET
 };
 
 struct settings_parse_ctx {
@@ -25,6 +27,8 @@
 
 	struct server_settings *root, *server;
 	struct auth_settings *auth;
+	struct socket_settings *socket;
+	struct auth_socket_settings *auth_socket;
         struct namespace_settings *namespace;
 
 	int level;
@@ -142,7 +146,29 @@
 
 	DEF(SET_INT, count),
 	DEF(SET_INT, process_size),
-	DEF(SET_STR, extra_sockets),
+
+	{ 0, NULL, 0 }
+};
+
+#undef DEF
+#define DEF(type, name) \
+	{ type, #name, offsetof(struct socket_settings, name) }
+
+static struct setting_def socket_setting_defs[] = {
+	DEF(SET_STR, path),
+	DEF(SET_INT, mode),
+	DEF(SET_STR, user),
+	DEF(SET_STR, group),
+
+	{ 0, NULL, 0 }
+};
+
+#undef DEF
+#define DEF(type, name) \
+	{ type, #name, offsetof(struct auth_socket_settings, name) }
+
+static struct setting_def auth_socket_setting_defs[] = {
+	DEF(SET_STR, type),
 
 	{ 0, NULL, 0 }
 };
@@ -281,11 +307,11 @@
 
 	MEMBER(count) 1,
 	MEMBER(process_size) 256,
-	MEMBER(extra_sockets) NULL,
 
 	/* .. */
 	MEMBER(uid) 0,
-	MEMBER(gid) 0
+	MEMBER(gid) 0,
+	MEMBER(sockets) NULL
 };
 
 static pool_t settings_pool, settings2_pool;
@@ -406,6 +432,22 @@
 	return TRUE;
 }
 
+static int settings_have_connect_sockets(struct settings *set)
+{
+	struct auth_settings *auth;
+	struct server_settings *server;
+
+	for (server = set->server; server != NULL; server = server->next) {
+		for (auth = server->auths; auth != NULL; auth = auth->next) {
+			if (auth->sockets != NULL &&
+			    strcmp(auth->sockets->type, "connect") == 0)
+				return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
 static int settings_verify(struct settings *set)
 {
 	const char *dir;
@@ -484,10 +526,15 @@
 			  PKG_RUNDIR);
 	}
 
-	/* wipe out contents of login directory, if it exists */
-	if (unlink_directory(set->login_dir, FALSE) < 0) {
-		i_error("unlink_directory() failed for %s: %m", set->login_dir);
-		return FALSE;
+	/* wipe out contents of login directory, if it exists.
+	   except if we're using external authentication - then we would
+	   otherwise wipe existing auth sockets */
+	if (!settings_have_connect_sockets(set)) {
+		if (unlink_directory(set->login_dir, FALSE) < 0) {
+			i_error("unlink_directory() failed for %s: %m",
+				set->login_dir);
+			return FALSE;
+		}
 	}
 
 	if (safe_mkdir(set->login_dir, 0750,
@@ -570,6 +617,44 @@
 	return auth_settings_new(server, name);
 }
 
+static struct auth_socket_settings *
+auth_socket_settings_new(struct auth_settings *auth, const char *type)
+{
+	struct auth_socket_settings *as, **as_p;
+
+	as = p_new(settings_pool, struct auth_socket_settings, 1);
+
+	as->parent = auth;
+	as->type = str_lcase(p_strdup(settings_pool, type));
+
+	as_p = &auth->sockets;
+	while (*as_p != NULL)
+		as_p = &(*as_p)->next;
+	*as_p = as;
+
+	return as;
+}
+
+static struct auth_socket_settings *
+parse_new_auth_socket(struct auth_settings *auth, const char *name,
+		      const char **errormsg)
+{
+	if (strcmp(name, "connect") != 0 && strcmp(name, "listen") != 0) {
+		*errormsg = "Unknown auth socket type";
+		return NULL;
+	}
+
+	if ((auth->sockets != NULL && strcmp(name, "connect") == 0) ||
+	    (auth->sockets != NULL &&
+	     strcmp(auth->sockets->type, "listen") == 0)) {
+		*errormsg = "With connect auth socket no other sockets "
+			"can be used in same auth section";
+		return NULL;
+	}
+
+	return auth_socket_settings_new(auth, name);
+}
+
 static struct namespace_settings *
 namespace_settings_new(struct server_settings *server, const char *type)
 {
@@ -657,10 +742,18 @@
 			key += 5;
 		return parse_setting_from_defs(settings_pool, auth_setting_defs,
 					       ctx->auth, key, value);
+	case SETTINGS_TYPE_AUTH_SOCKET:
+		return parse_setting_from_defs(settings_pool,
+					       auth_socket_setting_defs,
+					       ctx->auth_socket, key, value);
 	case SETTINGS_TYPE_NAMESPACE:
 		return parse_setting_from_defs(settings_pool,
 					       namespace_setting_defs,
 					       ctx->namespace, key, value);
+	case SETTINGS_TYPE_SOCKET:
+		return parse_setting_from_defs(settings_pool,
+					       socket_setting_defs,
+					       ctx->socket, key, value);
 	}
 
 	i_unreached();
@@ -705,12 +798,20 @@
 
 	if (type == NULL) {
 		/* section closing */
-		if (ctx->level > 0) {
-			ctx->level--;
+		if (--ctx->level > 0) {
+			ctx->type = ctx->parent_type;
 			ctx->protocol = MAIL_PROTOCOL_ANY;
+
+			switch (ctx->type) {
+			case SETTINGS_TYPE_AUTH_SOCKET:
+				ctx->parent_type = SETTINGS_TYPE_AUTH;
+				break;
+			default:
+				ctx->parent_type = SETTINGS_TYPE_ROOT;
+				break;
+			}
 		} else {
-			ctx->type = ctx->parent_type;
-			ctx->parent_type = SETTINGS_TYPE_ROOT;
+			ctx->type = SETTINGS_TYPE_ROOT;
 			ctx->server = ctx->root;
 			ctx->auth = &ctx->root->auth_defaults;
 			ctx->namespace = NULL;
@@ -718,15 +819,16 @@
 		return TRUE;
 	}
 
+	ctx->level++;
+	ctx->parent_type = ctx->type;
+
 	if (strcmp(type, "server") == 0) {
 		if (ctx->type != SETTINGS_TYPE_ROOT) {
 			*errormsg = "Server section not allowed here";
 			return FALSE;
 		}
 
-		ctx->parent_type = ctx->type;
 		ctx->type = SETTINGS_TYPE_SERVER;
-
 		ctx->server = create_new_server(name, ctx->server->imap,
 						ctx->server->pop3);
                 server = ctx->root;
@@ -739,7 +841,7 @@
 	if (strcmp(type, "protocol") == 0) {
 		if ((ctx->type != SETTINGS_TYPE_ROOT &&
 		     ctx->type != SETTINGS_TYPE_SERVER) ||
-		    ctx->level != 0) {
+		    ctx->level != 1) {
 			*errormsg = "Protocol section not allowed here";
 			return FALSE;
 		}
@@ -752,7 +854,6 @@
 			*errormsg = "Unknown protocol name";
 			return FALSE;
 		}
-		ctx->level++;
 		return TRUE;
 	}
 
@@ -768,6 +869,28 @@
 		return ctx->auth != NULL;
 	}
 
+	if (ctx->type == SETTINGS_TYPE_AUTH &&
+	    strcmp(type, "socket") == 0) {
+		ctx->type = SETTINGS_TYPE_AUTH_SOCKET;
+		ctx->auth_socket = parse_new_auth_socket(ctx->auth,
+							 name, errormsg);
+		return ctx->auth_socket != NULL;
+	}
+
+	if (ctx->type == SETTINGS_TYPE_AUTH_SOCKET) {
+		ctx->type = SETTINGS_TYPE_SOCKET;
+
+		if (strcmp(type, "master") == 0) {
+			ctx->socket = &ctx->auth_socket->master;
+			return TRUE;
+		}
+
+		if (strcmp(type, "client") == 0) {
+			ctx->socket = &ctx->auth_socket->client;
+			return TRUE;
+		}
+	}
+
 	if (strcmp(type, "namespace") == 0) {
 		if (ctx->type != SETTINGS_TYPE_ROOT &&
 		    ctx->type != SETTINGS_TYPE_SERVER) {

Index: master-settings.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/master-settings.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- master-settings.h	16 Jun 2004 02:04:02 -0000	1.35
+++ master-settings.h	23 Jun 2004 17:50:44 -0000	1.36
@@ -98,6 +98,22 @@
 	int listen_fd, ssl_listen_fd;
 };
 
+struct socket_settings {
+	const char *path;
+	unsigned int mode;
+	const char *user;
+	const char *group;
+};
+
+struct auth_socket_settings {
+	struct auth_settings *parent;
+	struct auth_socket_settings *next;
+
+	const char *type;
+	struct socket_settings master;
+        struct socket_settings client;
+};
+
 struct auth_settings {
 	struct server_settings *parent;
 	struct auth_settings *next;
@@ -119,11 +135,11 @@
 
 	unsigned int count;
 	unsigned int process_size;
-	const char *extra_sockets;
 
 	/* .. */
 	uid_t uid;
 	gid_t gid;
+	struct auth_socket_settings *sockets;
 };
 
 struct namespace_settings {



More information about the dovecot-cvs mailing list