static int msg_release(char *nick, char *host, struct userrec *u, char *par) { char *pass = NULL; if (match_my_nick(nick)) return BIND_RET_BREAK; if (u && u->bot) return BIND_RET_BREAK; pass = newsplit(&par); if (u && u_pass_match(u, pass) && !u_pass_match(u, "-")) { struct flag_record fr = {FR_GLOBAL, 0, 0, 0 }; get_user_flagrec(u, &fr, NULL); if (glob_master(fr)) { putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! RELEASE"), nick, host, u->handle); egg_timeval_t howlong; howlong.sec = 5; howlong.usec = 0; timer_create(&howlong, "Release jupenick", (Function) release_nick); // release_nick(); } else putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed RELEASE (User it not +m)"), nick, host, u->handle); } else putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed RELEASE"), nick, host, u ? u->handle : "*"); return BIND_RET_BREAK; }
static int msg_pass(char *nick, char *host, struct userrec *u, char *par) { char *old = NULL, *mynew = NULL; if (match_my_nick(nick)) return BIND_RET_BREAK; if (!u) { putlog(LOG_CMDS, "*", "(%s!%s) !*! PASS", nick, host); return BIND_RET_BREAK; } if (u->bot) return BIND_RET_BREAK; if (!par[0]) { notice(nick, u_pass_match(u, "-") ? "You don't have a password set." : "You have a password set.", DP_HELP); putlog(LOG_CMDS, "*", "(%s!%s) !%s! PASS?", nick, host, u->handle); return BIND_RET_BREAK; } old = newsplit(&par); if (!u_pass_match(u, "-") && !par[0]) { putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle); notice(nick, "You already have a password set.", DP_HELP); return BIND_RET_BREAK; } if (par[0]) { if (!u_pass_match(u, old)) { putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle); notice(nick, "Incorrect password.", DP_HELP); return BIND_RET_BREAK; } mynew = newsplit(&par); } else { mynew = old; } if (strlen(mynew) > MAXPASSLEN) mynew[MAXPASSLEN] = 0; if (!goodpass(mynew, 0, nick)) { putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle); return BIND_RET_BREAK; } putlog(LOG_CMDS, "*", "(%s!%s) !%s! PASS", nick, host, u->handle); set_user(&USERENTRY_PASS, u, mynew); bd::String msg; msg = bd::String::printf("%s '%s'.", mynew == old ? "Password set to:" : "Password changed to:", mynew); notice(nick, msg.c_str(), DP_HELP); return BIND_RET_BREAK; }
static int ctcp_CHAT(char *nick, char *uhost, struct userrec *u, char *object, char *keyword, char *text) { if (!ischanhub()) return BIND_RET_LOG; if (u_pass_match(u, "-")) { strlcat(ctcp_reply, "\001ERROR no password set\001", sizeof(ctcp_reply)); return BIND_RET_BREAK; } int ix = -1, i = 0; for (i = 0; i < dcc_total; i++) { if (dcc[i].type && (dcc[i].type->flags & DCT_LISTEN) && (!strcmp(dcc[i].nick, "(telnet)"))) ix = i; } if (!iptolong(getmyip())) { simple_snprintf(&ctcp_reply[strlen(ctcp_reply)], sizeof(ctcp_reply) - strlen(ctcp_reply), "\001ERROR no ipv4 ip defined. Use /dcc chat %s\001", botname); } else if (dcc_total == max_dcc || (ix < 0 && (ix = listen_all(0, 0, 0)) < 0)) strlcat(ctcp_reply, "\001ERROR no telnet port\001", sizeof(ctcp_reply)); else { if (listen_time <= 2) listen_time++; /* do me a favour and don't change this back to a CTCP reply, * CTCP replies are NOTICE's this has to be a PRIVMSG * -poptix 5/1/1997 */ bd::String msg; msg = bd::String::printf("\001DCC CHAT chat %lu %u\001", iptolong(getmyip()), dcc[ix].port); privmsg(nick, msg.c_str(), DP_SERVER); } return BIND_RET_BREAK; }
static int msg_ident(char *nick, char *host, struct userrec *u, char *par) { char s[UHOSTLEN] = "", s1[UHOSTLEN] = "", *pass = NULL, who[HANDLEN + 1] = ""; struct userrec *u2 = NULL; if (match_my_nick(nick) || (u && u->bot)) return BIND_RET_BREAK; pass = newsplit(&par); if (!par[0]) strlcpy(who, nick, sizeof(who)); else { strlcpy(who, par, sizeof(who)); } bd::String msg; u2 = get_user_by_handle(userlist, who); if (u2 && rfc_casecmp(who, origbotname) && !u2->bot) { /* This could be used as detection... */ if (u_pass_match(u2, "-")) { putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who); } else if (!u_pass_match(u2, pass)) { putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who); return BIND_RET_BREAK; } else if (u == u2) { notice(nick, "I recognize you there.", DP_HELP); return BIND_RET_BREAK; } else if (u) { msg = bd::String::printf("You're not %s, you're %s.", who, u->handle); notice(nick, msg.c_str(), DP_HELP); return BIND_RET_BREAK; } else { putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who); simple_snprintf(s, sizeof s, "%s!%s", nick, host); maskaddr(s, s1, 0); /* *!user@host */ msg = bd::String::printf("Added hostmask: %s", s1); notice(nick, msg.c_str(), DP_HELP); addhost_by_handle(who, s1); check_this_user(who, 0, NULL); return BIND_RET_BREAK; } } putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who); return BIND_RET_BREAK; }
static int msg_invite(char *nick, char *host, struct userrec *u, char *par) { char *pass = NULL; struct chanset_t *chan = NULL; struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 }; if (match_my_nick(nick)) return BIND_RET_BREAK; pass = newsplit(&par); if (u_pass_match(u, pass) && !u_pass_match(u, "-")) { if (par[0] == '*') { for (chan = chanset; chan; chan = chan->next) { get_user_flagrec(u, &fr, chan->dname, chan); if (chk_op(fr, chan) && (chan->channel.mode & CHANINV)) { cache_invite(chan, nick, host, u->handle, 0, 0); } } putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE ALL", nick, host, u->handle); return BIND_RET_BREAK; } bd::String msg; if (!(chan = findchan_by_dname(par))) { msg = bd::String::printf("Usage: /MSG %s %s <pass> <channel>", botname, msginvite); notice(nick, msg.c_str(), DP_HELP); return BIND_RET_BREAK; } if (!channel_active(chan)) { msg = bd::String::printf("%s: Not on that channel right now.", par); notice(nick, msg.c_str(), DP_HELP); return BIND_RET_BREAK; } /* We need to check access here also (dw 991002) */ get_user_flagrec(u, &fr, par, chan); if (chk_op(fr, chan)) { cache_invite(chan, nick, host, u->handle, 0, 0); putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE %s", nick, host, u->handle, par); return BIND_RET_BREAK; } } putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed INVITE %s", nick, host, (u ? u->handle : "*"), par); return BIND_RET_BREAK; }
static int ctcp_CHAT(char *nick, char *uhost, char *handle, char *object, char *keyword, char *text) { struct userrec *u = get_user_by_handle(userlist, handle); int atr = u ? u->flags : 0, i; char s[INET6_ADDRSTRLEN]; #ifdef TLS int ssl = 0; #endif if ((atr & (USER_PARTY | USER_XFER)) || ((atr & USER_OP) && !require_p)) { if (u_pass_match(u, "-")) { simple_sprintf(ctcp_reply, "%s\001ERROR no password set\001", ctcp_reply); return 1; } #ifdef TLS if (!egg_strcasecmp(keyword, "SCHAT")) ssl = 1; #endif for (i = 0; i < dcc_total; i++) { if ((dcc[i].type->flags & DCT_LISTEN) && #ifdef TLS (ssl == dcc[i].ssl) && #endif (!strcmp(dcc[i].nick, "(telnet)") || !strcmp(dcc[i].nick, "(users)")) && getdccaddr(&dcc[i].sockname, s, sizeof s)) { /* Do me a favour and don't change this back to a CTCP reply, * CTCP replies are NOTICE's this has to be a PRIVMSG * -poptix 5/1/1997 */ #ifdef TLS dprintf(DP_SERVER, ":%s PRIVMSG %s :\001DCC %sCHAT chat %s %u\001\n", botname, nick, (ssl ? "S" : ""), s, dcc[i].port); #else dprintf(DP_SERVER, ":%s PRIVMSG %s :\001DCC CHAT chat %s %u\001\n", botname, nick, s, dcc[i].port); #endif return 1; } } #ifdef TLS simple_sprintf(ctcp_reply, "%s\001ERROR no %stelnet port\001", ctcp_reply, (ssl ? "SSL enabled " : "")); #else simple_sprintf(ctcp_reply, "%s\001ERROR no telnet port\001", ctcp_reply); #endif } return 1; }
static int msg_auth(char *nick, char *host, struct userrec *u, char *par) { char *pass = NULL; if (match_my_nick(nick)) return BIND_RET_BREAK; if (u && u->bot) return BIND_RET_BREAK; Auth *auth = Auth::Find(host); if (!auth || auth->Status() != AUTH_PASS) return BIND_RET_BREAK; pass = newsplit(&par); if (u_pass_match(u, pass) && !u_pass_match(u, "-")) { auth->user = u; if (strlen(auth_key) && get_user(&USERENTRY_SECPASS, u)) { putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! AUTH"), nick, host, u->handle); auth->Status(AUTH_HASH); auth->MakeHash(); bd::String msg; msg = bd::String::printf(STR("-Auth %s %s"), auth->rand, conf.bot->nick); privmsg(nick, msg.c_str(), DP_HELP); } else { /* no auth_key and/or no SECPASS for the user, don't require a hash auth */ AuthFinish(auth); } } else { putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed AUTH"), nick, host, u->handle); delete auth; } return BIND_RET_BREAK; }
static void dcc_files_pass(int idx, char *buf, int x) { struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick); if (!x) return; if (u_pass_match(u, buf)) { if (too_many_filers()) { dprintf(idx, "Too many people are in the file system right now.\n"); dprintf(idx, "Please try again later.\n"); putlog(LOG_MISC, "*", "File area full: DCC chat [%s]%s", dcc[idx].nick, dcc[idx].host); killsock(dcc[idx].sock); lostdcc(idx); return; } dcc[idx].type = &DCC_FILES; if (dcc[idx].status & STAT_TELNET) dprintf(idx, "\377\374\001\n"); /* turn echo back on */ putlog(LOG_FILES, "*", "File system: [%s]%s/%d", dcc[idx].nick, dcc[idx].host, dcc[idx].port); if (!welcome_to_files(idx)) { putlog(LOG_FILES, "*", "File system broken."); killsock(dcc[idx].sock); lostdcc(idx); } else { struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick); touch_laston(u, "filearea", now); } return; } dprintf(idx, "Negative on that, Houston.\n"); putlog(LOG_MISC, "*", "Bad password: DCC chat [%s]%s", dcc[idx].nick, dcc[idx].host); killsock(dcc[idx].sock); lostdcc(idx); }
/* notes <pass> <func> */ static int msg_notes(char *nick, char *host, struct userrec *u, char *par) { char *pwd, *fcn; if (!u) return 0; if (u->flags & (USER_BOT | USER_COMMON)) return 1; if (!par[0]) { dprintf(DP_HELP, "NOTICE %s :%s: NOTES <pass> INDEX\n", nick, NOTES_USAGE); dprintf(DP_HELP, "NOTICE %s :NOTES <pass> TO <hand> <msg>\n", nick); dprintf(DP_HELP, "NOTICE %s :NOTES <pass> READ <# or ALL>\n", nick); dprintf(DP_HELP, "NOTICE %s :NOTES <pass> ERASE <# or ALL>\n", nick); dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_MAYBE); dprintf(DP_HELP, "NOTICE %s :Ex: NOTES mypass ERASE 2-4;8;16-\n", nick); return 1; } if (!u_pass_match(u, "-")) { /* Do the have a password set? */ pwd = newsplit(&par); if (!u_pass_match(u, pwd)) return 0; } fcn = newsplit(&par); if (!egg_strcasecmp(fcn, "INDEX")) notes_read(u->handle, nick, "+", -1); else if (!egg_strcasecmp(fcn, "READ")) { if (!egg_strcasecmp(par, "ALL")) notes_read(u->handle, nick, "-", -1); else notes_read(u->handle, nick, par, -1); } else if (!egg_strcasecmp(fcn, "ERASE")) { if (!egg_strcasecmp(par, "ALL")) notes_del(u->handle, nick, "-", -1); else notes_del(u->handle, nick, par, -1); } else if (!egg_strcasecmp(fcn, "TO")) { char *to; int i; FILE *f; struct userrec *u2; to = newsplit(&par); if (!par[0]) { dprintf(DP_HELP, "NOTICE %s :%s: NOTES <pass> TO <hand> <message>\n", nick, NOTES_USAGE); return 0; } u2 = get_user_by_handle(userlist, to); if (!u2) { dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_USERF_UNKNOWN); return 1; } else if (is_bot(u2)) { dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_NOTTO_BOT); return 1; } for (i = 0; i < dcc_total; i++) { if ((!egg_strcasecmp(dcc[i].nick, to)) && (dcc[i].type->flags & DCT_GETNOTES)) { int aok = 1; if (dcc[i].type->flags & DCT_CHAT) if (dcc[i].u.chat->away != NULL) aok = 0; if (!(dcc[i].type->flags & DCT_CHAT)) aok = 0; /* Assume non dcc-chat == something weird, so * store notes for later */ if (aok) { dprintf(i, "\007%s [%s]: %s\n", u->handle, NOTES_OUTSIDE, par); dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_DELIVERED); return 1; } } } if (notefile[0] == 0) { dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_UNSUPPORTED); return 1; } f = fopen(notefile, "a"); if (f == NULL) f = fopen(notefile, "w"); if (f == NULL) { dprintf(DP_HELP, "NOTICE %s :%s", nick, NOTES_NOTEFILE_FAILED); putlog(LOG_MISC, "*", "* %s", NOTES_NOTEFILE_UNREACHABLE); return 1; } chmod(notefile, userfile_perm); /* Use userfile permissions. */ fprintf(f, "%s %s %li %s\n", to, u->handle, (long) now, par); fclose(f); dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_DELIVERED); return 1; } else dprintf(DP_HELP, "NOTICE %s :%s: NOTES <pass> INDEX, READ, ERASE, TO\n", nick, NOTES_USAGE); putlog(LOG_CMDS, "*", "(%s!%s) !%s! NOTES %s %s", nick, host, u->handle, fcn, par[0] ? "..." : ""); return 1; }
/* this only handles CHAT requests, otherwise it's handled in filesys */ static int filesys_DCC_CHAT(char *nick, char *from, char *handle, char *object, char *keyword, char *text) { char *param, *ip, *prt, buf[512], *msg = buf; int i, sock; struct userrec *u = get_user_by_handle(userlist, handle); struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0}; Context; if (!strncasecmp(text, "SEND ", 5)) { filesys_dcc_send(nick, from, u, text + 5); return 1; } if (strncasecmp(text, "CHAT ", 5) || !u) return 0; strcpy(buf, text + 5); get_user_flagrec(u, &fr, 0); param = newsplit(&msg); if (dcc_total == max_dcc) { putlog(LOG_MISC, "*", DCC_TOOMANYDCCS2, "CHAT(file)", param, nick, from); } else if (glob_party(fr) || (!require_p && chan_op(fr))) return 0; /* allow ctcp.so to pick up the chat */ else if (!glob_xfer(fr)) { if (!quiet_reject) dprintf(DP_HELP, "NOTICE %s :.\n", nick, DCC_REFUSED3); putlog(LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED, nick, from); } else if (u_pass_match(u, "-")) { if (!quiet_reject) dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, DCC_REFUSED3); putlog(LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED4, nick, from); } else if (!dccdir[0]) { putlog(LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED5, nick, from); } else { ip = newsplit(&msg); prt = newsplit(&msg); sock = getsock(0); if (open_telnet_dcc(sock, ip, prt) < 0) { neterror(buf); if (!quiet_reject) dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", nick, DCC_CONNECTFAILED1, buf); putlog(LOG_MISC, "*", "%s: CHAT(file) (%s!%s)", DCC_CONNECTFAILED2, nick, from); putlog(LOG_MISC, "*", " (%s)", buf); killsock(sock); } else if ((atoi(prt) < min_dcc_port) || (atoi(prt) > max_dcc_port)) { /* invalid port range, do clients even use over 5000?? */ if (!quiet_reject) dprintf(DP_HELP, "NOTICE %s :%s (invalid port)\n", nick, DCC_CONNECTFAILED1); putlog(LOG_FILES, "*", "%s: %s!%s", DCC_REFUSED7, nick, from); } else { i = new_dcc(&DCC_FILES_PASS, sizeof(struct file_info)); dcc[i].addr = my_atoul(ip); dcc[i].port = atoi(prt); dcc[i].sock = sock; strcpy(dcc[i].nick, u->handle); strcpy(dcc[i].host, from); dcc[i].status = STAT_ECHO; dcc[i].timeval = now; dcc[i].u.file->chat = get_data_ptr(sizeof(struct chat_info)); bzero(dcc[i].u.file->chat, sizeof(struct chat_info)); strcpy(dcc[i].u.file->chat->con_chan, "*"); dcc[i].user = u; putlog(LOG_MISC, "*", "DCC connection: CHAT(file) (%s!%s)", nick, from); dprintf(i, "%s\n", DCC_ENTERPASS); } } return 1; }
static int msg_op(char *nick, char *host, struct userrec *u, char *par) { struct chanset_t *chan = NULL; char *pass = NULL; struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 }; if (match_my_nick(nick)) return BIND_RET_BREAK; pass = newsplit(&par); bd::String msg; if (homechan[0]) { struct chanset_t *hchan = NULL; hchan = findchan_by_dname(homechan); if (hchan && channel_active(hchan) && !ismember(hchan, nick)) { putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP %s (not in %s)", nick, host, par, homechan); if (par[0]) msg = bd::String::printf("---- (%s!%s) attempted to OP for %s but is not currently in %s.", nick, host, par, homechan); else msg = bd::String::printf("---- (%s!%s) attempted to OP but is not currently in %s.", nick, host, homechan); privmsg(homechan, msg.c_str(), DP_SERVER); return BIND_RET_BREAK; } } if (u_pass_match(u, pass)) { if (!u_pass_match(u, "-")) { if (par[0]) { chan = findchan_by_dname(par); if (chan && channel_active(chan)) { get_user_flagrec(u, &fr, par, chan); if (chk_op(fr, chan)) { if (do_op(nick, chan, 0, 1)) { stats_add(u, 0, 1); putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP %s", nick, host, u->handle, par); if (manop_warn && chan->manop) { msg = bd::String::printf("%s is currently set to punish for manual op.", chan->dname); notice(nick, msg.c_str(), DP_HELP); } } } return BIND_RET_BREAK; } } else { int stats = 0; for (chan = chanset; chan; chan = chan->next) { get_user_flagrec(u, &fr, chan->dname, chan); if (chk_op(fr, chan)) { if (do_op(nick, chan, 0, 1)) { stats++; if (manop_warn && chan->manop) { msg = bd::String::printf("%s is currently set to punish for manual op.", chan->dname); notice(nick, msg.c_str(), DP_HELP); } } } } putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP", nick, host, u->handle); if (stats) stats_add(u, 0, 1); return BIND_RET_BREAK; } } } putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP", nick, host); return BIND_RET_BREAK; }