summary refs log tree commit diff stats
path: root/INSTALL.w32
blob: 846741a05e3702252803aabdbfa8faf590664f18 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
COMPILING ON WIN32
~~~~~~~~~~~~~~~~~~
It is not easy! Be warned! You need either one of these compilers:

	* Mingw (http://www.mingw.org)
	* MS Visual C

Note: This source code is meant for Linux/Unix like systems. Compiling this for
Windows will produce a below-par quality product. The official XChat for Windows
is not built with this unix source code.


Getting GTK
~~~~~~~~~~~

You also need GTK+ 2.10 for win32. Altough the GTK packages from the GIMP
website are larger and harder to install they work very well.

	1) Get the following packages from: 
	  http://www.gimp.org/~tml/gimp/win32/downloads.html

	  - gtk+-2.4.3.tar.gz
	  - gtk+-dev-2.4.3.tar.gz
	  - dirent.zip
	  - gettext-runtime-0.13.1.zip
	  - gettext-tools-0.13.1.zip
	  - atk-1.6.0.zip
	  - atk-dev-1.6.0.zip
	  - pango-1.4.0.zip
	  - pango-dev-1.4.0.zip
	  - libpng (http://gnuwin32.sourceforge.net/packages/libpng.htm) Binaries & Developer files.
	  - GNU libiconv (Not source files)
	  - glib-2.4.2.zip
	  - glib-dev-2.4.2.zip
	  - pkgconfig-0.15.zip
	  - Zlib121-dll.zip

	2) Extract all files to a suitable place such as c:\devtools

	3) Windows 2000, XP & 2003 users:
	  - Start->(Settings->)Control Panel->System Applet
	  - Advanced Tab->Environment Variables
	  - Under "User variables for <user>" append ";C:\devtools" to the end of the PATH Variable
	  - Click Ok twice and close the Control Panel
	
	  For Windows 9x users your basicly on your own for now.


Mingw
~~~~~

	I havn't tried this yet, but ./configure --disable-xlib would be a start.


MS Visual C
~~~~~~~~~~~

	
	1) Edit src\makeinc.msc

	  You need to change the variables GLIB, GTK and LIBS to point
	  the correct paths for your harddrive. Use the program pkg-config
	  to find this information.

	  a) paste the output of `pkg-config glib-2.0 --msvc-syntax --cflags`
	     to the GLIB = ... line.

	  b) paste the output of `pkg-config gtk+-2.0 --msvc-syntax --cflags`
	     to the GTK = ... line.

	  c) paste the output of `pkg-config gtk+-2.0 --msvc-syntax --libs`
	     to the LIBS = ... line.

	2) In MSVC's includes directory, copy io.h to unistd.h.

	MS VC++ 6
	~~~~~~~~~

		3) Download Platform SDK from http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
		  (you only need Core SDK) - ~200 MB Download (Be warned).
		4) Open the build enviroment.
		 
		  a) If your planning on developing modifications to the xchat code go:
		     Start->Programs->Microsoft Platform SDK...->Open Build Enviroment...->(Choose OS)->... (Debug)

		  b) If your compiling just to use xchat and wish to no recieve debug messages:
		     Start->Programs->Microsoft Platform SDK...->Open Build Enviroment...->(Choose OS)->... (Retail)
		5) Change directory into where you have download the xchat source to and type this:
		  cd src
		  nmake -f makefile.msc clean
		  nmake -f makefile.msc
		6) Copy fe-gtk\xchat.exe to another place.
	MS VC++ 7 (.NET)
	~~~~~~~~~~~~~~~~

		3) Open the Visual Studio .NET Command Prompt
		 
		4) Change directory into where you have download the xchat source to and type this:
		  cd src
		  nmake -f makefile.msc clean
		  nmake -f makefile.msc
		5) Copy fe-gtk\xchat.exe to another place.
	

Common problems:
~~~~~~~~~~~~~~~~

 * gdk-pixbuf-csource must be in PATH.
   FIX: See step 3 for setting up GTK

 * You might need to install dirent.zip manually.
   FIX: Copy C:\devtools\include\dirent.h to C:\devtools\include\glib-2.0\dirent.h

 * Include path to libintl.h should be in GLIB= (makeinc.msc).
   FIX: Copy C:\devtools\include\libintl.h to C:\devtools\include\glib-2.0\libintl.h
