aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/bee.c
blob: 3a7dbbadc33c9cccd5206ccdd828d4269de3689f (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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/********************************************************************\
  * BitlBee -- An IRC to other IM-networks gateway                     *
  *                                                                    *
  * Copyright 2002-2010 Wilmer van der Gaast and others                *
  \********************************************************************/

/* Some IM-core stuff                                                   */

/*
  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., 51 Franklin St.,
  Fifth Floor, Boston, MA  02110-1301  USA
*/

#define BITLBEE_CORE
#include "bitlbee.h"

static char *set_eval_away_status(set_t *set, char *value);

bee_t *bee_new()
{
	bee_t *b = g_new0(bee_t, 1);
	set_t *s;

	s = set_add(&b->set, "auto_connect", "true", set_eval_bool, b);
	s = set_add(&b->set, "auto_reconnect", "true", set_eval_bool, b);
	s = set_add(&b->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, b);
	s = set_add(&b->set, "away", NULL, set_eval_away_status, b);
	s->flags |= SET_NULL_OK | SET_HIDDEN;
	s = set_add(&b->set, "debug", "false", set_eval_bool, b);
	s = set_add(&b->set, "mobile_is_away", "false", set_eval_bool, b);
	s = set_add(&b->set, "save_on_quit", "true", set_eval_bool, b);
	s = set_add(&b->set, "status", NULL, set_eval_away_status, b);
	s->flags |= SET_NULL_OK;
	s = set_add(&b->set, "strip_html", "true", NULL, b);

	b->user = g_malloc(1);

	return b;
}

void bee_free(bee_t *b)
{
	while (b->accounts) {
		if (b->accounts->ic) {
			imc_logout(b->accounts->ic, FALSE);
		} else if (b->accounts->reconnect) {
			cancel_auto_reconnect(b->accounts);
		}

		if (b->accounts->ic == NULL) {
			account_del(b, b->accounts);
		} else {
			/* Nasty hack, but account_del() doesn't work in this
			   case and we don't want infinite loops, do we? ;-) */
			b->accounts = b->accounts->next;
		}
	}

	while (b->set) {
		set_del(&b->set, b->set->key);
	}

	bee_group_free(b);

	g_free(b->user);
	g_free(b);
}

static char *set_eval_away_status(set_t *set, char *value)
{
	bee_t *bee = set->data;
	account_t *a;

	g_free(set->value);
	set->value = g_strdup(value);

	for (a = bee->accounts; a; a = a->next) {
		struct im_connection *ic = a->ic;

		if (ic && ic->flags & OPT_LOGGED_IN) {
			imc_away_send_update(ic);
		}
	}

	return value;
}
t">char tmp; /* Unfortunately the st-> stuff doesn't really improve readability here... */ st->i++; st->j += st->S[st->i]; tmp = st->S[st->i]; st->S[st->i] = st->S[st->j]; st->S[st->j] = tmp; tmp = (st->S[st->i] + st->S[st->j]) & 0xff; return st->S[tmp]; } /* The following two functions can be used for reliable encryption and decryption. Known plaintext attacks are prevented by adding some (6, by default) random bytes to the password before setting up the state structures. These 6 bytes are also saved in the results, because of course we'll need them in arc_decode(). Because the length of the resulting string is unknown to the caller, it should pass a char**. Since the encode/decode functions allocate memory for the string, make sure the char** points at a NULL-pointer (or at least to something you already free()d), or you'll leak memory. And of course, don't forget to free() the result when you don't need it anymore. Both functions return the number of bytes in the result string. Note that if you use the pad_to argument, you will need zero-termi- nation to find back the original string length after decryption. So it shouldn't be used if your string contains \0s by itself! */ int arc_encode(char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to) { struct arc_state *st; unsigned char *key; char *padded = NULL; int key_len, i, padded_len; key_len = strlen(password) + ARC_IV_LEN; if (clear_len <= 0) { clear_len = strlen(clear); } /* Pad the string to the closest multiple of pad_to. This makes it impossible to see the exact length of the password. */ if (pad_to > 0 && (clear_len % pad_to) > 0) { padded_len = clear_len + pad_to - (clear_len % pad_to); padded = g_malloc(padded_len); memcpy(padded, clear, clear_len); /* First a \0 and then random data, so we don't have to do anything special when decrypting. */ padded[clear_len] = 0; random_bytes((unsigned char *) padded + clear_len + 1, padded_len - clear_len - 1); clear = padded; clear_len = padded_len; } /* Prepare buffers and the key + IV */ *crypt = g_malloc(clear_len + ARC_IV_LEN); key = g_malloc(key_len); strcpy((char *) key, password); /* Add the salt. Save it for later (when decrypting) and, of course, add it to the encryption key. */ random_bytes(crypt[0], ARC_IV_LEN); memcpy(key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN); /* Generate the initial S[] from the IVed key. */ st = arc_keymaker(key, key_len, ARC_CYCLES); g_free(key); for (i = 0; i < clear_len; i++) { crypt[0][i + ARC_IV_LEN] = clear[i] ^ arc_getbyte(st); } g_free(st); g_free(padded); return clear_len + ARC_IV_LEN; } int arc_decode(unsigned char *crypt, int crypt_len, char **clear, const char *password) { struct arc_state *st; unsigned char *key; int key_len, clear_len, i; key_len = strlen(password) + ARC_IV_LEN; clear_len = crypt_len - ARC_IV_LEN; if (clear_len < 0) { *clear = g_strdup(""); return -1; } /* Prepare buffers and the key + IV */ *clear = g_malloc(clear_len + 1); key = g_malloc(key_len); strcpy((char *) key, password); for (i = 0; i < ARC_IV_LEN; i++) { key[key_len - ARC_IV_LEN + i] = crypt[i]; } /* Generate the initial S[] from the IVed key. */ st = arc_keymaker(key, key_len, ARC_CYCLES); g_free(key); for (i = 0; i < clear_len; i++) { clear[0][i] = crypt[i + ARC_IV_LEN] ^ arc_getbyte(st); } clear[0][i] = 0; /* Nice to have for plaintexts. */ g_free(st); return clear_len; }