bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen#include "lib.h"
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen#include "crc32.h"
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen#include "net.h"
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen#include "imap-keepalive.h"
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen#include <time.h>
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainenstatic bool imap_remote_ip_is_usable(const struct ip_addr *ip)
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen{
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen unsigned int addr;
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen if (ip->family == 0)
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen return FALSE;
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen if (ip->family == AF_INET) {
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen#define IP4(a,b,c,d) ((unsigned)(a)<<24|(unsigned)(b)<<16|(unsigned)(c)<<8|(unsigned)(d))
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen addr = ip->u.ip4.s_addr;
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen if (addr >= IP4(10,0,0,0) && addr <= IP4(10,255,255,255))
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen return FALSE; /* 10/8 */
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen if (addr >= IP4(192,168,0,0) && addr <= IP4(192,168,255,255))
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen return FALSE; /* 192.168/16 */
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen if (addr >= IP4(172,16,0,0) && addr <= IP4(172,31,255,255))
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen return FALSE; /* 172.16/12 */
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen if (addr >= IP4(127,0,0,0) && addr <= IP4(127,255,255,255))
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen return FALSE; /* 127/8 */
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen#undef IP4
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen }
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen else if (ip->family == AF_INET6) {
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen addr = ip->u.ip6.s6_addr[0];
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen if (addr == 0xfc || addr == 0xfd)
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen return FALSE; /* fc00::/7 */
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen }
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen return TRUE;
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen}
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainenunsigned int
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainenimap_keepalive_interval_msecs(const char *username, const struct ip_addr *ip,
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen unsigned int interval_secs)
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen{
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen unsigned int client_hash;
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen
4aeb50a8311a86fd8e5d3bb71d56f2e3094f19dfTimo Sirainen client_hash = ip != NULL && imap_remote_ip_is_usable(ip) ?
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen net_ip_hash(ip) : crc32_str(username);
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen interval_secs -= (time(NULL) + client_hash) % interval_secs;
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen return interval_secs * 1000;
9805f5093a0e0845f028fb8fd52b0eec27d8f7abTimo Sirainen}