9'>389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
/* X-Chat
 * Copyright (C) 1998 Peter Zelezny.
 *
 * 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 * MS Proxy (ISA server) support is (c) 2006 Pavel Fedin <sonic_amiga@rambler.ru>
 * based on Dante source code
 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
 *      Inferno Nettverk A/S, Norway.  All rights reserved.
 */

/*#define DEBUG_MSPROXY*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>

#ifndef WIN32
#include <unistd.h>
#endif

#define WANTSOCKET
#define WANTARPA
#include "inet.h"

#include "hexchat.h"
#include "network.h"
#include "hexchatc.h"
#include "server.h"
#include "msproxy.h"


#ifdef USE_MSPROXY
#include <ntlm.h>

static int
send_msprequest(s, state, request, end)
	int s;
	struct msproxy_state_t *state;
	struct msproxy_request_t *request;
	char *end;
{
	ssize_t w;
	size_t l;

	request->magic25 = htonl(MSPROXY_VERSION);
	request->serverack = state->seq_recv;
	/* don't start incrementing sequence until we are acking packet #2. */
	request->sequence	= (unsigned char)(request->serverack >= 2 ? state->seq_sent + 1 : 0);

	memcpy(request->RWSP, "RWSP", sizeof(request->RWSP));

	l = end - (char *)request;
	/* all requests must be atleast MSPROXY_MINLENGTH it seems. */
	if (l < MSPROXY_MINLENGTH) {
		bzero(end, (size_t)(MSPROXY_MINLENGTH - l));
		l = MSPROXY_MINLENGTH;
	}

	if ((w = send(s, request, l, 0)) != l) {
#ifdef DEBUG_MSPROXY
		printf ("send_msprequest(): send() failed (%d bytes sent instead of %d\n", w, l);
		perror ("Error is");
#endif
		return -1;
	}
	state->seq_sent = request->sequence;

	return w;
}

static int
recv_mspresponse(s, state, response)
	int s;
	struct msproxy_state_t *state;
	struct msproxy_response_t *response;
{
	ssize_t r;

	do {
		if ((r = recv (s, response, sizeof (*response), 0)) < MSPROXY_MINLENGTH) {
#ifdef DEBUG_MSPROXY
			printf ("recv_mspresponse(): expected to read atleast %d, read %d\n", MSPROXY_MINLENGTH, r);
#endif
			return -1;
		}
		if (state->seq_recv == 0)
			break; /* not started incrementing yet. */
#ifdef DEBUG_MSPROXY
		if (response->sequence == state->seq_recv)
			printf ("seq_recv: %d, dup response, seqnumber: 0x%x\n", state->seq_recv, response->sequence);
#endif
	} while (response->sequence == state->seq_recv);

	state->seq_recv = response->sequence;

	return r;
}

