CVS: Bahamut-1.8/src hosthash.c, NONE, 1.1 md5.c, NONE, 1.1 Makefile.in, 1.3, 1.4 s_conf.c, 1.3, 1.4 s_user.c, 1.9, 1.10

Mark Rutherford markr at nubian.blitzed.org
Sat Aug 20 21:51:09 UTC 2005


Update of /data/cvs/Bahamut-1.8/src
In directory nubian.blitzed.org:/tmp/cvs-serv57388/src

Modified Files:
	Makefile.in s_conf.c s_user.c 
Added Files:
	hosthash.c md5.c 
Log Message:

- hostmasking/mangling implemented (umode q)

added files:
- md5.c/h: hostmasking requires md5, these are there for cases 
where encryption is disabled.

hosthash.c: where it all takes place.


--- NEW FILE ---
/************************************************************************
 *   IRC - Internet Relay Chat, src/hosthash.c
 *   Copyright (C) 2004-2005 Mark Rutherford, Blitzed IRCD Team.
 *
 *   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 2, 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.
 *
 *
 * This file is part of the Blitzed IRCD, based on Bahamut.
 * portions (c) unreal ircd team
 * portions (c) Mark Rutherford
 * contributor(s):
 * ALACN, Anderson Luiz Alves     alacn at freequest.net
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <ctype.h>
#include <arpa/inet.h>
#include "ircsprintf.h"
#include "struct.h"
#include "common.h"
#include "h.h"

#ifdef USE_SSL
#include <openssl/md5.h>
#else
#include "md5.h"
#endif

static char *hidehost_ipv4(aClient *);
static char *hidehost_normalhost(aClient *);
static inline unsigned int downsample(char *);


/* some of the funtions below are right out of unreal. theirs is more secure.
 * the following functions are from unreals cloak module, slightly modified 
 * I could never come up with something this slick.
 */
/* determine if we have an ip, or a hostmask
 * then cipher it with the appropriate function and
 * return it.
 */
char *hidehost(aClient *cptr) 
{
	char *p;
	
	
	for (p = cptr->user->host; *p; p++)
	if (!isdigit(*p) && !(*p == '.'))
		break;
	if (!(*p))
		return hidehost_ipv4(cptr);
	/* Normal host */
	return hidehost_normalhost(cptr);
}


static char *hidehost_ipv4(aClient *cptr) {
	unsigned int a, b, c, d;
	MD5_CTX hash;
	static char buf[512], res[512], res2[512], result[128];
	unsigned long n;
	unsigned int alpha, beta, gamma;

        /*
         * Output: ALPHA.BETA.GAMMA.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 = downsample(md5(md5("KEY2:A.B.C.D:KEY3")+"KEY1"));
         * BETA  = downsample(md5(md5("KEY3:A.B.C:KEY1")+"KEY2"));
         * GAMMA = downsample(md5(md5("KEY1:A.B:KEY2")+"KEY3"));
         */
        sscanf(cptr->user->host, "%u.%u.%u.%u", &a, &b, &c, &d);

        /* ALPHA... */
        ircsprintf(buf, "%s:%s:%s", mangle.key2, cptr->user->host, mangle.key3);
        MD5_Init(&hash);
        MD5_Update(&hash, buf, strlen(buf));
        MD5_Final(res, &hash);
        strcpy(res+16, mangle.key1); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        MD5_Init(&hash);
        MD5_Update(&hash, res, n);
        MD5_Final(res2, &hash);
        alpha = downsample(res2);

        /* BETA... */
        ircsprintf(buf, "%s:%d.%d.%d:%s", mangle.key3, a, b, c, mangle.key1);
        MD5_Init(&hash);
        MD5_Update(&hash, buf, strlen(buf));
        MD5_Final(res, &hash);
        strcpy(res+16, mangle.key2); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        MD5_Init(&hash);
        MD5_Update(&hash, res, n);
        MD5_Final(res2, &hash);
        beta = downsample(res2);
	
        /* GAMMA... */
        ircsprintf(buf, "%s:%d.%d:%s", mangle.key1, a, b, mangle.key2);
        MD5_Init(&hash);
        MD5_Update(&hash, buf, strlen(buf));
        MD5_Final(res, &hash);
        strcpy(res+16, mangle.key3); /* first 16 bytes are filled, append our key.. */
        n = strlen(res+16) + 16;
        MD5_Init(&hash);
        MD5_Update(&hash, res, n);
        MD5_Final(res2, &hash);
        gamma = downsample(res2);
	ircsprintf(result, "%X.%X.%X.IP", alpha, beta, gamma);
        return result;
}

