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