/*
  decode_mmxp.c

  Meeting Maker.

  Thanks for Matt Power <mhpower@MIT.EDU> for his BUGTRAQ post
  on Meeting Maker encryption, and for providing me with traffic traces.

  The encryption algorithm seems to be much simpler than what Matt
  reversed - see below...
  
  Copyright (c) 2000 Dug Song <dugsong@monkey.org>
  
  $Id: decode_mmxp.c,v 1.5 2000/06/14 06:43:32 dugsong Exp $
*/

#include "config.h"

#include <sys/types.h>
#include <arpa/nameser.h>
#include <stdio.h>
#include <string.h>
#include "decode.h"

#define MM_SECRET	"Thisisastupidwasteoftimeandspace"

#define NEED(len)	{ if (end - p < len) return (0); }

int
decode_mmxp(u_char *buf, int len)
{
	static u_char *mm_xor = MM_SECRET;
	u_char *p, *end;
	u_int32_t i;
	int n, encrypt;

	end = buf + len;

	Buf[0] = '\0';
	
	if ((p = bufbuf(buf, len, "\x00\x00\x24\x55", 4)) == NULL)
		return (0);
	
	p += 4;	NEED(2);
	
	if (memcmp(p, "\x7f\xff", 2) == 0)
		encrypt = 1;
	else if (memcmp(p, "\xff\xff", 2) == 0)
		encrypt = 0;
	else return (0);
	
	p += 4; NEED(4);
	
	GETLONG(i, p);		/* XXX - always 5? */
	p += i;			/* XXX - always 'LPPPg'? */
	p += 4;			/* XXX - voodoo */
	NEED(4);
	
	/* Server name. */
	GETLONG(i, p);
	i = *p++; NEED(i);	/* XXX - strange redundancy? */
	snprintf(Buf, sizeof(Buf), "%.*s\n", (int) i, p);
	p += i; NEED(4);
	
	/* Username. */
	GETLONG(i, p);
	i = *p++; NEED(i);
	snprintf(Buf + strlen(Buf), sizeof(Buf) - strlen(Buf),
		 "%.*s\n", (int) i, p);
	p += i; NEED(4);
	
	/* Password. */
	GETLONG(i, p);
	i = *p++; NEED(i);
	
	if (encrypt) {
		for (n = 0; n < i; n++)
			p[n] ^= mm_xor[n % (sizeof(MM_SECRET) - 1)];
	}
	memmove(p - 1, p, i); p--;
	p[i] = '\0';
	
	snprintf(Buf + strlen(Buf), sizeof(Buf) - strlen(Buf), "%s\n", p);
	
	return (strlen(Buf));
}
	