static inline unsigned int downsample(char *i)
{
	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]);
}

static char *hidehost_normalhost(aClient *cptr) {
	char *p;
	MD5_CTX hash;
	static char buf[512], res[512], res2[512], result[HOSTLEN+1];
	unsigned int alpha, n;
	
	ircsprintf(buf, "%s:%s:%s", mangle.key1, cptr->user->host, mangle.key2);
	MD5_Init(&hash);
	MD5_Update(&hash, buf, strlen(buf));
	MD5_Final(res, &hash);
	strcpy(res+16, mangle.key3); /* first 16 bytes are filled, append our key.. */
	n = strlen(res+16) + 16;
	MD5_Init(&hash);
	MD5_Update(&hash, res, n);
	MD5_Final(res2, &hash);
	alpha = downsample(res2);
	
	for (p = cptr->user->host; *p; p++)
		if (*p == '.')
			if (isalpha(*(p + 1)))
				break;
	
	if (*p)
	{
		unsigned int len;
		p++;
		ircsprintf(result, "%s-%X.", mangle.prefix, alpha);
		len = strlen(result) + strlen(p);
		if (len <= HOSTLEN)
			strcat(result, p);
		else
			strcat(result, p + (len - HOSTLEN));
	} else
		ircsprintf(result,  "%s-%X", mangle.prefix, alpha);
	
	return result;
}

/* m_svskeys 
 * change the hostmangle keys.
 * parv[0] thru [3] = new keys to use
 */

int m_svskeys(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	
	if (!IsULine(sptr))
		return 0;

	if(parc < 4)
		return 0;
	
	MyFree(mangle.key1);
	MyFree(mangle.key1);
	MyFree(mangle.key1);
	
	DupString(mangle.key1, parv[0]);
	DupString(mangle.key1, parv[1]);
	DupString(mangle.key1, parv[2]);
	
	return 0;
}	



--- NEW FILE ---
/*
 * This is an OpenSSL-compatible implementation of the RSA Data Security,
 * Inc. MD5 Message-Digest Algorithm.
 *
 * Written by Solar Designer <solar at openwall.com> in 2001, and placed in
 * the public domain.  There's absolutely no warranty.
 *
 * This differs from Colin Plumb's older public domain implementation in
 * that no 32-bit integer data type is required, there's no compile-time
 * endianness configuration, and the function prototypes match OpenSSL's.
 * The primary goals are portability and ease of use.
 *
 * This implementation is meant to be fast, but not as fast as possible.
 * Some known optimizations are not included to reduce source code size
 * and avoid compile-time configuration.
 */

#if !defined(USE_SSL)

#include <string.h>

#include "md5.h"

/*
 * The basic MD5 functions.
 *
 * F is optimized compared to its RFC 1321 definition just like in Colin
 * Plumb's implementation.
 */
#define F(x, y, z)			((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z)			((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z)			((x) ^ (y) ^ (z))
#define I(x, y, z)			((y) ^ ((x) | ~(z)))

/*
 * The MD5 transformation for all four rounds.
 */
