aboutsummaryrefslogtreecommitdiffstats
path: root/doc/FAQ
blob: a47e066e604960836459179ccf47cdc9af75f182 (plain)
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
Frequently Asked Questions about BitlBee
========================================

Well, maybe not exactly "Frequently", but definitely "Asked" ... mostly by
the developers :-)

Q: WTH were you guys on when you thought of that _weird_ name?
A: Though we live in The Netherlands and one of us even lives in Amsterdam,
   we're not on drugs ... most of the time.

Q: Okay, so the cops are so evil there, you can't even admit the truth, but
   WTH does BitlBee mean then?
A: There are a few explanations. But the most symbolical goes like: the two
   colors of the bee symbolize the two worlds betwee which the Bee flies. On
   the one hand there's the IM-networks, on the other is IRC.
   
   Truth be told, it's absolute nonsense. The biggest nutcase in the
   development team just played around with words for half an hour or so.
   BitlBee was the result. We liked it, we kept it. We lovingly shorten it
   to "the Bee" or even "het Bijtje" (Dutch for "the little Bee") sometimes.

Q: What is 'root' doing in my control channel? I didn't start the Bee as
   root.
A: 'root' is just the name for the most powerful user in BitlBee. Just like
   in the system, it is root who is the ... eh ... root of the
   functionality. Luckily, in BitlBee, root follows your orders (mostly), so
   no BOFHs there.
   
   We get some complaints from time to time that 'root' is a confusing name.
   Because of that name, some package maintainers have renamed root to, for
   example, BitlBee. We recognize that some people see that need. If the
   package maintainer hasn't renamed root, you can do this yourself with the
   'rename' command.
   
   The name root is not likely to change in the 'official' releases, though.
   We find the metaphor of root correct and feel that there is no important
   (security threatening) reason to change this non-creative piece of
   artistic creativity.

Q: When is $random_feature going to be implemented?
A: It depends on the feature. We keep a list of all wishlist "bugs" in our
   Bug Tracking system at http://bugs.bitlbee.org/

Q: The messages I send and/or receive look weird. I see weird characters and
   annoying HTML codes. Or, BitlBee does evil things when I send messages with
   non-ASCII characters!
A: You probably have to change some settings. To get rid of HTML in messages,
   see "help set strip_html". If you seem to have problems with your charset,
   see "help set charset".
   
   Although actually most of these problems should be gone by now. So if you
   can't get things to work well, you might have found a bug.

Q: Is BitlBee forked from Gaim?
A: BitlBee 0.7 was, sort-of. It contained a lot of code from Gaim 0.58
   (mainly the IM-code), although heavily modified, to make it work better
   with BitlBee. We were planning to keep BitlBee up-to-date with later Gaim
   versions, but this turned out to be very time-consuming because the API
   changed a lot, and we don't have the time to keep up with those changes
   all the time.
   
   These days, we replaced the Yahoo! code with libyahoo2 (which is a
   separate Yahoo! module. It's derived from Gaim, but separately
   maintained) and wrote our own MSN module. More modules are probably going
   to be changed, so in the near future, the API might be the only thing
   left from Gaim.

Q: What's that Gaim doing in BitlBee error messages and my Jabber resource?
A: Ah, well, as you probably know we use some of Gaim's IM-modules, and we
   don't think it's worth our time to do a search-and-replace over the whole
   source to get rid of every reference to Gaim. In fact, we don't want to,
   since we don't want to pretend we wrote all that code.
   
   About Jabber: If you want a different resource string, you can set it
   when logging in by appending it to your Jabber ID, like:
   lintux@jabber.com/BitlBee
e.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
  /********************************************************************\
  * BitlBee -- An IRC to other IM-networks gateway                     *
  *                                                                    *
  * Copyright 2002-2004 Wilmer van der Gaast and others                *
  \********************************************************************/

/* SSL module - SSPI backend */

/* Copyright (C) 2005 Jelmer Vernooij <jelmer@samba.org> */

/*
  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 with
  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
  Suite 330, Boston, MA  02111-1307  USA
*/

#include "ssl_client.h"
#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
#include <sspi.h>
#include <schannel.h>
#include "sock.h"

static gboolean initialized = FALSE;
int ssl_errno;

struct scd
{
	int fd;
	ssl_input_function func;
	gpointer data;
	gboolean established;
  	CredHandle cred;		/* SSL credentials */
	CtxtHandle context;		/* SSL context */
	SecPkgContext_StreamSizes sizes;

	char *host;

	char *pending_raw_data;
	gsize pending_raw_data_len;
	char *pending_data;
	gsize pending_data_len;
};

static void ssl_connected(gpointer, gint, GaimInputCondition);

void sspi_global_init(void)
{
	/* FIXME */
}

void sspi_global_deinit(void)
{
	/* FIXME */
}

void *ssl_connect(char *host, int port, ssl_input_function func, gpointer data)
{
	struct scd *conn = g_new0(struct scd, 1);
		
	conn->fd = proxy_connect(host, port, ssl_connected, conn);
	sock_make_nonblocking(conn->fd);
	conn->func = func;
	conn->data = data;
	conn->host = g_strdup(host);
	
	if (conn->fd < 0)
	{
		g_free(conn);
		return NULL;
	}
	
	if (!initialized)
	{
		sspi_global_init();
		initialized = TRUE;
		atexit(sspi_global_deinit);
	}

	return conn;
}

