[dovecot-cvs] dovecot/src/auth auth-request.c, 1.49, 1.50 auth-request.h, 1.26, 1.27

tss-movial at dovecot.org tss-movial at dovecot.org
Mon Feb 27 20:46:31 EET 2006


Update of /var/lib/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv9044

Modified Files:
	auth-request.c auth-request.h 
Log Message:
Added "allow_nets" extra field. If set, the user can log in only from
within the given networks (hope the code is correct...)



Index: auth-request.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-request.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- auth-request.c	24 Feb 2006 13:41:57 -0000	1.49
+++ auth-request.c	27 Feb 2006 18:46:29 -0000	1.50
@@ -17,6 +17,8 @@
 #include "passdb-cache.h"
 #include "password-scheme.h"
 
+#include <stdlib.h>
+
 struct auth_request *
 auth_request_new(struct auth *auth, struct mech_module *mech,
 		 mech_callback_t *callback, void *context)
@@ -63,6 +65,12 @@
 {
 	i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
 
+	if (request->passdb_failure) {
+		/* password was valid, but some other check failed. */
+		auth_request_fail(request);
+		return;
+	}
+
 	request->state = AUTH_REQUEST_STATE_FINISHED;
 	request->successful = TRUE;
 	request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
@@ -582,6 +590,97 @@
         return request->requested_login_user != NULL;
 }
 
+static int is_ip_in_network(const char *network, const struct ip_addr *ip)
+{
+	const uint32_t *ip1, *ip2;
+	struct ip_addr net_ip;
+	const char *p;
+	unsigned int max_bits, bits, pos, i;
+	uint32_t mask;
+
+	max_bits = IPADDR_IS_V4(ip) ? 32 : 128;
+	p = strchr(network, '/');
+	if (p == NULL) {
+		/* full IP address must match */
+		bits = max_bits;
+	} else {
+		/* get the network mask */
+		network = t_strdup_until(network, p);
+		bits = strtoul(p+1, NULL, 10);
+		if (bits > max_bits)
+			bits = max_bits;
+	}
+
+	if (net_addr2ip(network, &net_ip) < 0)
+		return -1;
+
+	if (IPADDR_IS_V4(ip) && !IPADDR_IS_V4(&net_ip)) {
+		/* one is IPv6 and one is IPv4 */
+		return 0;
+	}
+	i_assert(IPADDR_IS_V6(ip) == IPADDR_IS_V6(&net_ip));
+
+	ip1 = (const uint32_t *)&ip->ip;
+	ip2 = (const uint32_t *)&net_ip.ip;
+
+	/* check first the full 32bit ints */
+	for (pos = 0, i = 0; pos + 32 <= bits; pos += 32, i++) {
+		if (ip1[i] != ip2[i])
+			return 0;
+	}
+
+	/* check the last full bytes */
+	for (mask = 0xff; pos + 8 <= bits; pos += 8, mask <<= 8) {
+		if ((ip1[i] & mask) != (ip2[i] & mask))
+			return 0;
+	}
+
+	/* check the last bits, they're reversed in bytes */
+	bits -= pos;
+	for (mask = 0x80 << (pos % 32); bits > 0; bits--, mask >>= 1) {
+		if ((ip1[i] & mask) != (ip2[i] & mask))
+			return 0;
+	}
+	return 1;
+}
+
+static void auth_request_validate_networks(struct auth_request *request,
+					   const char *networks)
+{
+	const char *const *net;
+	bool found = FALSE;
+
+	if (request->remote_ip.family == 0) {
+		/* IP not known */
+		auth_request_log_info(request, "passdb",
+			"allow_nets check failed: Remote IP not known");
+		request->passdb_failure = TRUE;
+		return;
+	}
+
+	t_push();
+	for (net = t_strsplit_spaces(networks, ", "); *net != NULL; net++) {
+		switch (is_ip_in_network(*net, &request->remote_ip)) {
+		case 1:
+			found = TRUE;
+			break;
+		case -1:
+			auth_request_log_info(request, "passdb",
+				"allow_nets: Invalid network '%s'", *net);
+			break;
+		default:
+			break;
+		}
+	}
+	t_pop();
+
+	if (!found) {
+		auth_request_log_info(request, "passdb",
+			"allow_nets check failed: IP not in allowed networks");
+	}
+	request->passdb_failure = !found;
+}
+
 void auth_request_set_field(struct auth_request *request,
 			    const char *name, const char *value,
 			    const char *default_scheme)
@@ -633,6 +732,11 @@
 		return;
 	}
 
+	if (strcmp(name, "allow_nets") == 0) {
+		auth_request_validate_networks(request, value);
+		return;
+	}
+
 	if (strcmp(name, "nologin") == 0) {
 		/* user can't actually login - don't keep this
 		   reply for master */

Index: auth-request.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-request.h,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- auth-request.h	24 Feb 2006 13:41:57 -0000	1.26
+++ auth-request.h	27 Feb 2006 18:46:29 -0000	1.27
@@ -64,6 +64,7 @@
         struct auth_master_connection *master;
 
 	unsigned int successful:1;
+	unsigned int passdb_failure:1;
 	unsigned int internal_failure:1;
 	unsigned int passdb_internal_failure:1;
 	unsigned int delayed_failure:1;



More information about the dovecot-cvs mailing list