#define STEP(f, a, b, c, d, x, t, s) \
	(a) += f((b), (c), (d)) + (x) + (t); \
	(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
	(a) += (b);

/*
 * SET reads 4 input bytes in little-endian byte order and stores them
 * in a properly aligned word in host byte order.
 *
 * The check for little-endian architectures which tolerate unaligned
 * memory accesses is just an optimization.  Nothing will break if it
 * doesn't work.
 */
#if defined(__i386__) || defined(__vax__)
#define SET(n) \
	(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
	SET(n)
#else
#define SET(n) \
	(ctx->block[(n)] = \
	(MD5_u32plus)ptr[(n) * 4] | \
	((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
	((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
	((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
	(ctx->block[(n)])
#endif

/*
 * This processes one or more 64-byte data blocks, but does NOT update
 * the bit counters.  There're no alignment requirements.
 */
static void *body(MD5_CTX *ctx, void *data, unsigned long size)
{
	unsigned char *ptr;
	MD5_u32plus a, b, c, d;
	MD5_u32plus saved_a, saved_b, saved_c, saved_d;

	ptr = data;

	a = ctx->a;
	b = ctx->b;
	c = ctx->c;
	d = ctx->d;

	do {
		saved_a = a;
		saved_b = b;
		saved_c = c;
		saved_d = d;

/* Round 1 */
		STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
		STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
		STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
		STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
		STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
		STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
		STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
		STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
		STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
		STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
		STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
		STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
		STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
		STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
		STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
		STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)

/* Round 2 */
		STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
		STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
		STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
		STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
		STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
		STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
		STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
		STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
		STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
		STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
		STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
		STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
		STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
		STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
		STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
		STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)

/* Round 3 */
		STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
		STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
		STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
		STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
		STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
		STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
		STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
		STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
		STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
		STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
		STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
		STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
		STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
		STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
		STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
		STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)

/* Round 4 */
		STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
		STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
		STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
		STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
		STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
		STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
		STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
		STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
		STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
		STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
		STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
		STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
		STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
		STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
		STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
		STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)

		a += saved_a;
		b += saved_b;
		c += saved_c;
		d += saved_d;

		ptr += 64;
	} while (size -= 64);

	ctx->a = a;
	ctx->b = b;
	ctx->c = c;
	ctx->d = d;

	return ptr;
}

void MD5_Init(MD5_CTX *ctx)
{
	ctx->a = 0x67452301;
	ctx->b = 0xefcdab89;
	ctx->c = 0x98badcfe;
	ctx->d = 0x10325476;

	ctx->lo = 0;
	ctx->hi = 0;
}

void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
{
	MD5_u32plus saved_lo;
	unsigned long used, free;

	saved_lo = ctx->lo;
	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
		ctx->hi++;
	ctx->hi += size >> 29;

	used = saved_lo & 0x3f;

	if (used) {
		free = 64 - used;

		if (size < free) {
			memcpy(&ctx->buffer[used], data, size);
			return;
		}

		memcpy(&ctx->buffer[used], data, free);
		data = (unsigned char *)data + free;
		size -= free;
		body(ctx, ctx->buffer, 64);
	}

	if (size >= 64) {
		data = body(ctx, data, size & ~(unsigned long)0x3f);
		size &= 0x3f;
	}

	memcpy(ctx->buffer, data, size);
}

void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
	unsigned long used, free;

	used = ctx->lo & 0x3f;

	ctx->buffer[used++] = 0x80;

	free = 64 - used;

	if (free < 8) {
		memset(&ctx->buffer[used], 0, free);
		body(ctx, ctx->buffer, 64);
		used = 0;
		free = 64;
	}

	memset(&ctx->buffer[used], 0, free - 8);

	ctx->lo <<= 3;
	ctx->buffer[56] = ctx->lo;
	ctx->buffer[57] = ctx->lo >> 8;
	ctx->buffer[58] = ctx->lo >> 16;
	ctx->buffer[59] = ctx->lo >> 24;
	ctx->buffer[60] = ctx->hi;
	ctx->buffer[61] = ctx->hi >> 8;
	ctx->buffer[62] = ctx->hi >> 16;
	ctx->buffer[63] = ctx->hi >> 24;

	body(ctx, ctx->buffer, 64);

	result[0] = ctx->a;
	result[1] = ctx->a >> 8;
	result[2] = ctx->a >> 16;
	result[3] = ctx->a >> 24;
	result[4] = ctx->b;
	result[5] = ctx->b >> 8;
	result[6] = ctx->b >> 16;
	result[7] = ctx->b >> 24;
	result[8] = ctx->c;
	result[9] = ctx->c >> 8;
	result[10] = ctx->c >> 16;
	result[11] = ctx->c >> 24;
	result[12] = ctx->d;
	result[13] = ctx->d >> 8;
	result[14] = ctx->d >> 16;
	result[15] = ctx->d >> 24;

	memset(ctx, 0, sizeof(ctx));
}

#endif

Index: Makefile.in
===================================================================
RCS file: /data/cvs/Bahamut-1.8/src/Makefile.in,v
retrieving revision 1.3
retrieving revision 1.4
diff --unified=6 -r1.3 -r1.4
--- Makefile.in	20 Aug 2005 17:26:04 -0000	1.3
+++ Makefile.in	20 Aug 2005 21:51:06 -0000	1.4
@@ -21,13 +21,13 @@
 SOURCES = blalloc.c bsd.c channel.c clientlist.c clones.c confparse.c \
           fdlist.c fds.c hash.c hide.c inet_addr.c ircd.c ircsprintf.c list.c \
           m_nick.c m_rwho.c m_server.c m_services.c m_stats.c m_who.c match.c \
           modules.c packet.c parse.c pcre.c res.c s_auth.c s_bsd.c s_conf.c \
           s_debug.c s_err.c s_misc.c s_numeric.c s_serv.c s_user.c sbuf.c \
           scache.c send.c struct.c support.c throttle.c userban.c whowas.c \
-          zlink.c ssl.c \
+          zlink.c ssl.c hosthash.c md5.c \
           $(ENGINE) $(CRYPTO)
 
 OBJECTS = $(SOURCES:.c=.o) version.o
 
 all:
 	@echo ""
@@ -315,12 +315,15 @@
   ../include/setup.h ../include/defs.h ../include/hash.h \
   ../include/sbuf.h ../include/common.h ../include/sys.h \
   ../include/numeric.h ../include/h.h ../include/send.h \
   ../include/fdlist.h ../include/ircsprintf.h ../include/find.h
 ssl.o: ssl.c ../include/struct.h ../include/common.h \
   ../include/h.h ../include/sys.h
+hosthash.o: hosthash.c  ../include/struct.h ../include/common.h \
+  ../include/h.h ../include/sys.h
+md5.o: md5.c ../include/md5.h
 
 dh.o: dh.c \
  ../include/patchlevel.h
 	$(CC) $(CFLAGS) $(OPENSSLINC) $(INCLUDEDIR) -c $<
 rc4.o: rc4.c \
  ../include/patchlevel.h

Index: s_conf.c
===================================================================
RCS file: /data/cvs/Bahamut-1.8/src/s_conf.c,v
retrieving revision 1.3
retrieving revision 1.4
diff --unified=6 -r1.3 -r1.4
--- s_conf.c	15 Aug 2005 22:12:59 -0000	1.3
+++ s_conf.c	20 Aug 2005 21:51:06 -0000	1.4
@@ -2351,6 +2351,55 @@
            aconn->host, aconn->name));
     return -1;
     }
     /* NOTREACHED */
     return 0;
 }
