Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/dll/arcfour/arcfour.c
1072 views
1
/* ARCFour - a symmetric streaming cipher - Implimentation by Humble
2
*
3
* This is a variable-key-length symmetric stream cipher developed in 1987
4
* by Ron Rivest (the R in RSA). It used to be proprietary but was reverse
5
* engineered and released publicly in September 1994. The cipher is now
6
* freely available but the name RC4 is a trademark of RSA Data Security
7
* Inc. This cipher is secure, proven, easy to impliment, and quite fast.
8
*/
9
#define IN_MODULE
10
#include "irc.h"
11
#include "struct.h"
12
#include "ircaux.h"
13
#include "ctcp.h"
14
#include "status.h"
15
#include "lastlog.h"
16
#include "server.h"
17
#include "screen.h"
18
#include "vars.h"
19
#include "misc.h"
20
#include "output.h"
21
#include "module.h"
22
#include "hash2.h"
23
#include "hook.h"
24
#include "dcc.h"
25
#include <stdlib.h>
26
#include <stdio.h>
27
#include <netinet/in.h>
28
#include <unistd.h>
29
#include "arcfour.h"
30
#include "md5.h"
31
#define INIT_MODULE
32
#include "modval.h"
33
34
typedef struct {
35
int sock;
36
char ukey[16];
37
arckey *outbox;
38
arckey *inbox;
39
} arclist;
40
41
/* from dcc.c. Why isnt this in dcc.h? */
42
43
typedef struct _DCC_List
44
{
45
struct _DCC_List *next;
46
char *nick; /* do NOT free this. it's a shared pointer. */
47
SocketList sock;
48
} DCC_List;
49
50
51
static arclist *keyboxes[16];
52
53
static const double arc_ver = 1.0;
54
static unsigned int typenum = 0;
55
56
/*
57
* Initialize our box, and return the key used. It better be enough to hold
58
* 16 chars + 1 null!
59
*/
60
61
static char *init_box(char *ukey, arckey *key)
62
{
63
MD5_CTX md5context;
64
char buf[256];
65
int fd;
66
67
fd = open("/dev/urandom", O_RDONLY);
68
if (fd >= 0) {
69
read(fd, buf, sizeof(buf));
70
close(fd);
71
}
72
else
73
{
74
buf[(int)buf[69]] ^= getpid();
75
buf[(int)buf[226]] ^= getuid();
76
buf[(int)buf[119]] ^= getpid();
77
}
78
79
MD5Init(&md5context);
80
MD5Update(&md5context, buf, sizeof(buf));
81
MD5Final(&md5context);
82
83
memcpy(ukey, buf, 16);
84
ukey[16] = '\0';
85
86
arcfourInit(key, md5context.digest, 16);
87
return ukey;
88
}
89
90
static inline void arcfourInit(arckey *arc, char *userkey, unsigned short len)
91
{
92
register arcword *S = arc->state, x = 0, y = 0, pos = 0, tmp;
93
94
/* Seed the S-box linearly, then mix in the key while stiring briskly */
95
arc->i = arc->j = 0; /* Initialize i and j to 0 */
96
while((S[x] = --x)); /* Initialize S-box, backwards */
97
98
/* Note: Some of these optimizations REQUIRE arcword to be 8-bit unsigned */
99
do { /* Spread user key into real key */
100
y += S[x] + userkey[pos]; /* Keys, shaken, not stirred */
101
tmp = S[x]; S[x] = S[y]; S[y] = tmp; /* Swap S[i] and S[j] */
102
if (++pos >= len) pos = 0; /* Repeat user key to fill array */
103
} while(++x); /* ++x is faster than x++ */
104
}
105
106
static inline char *arcfourCrypt(arckey *arc, char *data, int len)
107
{
108
register arcword *S = arc->state, i = arc->i, j = arc->j, tmp;
109
register int c = 0;
110
111
do {
112
j += S[++i]; /* Shake S-box, stir well */
113
tmp = S[i]; S[i] = S[j]; S[j] = tmp; /* Swap S[i] and S[j] */
114
data[c] ^= S[(S[i] + S[j])]; /* XOR the crypto into our data */
115
} while (++c < len); /* Neat, ++x is faster then x++ */
116
117
arc->i = i; /* Save modified i and j counters */
118
arc->j = j; /* Continue where we left off */
119
return data; /* Return pointer to ciphertext */
120
}
121
122
int Arcfour_Init(IrcCommandDll **intp, Function_ptr *global_table)
123
{
124
initialize_module("arcfour");
125
memset(keyboxes, 0, sizeof(keyboxes));
126
/*
127
dcc_output_func = send_dcc_encrypt;
128
dcc_input_func = get_dcc_encrypt;
129
dcc_open_func = start_dcc_crypt;
130
dcc_close_func = end_dcc_crypt;
131
*/
132
typenum = add_dcc_bind("SCHAT", "schat", init_schat, start_dcc_crypt, get_dcc_encrypt, send_dcc_encrypt, end_dcc_crypt);
133
add_module_proc(DCC_PROC, "schat", "schat", "Secure DCC Chat", 0, 0, dcc_sdcc, NULL);
134
return 0;
135
}
136
137
int Arcfour_Cleanup(IrcCommandDll **intp)
138
{
139
/* remove_dcc_bind("SCHAT", typenum); */
140
return 1;
141
}
142
143
static arclist *find_box(int sock)
144
{
145
int i, tmp;
146
tmp = sizeof(keyboxes)/sizeof(arclist *);
147
for (i = 0; i < tmp; i++)
148
if (keyboxes[i] && (keyboxes[i]->sock == sock))
149
return keyboxes[i];
150
return (arclist *)NULL;
151
}
152
153
154
static char *dcc_crypt (int sock, char *buf, int len)
155
{
156
arclist *box;
157
if ((box = find_box(sock))) {
158
arcfourCrypt(box->outbox, buf, len-2);
159
return buf;
160
}
161
return NULL;
162
}
163
164
static int send_dcc_encrypt (int type, int sock, char *buf, int len)
165
{
166
if (type == DCC_CHAT) {
167
if (dcc_crypt(sock, buf, len)) {
168
write(sock, buf, len);
169
return 0;
170
}
171
}
172
return -1;
173
}
174
175
static int get_dcc_encrypt (int type, int sock, char *buf, int parm, int len)
176
{
177
if (type == DCC_CHAT) {
178
if ((len = dgets(buf, sock, parm, BIG_BUFFER_SIZE, NULL)) > 0) {
179
buf[len-1] = '\0';
180
dcc_crypt(sock, buf, len);
181
if (buf[len])
182
buf[len] = '\0';
183
}
184
}
185
return len;
186
}
187
188
/* Here we initialize the cryptography. Send the other end our key, and read
189
* in theirs. The socket "s" won't have a crypt box unless it is supposed to
190
* an encrypted connection.
191
*/
192
193
194
static int start_dcc_crypt (int s, int type, unsigned long d_addr, int d_port)
195
{
196
arclist *tmpbox;
197
put_it("start_dcc_crypt");
198
if ((tmpbox = find_box(s))) {
199
int len;
200
char randkey[17];
201
char buf[BIG_BUFFER_SIZE+1];
202
memset(randkey, 0, sizeof(randkey));
203
memset(buf, 0, sizeof(buf));
204
tmpbox->outbox = (arckey *)new_malloc(sizeof(arckey));
205
init_box(randkey, tmpbox->outbox);
206
snprintf(buf, BIG_BUFFER_SIZE, "SecureDCC %s\r\n%n", randkey, &len);
207
write(s, buf, len);
208
memset(buf, 0, sizeof(buf));
209
if ((len = dgets(buf, s, 1, BIG_BUFFER_SIZE, NULL)) > 0) {
210
if (!my_strnicmp("SecureDCC", buf, 9)) {
211
tmpbox->inbox = (arckey *)new_malloc(sizeof(arckey));
212
arcfourInit(tmpbox->inbox, next_arg(buf, &buf), 16);
213
}
214
}
215
return 0;
216
}
217
return -1;
218
}
219
220
static int end_dcc_crypt (int s, unsigned long d_addr, int d_port)
221
{
222
int i;
223
for(i = 0; i < 16; i++) {
224
if (keyboxes[i] && (keyboxes[i]->sock == s)) {
225
new_free(&(keyboxes[i]->inbox));
226
new_free(&(keyboxes[i]->outbox));
227
new_free(&keyboxes[i]);
228
return 0;
229
}
230
}
231
return -1;
232
}
233
234
235
static void start_dcc_chat(int s)
236
{
237
struct sockaddr_in remaddr;
238
int sra;
239
int type;
240
int new_s = -1;
241
char *nick = NULL;
242
unsigned long flags;
243
DCC_int *n = NULL;
244
SocketList *sa;
245
246
sa = get_socket(s);
247
flags = sa->flags;
248
nick = sa->server;
249
sra = sizeof(struct sockaddr_in);
250
new_s = accept(s, (struct sockaddr *) &remaddr, &sra);
251
type = flags & DCC_TYPES;
252
n = get_socketinfo(s);
253
if ((add_socketread(new_s, ntohs(remaddr.sin_port), flags, nick, get_dcc_encrypt, NULL)) < 0)
254
{
255
erase_dcc_info(s, 0, "%s", convert_output_format("$G %RDCC error: accept() failed. punt!!", NULL, NULL));
256
close_socketread(s);
257
return;
258
}
259
flags &= ~DCC_WAIT;
260
flags |= DCC_ACTIVE;
261
set_socketflags(new_s, flags);
262
set_socketinfo(new_s, n);
263
264
/*
265
put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET),
266
"%s %s %s %s %s %d", update_clock(GET_TIME),
267
dcc_types[type],
268
nick, n->userhost?n->userhost:"u@h",
269
inet_ntoa(remaddr.sin_addr),ntohs(remaddr.sin_port)));
270
*/
271
get_time(&n->starttime);
272
close_socketread(s);
273
start_dcc_crypt(new_s, type, n->remote.s_addr, ntohs(remaddr.sin_port));
274
}
275
276
/* set up the dcc hooks */
277
278
void dcc_sdcc (char *name, char *args)
279
{
280
char *p;
281
int tmp, i;
282
DCC_int *new_sdcc;
283
if (!my_stricmp(name, "schat") && (strlen(args) > 0)) {
284
if (*args == ' ')
285
new_next_arg(args, &args);
286
else {
287
p = strchr(args, ' ');
288
if (p && *p)
289
*p = 0;
290
}
291
new_sdcc = dcc_create(args, "SCHAT", NULL, 0, 0, typenum, DCC_TWOCLIENTS, start_dcc_chat);
292
/* find_dcc_pending(new_sdcc->user, new_sdcc->filename, NULL, typenum, 1, -1); */
293
/* new_i = find_dcc_pending(nick, filename, NULL, type, 1, -1); */
294
tmp = sizeof(keyboxes)/sizeof(arclist *);
295
for (i = 0; i < tmp; i++)
296
if (!keyboxes[i])
297
/* keyboxes[i]->sock = new_i->sock */;
298
}
299
}
300
301
/* thanks to the new add_dcc_bind, we dont have to worry about any hooking... */
302
303
static int init_schat(char *type, char *nick, char *userhost, char *description, char *size, char *extra, unsigned long ip, unsigned int port)
304
{
305
/* new_sdcc = dcc_create(args, "SCHAT", NULL, 0, 0, typenum, DCC_TWOCLIENTS, start_dcc_chat); */
306
return 0;
307
}
308
309