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