+
+int confadd_mangle(cVar *vars[], int lnum) {
+    cVar *tmp;
+    int c = 0;
+    
+    for(tmp = vars[c]; tmp; tmp = vars[++c])
+    {
+        if(tmp->type && (tmp->type->flag & MANGLEF_PREFIX))
+        {
+                tmp->type = NULL;
+                DupString(mangle.prefix, tmp->value);
+        }
+        else if(tmp->type && (tmp->type->flag & MANGLEF_KEY1))
+        {
+                tmp->type = NULL;
+                DupString(mangle.key1, tmp->value);
+        }
+        else if(tmp->type && (tmp->type->flag & MANGLEF_KEY2))
+        {
+                tmp->type = NULL;
+                DupString(mangle.key2, tmp->value);
+        }
+        else if(tmp->type && (tmp->type->flag & MANGLEF_KEY3))
+        {
+                tmp->type = NULL;
+                DupString(mangle.key3, tmp->value);
+        }
+    }
+    
+    if(!mangle.prefix) {
+        confparse_error("Lacking prefix in mangle block", lnum);
+        return -1;
+    }
+    if(!mangle.key1) {
+        confparse_error("Lacking key1 in mangle block", lnum);
+        return -1;
+    }
+    if(!mangle.key2) {
+        confparse_error("Lacking key2 in mangle block", lnum);
+        return -1;
+    }
+    if(!mangle.key3) {
+        confparse_error("Lacking key3 in mangle block", lnum);
+        return -1;
+    }
+    return lnum;
+}
+
+