int
traverse_msproxy (int sok, char *serverAddr, int port, struct msproxy_state_t *state, netstore *ns_proxy, int csok4, int csok6, int *csok, char bound)
{
	struct msproxy_request_t req;
	struct msproxy_response_t res;
	char *data, *p;
	char hostname[NT_MAXNAMELEN];
	char ntdomain[NT_MAXNAMELEN];
	char challenge[8];
	netstore *ns_client;
	int clientport;
	guint32 destaddr;
	guint32 flags;

	if (!prefs.hex_net_proxy_auth || !prefs.hex_net_proxy_user[0] || !prefs.hex_net_proxy_pass[0] )
		return 1;

	/* MS proxy protocol implementation currently doesn't support IPv6 */
	destaddr = net_getsockaddr_v4 (ns_proxy);
	if (!destaddr)
		return 1;

	state->seq_recv = 0;
	state->seq_sent = 0;

#ifdef DEBUG_MSPROXY
	printf ("Connecting to %s:%d via MS proxy\n", serverAddr, port);
#endif

	gethostname (hostname, NT_MAXNAMELEN);
	p = strchr (hostname, '.');
        if (p)
        	*p = '\0';

	bzero (&req, sizeof(req));
	req.clientid		= htonl(0x0a000000);	/* Initial client ID is always 0x0a		*/
	req.command		= htons(MSPROXY_HELLO);	/* HELLO command					*/
	req.packet.hello.magic5	= htons(0x4b00);	/* Fill in magic values				*/
	req.packet.hello.magic10	= htons(0x1400);
	req.packet.hello.magic15	= htons(0x0400);
	req.packet.hello.magic20	= htons(0x5704);
	req.packet.hello.magic25	= htons(0x0004);
	req.packet.hello.magic30	= htons(0x0100);
	req.packet.hello.magic35	= htons(0x4a02);
	req.packet.hello.magic40	= htons(0x3000);
	req.packet.hello.magic45	= htons(0x4400);
	req.packet.hello.magic50	= htons(0x3900);
	data = req.packet.hello.data;
	strcpy (data, prefs.hex_net_proxy_user);		/* Append a username				*/
	data += strlen (prefs.hex_net_proxy_user)+2;		/* +2 automatically creates second empty string	*/
	strcpy (data, MSPROXY_EXECUTABLE);		/* Append an application name			*/
	data += strlen (MSPROXY_EXECUTABLE)+1;
	strcpy (data, hostname);				/* Append a hostname				*/
	data += strlen (hostname)+1;

	if (send_msprequest(sok, state, &req, data) == -1)
		return 1;

	if (recv_mspresponse(sok, state, &res) == -1)
		return 1;

	if (strcmp(res.RWSP, "RWSP") != 0) {
#ifdef DEBUG_MSPROXY
		printf ("Received mailformed packet (no RWSP signature)\n");
#endif
		return 1;
	}

	if (ntohs(res.command) >> 8 != 0x10) {
#ifdef DEBUG_MSPROXY
		printf ("expected res.command = 10??, is %x", ntohs(res.command));
#endif
		return 1;
	}

	state->clientid	= htonl(rand());
	state->serverid	= res.serverid;

#ifdef DEBUG_MSPROXY
	printf ("clientid: 0x%x, serverid: 0x%0x\n", state->clientid, state->serverid);
	printf ("packet #2\n");
#endif

	/* almost identical. */
	req.clientid	= state->clientid;
	req.serverid	= state->serverid;

	if (send_msprequest(sok, state, &req, data) == -1)
		return 1;

	if (recv_mspresponse(sok, state, &res) == -1)
		return 1;

	if (res.serverid != state->serverid) {
#ifdef DEBUG_MSPROXY
		printf ("expected serverid = 0x%x, is 0x%x\n",state->serverid, res.serverid);
#endif
		return 1;
	}

	if (res.sequence != 0x01) {
#ifdef DEBUG_MSPROXY
		printf ("expected res.sequence = 0x01, is 0x%x\n", res.sequence);
#endif
		return 1;
	}

	if (ntohs(res.command) != MSPROXY_USERINFO_ACK) {
#ifdef DEBUG_MSPROXY
		printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_USERINFO_ACK, ntohs(res.command));
#endif
		return 1;
	}

#ifdef DEBUG_MSPROXY
	printf ("packet #3\n");
#endif

	bzero(&req, sizeof(req));
	req.clientid			= state->clientid;
	req.serverid			= state->serverid;
	req.command			= htons(MSPROXY_AUTHENTICATE);
	memcpy(req.packet.auth.NTLMSSP, "NTLMSSP", sizeof("NTLMSSP"));
	req.packet.auth.bindaddr	= htonl(0x02000000);
	req.packet.auth.msgtype		= htonl(0x01000000);
	/* NTLM flags:	0x80000000 Negotiate LAN Manager key
			0x10000000 Negotiate sign
			0x04000000 Request target
			0x02000000 Negotiate OEM
			0x00800000 Always sign
			0x00020000 Negotiate NTLM
	*/
	req.packet.auth.flags		= htonl(0x06020000);

	if (send_msprequest(sok, state, &req, &req.packet.auth.data) == -1)
		return 1;

	if (recv_mspresponse(sok, state, &res) == -1)
		return 1;

	if (res.serverid != state->serverid) {
#ifdef DEBUG_MSPROXY
		printf ("expected serverid = 0x%x, is 0x%x\n", state->serverid, res.serverid);
#endif
		return 1;
	}

	if (ntohs(res.command) != MSPROXY_AUTHENTICATE_ACK) {
#ifdef DEBUG_MSPROXY
		printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_AUTHENTICATE_ACK, ntohs(res.command));
#endif
		return 1;
	}

	flags = res.packet.auth.flags & htonl(0x00020000);			/* Remember if the server supports NTLM */
	memcpy(challenge, &res.packet.auth.challenge, sizeof(challenge));
	memcpy(ntdomain, &res.packet.auth.NTLMSSP[res.packet.auth.target.offset], res.packet.auth.target.len);
	ntdomain[res.packet.auth.target.len] = 0;

