static int u_delinvite(struct chanset_t *c, char *who, int doit) { int j, i = 0; maskrec *t; maskrec **u = c ? &(c->invites) : &global_invites; char temp[256]; if (!strchr(who, '!') && str_isdigit(who)) { j = atoi(who); j--; for (; (*u) && j; u = &((*u)->next), j--); if (*u) { strncpyz(temp, (*u)->mask, sizeof temp); i = 1; } else return -j - 1; } else { /* Find matching host, if there is one */ for (; *u && !i; u = &((*u)->next)) if (!rfc_casecmp((*u)->mask, who)) { strncpyz(temp, who, sizeof temp); i = 1; break; } if (!*u) return 0; } if (i && doit) { if (!noshare) { char *mask = str_escape(temp, ':', '\\'); if (mask) { /* Distribute chan invites differently */ if (c) shareout(c, "-invc %s %s\n", c->dname, mask); else shareout(NULL, "-inv %s\n", mask); nfree(mask); } } if (lastdeletedmask) nfree(lastdeletedmask); lastdeletedmask = nmalloc(strlen((*u)->mask) + 1); strcpy(lastdeletedmask, (*u)->mask); nfree((*u)->mask); if ((*u)->desc) nfree((*u)->desc); if ((*u)->user) nfree((*u)->user); t = *u; *u = (*u)->next; nfree(t); } return i; }
void set_user_flagrec(struct userrec *u, struct flag_record *fr, char *chname) { struct chanuserrec *cr = NULL; int oldflags = fr->match; char buffer[100]; struct chanset_t *ch; if (!u) return; if (oldflags & FR_GLOBAL) { u->flags = fr->global; u->flags_udef = fr->udef_global; if (!noshare && !(u->flags & USER_UNSHARED)) { fr->match = FR_GLOBAL; build_flags(buffer, fr, NULL); shareout(NULL, "a %s %s\n", u->handle, buffer); } } if ((oldflags & FR_BOT) && (u->flags & USER_BOT)) set_user(&USERENTRY_BOTFL, u, (void *) fr->bot); /* dont share bot attrs */ if ((oldflags & FR_CHAN) && chname) { for (cr = u->chanrec; cr; cr = cr->next) if (!rfc_casecmp(chname, cr->channel)) break; ch = findchan(chname); if (!cr && ch) { cr = user_malloc(sizeof(struct chanuserrec)); bzero(cr, sizeof(struct chanuserrec)); cr->next = u->chanrec; u->chanrec = cr; strncpy(cr->channel, chname, 80); cr->channel[80] = 0; } if (cr && ch) { cr->flags = fr->chan; cr->flags_udef = fr->udef_chan; if (!noshare && !(u->flags & USER_UNSHARED) && channel_shared(ch)) { fr->match = FR_CHAN; build_flags(buffer, fr, NULL); shareout(ch, "a %s %s %s\n", u->handle, buffer, chname); } } } fr->match = oldflags; }
static bool console_set(struct userrec *u, struct user_entry *e, void *buf) { struct console_info *ci = (struct console_info *) e->u.extra; if (!ci && !buf) return 1; if (ci != buf) { if (ci) { free(ci->channel); free(ci); } ci = (struct console_info *) buf; e->u.extra = (struct console_info *) buf; } if (!noshare && !u->bot) { char string[501] = ""; simple_snprintf(string, sizeof string, "%s %s %s %d %d %d %d %d %d %d %d", ci->channel, masktype(ci->conflags), stripmasktype(ci->stripflags), ci->echoflags, ci->page, ci->conchan, ci->color, ci->banner, ci->channels, ci->bots, ci->whom); /* shareout("c %s %s %s\n", e->type->name, u->handle, string); */ shareout("c CONSOLE %s %s\n", u->handle, string); } return 1; }
static bool pass1_set(struct userrec *u, struct user_entry *e, void *buf) { register char *pass = (char *) buf; if (e->u.extra) free(e->u.extra); if (!pass || !pass[0] || (pass[0] == '-')) e->u.extra = NULL; else { unsigned char *p = (unsigned char *) pass; while (*p) { if ((*p <= 32) || (*p == 127)) *p = '?'; p++; } if (u->bot || (pass[0] == '+')) e->u.extra = strdup(pass); else e->u.extra = encrypt_string(u->handle, pass); } if (!noshare) shareout("c %s %s %s\n", e->type->name, u->handle, pass ? pass : ""); return 1; }
static bool pass_set(struct userrec *u, struct user_entry *e, void *buf) { char *newpass = NULL; register char *pass = (char *) buf; if (e->u.extra) free(e->u.extra); if (!pass || !pass[0] || (pass[0] == '-')) e->u.extra = NULL; else { unsigned char *p = (unsigned char *) pass; if (u->bot || (pass[0] == '+')) newpass = strdup(pass); else { while (*p) { if ((*p <= 32) || (*p == 127)) *p = '?'; p++; } newpass = salted_sha1(pass); } e->u.extra = strdup(newpass); } if (!noshare) shareout("c %s %s %s\n", e->type->name, u->handle, newpass ? newpass : ""); if (newpass) free(newpass); /* clear old records */ noshare = 1; set_user(&USERENTRY_PASS1, u, NULL); noshare = 0; return 1; }
static void set_handle_chaninfo(struct userrec *bu, char *handle, char *chname, char *info) { struct userrec *u; struct chanuserrec *ch; struct chanset_t *cst; u = get_user_by_handle(bu, handle); if (!u) return; ch = get_chanrec(u, chname); if (!ch) { add_chanrec_by_handle(bu, handle, chname); ch = get_chanrec(u, chname); } if (ch->info != NULL) nfree(ch->info); if (info && info[0]) { ch->info = (char *) user_malloc(strlen(info) + 1); strcpy(ch->info, info); } else ch->info = NULL; cst = findchan_by_dname(chname); if ((!noshare) && (bu == userlist) && !(u->flags & (USER_UNSHARED | USER_BOT)) && share_greet) { shareout(cst, "chchinfo %s %s %s\n", handle, chname, info ? info : ""); } }
int def_set(struct userrec *u, struct user_entry *e, void *buf) { char *string = (char *) buf; if (string && !string[0]) string = NULL; if (!string && !e->u.string) return 1; if (string) { int l = strlen(string); char *i; e->u.string = user_realloc(e->u.string, l + 1); strncpyz(e->u.string, string, l + 1); for (i = e->u.string; *i; i++) /* Allow bold, inverse, underline, color text here... * But never add cr or lf!! --rtc */ if ((unsigned int) *i < 32 && !strchr("\002\003\026\037", *i)) *i = '?'; } else { nfree(e->u.string); e->u.string = NULL; } if (!noshare && !(u->flags & (USER_BOT | USER_UNSHARED))) { if (e->type != &USERENTRY_INFO || share_greet) shareout(NULL, "c %s %s %s\n", e->type->name, u->handle, e->u.string ? e->u.string : ""); } return 1; }
void set_user_flagrec(struct userrec *u, struct flag_record *fr, const char *chname) { if (!u) return; struct chanuserrec *cr = NULL; flag_t oldflags = fr->match; char buffer[100] = ""; struct chanset_t *ch; if (oldflags & FR_GLOBAL) { u->flags = fr->global; if (!noshare) { fr->match = FR_GLOBAL; build_flags(buffer, fr, NULL); shareout("a %s %s\n", u->handle, buffer); } } if ((oldflags & FR_CHAN) && chname) { for (cr = u->chanrec; cr; cr = cr->next) if (!rfc_casecmp(chname, cr->channel)) break; ch = findchan_by_dname(chname); if (!cr && ch) { cr = (struct chanuserrec *) my_calloc(1, sizeof(struct chanuserrec)); cr->next = u->chanrec; u->chanrec = cr; strlcpy(cr->channel, chname, sizeof cr->channel); } if (cr && ch) { cr->flags = fr->chan; if (!noshare) { fr->match = FR_CHAN; build_flags(buffer, fr, NULL); shareout("a %s %s %s\n", u->handle, buffer, chname); } } } fr->match = oldflags; }
static struct chanuserrec *add_chanrec(struct userrec *u, char *chname) { struct chanuserrec *ch = NULL; if (findchan_by_dname(chname)) { ch = user_malloc(sizeof(struct chanuserrec)); ch->next = u->chanrec; u->chanrec = ch; ch->info = NULL; ch->flags = 0; ch->flags_udef = 0; ch->laston = 0; strncpy(ch->channel, chname, 81); ch->channel[80] = 0; if (!noshare && !(u->flags & USER_UNSHARED)) shareout(findchan_by_dname(chname), "+cr %s %s\n", u->handle, chname); } return ch; }
static void del_chanrec(struct userrec *u, char *chname) { struct chanuserrec *ch = u->chanrec, *lst = NULL; while (ch) { if (!rfc_casecmp(chname, ch->channel)) { if (lst == NULL) u->chanrec = ch->next; else lst->next = ch->next; if (ch->info != NULL) nfree(ch->info); nfree(ch); if (!noshare && !(u->flags & USER_UNSHARED)) shareout(findchan_by_dname(chname), "-cr %s %s\n", u->handle, chname); return; } lst = ch; ch = ch->next; } }
bool def_set_real(struct userrec *u, struct user_entry *e, void *buf, bool protect) { char *string = (char *) buf; if (string && !string[0]) string = NULL; if (!string && !e->u.string) return 1; if (string) { size_t l = strlen (string); char *i = NULL; if (l > 160) l = 160; e->u.string = (char *) my_realloc (e->u.string, l + 1); strlcpy (e->u.string, string, l + 1); for (i = e->u.string; *i; i++) /* Allow bold, inverse, underline, color text here... * But never add cr or lf!! --rtc */ if ((unsigned int) *i < 32 && !strchr ("\002\003\026\037", *i)) *i = '?'; } else { /* string == NULL && e->u.string != NULL */ free(e->u.string); e->u.string = NULL; } if (!noshare) { if (protect) shareout_prot(u, "c %s %s %s\n", e->type->name, u->handle, e->u.string ? e->u.string : ""); else shareout("c %s %s %s\n", e->type->name, u->handle, e->u.string ? e->u.string : ""); } return 1; }
/* Set sticky attribute for a mask. */ static int u_setsticky_mask(struct chanset_t *chan, maskrec *u, char *uhost, int sticky, char *botcmd) { int j; if (str_isdigit(uhost)) j = atoi(uhost); else j = -1; while (u) { if (j >= 0) j--; if (!j || ((j < 0) && !rfc_casecmp(u->mask, uhost))) { if (sticky > 0) u->flags |= MASKREC_STICKY; else if (!sticky) u->flags &= ~MASKREC_STICKY; else /* We don't actually want to change, just skip over */ return 0; if (!j) strcpy(uhost, u->mask); if (!noshare) shareout(chan, "%s %s %d %s\n", botcmd, uhost, sticky, (chan) ? chan->dname : ""); return 1; } u = u->next; } if (j >= 0) return -j; return 0; }
static bool botaddr_set(struct userrec *u, struct user_entry *e, void *buf) { register struct bot_addr *bi = (struct bot_addr *) e->u.extra; if (!bi && !buf) return 1; if (bi != buf) { if (bi) { free(bi->address); free(bi->uplink); free(bi); } ContextNote("botaddr_set", "(sharebug) occurred in botaddr_set"); bi = (struct bot_addr *) buf; e->u.extra = (struct bot_addr *) buf; } if (bi && !noshare) { shareout("c BOTADDR %s %s %d %d %d %s\n",u->handle, (bi->address && bi->address[0]) ? bi->address : "127.0.0.1", bi->telnet_port, bi->relay_port, bi->hublevel, bi->uplink); } return 1; }
/* Note: If first char of note is '*' it's a sticky exempt. */ static int u_addexempt(struct chanset_t *chan, char *exempt, char *from, char *note, time_t expire_time, int flags) { char host[1024], s[1024]; maskrec *p = NULL, *l, **u = chan ? &chan->exempts : &global_exempts; strcpy(host, exempt); /* Choke check: fix broken exempts (must have '!' and '@') */ if ((strchr(host, '!') == NULL) && (strchr(host, '@') == NULL)) strcat(host, "!*@*"); else if (strchr(host, '@') == NULL) strcat(host, "@*"); else if (strchr(host, '!') == NULL) { char *i = strchr(host, '@'); strcpy(s, i); *i = 0; strcat(host, "!*"); strcat(host, s); } for (l = *u; l; l = l->next) if (!rfc_casecmp(l->mask, host)) { p = l; break; } /* It shouldn't expire and be sticky also */ if (note[0] == '*') { flags |= MASKREC_STICKY; note++; } if ((expire_time == 0L) || (flags & MASKREC_PERM)) { flags |= MASKREC_PERM; expire_time = 0L; } if (p == NULL) { p = user_malloc(sizeof(maskrec)); p->next = *u; *u = p; } else { nfree(p->mask); nfree(p->user); nfree(p->desc); } p->expire = expire_time; p->added = now; p->lastactive = 0; p->flags = flags; p->mask = user_malloc(strlen(host) + 1); strcpy(p->mask, host); p->user = user_malloc(strlen(from) + 1); strcpy(p->user, from); p->desc = user_malloc(strlen(note) + 1); strcpy(p->desc, note); if (!noshare) { char *mask = str_escape(host, ':', '\\'); if (mask) { if (!chan) shareout(NULL, "+e %s %li %s%s %s %s\n", mask, expire_time - now, (flags & MASKREC_STICKY) ? "s" : "", (flags & MASKREC_PERM) ? "p" : "-", from, note); else shareout(chan, "+ec %s %li %s %s%s %s %s\n", mask, expire_time - now, chan->dname, (flags & MASKREC_STICKY) ? "s" : "", (flags & MASKREC_PERM) ? "p" : "-", from, note); nfree(mask); } } return 1; }
/* Note: If first char of note is '*' it's a sticky ban. */ static int u_addban(struct chanset_t *chan, char *ban, char *from, char *note, time_t expire_time, int flags) { char host[1024], s[1024]; maskrec *p = NULL, *l, **u = chan ? &chan->bans : &global_bans; module_entry *me; strcpy(host, ban); /* Choke check: fix broken bans (must have '!' and '@') */ if ((strchr(host, '!') == NULL) && (strchr(host, '@') == NULL)) strcat(host, "!*@*"); else if (strchr(host, '@') == NULL) strcat(host, "@*"); else if (strchr(host, '!') == NULL) { char *i = strchr(host, '@'); strcpy(s, i); *i = 0; strcat(host, "!*"); strcat(host, s); } if ((me = module_find("server", 0, 0)) && me->funcs) { simple_sprintf(s, "%s!%s", me->funcs[SERVER_BOTNAME], me->funcs[SERVER_BOTUSERHOST]); if (match_addr(host, s)) { putlog(LOG_MISC, "*", IRC_IBANNEDME); return 0; } } if (expire_time == now) return 1; for (l = *u; l; l = l->next) if (!rfc_casecmp(l->mask, host)) { p = l; break; } /* It shouldn't expire and be sticky also */ if (note[0] == '*') { flags |= MASKREC_STICKY; note++; } if ((expire_time == 0L) || (flags & MASKREC_PERM)) { flags |= MASKREC_PERM; expire_time = 0L; } if (p == NULL) { p = user_malloc(sizeof(maskrec)); p->next = *u; *u = p; } else { nfree(p->mask); nfree(p->user); nfree(p->desc); } p->expire = expire_time; p->added = now; p->lastactive = 0; p->flags = flags; p->mask = user_malloc(strlen(host) + 1); strcpy(p->mask, host); p->user = user_malloc(strlen(from) + 1); strcpy(p->user, from); p->desc = user_malloc(strlen(note) + 1); strcpy(p->desc, note); if (!noshare) { char *mask = str_escape(host, ':', '\\'); if (mask) { if (!chan) shareout(NULL, "+b %s %li %s%s %s %s\n", mask, expire_time - now, (flags & MASKREC_STICKY) ? "s" : "", (flags & MASKREC_PERM) ? "p" : "-", from, note); else shareout(chan, "+bc %s %li %s %s%s %s %s\n", mask, expire_time - now, chan->dname, (flags & MASKREC_STICKY) ? "s" : "", (flags & MASKREC_PERM) ? "p" : "-", from, note); nfree(mask); } } return 1; }