Index: s_user.c
===================================================================
RCS file: /data/cvs/Bahamut-1.8/src/s_user.c,v
retrieving revision 1.9
retrieving revision 1.10
diff --unified=6 -r1.9 -r1.10
--- s_user.c	20 Aug 2005 17:26:04 -0000	1.9
+++ s_user.c	20 Aug 2005 21:51:06 -0000	1.10
@@ -92,12 +92,13 @@
     UMODE_K, 'K',
     UMODE_I, 'I',
 #ifdef USE_SSL
     UMODE_S, 'S',
 #endif
     UMODE_p, 'p',
+    UMODE_q, 'q',
     0, 0
 };
 
 /* externally defined functions */
 extern Link *find_channel_link(Link *, aChannel *);     /* defined in list.c */
 #ifdef FLUD
@@ -1993,12 +1994,19 @@
         member = (user->channel) ? 1 : 0;
                 
         a2cptr = acptr->uplink;
                 
         sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name, parv[0], name,
                    user->username, user->host, acptr->info);
+	/* show the users real host to opers */
+        if(MyConnect(acptr) && HostIsHidden(acptr) && (IsOper(sptr) || (sptr == acptr)))
+        {
+          sendto_one(sptr, rpl_str(RPL_WHOISACTUALLY), me.name, sptr->name, 
+             name, user->username, user->originalhost, 
+            acptr->hostip);
+        }
 #if (RIDICULOUS_PARANOIA_LEVEL>=1)
 #if (RIDICULOUS_PARANOIA_LEVEL==1)
         if(MyConnect(acptr) && user->real_oper_host && 
                 (IsAdmin(sptr) || (IsAnOper(acptr) && sptr == acptr)))
             sendto_one(sptr, rpl_str(RPL_WHOISACTUALLY), me.name, sptr->name, 
                        name, user->real_oper_username, user->real_oper_host, 
@@ -3180,13 +3188,32 @@
     }
     
     if (!(setflags & UMODE_i) && IsInvisible(sptr))
         Count.invisi++;
     if ((setflags & UMODE_i) && !IsInvisible(sptr))
         Count.invisi--;
-    
+    if (!(setflags & UMODE_q) && HostIsHidden(sptr)) 
+    {
+	strcpy(sptr->user->originalhost, sptr->user->host);
+	if (MyClient(sptr))
+	    strcpy(sptr->originalsockhost, sptr->sockhost);
+
+	strcpy(sptr->user->host, (char*) hidehost(sptr));
+	if (MyClient(sptr)) 
+            sendto_one(sptr,":%s NOTICE %s :*** Your hostname/IP has been masked to %s. To regain your old host, type /MODE %s -q",
+                                me.name, sptr->name,  sptr->user->host, sptr->name);
+    }
+    if ((setflags & UMODE_q) && !HostIsHidden(sptr)) 
+    {
+        strcpy(sptr->user->host, sptr->user->originalhost); 
+        if (MyClient(sptr)) 
+        {
+            strcpy(sptr->sockhost, sptr->originalsockhost); 
+            sendto_one(sptr,":%s NOTICE %s :*** Your original hostname/IP has been restored.", me.name, sptr->name);
+        }
+    }
     /*
      * compare new flags with old flags and send string which will cause
      * servers to update correctly.
      */
     if (!IsAnOper(sptr) && !IsServer(cptr))
     {



More information about the ircd-checkins mailing list