#ifdef DEBUG_MSPROXY
	printf ("ntdomain: \"%s\"\n", ntdomain);
	printf ("packet #4\n");
#endif

	bzero(&req, sizeof(req));
	req.clientid			= state->clientid;
	req.serverid			= state->serverid;
	req.command			= htons(MSPROXY_AUTHENTICATE_2);	/* Authentication response			*/
	req.packet.auth2.magic3		= htons(0x0200);			/* Something					*/
	memcpy(req.packet.auth2.NTLMSSP, "NTLMSSP", sizeof("NTLMSSP"));		/* Start of NTLM message				*/
	req.packet.auth2.msgtype		= htonl(0x03000000);			/* Message type 2				*/
	req.packet.auth2.flags		= flags | htonl(0x02000000);		/* Choose authentication method			*/
	data = req.packet.auth2.data;
	if (flags) {
		req.packet.auth2.lm_resp.len	= 0;				/* We are here if NTLM is supported,		*/
		req.packet.auth2.lm_resp.alloc	= 0;				/* Do not fill in insecure LM response		*/
		req.packet.auth2.lm_resp.offset	= data - req.packet.auth2.NTLMSSP;
		req.packet.auth2.ntlm_resp.len = 24;				/* Fill in NTLM response security buffer	*/
		req.packet.auth2.ntlm_resp.alloc = 24;
		req.packet.auth2.ntlm_resp.offset = data - req.packet.auth2.NTLMSSP;
		ntlm_smb_nt_encrypt(prefs.hex_net_proxy_pass, challenge, data);		/* Append an NTLM response			*/
		data += 24;	
	} else {
		req.packet.auth2.lm_resp.len	= 24;				/* Fill in LM response security buffer		*/
		req.packet.auth2.lm_resp.alloc	= 24;
		req.packet.auth2.lm_resp.offset	= data - req.packet.auth2.NTLMSSP;
		ntlm_smb_encrypt(prefs.hex_net_proxy_pass, challenge, data);		/* Append an LM response			*/
		data += 24;
		req.packet.auth2.ntlm_resp.len = 0;				/* NTLM response is empty			*/
		req.packet.auth2.ntlm_resp.alloc = 0;
		req.packet.auth2.ntlm_resp.offset = data - req.packet.auth2.NTLMSSP;
	}
	req.packet.auth2.ntdomain_buf.len = strlen(ntdomain);			/* Domain name					*/
	req.packet.auth2.ntdomain_buf.alloc = req.packet.auth2.ntdomain_buf.len;
	req.packet.auth2.ntdomain_buf.offset = data - req.packet.auth2.NTLMSSP;
	strcpy(data, ntdomain);
	data += req.packet.auth2.ntdomain_buf.len;
	req.packet.auth2.username_buf.len = strlen(prefs.hex_net_proxy_user);		/* Username					*/
	req.packet.auth2.username_buf.alloc = req.packet.auth2.username_buf.len;
	req.packet.auth2.username_buf.offset = data - req.packet.auth2.NTLMSSP;
	strcpy(data, prefs.hex_net_proxy_user);
	data += req.packet.auth2.username_buf.len;
	req.packet.auth2.clienthost_buf.len = strlen(hostname);			/* Hostname					*/
	req.packet.auth2.clienthost_buf.alloc = req.packet.auth2.clienthost_buf.len;
	req.packet.auth2.clienthost_buf.offset = data - req.packet.auth2.NTLMSSP;
	strcpy(data, hostname);
	data += req.packet.auth2.clienthost_buf.len;
	req.packet.auth2.sessionkey_buf.len = 0;				/* Session key (we don't use it)		*/
	req.packet.auth2.sessionkey_buf.alloc = 0;
	req.packet.auth2.sessionkey_buf.offset = data - req.packet.auth2.NTLMSSP;

	if (send_msprequest(sok, state, &req, data) == -1)
		return 1;

	if (recv_mspresponse(sok, state, &res) == -1)
		return 1;

	if (res.serverid != state->serverid) {
#ifdef DEBUG_MSPROXY
		printf ("expected res.serverid = 0x%x, is 0x%x\n", state->serverid, res.serverid);
#endif
		return 1;
	}

	if (res.clientack != 0x01) {
#ifdef DEBUG_MSPROXY
		printf ("expected res.clientack = 0x01, is 0x%x\n", res.clientack);
#endif
		return 1;
	}

	if (ntohs(res.command) >> 8 != 0x47) {
#ifdef DEBUG_MSPROXY
		printf ("expected res.command = 47??, is 0x%x\n", ntohs(res.command));
#endif
		return 1;
	}

	if (ntohs(res.command) ==  MSPROXY_AUTHENTICATE_2_NAK) {
#ifdef DEBUG_MSPROXY
		printf ("Authentication failed\n");
#endif
		return -1;
	}

