Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/contrib/bx12-sasl.diff
1069 views
1
Index: include/ircaux.h
2
===================================================================
3
--- include/ircaux.h (revision 210)
4
+++ include/ircaux.h (working copy)
5
@@ -256,6 +256,8 @@
6
char *tparm (const char *, ...);
7
#endif
8
9
+ int my_base64_encode (const void *, int, char **);
10
+
11
#ifndef HAVE_STRTOUL
12
unsigned long strtoul (const char *, char **, int);
13
#endif
14
Index: include/modval.h
15
===================================================================
16
--- include/modval.h (revision 210)
17
+++ include/modval.h (working copy)
18
@@ -505,11 +505,11 @@
19
#define close_all_server (*(void (*)(void ))global[CLOSE_ALL_SERVER])
20
21
#define read_server_file (*(int (*)(char *))global[READ_SERVER_FILE])
22
-#define add_to_server_list (*(void (*)(char *, int , char *, char *, char *, int , int ))global[ADD_TO_SERVER_LIST])
23
+#define add_to_server_list (*(void (*)(char *, int , char *, char *, char *, char *, char *, int , int ))global[ADD_TO_SERVER_LIST])
24
#define build_server_list (*(int (*)(char *))global[BUILD_SERVER_LIST])
25
#define display_server_list (*(void (*)(void ))global[DISPLAY_SERVER_LIST])
26
#define create_server_list (*(char *(*)(char *))global[CREATE_SERVER_LIST])
27
-#define parse_server_info (*(void (*)(char *, char **, char **, char **, char **))global[PARSE_SERVER_INFO])
28
+#define parse_server_info (*(void (*)(char *, char **, char **, char **, char **, char **, char **))global[PARSE_SERVER_INFO])
29
#define server_list_size (*(int (*)(void ))global[SERVER_LIST_SIZE])
30
31
#define find_server_refnum (*(int (*)(char *, char **))global[FIND_SERVER_REFNUM])
32
Index: include/server.h
33
===================================================================
34
--- include/server.h (revision 210)
35
+++ include/server.h (working copy)
36
@@ -165,6 +165,8 @@
37
int ssl_error;
38
SSL* ssl_fd;
39
#endif
40
+ char *sasl_nick;
41
+ char *sasl_pass;
42
43
/* recv_nick: the nickname of the last person to send you a privmsg */
44
char *recv_nick;
45
@@ -185,7 +187,7 @@
46
int find_server_group (char *, int);
47
char * find_server_group_name (int);
48
49
- void BX_add_to_server_list (char *, int, char *, char *, char *, int, int);
50
+ void BX_add_to_server_list (char *, int, char *, char *, char *, char *, char *, int, int);
51
int BX_build_server_list (char *);
52
int connect_to_server (char *, int, int);
53
void BX_get_connected (int, int);
54
@@ -227,7 +229,7 @@
55
void BX_set_server_operator (int, int);
56
void BX_server_is_connected (int, int);
57
int BX_parse_server_index (char *);
58
- void BX_parse_server_info (char *, char **, char **, char **, char **);
59
+ void BX_parse_server_info (char *, char **, char **, char **, char **, char **, char **);
60
long set_server_bits (fd_set *, fd_set *);
61
void BX_set_server_itsname (int, char *);
62
void BX_set_server_version (int, int);
63
@@ -395,6 +397,10 @@
64
void clean_split_server_list (int, time_t);
65
void write_server_list(char *);
66
void write_server_file (char *);
67
+// void set_server_sasl_nick(int, const char *);
68
+ char *get_server_sasl_nick(int);
69
+// void set_server_sasl_pass(int, const char *);
70
+ char *get_server_sasl_pass(int);
71
72
#define USER_MODE 0x0001
73
#define USER_MODE_A USER_MODE << 0
74
Index: source/numbers.c
75
===================================================================
76
--- source/numbers.c (revision 210)
77
+++ source/numbers.c (working copy)
78
@@ -1407,6 +1407,17 @@
79
}
80
}
81
}
82
+ case 903: /* SASL authentication successful */
83
+ case 904: /* SASL authentication failed */
84
+ case 905: /* SASL message too long */
85
+ case 906: /* SASL authentication aborted */
86
+ case 907: /* You have already completed SASL authentication */
87
+ {
88
+ my_send_to_server(from_server, "CAP END");
89
+ if (do_hook(current_numeric, "%s %s", from, *ArgList))
90
+ display_msg(from, ArgList);
91
+ break;
92
+ }
93
case 305:
94
{
95
if (comm == 305 && get_server_away(from_server))
96
Index: source/compat.c
97
===================================================================
98
--- source/compat.c (revision 210)
99
+++ source/compat.c (working copy)
100
@@ -2401,3 +2401,58 @@
101
return count;
102
}
103
#endif
104
+
105
+/* ----------------------- start of base64 stuff ---------------------------*/
106
+/*
107
+ * Copyright (c) 1995-2001 Kungliga Tekniska H�gskolan
108
+ * (Royal Institute of Technology, Stockholm, Sweden).
109
+ * All rights reserved.
110
+ *
111
+ * This is licensed under the 3-clause BSD license, which is found above.
112
+ */
113
+
114
+static char base64_chars[] =
115
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
116
+
117
+/*
118
+ * Return a malloced, base64 string representation of the first 'size' bytes
119
+ * starting at 'data'. Returns strlen(*str).
120
+ */
121
+int my_base64_encode (const void *data, int size, char **str)
122
+{
123
+ char *s, *p;
124
+ int i;
125
+ unsigned c;
126
+ const unsigned char *q;
127
+
128
+// XXX
129
+// p = s = (char *)new_malloc(size * 4 / 3 + 4);
130
+ p = s = (char *)malloc(size * 4 / 3 + 4);
131
+ if (p == NULL)
132
+ return -1;
133
+ q = (const unsigned char *) data;
134
+ i = 0;
135
+ for (i = 0; i < size;) {
136
+ c = (unsigned)(unsigned char)q[i++];
137
+ c *= 256;
138
+ if (i < size)
139
+ c += (unsigned)(unsigned char)q[i];
140
+ i++;
141
+ c *= 256;
142
+ if (i < size)
143
+ c += (unsigned)(unsigned char)q[i];
144
+ i++;
145
+ p[0] = base64_chars[(c & 0x00fc0000) >> 18];
146
+ p[1] = base64_chars[(c & 0x0003f000) >> 12];
147
+ p[2] = base64_chars[(c & 0x00000fc0) >> 6];
148
+ p[3] = base64_chars[(c & 0x0000003f) >> 0];
149
+ if (i > size)
150
+ p[3] = '=';
151
+ if (i > size + 1)
152
+ p[2] = '=';
153
+ p += 4;
154
+ }
155
+ *p = 0;
156
+ *str = s;
157
+ return strlen(s);
158
+}
159
Index: source/server.c
160
===================================================================
161
--- source/server.c (revision 210)
162
+++ source/server.c (working copy)
163
@@ -700,7 +700,9 @@
164
char *cport = NULL,
165
*password = NULL,
166
*nick = NULL,
167
- *snetwork = NULL;
168
+ *snetwork = NULL,
169
+ *sasl_nick = NULL,
170
+ *sasl_pass = NULL;
171
172
/*
173
* First of all, check for an existing server refnum
174
@@ -708,10 +710,10 @@
175
if ((refnum = parse_server_index(server)) != -1)
176
return refnum;
177
/*
178
- * Next check to see if its a "server:port:password:nick:network"
179
+ * Next check to see if its a "server:port:password:nick:network:saslnick:saslpass"
180
*/
181
else if (index(server, ':') || index(server, ','))
182
- parse_server_info(server, &cport, &password, &nick, &snetwork);
183
+ parse_server_info(server, &cport, &password, &nick, &snetwork, &sasl_nick, &sasl_pass);
184
185
else if (index(server, '['))
186
{
187
@@ -727,7 +729,7 @@
188
}
189
}
190
/*
191
- * Next check to see if its "server port password nick"
192
+ * Next check to see if its "server port password nick network saslnick saslport"
193
*/
194
else if (rest && *rest)
195
{
196
@@ -735,6 +737,8 @@
197
password = next_arg(*rest, rest);
198
nick = next_arg(*rest, rest);
199
snetwork = next_arg(*rest, rest);
200
+ sasl_nick = next_arg(*rest, rest);
201
+ sasl_pass = next_arg(*rest, rest);
202
}
203
204
if (cport && *cport)
205
@@ -744,7 +748,7 @@
206
* Add to the server list (this will update the port
207
* and password fields).
208
*/
209
- add_to_server_list(server, port, password, nick, snetwork, 0, 1);
210
+ add_to_server_list(server, port, password, nick, snetwork, sasl_nick, sasl_pass, 0, 1);
211
return from_server;
212
}
213
214
@@ -756,7 +760,7 @@
215
* passes. If the server is not on the list, it is added to the end. In
216
* either case, the server is made the current server.
217
*/
218
-void BX_add_to_server_list (char *server, int port, char *password, char *nick, char *snetwork, int ssl, int overwrite)
219
+void BX_add_to_server_list (char *server, int port, char *password, char *nick, char *snetwork, char *sasl_nick, char *sasl_pass, int ssl, int overwrite)
220
{
221
extern int default_swatch;
222
if ((from_server = find_in_server_list(server, port)) == -1)
223
@@ -785,6 +789,11 @@
224
else if (!server_list[from_server].d_nickname)
225
malloc_strcpy(&(server_list[from_server].d_nickname), nickname);
226
227
+ if (sasl_nick && *sasl_nick)
228
+ malloc_strcpy(&(server_list[from_server].sasl_nick), sasl_nick);
229
+ if (sasl_pass && *sasl_pass)
230
+ malloc_strcpy(&(server_list[from_server].sasl_pass), sasl_pass);
231
+
232
make_notify_list(from_server);
233
make_watch_list(from_server);
234
set_umode(from_server);
235
@@ -808,6 +817,20 @@
236
else
237
new_free(&(server_list[from_server].d_nickname));
238
}
239
+ if (sasl_nick || !server_list[from_server].sasl_nick)
240
+ {
241
+ if (sasl_nick && *sasl_nick)
242
+ malloc_strcpy(&(server_list[from_server].sasl_nick), sasl_nick);
243
+ else
244
+ new_free(&(server_list[from_server].sasl_nick));
245
+ }
246
+ if (sasl_pass || !server_list[from_server].sasl_pass)
247
+ {
248
+ if (sasl_pass && *sasl_pass)
249
+ malloc_strcpy(&(server_list[from_server].sasl_pass), sasl_pass);
250
+ else
251
+ new_free(&(server_list[from_server].sasl_pass));
252
+ }
253
}
254
if (strlen(server) > strlen(server_list[from_server].name))
255
malloc_strcpy(&(server_list[from_server].name), server);
256
@@ -882,13 +905,13 @@
257
*
258
* With IPv6 patch it also supports comma as a delimiter.
259
*/
260
-void BX_parse_server_info (char *name, char **port, char **password, char **nick, char **snetwork)
261
+void BX_parse_server_info (char *name, char **port, char **password, char **nick, char **snetwork, char **sasl_nick, char **sasl_pass)
262
{
263
char *ptr, delim;
264
265
delim = (index(name, ',')) ? ',' : ':';
266
267
- *port = *password = *nick = NULL;
268
+ *port = *password = *nick = *sasl_nick = *sasl_pass = NULL;
269
if ((ptr = (char *) strchr(name, delim)) != NULL)
270
{
271
*(ptr++) = (char) 0;
272
@@ -920,7 +943,28 @@
273
if (!strlen(ptr))
274
*snetwork = NULL;
275
else
276
+ {
277
*snetwork = ptr;
278
+ if ((ptr = strchr(ptr, delim)) != NULL)
279
+ {
280
+ *(ptr++) = 0;
281
+ if (!strlen(ptr))
282
+ *sasl_nick = NULL;
283
+ else
284
+ {
285
+ *sasl_nick = ptr;
286
+ if ((ptr = strchr(ptr, delim)) != NULL)
287
+ {
288
+ *(ptr++) = 0;
289
+ if (!strlen(ptr))
290
+ *sasl_pass = NULL;
291
+ else
292
+ *sasl_pass = ptr;
293
+ }
294
+
295
+ }
296
+ }
297
+ }
298
}
299
}
300
}
301
@@ -941,8 +985,8 @@
302
* servername:port
303
* servername:port:password
304
* servername::password
305
- * servernetwork
306
- * servername:port:password:nick:servernetwork
307
+ * [servernetwork]
308
+ * servername:port:password:nick:servernetwork:saslnick:saslpass
309
* Note also that this routine mucks around with the server string passed to it,
310
* so make sure this is ok
311
*/
312
@@ -955,7 +999,9 @@
313
*password = NULL,
314
*port = NULL,
315
*nick = NULL,
316
- *snetwork = NULL;
317
+ *snetwork = NULL,
318
+ *sasl_nick = NULL,
319
+ *sasl_pass = NULL;
320
321
int port_num;
322
int i = 0;
323
@@ -995,7 +1041,7 @@
324
snetwork = NULL;
325
continue;
326
}
327
- parse_server_info(host, &port, &password, &nick, &snetwork);
328
+ parse_server_info(host, &port, &password, &nick, &snetwork, &sasl_nick, &sasl_pass);
329
if (port && *port)
330
{
331
if (!(port_num = my_atol(port)))
332
@@ -1004,7 +1050,7 @@
333
else
334
port_num = irc_port;
335
336
- add_to_server_list(host, port_num, password, nick, snetwork ? snetwork : default_network, do_use_ssl, 0);
337
+ add_to_server_list(host, port_num, password, nick, snetwork ? snetwork : default_network, sasl_nick, sasl_pass, do_use_ssl, 0);
338
i++;
339
}
340
servers = rest;
341
@@ -1273,7 +1319,7 @@
342
#endif
343
344
update_all_status(current_window, NULL, 0);
345
- add_to_server_list(server_name, port, NULL, NULL, NULL, 0, 1);
346
+ add_to_server_list(server_name, port, NULL, NULL, NULL, NULL, NULL, 0, 1);
347
348
server_list[from_server].closing = 0;
349
if (port)
350
@@ -1638,7 +1684,7 @@
351
{
352
if (!(server=new_next_arg(args,&args)))
353
{
354
- say("Not enough paramters - supply server name");
355
+ say("Not enough parameters - supply server name");
356
return;
357
}
358
say("Trying to establish ssl connection with server: %s",server);
359
@@ -2283,6 +2329,9 @@
360
int old_from_server = from_server;
361
if (server_list[ssn_index].password)
362
my_send_to_server(ssn_index, "PASS %s", server_list[ssn_index].password);
363
+
364
+ if (server_list[ssn_index].sasl_nick && server_list[ssn_index].sasl_pass)
365
+ my_send_to_server(ssn_index, "CAP REQ :sasl");
366
367
my_send_to_server(ssn_index, "USER %s %s %s :%s", username,
368
(send_umode && *send_umode) ? send_umode :
369
@@ -3794,3 +3843,41 @@
370
}
371
return i;
372
}
373
+
374
+#if 0
375
+void set_server_sasl_nick(int server, const char *nick)
376
+{
377
+ if (server <= -1 || server >= number_of_servers)
378
+ return;
379
+ if (nick)
380
+ malloc_strcpy(&server_list[server].sasl_nick, nick);
381
+ else
382
+ new_free(&server_list[server].sasl_nick);
383
+}
384
+#endif
385
+
386
+char *get_server_sasl_nick(int server)
387
+{
388
+ if (server <= -1 || server >= number_of_servers)
389
+ return NULL;
390
+ return server_list[server].sasl_nick;
391
+}
392
+
393
+#if 0
394
+void set_server_sasl_pass(int server, const char *pass)
395
+{
396
+ if (server <= -1 || server >= number_of_servers)
397
+ return;
398
+ if (pass)
399
+ malloc_strcpy(&server_list[server].sasl_pass, pass);
400
+ else
401
+ new_free(&server_list[server].sasl_pass);
402
+}
403
+#endif
404
+
405
+char *get_server_sasl_pass(int server)
406
+{
407
+ if (server <= -1 || server >= number_of_servers)
408
+ return NULL;
409
+ return server_list[server].sasl_pass;
410
+}
411
Index: source/parse.c
412
===================================================================
413
--- source/parse.c (revision 210)
414
+++ source/parse.c (working copy)
415
@@ -887,6 +887,79 @@
416
say("%s", ArgList[0]);
417
}
418
419
+/*
420
+ * This only handles negotiating the SASL capability with the PLAIN method. It would
421
+ * be good to add DH-BLOWFISH, and later, full capability support.
422
+ */
423
+static void p_cap(char *from, char **ArgList)
424
+{
425
+ char *caps, *p;
426
+
427
+ if (!strcmp(ArgList[1], "ACK"))
428
+ {
429
+ caps = LOCAL_COPY(ArgList[2]);
430
+ while ((p = next_arg(caps, &caps)) != NULL)
431
+ {
432
+ /* Only AUTHENTICATE before registration */
433
+ if (!strcmp(p, "sasl") && !is_server_connected(from_server))
434
+ {
435
+ my_send_to_server(from_server, "AUTHENTICATE PLAIN");
436
+ break;
437
+ }
438
+ }
439
+ }
440
+ else if (!strcmp(ArgList[1], "NAK"))
441
+ {
442
+ caps = LOCAL_COPY(ArgList[2]);
443
+ while ((p = next_arg(caps, &caps)) != NULL)
444
+ {
445
+ /* End capability negotiation to continue registration */
446
+ if (!strcmp(p, "sasl") && !is_server_connected(from_server))
447
+ {
448
+ my_send_to_server(from_server, "CAP END");
449
+ break;
450
+ }
451
+ }
452
+ }
453
+}
454
+
455
+static void p_authenticate(char *from, char **ArgList)
456
+{
457
+ char buf[512];
458
+ char *output = NULL;
459
+ char *nick, *pass;
460
+
461
+ /* "AUTHENTICATE command MUST be used before registration is complete" */
462
+ if (is_server_connected(from_server))
463
+ return;
464
+
465
+ if (!strcmp(ArgList[0], "+"))
466
+ {
467
+ nick = get_server_sasl_nick(from_server);
468
+ pass = get_server_sasl_pass(from_server);
469
+
470
+ /* "The client can abort an authentication by sending an asterisk as the data" */
471
+ if (!nick || !pass)
472
+ {
473
+ my_send_to_server(from_server, "AUTHENTICATE *");
474
+ return;
475
+ }
476
+
477
+ strlcpy(buf, nick, sizeof buf);
478
+ strlcpy(buf + strlen(nick) + 1, nick, sizeof buf);
479
+ strlcpy(buf + strlen(nick) * 2 + 2, pass, sizeof buf);
480
+
481
+ if (my_base64_encode(buf, strlen(nick) * 2 + strlen(pass) + 2, &output) != -1)
482
+ {
483
+ my_send_to_server(from_server, "AUTHENTICATE %s", output);
484
+// XXX new_free(&output);
485
+ free(output);
486
+ }
487
+ else
488
+ my_send_to_server(from_server, "AUTHENTICATE *");
489
+ }
490
+}
491
+
492
void add_user_who (WhoEntry *w, char *from, char **ArgList)
493
{
494
char *userhost;
495
@@ -1758,7 +1831,9 @@
496
497
protocol_command rfc1459[] = {
498
{ "ADMIN", NULL, NULL, 0, 0, 0},
499
+{ "AUTHENTICATE", p_authenticate, NULL, 0, 0, 0},
500
{ "AWAY", NULL, NULL, 0, 0, 0},
501
+{ "CAP", p_cap, NULL, 0, 0, 0},
502
{ "CONNECT", NULL, NULL, 0, 0, 0},
503
{ "ERROR", p_error, NULL, 0, 0, 0},
504
{ "ERROR:", p_error, NULL, 0, 0, 0},
505
506