/[cvs]/eggdrop1.8/src/userent.c
ViewVC logotype

Contents of /eggdrop1.8/src/userent.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (show annotations) (download) (as text)
Tue Oct 19 12:13:33 2010 UTC (8 years, 10 months ago) by pseudo
Branch: MAIN
Changes since 1.2: +153 -29 lines
File MIME type: text/x-chdr
Added full SSL support including Tcl commands.
Added support for certificate authentication.
Added support for botnet and partyline encryption using ssl.
Documented the new features and commands.
Fixed add_server() problems with IPv6 addresses in the server list.

1 /*
2 * userent.c -- handles:
3 * user-entry handling, new style more versatile.
4 *
5 * $Id: userent.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
6 */
7 /*
8 * Copyright (C) 1997 Robey Pointer
9 * Copyright (C) 1999 - 2010 Eggheads Development Team
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 #include "main.h"
27 #include "users.h"
28
29
30 extern int noshare;
31 extern struct userrec *userlist;
32 extern struct dcc_t *dcc;
33 extern Tcl_Interp *interp;
34 extern char whois_fields[];
35
36
37 int share_greet = 0; /* Share greeting info */
38 static struct user_entry_type *entry_type_list;
39
40
41 void init_userent()
42 {
43 entry_type_list = 0;
44 add_entry_type(&USERENTRY_COMMENT);
45 add_entry_type(&USERENTRY_XTRA);
46 add_entry_type(&USERENTRY_INFO);
47 add_entry_type(&USERENTRY_LASTON);
48 add_entry_type(&USERENTRY_BOTADDR);
49 add_entry_type(&USERENTRY_PASS);
50 add_entry_type(&USERENTRY_HOSTS);
51 add_entry_type(&USERENTRY_BOTFL);
52 #ifdef TLS
53 add_entry_type(&USERENTRY_FPRINT);
54 #endif
55 }
56
57 void list_type_kill(struct list_type *t)
58 {
59 struct list_type *u;
60
61 while (t) {
62 u = t->next;
63 if (t->extra)
64 nfree(t->extra);
65 nfree(t);
66 t = u;
67 }
68 }
69
70 int list_type_expmem(struct list_type *t)
71 {
72 int tot = 0;
73
74 for (; t; t = t->next)
75 tot += sizeof(struct list_type) + strlen(t->extra) + 1;
76
77 return tot;
78 }
79
80 int def_unpack(struct userrec *u, struct user_entry *e)
81 {
82 char *tmp;
83
84 tmp = e->u.list->extra;
85 e->u.list->extra = NULL;
86 list_type_kill(e->u.list);
87 e->u.string = tmp;
88 return 1;
89 }
90
91 int def_pack(struct userrec *u, struct user_entry *e)
92 {
93 char *tmp;
94
95 tmp = e->u.string;
96 e->u.list = user_malloc(sizeof(struct list_type));
97 e->u.list->next = NULL;
98 e->u.list->extra = tmp;
99 return 1;
100 }
101
102 int def_kill(struct user_entry *e)
103 {
104 nfree(e->u.string);
105 nfree(e);
106 return 1;
107 }
108
109 int def_write_userfile(FILE *f, struct userrec *u, struct user_entry *e)
110 {
111 if (fprintf(f, "--%s %s\n", e->type->name, e->u.string) == EOF)
112 return 0;
113 return 1;
114 }
115
116 void *def_get(struct userrec *u, struct user_entry *e)
117 {
118 return e->u.string;
119 }
120
121 int def_set(struct userrec *u, struct user_entry *e, void *buf)
122 {
123 char *string = (char *) buf;
124
125 if (string && !string[0])
126 string = NULL;
127 if (!string && !e->u.string)
128 return 1;
129 if (string) {
130 int l = strlen(string);
131 char *i;
132
133 if (l > 160)
134 l = 160;
135
136
137 e->u.string = user_realloc(e->u.string, l + 1);
138
139 strncpyz(e->u.string, string, l + 1);
140
141 for (i = e->u.string; *i; i++)
142 /* Allow bold, inverse, underline, color text here...
143 * But never add cr or lf!! --rtc
144 */
145 if ((unsigned int) *i < 32 && !strchr("\002\003\026\037", *i))
146 *i = '?';
147 } else {
148 nfree(e->u.string);
149 e->u.string = NULL;
150 }
151 if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED))) {
152 if (e->type != &USERENTRY_INFO || share_greet)
153 shareout(NULL, "c %s %s %s\n", e->type->name, u->handle,
154 e->u.string ? e->u.string : "");
155 }
156 return 1;
157 }
158
159 int def_gotshare(struct userrec *u, struct user_entry *e, char *data, int idx)
160 {
161 putlog(LOG_CMDS, "*", "%s: change %s %s", dcc[idx].nick, e->type->name,
162 u->handle);
163 return e->type->set(u, e, data);
164 }
165
166 int def_tcl_get(Tcl_Interp * interp, struct userrec *u,
167 struct user_entry *e, int argc, char **argv)
168 {
169 Tcl_AppendResult(interp, e->u.string, NULL);
170 return TCL_OK;
171 }
172
173 int def_tcl_set(Tcl_Interp * irp, struct userrec *u,
174 struct user_entry *e, int argc, char **argv)
175 {
176 BADARGS(4, 4, " handle type setting");
177
178 e->type->set(u, e, argv[3]);
179 return TCL_OK;
180 }
181
182 int def_expmem(struct user_entry *e)
183 {
184 return strlen(e->u.string) + 1;
185 }
186
187 void def_display(int idx, struct user_entry *e)
188 {
189 dprintf(idx, " %s: %s\n", e->type->name, e->u.string);
190 }
191
192 int def_dupuser(struct userrec *new, struct userrec *old, struct user_entry *e)
193 {
194 return set_user(e->type, new, e->u.string);
195 }
196
197 static void comment_display(int idx, struct user_entry *e)
198 {
199 if (dcc[idx].user && (dcc[idx].user->flags & USER_MASTER))
200 dprintf(idx, " COMMENT: %.70s\n", e->u.string);
201 }
202
203 struct user_entry_type USERENTRY_COMMENT = {
204 0, /* always 0 ;) */
205 def_gotshare,
206 def_dupuser,
207 def_unpack,
208 def_pack,
209 def_write_userfile,
210 def_kill,
211 def_get,
212 def_set,
213 def_tcl_get,
214 def_tcl_set,
215 def_expmem,
216 comment_display,
217 "COMMENT"
218 };
219
220 struct user_entry_type USERENTRY_INFO = {
221 0, /* always 0 ;) */
222 def_gotshare,
223 def_dupuser,
224 def_unpack,
225 def_pack,
226 def_write_userfile,
227 def_kill,
228 def_get,
229 def_set,
230 def_tcl_get,
231 def_tcl_set,
232 def_expmem,
233 def_display,
234 "INFO"
235 };
236
237 int pass_set(struct userrec *u, struct user_entry *e, void *buf)
238 {
239 char new[32];
240 register char *pass = buf;
241
242 if (e->u.extra)
243 nfree(e->u.extra);
244 if (!pass || !pass[0] || (pass[0] == '-'))
245 e->u.extra = NULL;
246 else {
247 unsigned char *p = (unsigned char *) pass;
248
249 if (strlen(pass) > 30)
250 pass[30] = 0;
251 while (*p) {
252 if ((*p <= 32) || (*p == 127))
253 *p = '?';
254 p++;
255 }
256 if ((u->flags & USER_BOT) || (pass[0] == '+'))
257 strcpy(new, pass);
258 else
259 encrypt_pass(pass, new);
260 e->u.extra = user_malloc(strlen(new) + 1);
261 strcpy(e->u.extra, new);
262 }
263 if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
264 shareout(NULL, "c PASS %s %s\n", u->handle, pass ? pass : "");
265 return 1;
266 }
267
268 static int pass_tcl_set(Tcl_Interp * irp, struct userrec *u,
269 struct user_entry *e, int argc, char **argv)
270 {
271 BADARGS(3, 4, " handle PASS ?newpass?");
272
273 pass_set(u, e, argc == 3 ? NULL : argv[3]);
274 return TCL_OK;
275 }
276
277 struct user_entry_type USERENTRY_PASS = {
278 0,
279 def_gotshare,
280 0,
281 def_unpack,
282 def_pack,
283 def_write_userfile,
284 def_kill,
285 def_get,
286 pass_set,
287 def_tcl_get,
288 pass_tcl_set,
289 def_expmem,
290 0,
291 "PASS"
292 };
293
294 static int laston_unpack(struct userrec *u, struct user_entry *e)
295 {
296 char *par, *arg;
297 struct laston_info *li;
298
299 par = e->u.list->extra;
300 arg = newsplit(&par);
301 if (!par[0])
302 par = "???";
303 li = user_malloc(sizeof(struct laston_info));
304 li->lastonplace = user_malloc(strlen(par) + 1);
305 li->laston = atoi(arg);
306 strcpy(li->lastonplace, par);
307 list_type_kill(e->u.list);
308 e->u.extra = li;
309 return 1;
310 }
311
312 static int laston_pack(struct userrec *u, struct user_entry *e)
313 {
314 char work[1024];
315 long tv;
316 struct laston_info *li;
317 int l;
318
319 li = (struct laston_info *) e->u.extra;
320 tv = li->laston;
321 l = sprintf(work, "%lu %s", tv, li->lastonplace);
322 e->u.list = user_malloc(sizeof(struct list_type));
323 e->u.list->next = NULL;
324 e->u.list->extra = user_malloc(l + 1);
325 strcpy(e->u.list->extra, work);
326 nfree(li->lastonplace);
327 nfree(li);
328 return 1;
329 }
330
331 static int laston_write_userfile(FILE *f, struct userrec *u,
332 struct user_entry *e)
333 {
334 long tv;
335 struct laston_info *li = (struct laston_info *) e->u.extra;
336
337 tv = li->laston;
338 if (fprintf(f, "--LASTON %lu %s\n", tv,
339 li->lastonplace ? li->lastonplace : "") == EOF)
340 return 0;
341 return 1;
342 }
343
344 static int laston_kill(struct user_entry *e)
345 {
346 if (((struct laston_info *) (e->u.extra))->lastonplace)
347 nfree(((struct laston_info *) (e->u.extra))->lastonplace);
348 nfree(e->u.extra);
349 nfree(e);
350 return 1;
351 }
352
353 static int laston_set(struct userrec *u, struct user_entry *e, void *buf)
354 {
355 struct laston_info *li = (struct laston_info *) e->u.extra;
356
357 if (li != buf) {
358 if (li) {
359 nfree(li->lastonplace);
360 nfree(li);
361 }
362
363 li = e->u.extra = buf;
364 }
365 /* donut share laston info */
366 return 1;
367 }
368
369 static int laston_tcl_get(Tcl_Interp * irp, struct userrec *u,
370 struct user_entry *e, int argc, char **argv)
371 {
372 struct laston_info *li = (struct laston_info *) e->u.extra;
373 char number[20];
374 long tv;
375 struct chanuserrec *cr;
376
377 BADARGS(3, 4, " handle LASTON ?channel?");
378
379 if (argc == 4) {
380 for (cr = u->chanrec; cr; cr = cr->next)
381 if (!rfc_casecmp(cr->channel, argv[3])) {
382 Tcl_AppendResult(irp, int_to_base10(cr->laston), NULL);
383 break;
384 }
385 if (!cr)
386 Tcl_AppendResult(irp, "0", NULL);
387 } else {
388 tv = li->laston;
389 sprintf(number, "%lu ", tv);
390 Tcl_AppendResult(irp, number, li->lastonplace, NULL);
391 }
392 return TCL_OK;
393 }
394
395 static int laston_tcl_set(Tcl_Interp * irp, struct userrec *u,
396 struct user_entry *e, int argc, char **argv)
397 {
398 struct laston_info *li;
399 struct chanuserrec *cr;
400
401 BADARGS(4, 5, " handle LASTON time ?place?");
402
403 if ((argc == 5) && argv[4][0] && strchr(CHANMETA, argv[4][0])) {
404 /* Search for matching channel */
405 for (cr = u->chanrec; cr; cr = cr->next)
406 if (!rfc_casecmp(cr->channel, argv[4])) {
407 cr->laston = atoi(argv[3]);
408 break;
409 }
410 }
411 /* Save globally */
412 li = user_malloc(sizeof(struct laston_info));
413
414 if (argc == 5) {
415 li->lastonplace = user_malloc(strlen(argv[4]) + 1);
416 strcpy(li->lastonplace, argv[4]);
417 } else {
418 li->lastonplace = user_malloc(1);
419 li->lastonplace[0] = 0;
420 }
421 li->laston = atoi(argv[3]);
422 set_user(&USERENTRY_LASTON, u, li);
423 return TCL_OK;
424 }
425
426 static int laston_expmem(struct user_entry *e)
427 {
428 return sizeof(struct laston_info) +
429 strlen(((struct laston_info *) (e->u.extra))->lastonplace) + 1;
430 }
431
432 static int laston_dupuser(struct userrec *new, struct userrec *old,
433 struct user_entry *e)
434 {
435 struct laston_info *li = e->u.extra, *li2;
436
437 if (li) {
438 li2 = user_malloc(sizeof(struct laston_info));
439
440 li2->laston = li->laston;
441 li2->lastonplace = user_malloc(strlen(li->lastonplace) + 1);
442 strcpy(li2->lastonplace, li->lastonplace);
443 return set_user(&USERENTRY_LASTON, new, li2);
444 }
445 return 0;
446 }
447
448 struct user_entry_type USERENTRY_LASTON = {
449 0, /* always 0 ;) */
450 0,
451 laston_dupuser,
452 laston_unpack,
453 laston_pack,
454 laston_write_userfile,
455 laston_kill,
456 def_get,
457 laston_set,
458 laston_tcl_get,
459 laston_tcl_set,
460 laston_expmem,
461 0,
462 "LASTON"
463 };
464
465 static int botaddr_unpack(struct userrec *u, struct user_entry *e)
466 {
467 char *p, *q;
468 struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
469
470 egg_bzero(bi, sizeof(struct bot_addr));
471
472 if (!(q = strchr((p = e->u.list->extra), ':'))) {
473 bi->address = user_malloc(strlen(p) + 1);
474 strcpy(bi->address, p);
475 } else {
476 bi->address = user_malloc((q - p) + 1);
477 strncpy(bi->address, p, q - p);
478 bi->address[q - p] = 0;
479 q++;
480 #ifdef TLS
481 if (*q == '+')
482 bi->ssl = 1;
483 #endif
484 bi->telnet_port = atoi(q);
485 if ((q = strchr(q, '/')))
486 #ifdef TLS
487 {
488 if (q[1] == '+')
489 bi->ssl = 1;
490 bi->relay_port = atoi(q + 1);
491 }
492 #else
493 bi->relay_port = atoi(q + 1);
494 #endif
495 }
496 #ifdef IPV6
497 for (p = bi->address; *p; p++)
498 if (*p == ';')
499 *p = ':';
500 #endif
501 if (!bi->telnet_port)
502 bi->telnet_port = 3333;
503 if (!bi->relay_port)
504 bi->relay_port = bi->telnet_port;
505 list_type_kill(e->u.list);
506 e->u.extra = bi;
507 return 1;
508 }
509
510 static int botaddr_pack(struct userrec *u, struct user_entry *e)
511 {
512 char work[1024], *p, *q = work;
513 struct bot_addr *bi;
514 int l;
515
516 bi = (struct bot_addr *) e->u.extra;
517 for (p = bi->address; *p; p++)
518 if (*p == ':')
519 *q++ = ';';
520 else
521 *q++ = *p;
522 #ifdef TLS
523 if (bi->ssl)
524 l = simple_sprintf(q, ":+%u/+%u", bi->telnet_port, bi->relay_port);
525 else
526 #endif
527 l = simple_sprintf(q, ":%u/%u", bi->telnet_port, bi->relay_port);
528 e->u.list = user_malloc(sizeof(struct list_type));
529 e->u.list->next = NULL;
530 e->u.list->extra = user_malloc(l + 1);
531 strcpy(e->u.list->extra, work);
532 nfree(bi->address);
533 nfree(bi);
534 return 1;
535 }
536
537 static int botaddr_kill(struct user_entry *e)
538 {
539 nfree(((struct bot_addr *) (e->u.extra))->address);
540 nfree(e->u.extra);
541 nfree(e);
542 return 1;
543 }
544
545 static int botaddr_write_userfile(FILE *f, struct userrec *u,
546 struct user_entry *e)
547 {
548 int ret = 1;
549 char *p, *q, *addr;
550 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
551
552 p = bi->address;
553 addr = user_malloc(strlen(bi->address) + 1);
554 for (q = addr; *p; p++)
555 if (*p == ':')
556 *q++ = ';';
557 else
558 *q++ = *p;
559 *q = 0;
560 #ifdef TLS
561 if (bi->ssl) {
562 if (fprintf(f, "--%s %s:+%u/+%u\n", e->type->name, addr,
563 bi->telnet_port, bi->relay_port) == EOF)
564 ret = 0;
565 } else
566 #endif
567 if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, addr,
568 bi->telnet_port, bi->relay_port) == EOF)
569 ret = 0;
570 nfree(addr);
571 return ret;
572 }
573
574 static int botaddr_set(struct userrec *u, struct user_entry *e, void *buf)
575 {
576 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
577
578 if (!bi && !buf)
579 return 1;
580 if (bi != buf) {
581 if (bi) {
582 nfree(bi->address);
583 nfree(bi);
584 }
585 bi = e->u.extra = buf;
586 }
587 if (bi && !noshare && !(u->flags & USER_UNSHARED)) {
588 #ifdef TLS
589 if (bi->ssl)
590 shareout(NULL, "c BOTADDR %s %s +%d +%d\n", u->handle,
591 bi->address, bi->telnet_port, bi->relay_port);
592 else
593 #endif
594 shareout(NULL, "c BOTADDR %s %s %d %d\n", u->handle,
595 bi->address, bi->telnet_port, bi->relay_port);
596 }
597 return 1;
598 }
599
600 static int botaddr_tcl_get(Tcl_Interp * interp, struct userrec *u,
601 struct user_entry *e, int argc, char **argv)
602 {
603 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
604 char number[20];
605
606 #ifdef TLS
607 if (bi->ssl)
608 sprintf(number, " +%d", bi->telnet_port);
609 else
610 #endif
611 sprintf(number, " %d", bi->telnet_port);
612 Tcl_AppendResult(interp, bi->address, number, NULL);
613 #ifdef TLS
614 if (bi->ssl)
615 sprintf(number, " +%d", bi->relay_port);
616 else
617 #endif
618 sprintf(number, " %d", bi->relay_port);
619 Tcl_AppendResult(interp, number, NULL);
620 return TCL_OK;
621 }
622
623 static int botaddr_tcl_set(Tcl_Interp * irp, struct userrec *u,
624 struct user_entry *e, int argc, char **argv)
625 {
626 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
627
628 BADARGS(4, 6, " handle type address ?telnetport ?relayport??");
629
630 if (u->flags & USER_BOT) {
631 /* Silently ignore for users */
632 if (!bi) {
633 bi = user_malloc(sizeof(struct bot_addr));
634 egg_bzero(bi, sizeof(struct bot_addr));
635 } else
636 nfree(bi->address);
637 bi->address = user_malloc(strlen(argv[3]) + 1);
638 strcpy(bi->address, argv[3]);
639 if (argc > 4)
640 #ifdef TLS
641 {
642 if (*argv[4] == '+')
643 bi->ssl = 1;
644 bi->telnet_port = atoi(argv[4]);
645 }
646 #else
647 bi->telnet_port = atoi(argv[4]);
648 #endif
649 if (argc > 5)
650 #ifdef TLS
651 {
652 if (*argv[5] == '+')
653 bi->ssl = 1;
654 bi->relay_port = atoi(argv[5]);
655 }
656 #else
657 bi->relay_port = atoi(argv[5]);
658 #endif
659 if (!bi->telnet_port)
660 bi->telnet_port = 3333;
661 if (!bi->relay_port)
662 bi->relay_port = bi->telnet_port;
663 botaddr_set(u, e, bi);
664 }
665 return TCL_OK;
666 }
667
668 static int botaddr_expmem(struct user_entry *e)
669 {
670 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
671
672 return strlen(bi->address) + 1 + sizeof(struct bot_addr);
673 }
674
675 static void botaddr_display(int idx, struct user_entry *e)
676 {
677 register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
678
679 dprintf(idx, " ADDRESS: %.70s\n", bi->address);
680 #ifdef TLS
681 if (bi->ssl)
682 dprintf(idx, " users: +%d, bots: +%d\n", bi->relay_port,
683 bi->telnet_port);
684 else
685 #endif
686 dprintf(idx, " users: %d, bots: %d\n", bi->relay_port, bi->telnet_port);
687 }
688
689 static int botaddr_gotshare(struct userrec *u, struct user_entry *e,
690 char *buf, int idx)
691 {
692 struct bot_addr *bi = user_malloc(sizeof(struct bot_addr));
693 char *arg;
694
695 egg_bzero(bi, sizeof(struct bot_addr));
696 arg = newsplit(&buf);
697 bi->address = user_malloc(strlen(arg) + 1);
698 strcpy(bi->address, arg);
699 arg = newsplit(&buf);
700 #ifdef TLS
701 if (*arg == '+' || *buf == '+')
702 bi->ssl = 1;
703 #endif
704 bi->telnet_port = atoi(arg);
705 bi->relay_port = atoi(buf);
706 if (!bi->telnet_port)
707 bi->telnet_port = 3333;
708 if (!bi->relay_port)
709 bi->relay_port = bi->telnet_port;
710 if (!(dcc[idx].status & STAT_GETTING))
711 putlog(LOG_CMDS, "*", "%s: change botaddr %s", dcc[idx].nick, u->handle);
712 return botaddr_set(u, e, bi);
713 }
714
715 static int botaddr_dupuser(struct userrec *new, struct userrec *old,
716 struct user_entry *e)
717 {
718 if (old->flags & USER_BOT) {
719 struct bot_addr *bi = e->u.extra, *bi2;
720
721 if (bi) {
722 bi2 = user_malloc(sizeof(struct bot_addr));
723
724 bi2->telnet_port = bi->telnet_port;
725 bi2->relay_port = bi->relay_port;
726 #ifdef TLS
727 bi2->ssl = bi->ssl;
728 #endif
729 bi2->address = user_malloc(strlen(bi->address) + 1);
730 strcpy(bi2->address, bi->address);
731 return set_user(&USERENTRY_BOTADDR, new, bi2);
732 }
733 }
734 return 0;
735 }
736
737 struct user_entry_type USERENTRY_BOTADDR = {
738 0, /* always 0 ;) */
739 botaddr_gotshare,
740 botaddr_dupuser,
741 botaddr_unpack,
742 botaddr_pack,
743 botaddr_write_userfile,
744 botaddr_kill,
745 def_get,
746 botaddr_set,
747 botaddr_tcl_get,
748 botaddr_tcl_set,
749 botaddr_expmem,
750 botaddr_display,
751 "BOTADDR"
752 };
753
754 int xtra_set(struct userrec *u, struct user_entry *e, void *buf)
755 {
756 struct xtra_key *curr, *old = NULL, *new = buf;
757
758 for (curr = e->u.extra; curr; curr = curr->next) {
759 if (curr->key && !egg_strcasecmp(curr->key, new->key)) {
760 old = curr;
761 break;
762 }
763 }
764 if (!old && (!new->data || !new->data[0])) {
765 /* Delete non-existant entry -- doh ++rtc */
766 nfree(new->key);
767 if (new->data)
768 nfree(new->data);
769 nfree(new);
770 return TCL_OK;
771 }
772
773 /* We will possibly free new below, so let's send the information
774 * to the botnet now
775 */
776 if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
777 shareout(NULL, "c XTRA %s %s %s\n", u->handle, new->key,
778 new->data ? new->data : "");
779 if ((old && old != new) || !new->data || !new->data[0]) {
780 egg_list_delete(&e->u.list, (struct list_type *) old);
781 nfree(old->key);
782 nfree(old->data);
783 nfree(old);
784 }
785 if (old != new && new->data) {
786 if (new->data[0])
787 list_insert((&e->u.extra), new) /* do not add a ';' here */
788 } else {
789 if (new->data)
790 nfree(new->data);
791 nfree(new->key);
792 nfree(new);
793 }
794 return TCL_OK;
795 }
796
797 static int xtra_tcl_set(Tcl_Interp * irp, struct userrec *u,
798 struct user_entry *e, int argc, char **argv)
799 {
800 struct xtra_key *xk;
801 int l;
802
803 BADARGS(4, 5, " handle type key ?value?");
804
805 xk = user_malloc(sizeof(struct xtra_key));
806 l = strlen(argv[3]);
807 egg_bzero(xk, sizeof(struct xtra_key));
808 if (l > 500)
809 l = 500;
810 xk->key = user_malloc(l + 1);
811 strncpyz(xk->key, argv[3], l + 1);
812
813 if (argc == 5) {
814 int k = strlen(argv[4]);
815
816 if (k > 500 - l)
817 k = 500 - l;
818 xk->data = user_malloc(k + 1);
819 strncpyz(xk->data, argv[4], k + 1);
820 }
821 xtra_set(u, e, xk);
822 return TCL_OK;
823 }
824
825 int xtra_unpack(struct userrec *u, struct user_entry *e)
826 {
827 struct list_type *curr, *head;
828 struct xtra_key *t;
829 char *key, *data;
830
831 head = curr = e->u.list;
832 e->u.extra = NULL;
833 while (curr) {
834 t = user_malloc(sizeof(struct xtra_key));
835
836 data = curr->extra;
837 key = newsplit(&data);
838 if (data[0]) {
839 t->key = user_malloc(strlen(key) + 1);
840 strcpy(t->key, key);
841 t->data = user_malloc(strlen(data) + 1);
842 strcpy(t->data, data);
843 list_insert((&e->u.extra), t);
844 }
845 curr = curr->next;
846 }
847 list_type_kill(head);
848 return 1;
849 }
850
851 static int xtra_pack(struct userrec *u, struct user_entry *e)
852 {
853 struct list_type *t;
854 struct xtra_key *curr, *next;
855
856 curr = e->u.extra;
857 e->u.list = NULL;
858 while (curr) {
859 t = user_malloc(sizeof(struct list_type));
860 t->extra = user_malloc(strlen(curr->key) + strlen(curr->data) + 4);
861 sprintf(t->extra, "%s %s", curr->key, curr->data);
862 list_insert((&e->u.list), t);
863 next = curr->next;
864 nfree(curr->key);
865 nfree(curr->data);
866 nfree(curr);
867 curr = next;
868 }
869 return 1;
870 }
871
872 static void xtra_display(int idx, struct user_entry *e)
873 {
874 int code, lc, j;
875 EGG_CONST char **list;
876 struct xtra_key *xk;
877
878 code = Tcl_SplitList(interp, whois_fields, &lc, &list);
879 if (code == TCL_ERROR)
880 return;
881 /* Scan thru xtra field, searching for matches */
882 for (xk = e->u.extra; xk; xk = xk->next) {
883 /* Ok, it's a valid xtra field entry */
884 for (j = 0; j < lc; j++) {
885 if (!egg_strcasecmp(list[j], xk->key))
886 dprintf(idx, " %s: %s\n", xk->key, xk->data);
887 }
888 }
889 Tcl_Free((char *) list);
890 }
891
892 static int xtra_gotshare(struct userrec *u, struct user_entry *e,
893 char *buf, int idx)
894 {
895 char *arg;
896 struct xtra_key *xk;
897 int l;
898
899 arg = newsplit(&buf);
900 if (!arg[0])
901 return 1;
902
903 xk = user_malloc(sizeof(struct xtra_key));
904 egg_bzero(xk, sizeof(struct xtra_key));
905 l = strlen(arg);
906 if (l > 500)
907 l = 500;
908 xk->key = user_malloc(l + 1);
909 strncpyz(xk->key, arg, l + 1);
910
911 if (buf[0]) {
912 int k = strlen(buf);
913
914 if (k > 500 - l)
915 k = 500 - l;
916 xk->data = user_malloc(k + 1);
917 strncpyz(xk->data, buf, k + 1);
918 }
919 xtra_set(u, e, xk);
920 return 1;
921 }
922
923 static int xtra_dupuser(struct userrec *new, struct userrec *old,
924 struct user_entry *e)
925 {
926 struct xtra_key *x1, *x2;
927
928 for (x1 = e->u.extra; x1; x1 = x1->next) {
929 x2 = user_malloc(sizeof(struct xtra_key));
930
931 x2->key = user_malloc(strlen(x1->key) + 1);
932 strcpy(x2->key, x1->key);
933 x2->data = user_malloc(strlen(x1->data) + 1);
934 strcpy(x2->data, x1->data);
935 set_user(&USERENTRY_XTRA, new, x2);
936 }
937 return 1;
938 }
939
940 static int xtra_write_userfile(FILE *f, struct userrec *u,
941 struct user_entry *e)
942 {
943 struct xtra_key *x;
944
945 for (x = e->u.extra; x; x = x->next)
946 if (fprintf(f, "--XTRA %s %s\n", x->key, x->data) == EOF)
947 return 0;
948 return 1;
949 }
950
951 int xtra_kill(struct user_entry *e)
952 {
953 struct xtra_key *x, *y;
954
955 for (x = e->u.extra; x; x = y) {
956 y = x->next;
957 nfree(x->key);
958 nfree(x->data);
959 nfree(x);
960 }
961 nfree(e);
962 return 1;
963 }
964
965 static int xtra_tcl_get(Tcl_Interp * irp, struct userrec *u,
966 struct user_entry *e, int argc, char **argv)
967 {
968 struct xtra_key *x;
969
970 BADARGS(3, 4, " handle XTRA ?key?");
971
972 if (argc == 4) {
973 for (x = e->u.extra; x; x = x->next)
974 if (!egg_strcasecmp(argv[3], x->key)) {
975 Tcl_AppendResult(irp, x->data, NULL);
976 return TCL_OK;
977 }
978 return TCL_OK;
979 }
980 for (x = e->u.extra; x; x = x->next) {
981 char *p;
982 EGG_CONST char *list[2];
983
984 list[0] = x->key;
985 list[1] = x->data;
986 p = Tcl_Merge(2, list);
987 Tcl_AppendElement(irp, p);
988 Tcl_Free((char *) p);
989 }
990 return TCL_OK;
991 }
992
993 static int xtra_expmem(struct user_entry *e)
994 {
995 struct xtra_key *x;
996 int tot = 0;
997
998 for (x = e->u.extra; x; x = x->next) {
999 tot += sizeof(struct xtra_key);
1000
1001 tot += strlen(x->key) + 1;
1002 tot += strlen(x->data) + 1;
1003 }
1004 return tot;
1005 }
1006
1007 struct user_entry_type USERENTRY_XTRA = {
1008 0,
1009 xtra_gotshare,
1010 xtra_dupuser,
1011 xtra_unpack,
1012 xtra_pack,
1013 xtra_write_userfile,
1014 xtra_kill,
1015 def_get,
1016 xtra_set,
1017 xtra_tcl_get,
1018 xtra_tcl_set,
1019 xtra_expmem,
1020 xtra_display,
1021 "XTRA"
1022 };
1023
1024 static int hosts_dupuser(struct userrec *new, struct userrec *old,
1025 struct user_entry *e)
1026 {
1027 struct list_type *h;
1028
1029 for (h = e->u.extra; h; h = h->next)
1030 set_user(&USERENTRY_HOSTS, new, h->extra);
1031 return 1;
1032 }
1033
1034 static int hosts_null(struct userrec *u, struct user_entry *e)
1035 {
1036 return 1;
1037 }
1038
1039 static int hosts_write_userfile(FILE *f, struct userrec *u,
1040 struct user_entry *e)
1041 {
1042 struct list_type *h;
1043
1044 for (h = e->u.extra; h; h = h->next)
1045 if (fprintf(f, "--HOSTS %s\n", h->extra) == EOF)
1046 return 0;
1047 return 1;
1048 }
1049
1050 static int hosts_kill(struct user_entry *e)
1051 {
1052 list_type_kill(e->u.list);
1053 nfree(e);
1054 return 1;
1055 }
1056
1057 static int hosts_expmem(struct user_entry *e)
1058 {
1059 return list_type_expmem(e->u.list);
1060 }
1061
1062 static void hosts_display(int idx, struct user_entry *e)
1063 {
1064 char s[1024];
1065 struct list_type *q;
1066
1067 s[0] = 0;
1068 strcpy(s, " HOSTS: ");
1069 for (q = e->u.list; q; q = q->next) {
1070 if (s[0] && !s[9])
1071 strcat(s, q->extra);
1072 else if (!s[0])
1073 sprintf(s, " %s", q->extra);
1074 else {
1075 if (strlen(s) + strlen(q->extra) + 2 > 65) {
1076 dprintf(idx, "%s\n", s);
1077 sprintf(s, " %s", q->extra);
1078 } else {
1079 strcat(s, ", ");
1080 strcat(s, q->extra);
1081 }
1082 }
1083 }
1084 if (s[0])
1085 dprintf(idx, "%s\n", s);
1086 }
1087
1088 static int hosts_set(struct userrec *u, struct user_entry *e, void *buf)
1089 {
1090 if (!buf || !egg_strcasecmp(buf, "none")) {
1091 /* When the bot crashes, it's in this part, not in the 'else' part */
1092 list_type_kill(e->u.list);
1093 e->u.list = NULL;
1094 } else {
1095 char *host = buf, *p = strchr(host, ',');
1096 struct list_type **t;
1097
1098 /* Can't have ,'s in hostmasks */
1099 while (p) {
1100 *p = '?';
1101 p = strchr(host, ',');
1102 }
1103 /* fred1: check for redundant hostmasks with
1104 * controversial "superpenis" algorithm ;) */
1105 /* I'm surprised Raistlin hasn't gotten involved in this controversy */
1106 t = &(e->u.list);
1107 while (*t) {
1108 if (cmp_usermasks(host, (*t)->extra)) {
1109 struct list_type *u;
1110
1111 u = *t;
1112 *t = (*t)->next;
1113 if (u->extra)
1114 nfree(u->extra);
1115 nfree(u);
1116 } else
1117 t = &((*t)->next);
1118 }
1119 *t = user_malloc(sizeof(struct list_type));
1120
1121 (*t)->next = NULL;
1122 (*t)->extra = user_malloc(strlen(host) + 1);
1123 strcpy((*t)->extra, host);
1124 }
1125 return 1;
1126 }
1127
1128 static int hosts_tcl_get(Tcl_Interp * irp, struct userrec *u,
1129 struct user_entry *e, int argc, char **argv)
1130 {
1131 struct list_type *x;
1132
1133 BADARGS(3, 3, " handle HOSTS");
1134
1135 for (x = e->u.list; x; x = x->next)
1136 Tcl_AppendElement(irp, x->extra);
1137 return TCL_OK;
1138 }
1139
1140 static int hosts_tcl_set(Tcl_Interp * irp, struct userrec *u,
1141 struct user_entry *e, int argc, char **argv)
1142 {
1143 BADARGS(3, 4, " handle HOSTS ?host?");
1144
1145 if (argc == 4)
1146 addhost_by_handle(u->handle, argv[3]);
1147 else
1148 addhost_by_handle(u->handle, "none"); /* drummer */
1149 return TCL_OK;
1150 }
1151
1152 static int hosts_gotshare(struct userrec *u, struct user_entry *e,
1153 char *buf, int idx)
1154 {
1155 /* doh, try to be too clever and it bites your butt */
1156 return 0;
1157 }
1158
1159 struct user_entry_type USERENTRY_HOSTS = {
1160 0,
1161 hosts_gotshare,
1162 hosts_dupuser,
1163 hosts_null,
1164 hosts_null,
1165 hosts_write_userfile,
1166 hosts_kill,
1167 def_get,
1168 hosts_set,
1169 hosts_tcl_get,
1170 hosts_tcl_set,
1171 hosts_expmem,
1172 hosts_display,
1173 "HOSTS"
1174 };
1175
1176 #ifdef TLS
1177 int fprint_unpack(struct userrec *u, struct user_entry *e)
1178 {
1179 char *tmp;
1180
1181 tmp = ssl_fpconv(e->u.list->extra, NULL);
1182 nfree(e->u.list->extra);
1183 e->u.list->extra = NULL;
1184 list_type_kill(e->u.list);
1185 e->u.string = tmp;
1186 return 1;
1187 }
1188
1189 int fprint_set(struct userrec *u, struct user_entry *e, void *buf)
1190 {
1191 char *fp = buf;
1192
1193 if (!fp || !fp[0] || (fp[0] == '-')) {
1194 if (e->u.string) {
1195 nfree(e->u.string);
1196 e->u.string = NULL;
1197 }
1198 } else {
1199 fp = ssl_fpconv(buf, e->u.string);
1200 if (fp)
1201 e->u.string = fp;
1202 else
1203 return 0;
1204 }
1205 if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED)))
1206 shareout(NULL, "c FPRINT %s %s\n", u->handle, e->u.string ? e->u.string : "");
1207 return 1;
1208 }
1209
1210 static int fprint_tcl_set(Tcl_Interp * irp, struct userrec *u,
1211 struct user_entry *e, int argc, char **argv)
1212 {
1213 BADARGS(3, 4, " handle FPRINT ?new-fingerprint?");
1214
1215 fprint_set(u, e, argc == 3 ? NULL : argv[3]);
1216 return TCL_OK;
1217 }
1218
1219 struct user_entry_type USERENTRY_FPRINT = {
1220 0,
1221 def_gotshare,
1222 0,
1223 fprint_unpack,
1224 def_pack,
1225 def_write_userfile,
1226 def_kill,
1227 def_get,
1228 fprint_set,
1229 def_tcl_get,
1230 fprint_tcl_set,
1231 def_expmem,
1232 0,
1233 "FPRINT"
1234 };
1235 #endif /* TLS */
1236
1237 int egg_list_append(struct list_type **h, struct list_type *i)
1238 {
1239 for (; *h; h = &((*h)->next));
1240 *h = i;
1241 return 1;
1242 }
1243
1244 int egg_list_delete(struct list_type **h, struct list_type *i)
1245 {
1246 for (; *h; h = &((*h)->next))
1247 if (*h == i) {
1248 *h = i->next;
1249 return 1;
1250 }
1251 return 0;
1252 }
1253
1254 int egg_list_contains(struct list_type *h, struct list_type *i)
1255 {
1256 for (; h; h = h->next)
1257 if (h == i) {
1258 return 1;
1259 }
1260 return 0;
1261 }
1262
1263 int add_entry_type(struct user_entry_type *type)
1264 {
1265 struct userrec *u;
1266
1267 list_insert(&entry_type_list, type);
1268 for (u = userlist; u; u = u->next) {
1269 struct user_entry *e = find_user_entry(type, u);
1270
1271 if (e && e->name) {
1272 e->type = type;
1273
1274 e->type->unpack(u, e);
1275 nfree(e->name);
1276 e->name = NULL;
1277 }
1278 }
1279 return 1;
1280 }
1281
1282 int del_entry_type(struct user_entry_type *type)
1283 {
1284 struct userrec *u;
1285
1286 for (u = userlist; u; u = u->next) {
1287 struct user_entry *e = find_user_entry(type, u);
1288
1289 if (e && !e->name) {
1290 e->type->pack(u, e);
1291 e->name = user_malloc(strlen(e->type->name) + 1);
1292 strcpy(e->name, e->type->name);
1293 e->type = NULL;
1294 }
1295 }
1296 return egg_list_delete((struct list_type **) &entry_type_list,
1297 (struct list_type *) type);
1298 }
1299
1300 struct user_entry_type *find_entry_type(char *name)
1301 {
1302 struct user_entry_type *p;
1303
1304 for (p = entry_type_list; p; p = p->next) {
1305 if (!egg_strcasecmp(name, p->name))
1306 return p;
1307 }
1308 return NULL;
1309 }
1310
1311 struct user_entry *find_user_entry(struct user_entry_type *et,
1312 struct userrec *u)
1313 {
1314 struct user_entry **e, *t;
1315
1316 for (e = &(u->entries); *e; e = &((*e)->next)) {
1317 if (((*e)->type == et) ||
1318 ((*e)->name && !egg_strcasecmp((*e)->name, et->name))) {
1319 t = *e;
1320 *e = t->next;
1321 t->next = u->entries;
1322 u->entries = t;
1323 return t;
1324 }
1325 }
1326 return NULL;
1327 }
1328
1329 void *get_user(struct user_entry_type *et, struct userrec *u)
1330 {
1331 struct user_entry *e;
1332
1333 if (u && (e = find_user_entry(et, u)))
1334 return et->get(u, e);
1335 return 0;
1336 }
1337
1338 int set_user(struct user_entry_type *et, struct userrec *u, void *d)
1339 {
1340 struct user_entry *e;
1341 int r;
1342
1343 if (!u || !et)
1344 return 0;
1345
1346 if (!(e = find_user_entry(et, u))) {
1347 e = user_malloc(sizeof(struct user_entry));
1348
1349 e->type = et;
1350 e->name = NULL;
1351 e->u.list = NULL;
1352 list_insert((&(u->entries)), e);
1353 }
1354 r = et->set(u, e, d);
1355 if (!e->u.list) {
1356 egg_list_delete((struct list_type **) &(u->entries), (struct list_type *) e);
1357 nfree(e);
1358 }
1359 return r;
1360 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23