/* * IRC - Internet Relay Chat, ircd/ircd_cloaking.c * Copyright (C) 1999 Thomas Helvey * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file * @brief Implementation of IP and host cloaking functions.. * @version $Id$ */ #include "config.h" #include "ircd_chattr.h" #include "ircd_cloaking.h" #include "ircd_defs.h" #include "ircd_features.h" #include "ircd_md5.h" #include "ircd_snprintf.h" #include "res.h" #include #include #undef KEY1 #undef KEY2 #undef KEY3 #undef PREFIX #define KEY1 feature_str(FEAT_HOST_HIDING_KEY1) #define KEY2 feature_str(FEAT_HOST_HIDING_KEY2) #define KEY3 feature_str(FEAT_HOST_HIDING_KEY3) #define PREFIX feature_str(FEAT_HOST_HIDING_PREFIX) /** Downsamples a 128bit result to 32bits (md5 -> unsigned int) */ static inline unsigned int downsample(unsigned char *i) { unsigned char r[4]; r[0] = i[0] ^ i[1] ^ i[2] ^ i[3]; r[1] = i[4] ^ i[5] ^ i[6] ^ i[7]; r[2] = i[8] ^ i[9] ^ i[10] ^ i[11]; r[3] = i[12] ^ i[13] ^ i[14] ^ i[15]; return ( ((unsigned int)r[0] << 24) + ((unsigned int)r[1] << 16) + ((unsigned int)r[2] << 8) + (unsigned int)r[3]); } /** Downsamples a 128bit result to 24bits (md5 > unsigned int) */ static inline unsigned int downsample24(unsigned char *i) { unsigned char r[4]; r[0] = i[0] ^ i[1] ^ i[2] ^ i[3] ^ i[4]; r[1] = i[5] ^ i[6] ^ i[7] ^ i[8] ^ i[9] ^ i[10]; r[2] = i[11] ^ i[12] ^ i[13] ^ i[14] ^ i[15]; return ( ((unsigned int)r[0] << 16) + ((unsigned int)r[1] << 8) + (unsigned int)r[2]); } char *hidehost_ipv4(struct irc_in_addr *ip) { unsigned int a, b, c, d; static char buf[512], res[512], res2[512], result[128]; unsigned long n; unsigned int alpha, beta, gamma, delta; unsigned char *pch; /* * Output: ALPHA.BETA.GAMMA.DELTA.IP * ALPHA is unique for a.b.c.d * BETA is unique for a.b.c.* * GAMMA is unique for a.b.* * We cloak like this: * ALPHA = downsample24(md5(md5("KEY2:A.B.C.D:KEY3")+"KEY1")); * BETA = downsample24(md5(md5("KEY3:A.B.C:KEY1")+"KEY2")); * GAMMA = downsample24(md5(md5("KEY1:A.B:KEY2")+"KEY3")); * DELTA = downsample24(md5(md5("KEY2:A:KEY1:KEY3")+"KEY1")); */ if (!irc_in_addr_is_ipv4(ip)) return hidehost_ipv6(ip); pch = (unsigned char*)&ip->in6_16[6]; a = *pch++; b = *pch; pch = (unsigned char*)&ip->in6_16[7]; c = *pch++; d = *pch; /* ALPHA... */ ircd_snprintf(0, buf, 512, "%s:%03d.%03d.%03d.%03d:%s", KEY2, a, b, c, d, KEY3); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY1); /* first 16 bytes are filled, append our key.. */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); alpha = downsample24((unsigned char *)&res2); /* BETA... */ ircd_snprintf(0, buf, 512, "%s:%03d.%03d.%03d:%s", KEY3, a, b, c, KEY1); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY2); /* first 16 bytes are filled, append our key.. */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); beta = downsample24((unsigned char *)&res2); /* GAMMA... */ ircd_snprintf(0, buf, 512, "%s:%03d.%03d:%s", KEY1, a, b, KEY2); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY3); /* first 16 bytes are filled, append our key.. */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); gamma = downsample24((unsigned char *)&res2); /* DELTA... */ ircd_snprintf(0, buf, 512, "%s:%03d:%s:%s", KEY2, a, KEY1, KEY3); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY1); /* first 16 bytes are filled, append our key.. */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); delta = downsample24((unsigned char *)&res2); ircd_snprintf(0, result, HOSTLEN, "%X.%X.%X.%X.IP", alpha, beta, gamma, delta); return result; } char *hidehost_ipv6(struct irc_in_addr *ip) { unsigned int a, b, c, d, e, f, g, h; static char buf[512], res[512], res2[512], result[128]; unsigned long n; unsigned int alpha, beta, gamma, delta; /* * Output: ALPHA:BETA:GAMMA:IP * ALPHA is unique for a:b:c:d:e:f:g:h * BETA is unique for a:b:c:d:e:f:g * GAMMA is unique for a:b:c:d * We cloak like this: * ALPHA = downsample24(md5(md5("KEY2:a:b:c:d:e:f:g:h:KEY3")+"KEY1")); * BETA = downsample24(md5(md5("KEY3:a:b:c:d:e:f:g:KEY1")+"KEY2")); * GAMMA = downsample24(md5(md5("KEY1:a:b:c:d:KEY2")+"KEY3")); * DELTA = downsample24(md5(md5("KEY2:a:b:KEY1:KEY3")+"KEY1")); */ if (irc_in_addr_is_ipv4(ip)) return hidehost_ipv4(ip); a = ntohs(ip->in6_16[0]); b = ntohs(ip->in6_16[1]); c = ntohs(ip->in6_16[2]); d = ntohs(ip->in6_16[3]); e = ntohs(ip->in6_16[4]); f = ntohs(ip->in6_16[5]); g = ntohs(ip->in6_16[6]); h = ntohs(ip->in6_16[7]); /* ALPHA... */ ircd_snprintf(0, buf, 512, "%s:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%s", KEY2, a, b, c, d, e, f, g, h, KEY3); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY1); /* first 16 bytes are filled, append our key */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); alpha = downsample24((unsigned char *)&res2); /* BETA... */ ircd_snprintf(0, buf, 512, "%s:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%s", KEY3, a, b, c, d, e, f, g, KEY1); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY2); /* first 16 bytes are filled, append our key.. */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); beta = downsample24((unsigned char *)&res2); /* GAMMA... */ ircd_snprintf(0, buf, 512, "%s:%04x:%04x:%04x:%04x:%s", KEY1, a, b, c, d, KEY2); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY3); /* first 16 bytes are filled, append our key.. */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); gamma = downsample24((unsigned char *)&res2); /* DELTA... */ ircd_snprintf(0, buf, 512, "%s:%04x:%04x:%s:%s", KEY2, a, b, KEY1, KEY3); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY1); /* first 16 bytes are filled, append our key.. */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); delta = downsample24((unsigned char *)&res2); ircd_snprintf(0, result, HOSTLEN, "%X:%X:%X:%X:IP", alpha, beta, gamma, delta); return result; } char *hidehost_normalhost(char *host, int components) { char *p, *c; static char buf[512], res[512], res2[512], result[HOSTLEN+1]; unsigned int alpha, n; int comps = 0; ircd_snprintf(0, buf, 512, "%s:%s:%s", KEY1, host, KEY2); DoMD5((unsigned char *)&res, (unsigned char *)&buf, strlen(buf)); strcpy(res+16, KEY3); /* first 16 bytes are filled, append our key */ n = strlen(res+16) + 16; DoMD5((unsigned char *)&res2, (unsigned char *)&res, n); alpha = downsample((unsigned char *)&res2); for (p = host; *p; p++) { if (*p == '.') { comps++; if ((comps >= components) && IsHostChar(*(p + 1))) break; } } if (*p) { unsigned int len; p++; ircd_snprintf(0, result, HOSTLEN, "%s-%X.", PREFIX, alpha); len = strlen(result) + strlen(p); if (len <= HOSTLEN) strcat(result, p); else { c = p + (len - HOSTLEN); if ((*c == '.') && *(c+1)) c++; strcat(result, c); } } else ircd_snprintf(0, result, HOSTLEN, "%s-%X", PREFIX, alpha); return result; }