static void ssl_connected(gpointer _conn, gint fd, GaimInputCondition cond)
{
	struct scd *conn = _conn;
	SCHANNEL_CRED ssl_cred;
	TimeStamp timestamp;
	SecBuffer ibuf[2],obuf[1];
	SecBufferDesc ibufs,obufs;
	ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
    	ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY |
      	ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR |
		ISC_REQ_MANUAL_CRED_VALIDATION;
	ULONG a;
	gsize size = 0;
	gchar *data = NULL;

	memset(&ssl_cred, 0, sizeof(SCHANNEL_CRED));
	ssl_cred.dwVersion = SCHANNEL_CRED_VERSION;
	ssl_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;

	SECURITY_STATUS st = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &ssl_cred, NULL, NULL, &conn->cred, &timestamp);

	if (st != SEC_E_OK) {
		conn->func(conn->data, NULL, cond);
		return;
	}
	
	do {
		/* initialize buffers */
	    ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = data;
	    ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NULL;
	    obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NULL;
    	ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;
	    ibuf[1].BufferType = SECBUFFER_EMPTY;

		/* initialize buffer descriptors */
	    ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
	    ibufs.cBuffers = 2; obufs.cBuffers = 1;
	    ibufs.pBuffers = ibuf; obufs.pBuffers = obuf;

		st = InitializeSecurityContext(&conn->cred, size?&conn->context:NULL, conn->host, req, 0, SECURITY_NETWORK_DREP, size?&ibufs:NULL, 0, &conn->context, &obufs, &a, &timestamp);  
    	if (obuf[0].pvBuffer && obuf[0].cbBuffer) {
			/* FIXME: Check return value */
			send(conn->fd, obuf[0].pvBuffer, obuf[0].cbBuffer, 0);
		}

		switch (st) {
		case SEC_I_INCOMPLETE_CREDENTIALS:
			break;
		case SEC_I_CONTINUE_NEEDED:
			break;
		case SEC_E_INCOMPLETE_MESSAGE:
			break;
		case SEC_E_OK:
			break;
		}
	
		QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->sizes);
	} while (1);

	conn->func(conn->data, conn, cond);
}

int ssl_read(void *conn, char *retdata, int len)
{
	struct scd *scd = conn;
	SecBufferDesc msg;
	SecBuffer buf[4];
	int ret = -1, i;
	char *data = g_malloc(scd->sizes.cbHeader + scd->sizes.cbMaximumMessage + scd->sizes.cbTrailer);

	/* FIXME: Try to read some data */

  	msg.ulVersion = SECBUFFER_VERSION;
	msg.cBuffers = 4;
	msg.pBuffers = buf;
	
	buf[0].BufferType = SECBUFFER_DATA;
	buf[0].cbBuffer = len;
	buf[0].pvBuffer = data;

	buf[1].BufferType = SECBUFFER_EMPTY;
	buf[2].BufferType = SECBUFFER_EMPTY;
	buf[3].BufferType = SECBUFFER_EMPTY;

	SECURITY_STATUS st = DecryptMessage(&scd->context, &msg, 0, NULL);

	if (st != SEC_E_OK) {
		/* FIXME */
		return -1;
	}

	for (i = 0; i < 4; i++) {
		if (buf[i].BufferType == SECBUFFER_DATA) {
			memcpy(retdata, buf[i].pvBuffer, len);
			ret = len;
		}	
	}

	g_free(data);
	return -1;
}

int ssl_write(void *conn, const char *userdata, int len)
{
	struct scd *scd = conn;
	SecBuffer buf[4];
	SecBufferDesc msg;
	char *data;
	int ret;

	msg.ulVersion = SECBUFFER_VERSION;
	msg.cBuffers = 4;
	msg.pBuffers = buf;

	data = g_malloc(scd->sizes.cbHeader + scd->sizes.cbMaximumMessage + scd->sizes.cbTrailer);
	memcpy(data + scd->sizes.cbHeader, userdata, len);

	buf[0].BufferType = SECBUFFER_STREAM_HEADER;
	buf[0].cbBuffer = scd->sizes.cbHeader;
	buf[0].pvBuffer = data;

	buf[1].BufferType = SECBUFFER_DATA;
	buf[1].cbBuffer = len;
	buf[1].pvBuffer = data + scd->sizes.cbHeader;

	buf[2].BufferType = SECBUFFER_STREAM_TRAILER;
	buf[2].cbBuffer = scd->sizes.cbTrailer;
	buf[2].pvBuffer = data + scd->sizes.cbHeader + len;
	buf[3].BufferType = SECBUFFER_EMPTY;

	SECURITY_STATUS st = EncryptMessage(&scd->context, 0, &msg, 0);

	ret = send(scd->fd, data, 
				buf[0].cbBuffer + buf[1].cbBuffer + buf[2].cbBuffer, 0);

	g_free(data);

	return ret;
}

void ssl_disconnect(void *conn)
{
	struct scd *scd = conn;

	SecBufferDesc msg;
	SecBuffer buf;
	DWORD dw;

	dw = SCHANNEL_SHUTDOWN;
	buf.cbBuffer = sizeof(dw);
	buf.BufferType = SECBUFFER_TOKEN;
	buf.pvBuffer = &dw;
	
	msg.ulVersion = SECBUFFER_VERSION;
	msg.cBuffers = 1;
	msg.pBuffers = &buf;

	SECURITY_STATUS st = ApplyControlToken(&scd->context, &msg);

	if (st != SEC_E_OK) {
		/* FIXME */
	}
	
	/* FIXME: call InitializeSecurityContext(Schannel), passing 
	 * in empty buffers*/

	DeleteSecurityContext(&scd->context);

	FreeCredentialsHandle(&scd->cred);

	closesocket(scd->fd);
	g_free(scd->host);
	g_free(scd);
}

int ssl_getfd(void *conn)
{
	return ((struct scd*)conn)->fd;
}

GaimInputCondition ssl_getdirection( void *conn )
{
	return B_EV_IO_WRITE; /* FIXME: or B_EV_IO_READ */
}