#ifdef DEBUG_MSPROXY
	printf ("packet #5\n");
#endif

	bzero(&req, sizeof(req));
	req.clientid			= state->clientid;
	req.serverid			= state->serverid;
	req.command			= htons(MSPROXY_CONNECT);
	req.packet.connect.magic2	= htons(0x0200);
	req.packet.connect.magic6	= htons(0x0200);
	req.packet.connect.destport	= htons(port);
	req.packet.connect.destaddr	= destaddr;
	data = req.packet.connect.executable;
	strcpy(data, MSPROXY_EXECUTABLE);
	data += strlen(MSPROXY_EXECUTABLE) + 1;

	/*
	 * need to tell server what port we will connect from, so we bind our sockets.
	 */
	ns_client = net_store_new ();
	if (!bound) {
		net_store_fill_any (ns_client);
		net_bind(ns_client, csok4, csok6);
#ifdef DEBUG_MSPROXY
		perror ("bind() result");
#endif
	}
 	clientport = net_getsockport(csok4, csok6);
	if (clientport == -1) {
#ifdef DEBUG_MSPROXY
		printf ("Unable to obtain source port\n");
#endif
		return 1;
	}
	req.packet.connect.srcport = clientport;

	if (send_msprequest(sok, state, &req, data) == -1)
		return 1;

	if (recv_mspresponse(sok, state, &res) == -1)
		return 1;

	if (ntohs(res.command) != MSPROXY_CONNECT_ACK) {
#ifdef DEBUG_MSPROXY
		printf ("expected res.command = 0x%x, is 0x%x\n",MSPROXY_CONNECT_ACK, ntohs(res.command));
#endif
		return 1;
	}

	net_store_fill_v4 (ns_client, res.packet.connect.clientaddr, res.packet.connect.clientport);

#ifdef DEBUG_MSPROXY
	printf ("Connecting...\n");
#endif
	if (net_connect (ns_client, csok4, csok6, csok) != 0) {
#ifdef DEBUG_MSPROXY
		printf ("Failed to connect to port %d\n", htons(res.packet.connect.clientport));
#endif
		net_store_destroy (ns_client);
		return 1;
	}
	net_store_destroy (ns_client);
#ifdef DEBUG_MSPROXY
	printf ("packet #6\n");
#endif

	req.clientid	= state->clientid;
	req.serverid	= state->serverid;
	req.command	= htons(MSPROXY_USERINFO_ACK);		

	if (send_msprequest(sok, state, &req, req.packet.connack.data) == -1)
		return 1;

	return 0;
}

void
msproxy_keepalive (void)
{
	server *serv;
	GSList *list = serv_list;
	struct msproxy_request_t req;
	struct msproxy_response_t res;

	while (list)
	{
		serv = list->data;
		if (serv->connected && (serv->proxy_sok != -1))
		{
#ifdef DEBUG_MSPROXY
			printf ("sending MS proxy keepalive packet\n");
#endif

			bzero(&req, sizeof(req));
			req.clientid	= serv->msp_state.clientid;
			req.serverid	= serv->msp_state.serverid;
			req.command	= htons(MSPROXY_HELLO);
			
			if (send_msprequest(serv->proxy_sok, &serv->msp_state, &req, req.packet.hello.data) == -1)
				continue;

			recv_mspresponse(serv->proxy_sok, &serv->msp_state, &res);

#ifdef DEBUG_MSPROXY
			if (ntohs(res.command) != MSPROXY_USERINFO_ACK)
				printf ("expected res.command = 0x%x, is 0x%x\n", MSPROXY_USERINFO_ACK, ntohs(res.command));
#endif
		}
		list = list->next;
	}
}

#endif