return request->requested_login_user != NULL;
}
-static int is_ip_in_network(const char *network, const struct ip_addr *ip)
-{
- struct ip_addr src_ip, net_ip;
- const char *p;
- unsigned int max_bits, bits;
-
- if (net_ipv6_mapped_ipv4_convert(ip, &src_ip) == 0)
- ip = &src_ip;
-
- 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;
-
- return net_is_in_network(ip, &net_ip, bits);
-}
-
static void auth_request_validate_networks(struct auth_request *request,
const char *networks)
{
const char *const *net;
+ struct ip_addr net_ip;
+ unsigned int bits;
bool found = FALSE;
if (request->remote_ip.family == 0) {
for (net = t_strsplit_spaces(networks, ", "); *net != NULL; net++) {
auth_request_log_debug(request, "auth",
"allow_nets: Matching for network %s", *net);
- switch (is_ip_in_network(*net, &request->remote_ip)) {
- case 1:
- found = TRUE;
- break;
- case -1:
+
+ if (net_parse_range(*net, &net_ip, &bits) < 0) {
auth_request_log_info(request, "passdb",
"allow_nets: Invalid network '%s'", *net);
- break;
- default:
+ }
+
+ if (net_is_in_network(&request->remote_ip, &net_ip, bits)) {
+ found = TRUE;
break;
}
}
#include "fd-set-nonblock.h"
#include "network.h"
+#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
return TRUE;
}
+int net_parse_range(const char *network, struct ip_addr *ip_r,
+ unsigned int *bits_r)
+{
+ const char *p;
+ int bits, max_bits;
+
+ p = strchr(network, '/');
+ if (p != NULL)
+ network = t_strdup_until(network, p++);
+
+ if (net_addr2ip(network, ip_r) < 0)
+ return -1;
+
+ max_bits = IPADDR_IS_V4(ip_r) ? 32 : 128;
+ if (p == NULL) {
+ /* full IP address must match */
+ bits = max_bits;
+ } else {
+ /* get the network mask */
+ bits = atoi(p);
+ if (bits < 0 || bits > max_bits)
+ return -1;
+ }
+ *bits_r = bits;
+ return 0;
+}
+
bool net_is_in_network(const struct ip_addr *ip,
const struct ip_addr *net_ip, unsigned int bits)
{
+ struct ip_addr tmp_ip;
const uint32_t *ip1, *ip2;
uint32_t mask, i1, i2;
unsigned int pos, i;
+ if (net_ipv6_mapped_ipv4_convert(ip, &tmp_ip) == 0) {
+ /* IPv4 address mapped disguised as IPv6 address */
+ ip = &tmp_ip;
+ }
+
if (IPADDR_IS_V4(ip) != IPADDR_IS_V4(net_ip)) {
/* one is IPv6 and one is IPv4 */
return FALSE;
bool is_ipv4_address(const char *addr) ATTR_PURE;
bool is_ipv6_address(const char *addr) ATTR_PURE;
-/* Returns TRUE if ip is in net_ip/bits network. */
+/* Parse network as ip/bits. Returns 0 if successful, -1 if invalid input. */
+int net_parse_range(const char *network, struct ip_addr *ip_r,
+ unsigned int *bits_r);
+/* Returns TRUE if ip is in net_ip/bits network. IPv6 mapped IPv4 addresses
+ are converted to plain IPv4 addresses before matching. */
bool net_is_in_network(const struct ip_addr *ip, const struct ip_addr *net_ip,
unsigned int bits) ATTR_PURE;