/* ** mo_ojoin ** parv[1] = channel */ static void mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr; int move_me = 0; /* admins only */ if(!IsOperAdmin(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin"); return; } if(*parv[1] == '@' || *parv[1] == '+') { parv[1]++; move_me = 1; } if((chptr = find_channel(parv[1])) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return; } if(IsMember(source_p, chptr)) { sendto_one_notice(source_p, ":Please part %s before using OJOIN", parv[1]); return; } if(move_me == 1) parv[1]--; sendto_wallops_flags(UMODE_WALLOP, &me, "OJOIN called for %s by %s!%[email protected]%s", parv[1], source_p->name, source_p->username, source_p->host); ilog(L_MAIN, "OJOIN called for %s by %s", parv[1], get_oper_name(source_p)); /* only sends stuff for #channels remotely */ sendto_server(NULL, chptr, NOCAPS, NOCAPS, ":%s WALLOPS :OJOIN called for %s by %s!%[email protected]%s", me.name, parv[1], source_p->name, source_p->username, source_p->host); if(*parv[1] == '@') { add_user_to_channel(chptr, source_p, CHFL_CHANOP); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :@%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '+') { add_user_to_channel(chptr, source_p, CHFL_VOICE); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :+%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +v %s", me.name, chptr->chname, source_p->name); } else { add_user_to_channel(chptr, source_p, CHFL_PEON); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s JOIN %ld %s +", source_p->id, (long) chptr->channelts, chptr->chname); send_channel_join(chptr, source_p); } /* send the topic... */ if(chptr->topic != NULL) { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); } source_p->localClient->last_join_time = rb_current_time(); channel_member_names(chptr, source_p, 1); }
int m_scan_umodes(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[]) { char *umode_string = parv[2], *c; user_modes include_modes, exclude_modes; int what = MODE_ADD; int mode; int list_users = 1; int list_max = 0; int allowed = 1; int listed_so_far = 0, count = 0; char *mask = NULL; struct Client *acptr; int i; if (!HasUmode(sptr,UMODE_USER_AUSPEX)) { if (SeesOperMessages(sptr)) sendto_one(sptr,":%s NOTICE %s :You have no a umode", me.name, parv[0]); else sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (parc < 3) { if (!IsServer(sptr)) sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SCAN UMODES"); return 0; } ClearBitfield(include_modes); ClearBitfield(exclude_modes); for (c = umode_string; *c; c++) switch(*c) { case '+': what = MODE_ADD; break; case '-': what = MODE_DEL; break; default: if ((mode = user_modes_from_c_to_bitmask[(unsigned char)*c])) { if (what == MODE_ADD) SetBit(include_modes, mode); else SetBit(exclude_modes, mode); } else { sendto_one(sptr, form_str(ERR_UNKNOWNMODE), me.name, sptr->name, *c); return 0; } } for (i = 3; i < parc; i++) { if (!irccmp(parv[i], "no-list")) list_users = 0; else if (!irccmp(parv[i], "list")) list_users = 1; else if (!irccmp(parv[i], "allowed")) allowed = 1; else if (!irccmp(parv[i], "current")) allowed = 0; else if (i < (parc - 1)) { if (!irccmp(parv[i], "list-max")) { list_max = atoi(parv[++i]); } else if (!irccmp(parv[i], "mask")) { mask = parv[++i]; } } } for (acptr = GlobalClientList; acptr; acptr = acptr->next) { char *s; user_modes working_umodes; if (!IsClient(acptr)) continue; if (allowed) AndUmodes(working_umodes, acptr->allowed_umodes, include_modes); else AndUmodes(working_umodes, acptr->umodes, include_modes); if (!SameBits(working_umodes, include_modes)) continue; if (allowed) AndUmodes(working_umodes, acptr->allowed_umodes, exclude_modes); else AndUmodes(working_umodes, acptr->umodes, exclude_modes); if (AnyBits(working_umodes)) continue; s = make_nick_user_host(acptr->name, acptr->username, acptr->host); if (mask && !match(mask, s)) continue; if (list_users && (!list_max || (listed_so_far < list_max))) { char buf[BUFSIZE]; char *m = buf; int i; *m++ = '+'; for (i = 0; user_mode_table[i].letter && (m - buf < BUFSIZE - 4);i++) if (TestBit(allowed ? acptr->allowed_umodes : acptr->umodes, user_mode_table[i].mode)) *m++ = user_mode_table[i].letter; *m = '\0'; listed_so_far++; sendto_one(sptr, form_str(RPL_MODE), me.name, sptr->name, acptr->name, buf); } count++; } send_markup(sptr, &me, "UMODE-END", "End of user mode list"); /* send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */ send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count); return 0; }
/* * send_conf_options * * inputs - client pointer to send to * output - none * side effects - send config options to client */ static void send_conf_options(struct Client *source_p) { Info *infoptr; int i = 0; /* * Now send them a list of all our configuration options * (mostly from config.h) */ for (infoptr = MyInformation; infoptr->name; infoptr++) { if(infoptr->intvalue) { sendto_one(source_p, ":%s %d %s :%-30s %-5d [%-30s]", get_id(&me, source_p), RPL_INFO, get_id(source_p, source_p), infoptr->name, infoptr->intvalue, infoptr->desc); } else { sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", get_id(&me, source_p), RPL_INFO, get_id(source_p, source_p), infoptr->name, infoptr->strvalue, infoptr->desc); } } /* * Parse the info_table[] and do the magic. */ for (i = 0; info_table[i].name; i++) { switch (info_table[i].output_type) { /* * For "char *" references */ case OUTPUT_STRING: { char *option = *((char **) info_table[i].option); sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", get_id(&me, source_p), RPL_INFO, get_id(source_p, source_p), info_table[i].name, option ? option : "NONE", info_table[i].desc ? info_table[i].desc : "<none>"); break; } /* * For "char foo[]" references */ case OUTPUT_STRING_PTR: { char *option = (char *) info_table[i].option; sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", get_id(&me, source_p), RPL_INFO, get_id(source_p, source_p), info_table[i].name, EmptyString(option) ? "NONE" : option, info_table[i].desc ? info_table[i].desc : "<none>"); break; } /* * Output info_table[i].option as a decimal value. */ case OUTPUT_DECIMAL: { int option = *((int *) info_table[i].option); sendto_one(source_p, ":%s %d %s :%-30s %-5d [%-30s]", get_id(&me, source_p), RPL_INFO, get_id(source_p, source_p), info_table[i].name, option, info_table[i].desc ? info_table[i].desc : "<none>"); break; } /* * Output info_table[i].option as "ON" or "OFF" */ case OUTPUT_BOOLEAN: { int option = *((int *) info_table[i].option); sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", get_id(&me, source_p), RPL_INFO, get_id(source_p, source_p), info_table[i].name, option ? "ON" : "OFF", info_table[i].desc ? info_table[i].desc : "<none>"); break; } /* * Output info_table[i].option as "YES" or "NO" */ case OUTPUT_BOOLEAN_YN: { int option = *((int *) info_table[i].option); sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", get_id(&me, source_p), RPL_INFO, get_id(source_p, source_p), info_table[i].name, option ? "YES" : "NO", info_table[i].desc ? info_table[i].desc : "<none>"); break; } case OUTPUT_BOOLEAN2: { int option = *((int *) info_table[i].option); sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", me.name, RPL_INFO, source_p->name, info_table[i].name, option ? ((option == 1) ? "MASK" : "YES") : "NO", info_table[i].desc ? info_table[i].desc : "<none>"); } /* switch (info_table[i].output_type) */ } } /* forloop */ /* Don't send oper_only_umodes...it's a bit mask, we will have to decode it ** in order for it to show up properly to opers who issue INFO */ sendto_one_numeric(source_p, RPL_INFO, form_str(RPL_INFO), ""); }
int m_scan_cmodes(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[]) { char *cmode_string = parv[2], *c; unsigned int include_modes, exclude_modes; int require_autodline = 0, require_forward = 0; int what = MODE_ADD; int list_channels = 1; int list_max = 0; int listed_so_far = 0, count = 0; char *mask = NULL; struct Channel *achptr; int i; if (!HasUmode(sptr,UMODE_USER_AUSPEX)) { if (SeesOperMessages(sptr)) sendto_one(sptr,":%s NOTICE %s :You have no a umode", me.name, parv[0]); else sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (parc < 3) { if (!IsServer(sptr)) sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SCAN CMODES"); return 0; } include_modes = exclude_modes = 0; for (c = cmode_string; *c; c++) switch(*c) { case '+': what = MODE_ADD; break; case '-': what = MODE_DEL; break; default: { int this_mode = 0; switch(*c) { case 'c': this_mode = MODE_NOCOLOR; break; case 'D': require_autodline = what == MODE_ADD ? 1 : -1; break; #ifdef INVITE_CHANNEL_FORWARDING case 'f': require_forward = what == MODE_ADD ? 1 : -1; break; #endif case 'g': this_mode = MODE_FREEINVITE; break; case 'i': this_mode = MODE_INVITEONLY; break; #ifdef JUPE_CHANNEL case 'j': this_mode = MODE_JUPED; break; #endif case 'L': this_mode = MODE_LARGEBANLIST; break; case 'm': this_mode = MODE_MODERATED; break; case 'n': this_mode = MODE_NOPRIVMSGS; break; case 'P': this_mode = MODE_PERM; break; case 'Q': this_mode = MODE_NOFORWARD; break; case 'r': this_mode = MODE_NOUNIDENT; break; case 'R': this_mode = MODE_QUIETUNIDENT; break; case 's': this_mode = MODE_SECRET; break; case 't': this_mode = MODE_TOPICLIMIT; break; case 'z': this_mode = MODE_OPMODERATE; break; default: sendto_one(sptr, form_str(ERR_UNKNOWNMODE), me.name, sptr->name, *c); return 0; } if (what == MODE_ADD) include_modes |= this_mode; else exclude_modes |= this_mode; } } for (i = 3; i < parc; i++) { if (!irccmp(parv[i], "no-list")) list_channels = 0; else if (!irccmp(parv[i], "list")) list_channels = 1; else if (i < (parc - 1)) { if (!irccmp(parv[i], "list-max")) { list_max = strtoul(parv[++i], NULL, 0); } else if (!irccmp(parv[i], "mask")) { mask = parv[++i]; } } } for (achptr = channel; achptr; achptr = achptr->nextch) { if ((achptr->mode.mode & include_modes) != include_modes) continue; if ((achptr->mode.mode & exclude_modes)) continue; #ifdef INVITE_CHANNEL_FORWARDING if (achptr->mode.invite_forward_channel_name[0] && require_forward == -1) continue; if (!achptr->mode.invite_forward_channel_name[0] && require_forward == 1) continue; #endif if (achptr->mode.autodline_frequency && require_autodline == -1) continue; if (!achptr->mode.autodline_frequency && require_autodline == 1) continue; if (list_channels && (!list_max || (listed_so_far < list_max))) { static char modebuf[MODEBUFLEN]; static char parabuf[MODEBUFLEN]; listed_so_far++; *modebuf = *parabuf = '\0'; modebuf[1] = '\0'; channel_modes(sptr, modebuf, parabuf, achptr); sendto_one(sptr, form_str(RPL_CHANNELMODEIS), me.name, sptr->name, achptr->chname, modebuf, parabuf); } count++; } send_markup(sptr, &me, "CMODE-END", "End of channel mode list"); /* send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */ send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count); return 0; }
int m_scan_unklines(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[]) { char *mask = NULL; int list = 1, count = 0, listed_so_far = 0; int list_max = 100; int i; struct unkline_record **ukr, *ukr2; if (!HasUmode(sptr,UMODE_SEEKLINES)) { if (SeesOperMessages(sptr)) sendto_one(sptr,":%s NOTICE %s :You have no 2 umode", me.name, parv[0]); else sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (parc < 2) { if (!IsServer(sptr)) sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SCAN UNKLINES"); return 0; } for (i = 2; i < parc; i++) { if (!irccmp(parv[i], "no-list")) list = 0; else if (!irccmp(parv[i], "list")) list = 1; else if (i < (parc - 1)) { if (!irccmp(parv[i], "list-max")) { list_max = atoi(parv[++i]); } else if (!irccmp(parv[i], "mask")) { mask = parv[++i]; } } } for (ukr = &recorded_unklines; (ukr2 = *ukr); ukr = &ukr2->next) { if ((ukr2->placed + UNKLINE_CACHE_TIME) < CurrentTime) { *ukr = ukr2->next; MyFree(ukr2->mask); MyFree(ukr2); /* And put stuff back, safety in case we can't loop again */ if (!(ukr2 = *ukr)) break; } else { if (mask && !match(mask, ukr2->mask)) continue; count++; if (list && (list_max > ++listed_so_far)) /* send_markup(sptr, &me, "SCAN-UNKLINE", */ /* "!begin<1>%s!end<1> unklined at !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>)", */ /* ukr2->mask, ukr2->placed, ukr2->placed - CurrentTime); */ send_markup(sptr, &me, "SCAN-UNKLINE", "%s unklined at %s (%s)", ukr2->mask, smalldate(ukr2->placed), smalltime(ukr2->placed - CurrentTime)); } } send_markup(sptr, &me, "UNKLINE-END", "End of unkline list"); /* send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */ send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count); return 0; }
void m_registered(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { sendto_one(client_p, form_str(ERR_ALREADYREGISTRED), me.name, parv[0]); }
/* msg_client() * * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC * say NOTICE must not auto reply * - pointer to command, "PRIVMSG" or "NOTICE" * - pointer to source_p source (struct Client *) * - pointer to target_p target (struct Client *) * - pointer to text * output - NONE * side effects - message given channel either chanop or voice */ static void msg_client(int p_or_n, const char *command, struct Client *source_p, struct Client *target_p, const char *text) { if (MyClient(source_p)) { if (target_p->away[0] && p_or_n != NOTICE) sendto_one_numeric(source_p, &me, RPL_AWAY, target_p->name, target_p->away); if (HasUMode(target_p, UMODE_REGONLY) && target_p != source_p) { if (!HasUMode(source_p, UMODE_REGISTERED|UMODE_OPER)) { if (p_or_n != NOTICE) sendto_one_numeric(source_p, &me, ERR_NONONREG, target_p->name); return; } } } if (MyClient(target_p)) { if (!IsServer(source_p) && HasUMode(target_p, UMODE_CALLERID|UMODE_SOFTCALLERID)) { /* Here is the anti-flood bot/spambot code -db */ if (HasFlag(source_p, FLAGS_SERVICE) || accept_message(source_p, target_p) || (HasUMode(source_p, UMODE_OPER) && ConfigGeneral.opers_bypass_callerid)) { sendto_one(target_p, ":%s!%[email protected]%s %s %s :%s", source_p->name, source_p->username, source_p->host, command, target_p->name, text); } else { int callerid = !!HasUMode(target_p, UMODE_CALLERID); /* check for accept, flag recipient incoming message */ if (p_or_n != NOTICE) sendto_one_numeric(source_p, &me, RPL_TARGUMODEG, target_p->name, callerid ? "+g" : "+G", callerid ? "server side ignore" : "server side ignore with the exception of common channels"); if ((target_p->connection->last_caller_id_time + ConfigGeneral.caller_id_wait) < CurrentTime) { if (p_or_n != NOTICE) sendto_one_numeric(source_p, &me, RPL_TARGNOTIFY, target_p->name); sendto_one_numeric(target_p, &me, RPL_UMODEGMSG, get_client_name(source_p, HIDE_IP), callerid ? "+g" : "+G"); target_p->connection->last_caller_id_time = CurrentTime; } /* Only so opers can watch for floods */ flood_attack_client(p_or_n, source_p, target_p); } } else { /* * If the client is remote, we dont perform a special check for * flooding.. as we wouldn't block their message anyway.. this means * we dont give warnings.. we then check if theyre opered * (to avoid flood warnings), lastly if theyre our client * and flooding -- fl */ if (!MyClient(source_p) || HasUMode(source_p, UMODE_OPER) || !flood_attack_client(p_or_n, source_p, target_p)) sendto_anywhere(target_p, source_p, command, ":%s", text); } } else if (!MyClient(source_p) || HasUMode(source_p, UMODE_OPER) || !flood_attack_client(p_or_n, source_p, target_p)) sendto_anywhere(target_p, source_p, command, ":%s", text); }
int m_alias(aClient *cptr, aClient *sptr, int parc, char *parv[], char *cmd) { ConfigItem_alias *alias; aClient *acptr; int ret; if (!(alias = Find_alias(cmd))) { sendto_one(sptr, ":%s %d %s %s :Unknown command", me.name, ERR_UNKNOWNCOMMAND, parv[0], cmd); return 0; } /* If it isn't an ALIAS_COMMAND, we require a paramter ... We check ALIAS_COMMAND LATER */ if (alias->type != ALIAS_COMMAND && (parc < 2 || *parv[1] == '\0')) { sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]); return -1; } if (alias->type == ALIAS_SERVICES) { if (SERVICES_NAME && (acptr = find_person(alias->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0) return ret; sendto_one(acptr, ":%s PRIVMSG %[email protected]%s :%s", parv[0], alias->nick, SERVICES_NAME, parv[1]); } else sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0], alias->nick); } else if (alias->type == ALIAS_STATS) { if (STATS_SERVER && (acptr = find_person(alias->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0) return ret; sendto_one(acptr, ":%s PRIVMSG %[email protected]%s :%s", parv[0], alias->nick, STATS_SERVER, parv[1]); } else sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0], alias->nick); } else if (alias->type == ALIAS_NORMAL) { if ((acptr = find_person(alias->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0) return ret; if (MyClient(acptr)) sendto_one(acptr, ":%s!%[email protected]%s PRIVMSG %s :%s", parv[0], sptr->user->username, GetHost(sptr), alias->nick, parv[1]); else sendto_one(acptr, ":%s PRIVMSG %s :%s", parv[0], alias->nick, parv[1]); } else sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], alias->nick); } else if (alias->type == ALIAS_CHANNEL) { aChannel *chptr; if ((chptr = find_channel(alias->nick, NULL))) { if (!can_send(sptr, chptr, parv[1], 0)) { if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_CHANMSG, chptr->chname, 0, NULL)) < 0) return ret; sendto_channelprefix_butone(sptr, sptr, chptr, PREFIX_ALL, ":%s PRIVMSG %s :%s", parv[0], chptr->chname, parv[1]); return 0; } } sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, parv[0], cmd, "You may not use this command at this time"); } else if (alias->type == ALIAS_COMMAND) { ConfigItem_alias_format *format; char *ptr = ""; if (!(parc < 2 || *parv[1] == '\0')) ptr = parv[1]; for (format = alias->format; format; format = (ConfigItem_alias_format *)format->next) { if (regexec(&format->expr, ptr, 0, NULL, 0) == 0) { /* Parse the parameters */ int i = 0, j = 0, k = 1; char output[1024], current[1024]; char nums[4]; bzero(current, sizeof current); bzero(output, sizeof output); while(format->parameters[i] && j < 500) { k = 0; if (format->parameters[i] == '%') { i++; if (format->parameters[i] == '%') output[j++] = '%'; else if (isdigit(format->parameters[i])) { for(; isdigit(format->parameters[i]) && k < 2; i++, k++) { nums[k] = format->parameters[i]; } nums[k] = 0; i--; if (format->parameters[i+1] == '-') { strrangetok(ptr, current, ' ', atoi(nums),0); i++; } else strrangetok(ptr, current, ' ', atoi(nums), atoi(nums)); if (!*current) continue; if (j + strlen(current)+1 >= 500) break; strlcat(output, current, sizeof output); j += strlen(current); } else if (format->parameters[i] == 'n' || format->parameters[i] == 'N') { strlcat(output, parv[0], sizeof output); j += strlen(parv[0]); } else { output[j++] = '%'; output[j++] = format->parameters[i]; } i++; continue; } output[j++] = format->parameters[i++]; } output[j] = 0; /* Now check to make sure we have something to send */ if (strlen(output) == 0) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, cmd); return -1; } if (format->type == ALIAS_SERVICES) { if (SERVICES_NAME && (acptr = find_person(format->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0) return ret; sendto_one(acptr, ":%s PRIVMSG %[email protected]%s :%s", parv[0], format->nick, SERVICES_NAME, output); } else sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0], format->nick); } else if (format->type == ALIAS_STATS) { if (STATS_SERVER && (acptr = find_person(format->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0) return ret; sendto_one(acptr, ":%s PRIVMSG %[email protected]%s :%s", parv[0], format->nick, STATS_SERVER, output); } else sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0], format->nick); } else if (format->type == ALIAS_NORMAL) { if ((acptr = find_person(format->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0) return ret; if (MyClient(acptr)) sendto_one(acptr, ":%s!%[email protected]%s PRIVMSG %s :%s", parv[0], sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost, format->nick, output); else sendto_one(acptr, ":%s PRIVMSG %s :%s", parv[0], format->nick, output); } else sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], format->nick); } else if (format->type == ALIAS_CHANNEL) { aChannel *chptr; if ((chptr = find_channel(format->nick, NULL))) { if (!can_send(sptr, chptr, output, 0)) { if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_CHANMSG, chptr->chname, 0, NULL)) < 0) return ret; sendto_channelprefix_butone(sptr, sptr, chptr, PREFIX_ALL, ":%s PRIVMSG %s :%s", parv[0], chptr->chname, parv[1]); return 0; } } sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, parv[0], cmd, "You may not use this command at this time"); } else if (format->type == ALIAS_REAL) { int ret; char mybuf[500]; snprintf(mybuf, sizeof(mybuf), "%s %s", format->nick, output); if (recursive_alias) { sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, parv[0], cmd, "You may not use this command at this time -- recursion"); return -1; } recursive_alias = 1; ret = parse(sptr, mybuf, mybuf+strlen(mybuf)); recursive_alias = 0; return ret; } break; } } return 0; } return 0; }
static int m_displaymsg(struct Client *source_p, const char *channel, int underline, int action, const char *nick, const char *text) { struct Channel *chptr; struct membership *msptr; char nick2[NICKLEN+1]; char nick3[NICKLEN+1]; char text2[BUFSIZE]; if((chptr = find_channel(channel)) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), channel); return 0; } if(!(msptr = find_channel_membership(chptr, source_p))) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), chptr->chname); return 0; } if(!(chptr->mode.mode & chmode_flags['N'])) { sendto_one_numeric(source_p, 573, "%s :Roleplay commands are not enabled on this channel.", chptr->chname); return 0; } if(!can_send(chptr, source_p, msptr)) { sendto_one_numeric(source_p, 573, "%s :Cannot send to channel.", chptr->chname); return 0; } /* enforce flood stuff on roleplay commands */ if(flood_attack_channel(0, source_p, chptr, chptr->chname)) return 0; /* enforce target change on roleplay commands */ if(!is_chanop_voiced(msptr) && !IsOper(source_p) && !add_channel_target(source_p, chptr)) { sendto_one(source_p, form_str(ERR_TARGCHANGE), me.name, source_p->name, chptr->chname); return 0; } rb_strlcpy(nick3, nick, sizeof(nick3)); if(underline) snprintf(nick2, sizeof(nick2), "\x1F%s\x1F", strip_unprintable(nick3)); else snprintf(nick2, sizeof(nick2), "%s", strip_unprintable(nick3)); /* don't allow nicks to be empty after stripping * this prevents nastiness like fake factions, etc. */ if(EmptyString(nick3)) { sendto_one_numeric(source_p, 573, "%s :No visible non-stripped characters in nick.", chptr->chname); return 0; } if(action) snprintf(text2, sizeof(text2), "\1ACTION %s\1", text); else snprintf(text2, sizeof(text2), "%s", text); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%[email protected] PRIVMSG %s :%s (%s)", nick2, source_p->name, channel, text2, source_p->name); sendto_match_servs(source_p, "*", CAP_ENCAP, NOCAPS, "ENCAP * ROLEPLAY %s %s :%s", channel, nick2, text2); return 0; }
/* * m_lljoin * parv[0] = sender prefix * parv[1] = channel * parv[2] = nick ("!nick" == cjoin) * parv[3] = key (optional) * * If a lljoin is received, from our uplink, join * the requested client to the given channel, or ignore it * if there is an error. * * Ok, the way this works. Leaf client tries to join a channel, * it doesn't exist so the join does a cburst request on behalf of the * client, and aborts that join. The cburst sjoin's the channel if it * exists on the hub, and sends back an LLJOIN to the leaf. Thats where * this is now.. * */ static void ms_lljoin(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *chname = NULL; char *nick = NULL; char *key = NULL; int flags; int i; struct Client *target_p; struct Channel *chptr; if (uplink && !IsCapable(uplink,CAP_LL)) { sendto_realops_flags(UMODE_ALL, L_ALL, "*** LLJOIN requested from non LL server %s", client_p->name); return; } chname = parv[1]; if(chname == NULL) return; nick = parv[2]; if(nick == NULL) return; if (parc >3) key = parv[3]; flags = 0; target_p = find_person(client_p, nick); if (!target_p) return; if (!MyClient(target_p)) return; if (!check_channel_name(chname, 0)) { sendto_gnotice_flags(UMODE_DEBUG, L_ALL, me.name, &me, NULL, "*** Too long or invalid channel name from %s: %s", target_p->name, chname); return; } chptr = make_channel(chname); flags = CHFL_CHANOP; if(!chptr) return; if (dlink_list_length(&chptr->members) == 0) flags = CHFL_CHANOP; else flags = 0; /* XXX in m_join.c :( */ /* check_spambot_warning(target_p, chname); */ /* They _could_ join a channel twice due to lag */ if(chptr) { if (IsMember(target_p, chptr)) /* already a member, ignore this */ return; } else { sendto_one(target_p, form_str(ERR_UNAVAILRESOURCE), me.name, nick, chptr->chname); return; } if ((i = can_join(target_p, chptr, key))) { sendto_one(target_p, form_str(i), me.name, nick, chptr->chname); return; } if ((dlink_list_length(&target_p->channel) >= ConfigChannel.max_chans_per_user) && (!IsOper(target_p) || (dlink_list_length(&target_p->channel) >= ConfigChannel.max_chans_per_user*3))) { sendto_one(target_p, form_str(ERR_TOOMANYCHANNELS), me.name, nick, chptr->chname ); return; } if (flags == CHFL_CHANOP) { chptr->channelts = CurrentTime; sendto_one(uplink, ":%s SJOIN %lu %s + :@%s", me.name, (unsigned long) chptr->channelts, chptr->chname, nick); } sendto_one(uplink, ":%s SJOIN %lu %s + :%s", me.name, (unsigned long) chptr->channelts, chptr->chname, nick); add_user_to_channel(chptr, target_p, flags, YES); sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%[email protected]%s JOIN :%s", target_p->name, target_p->username, target_p->host, chptr->chname); if (flags & CHFL_CHANOP) { chptr->mode.mode |= MODE_TOPICLIMIT; chptr->mode.mode |= MODE_NOPRIVMSGS; sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s +nt", me.name, chptr->chname); sendto_one(uplink, ":%s MODE %s +nt", me.name, chptr->chname); } channel_member_names(target_p, chptr, 1); }
/* ** mo_ojoin ** parv[1] = channel */ static int mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr; int move_me = 0; /* admins only */ if(!IsOperAdmin(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin"); return 0; } if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!' || *parv[1] == '~') { parv[1]++; move_me = 1; } else { sendto_one_notice(source_p, ":Unrecognized op prefix '%c'", *parv[1]); return 0; } if((chptr = find_channel(parv[1])) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } if(IsMember(source_p, chptr)) { sendto_one_notice(source_p, ":Please part %s before using OJOIN", parv[1]); return 0; } if(move_me == 1) parv[1]--; /* only sends stuff for #channels remotely */ if(*parv[1] == '!') { if(!ConfigChannel.use_admin) { sendto_one_notice(source_p, ":This server's configuration file does not support admin prefix"); return 0; } add_user_to_channel(chptr, source_p, CHFL_ADMIN); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :!%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%[email protected]%s JOIN %s", source_p->name, source_p->username, source_p->host, chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '@') { add_user_to_channel(chptr, source_p, CHFL_CHANOP); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :@%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '%') { if(!ConfigChannel.use_halfop) { sendto_one_notice(source_p, ":This server's configuration file does not support halfop prefix"); return 0; } add_user_to_channel(chptr, source_p, CHFL_HALFOP); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :%s%s", me.id, (long) chptr->channelts, chptr->chname, "%", source_p->id); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%[email protected]%s JOIN %s", source_p->name, source_p->username, source_p->host, chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '+') { add_user_to_channel(chptr, source_p, CHFL_VOICE); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :+%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +v %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '~') { if(!ConfigChannel.use_founder) { sendto_one_notice(source_p, ":This server's configuration file does not support founder prefix"); return 0; } add_user_to_channel(chptr, source_p, CHFL_FOUNDER); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :~%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +u %s", me.name, chptr->chname, source_p->name); } else { add_user_to_channel(chptr, source_p, CHFL_PEON); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s JOIN %ld %s +", source_p->id, (long) chptr->channelts, chptr->chname); send_channel_join(chptr, source_p); } /* send the topic... */ if(chptr->topic != NULL) { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); } source_p->localClient->last_join_time = rb_current_time(); channel_member_names(chptr, source_p, 1); sendto_realops_snomask(SNO_GENERAL, L_ALL, "OJOIN called for %s by %s!%[email protected]%s", parv[1], source_p->name, source_p->username, source_p->host); ilog(L_MAIN, "OJOIN called for %s by %s", parv[1], get_oper_name(source_p)); return 0; }
static void ms_cburst(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *name; char *nick; const char *key; struct Channel *chptr; if(parc < 2 || *parv[1] == '\0') return; name = parv[1]; if(parc > 2) nick = parv[2]; else nick = NULL; if(parc > 3) key = parv[3]; else key = ""; #ifdef DEBUGLL sendto_realops_flags(UMODE_ALL, L_ALL, "CBURST called by %s for %s %s %s", client_p->name, name, nick ? nick : "", key ? key : ""); #endif if((chptr = hash_find_channel(name)) == NULL) { if((!nick) || (nick && *nick != '!')) { if(!check_channel_name(name, 0)) { sendto_realops_flags(UMODE_DEBUG, L_ALL, "*** Too long or invalid channel name from %s: %s", client_p->name, name); return; } chptr = make_channel(name); chptr->channelts = (time_t) (-1); /* highest possible TS so its always * over-ruled */ } else if(nick && *nick == '!') { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, nick + 1, name); return; } } if(IsCapable(client_p, CAP_LL)) { burst_channel(client_p, chptr); if(nick) sendto_one(client_p, ":%s LLJOIN %s %s %s", me.name, name, nick, key); } else { sendto_realops_flags(UMODE_ALL, L_ALL, "*** CBURST request received from non LL capable server! [%s]", client_p->name); } }
static int mo_testline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct ConfItem *aconf; struct ConfItem *resv_p; struct rb_sockaddr_storage ip; char user_trunc[USERLEN + 1], notildeuser_trunc[USERLEN + 1]; const char *name = NULL; const char *username = NULL; const char *host = NULL; char *mask; char *p; int host_mask; int type; int duration; char *puser, *phost, *reason, *operreason; char reasonbuf[BUFSIZE]; mask = LOCAL_COPY(parv[1]); if (IsChannelName(mask)) { resv_p = hash_find_resv(mask); if (resv_p != NULL) { sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, resv_p->hold ? 'q' : 'Q', resv_p->hold ? (long) ((resv_p->hold - rb_current_time()) / 60) : 0L, resv_p->host, resv_p->passwd); /* this is a false positive, so make sure it isn't counted in stats q * --nenolod */ resv_p->port--; } else sendto_one(source_p, form_str(RPL_NOTESTLINE), me.name, source_p->name, parv[1]); return 0; } if((p = strchr(mask, '!'))) { *p++ = '\0'; name = mask; mask = p; if(EmptyString(mask)) return 0; } if((p = strchr(mask, '@'))) { *p++ = '\0'; username = mask; host = p; if(EmptyString(host)) return 0; } else host = mask; /* parses as an IP, check for a dline */ if((type = parse_netmask(host, &ip, &host_mask)) != HM_HOST) { #ifdef RB_IPV6 if(type == HM_IPV6) aconf = find_dline((struct sockaddr *)&ip, AF_INET6); else #endif aconf = find_dline((struct sockaddr *)&ip, AF_INET); if(aconf && aconf->status & CONF_DLINE) { get_printable_kline(source_p, aconf, &phost, &reason, &puser, &operreason); snprintf(reasonbuf, sizeof(reasonbuf), "%s%s%s", reason, operreason ? "|" : "", operreason ? operreason : ""); sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'd' : 'D', (aconf->flags & CONF_FLAGS_TEMPORARY) ? (long) ((aconf->hold - rb_current_time()) / 60) : 0L, phost, reasonbuf); return 0; } /* Otherwise, aconf is an exempt{} */ if(aconf == NULL && (duration = is_reject_ip((struct sockaddr *)&ip))) sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, '!', duration / 60L, host, "Reject cache"); if(aconf == NULL && (duration = is_throttle_ip((struct sockaddr *)&ip))) sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, '!', duration / 60L, host, "Throttled"); } if (username != NULL) { rb_strlcpy(user_trunc, username, sizeof user_trunc); rb_strlcpy(notildeuser_trunc, *username == '~' ? username + 1 : username, sizeof notildeuser_trunc); } else { rb_strlcpy(user_trunc, "dummy", sizeof user_trunc); rb_strlcpy(notildeuser_trunc, "dummy", sizeof notildeuser_trunc); } /* now look for a matching I/K/G */ if((aconf = find_address_conf(host, NULL, user_trunc, notildeuser_trunc, (type != HM_HOST) ? (struct sockaddr *)&ip : NULL, (type != HM_HOST) ? ( #ifdef RB_IPV6 (type == HM_IPV6) ? AF_INET6 : #endif AF_INET) : 0, NULL))) { static char buf[HOSTLEN+USERLEN+2]; if(aconf->status & CONF_KILL) { get_printable_kline(source_p, aconf, &phost, &reason, &puser, &operreason); snprintf(buf, sizeof(buf), "%[email protected]%s", puser, phost); snprintf(reasonbuf, sizeof(reasonbuf), "%s%s%s", reason, operreason ? "|" : "", operreason ? operreason : ""); sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'k' : 'K', (aconf->flags & CONF_FLAGS_TEMPORARY) ? (long) ((aconf->hold - rb_current_time()) / 60) : 0L, buf, reasonbuf); return 0; } } /* they asked us to check a nick, so hunt for resvs.. */ if(name && (resv_p = find_nick_resv(name))) { sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, resv_p->hold ? 'q' : 'Q', resv_p->hold ? (long) ((resv_p->hold - rb_current_time()) / 60) : 0L, resv_p->host, resv_p->passwd); /* this is a false positive, so make sure it isn't counted in stats q * --nenolod */ resv_p->port--; return 0; } /* no matching resv, we can print the I: if it exists */ if(aconf && aconf->status & CONF_CLIENT) { sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), aconf->info.name, EmptyString(aconf->spasswd) ? "<NULL>" : aconf->spasswd, show_iline_prefix(source_p, aconf, aconf->user), aconf->host, aconf->port, aconf->className); return 0; } /* nothing matches.. */ sendto_one(source_p, form_str(RPL_NOTESTLINE), me.name, source_p->name, parv[1]); return 0; }
/* * m_challenge - generate RSA challenge for wouldbe oper * parv[1] = operator to challenge for, or +response * */ static int m_challenge(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct oper_conf *oper_p; char *challenge = NULL; /* to placate gcc */ char chal_line[CHALLENGE_WIDTH]; unsigned char *b_response; size_t cnt; int len = 0; /* if theyre an oper, reprint oper motd and ignore */ if(IsOper(source_p)) { sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name); send_oper_motd(source_p); return 0; } if(*parv[1] == '+') { /* Ignore it if we aren't expecting this... -A1kmm */ if(!source_p->localClient->challenge) return 0; if((rb_current_time() - source_p->localClient->chal_time) > CHALLENGE_EXPIRES) { sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name); ilog(L_FOPER, "EXPIRED CHALLENGE (%s) by (%s!%[email protected]%s) (%s)", source_p->localClient->opername, source_p->name, source_p->username, source_p->host, source_p->sockhost); if(ConfigFileEntry.failed_oper_notice) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Expired CHALLENGE attempt by %s (%[email protected]%s)", source_p->name, source_p->username, source_p->host); cleanup_challenge(source_p); return 0; } parv[1]++; b_response = rb_base64_decode((const unsigned char *)parv[1], strlen(parv[1]), &len); if(len != SHA_DIGEST_LENGTH || memcmp(source_p->localClient->challenge, b_response, SHA_DIGEST_LENGTH)) { sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name); ilog(L_FOPER, "FAILED CHALLENGE (%s) by (%s!%[email protected]%s) (%s)", source_p->localClient->opername, source_p->name, source_p->username, source_p->host, source_p->sockhost); if(ConfigFileEntry.failed_oper_notice) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Failed CHALLENGE attempt by %s (%[email protected]%s)", source_p->name, source_p->username, source_p->host); rb_free(b_response); cleanup_challenge(source_p); return 0; } rb_free(b_response); oper_p = find_oper_conf(source_p->username, source_p->orighost, source_p->sockhost, source_p->localClient->opername); if(oper_p == NULL) { sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST)); ilog(L_FOPER, "FAILED OPER (%s) by (%s!%[email protected]%s) (%s)", source_p->localClient->opername, source_p->name, source_p->username, source_p->host, source_p->sockhost); if(ConfigFileEntry.failed_oper_notice) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Failed CHALLENGE attempt - host mismatch by %s (%[email protected]%s)", source_p->name, source_p->username, source_p->host); return 0; } cleanup_challenge(source_p); oper_up(source_p, oper_p); ilog(L_OPERED, "OPER %s by %s!%[email protected]%s (%s)", source_p->localClient->opername, source_p->name, source_p->username, source_p->host, source_p->sockhost); return 0; } cleanup_challenge(source_p); oper_p = find_oper_conf(source_p->username, source_p->orighost, source_p->sockhost, parv[1]); if(oper_p == NULL) { sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST)); ilog(L_FOPER, "FAILED OPER (%s) by (%s!%[email protected]%s) (%s)", parv[1], source_p->name, source_p->username, source_p->host, source_p->sockhost); if(ConfigFileEntry.failed_oper_notice) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Failed CHALLENGE attempt - host mismatch by %s (%[email protected]%s)", source_p->name, source_p->username, source_p->host); return 0; } if(!oper_p->rsa_pubkey) { sendto_one_notice(source_p, ":I'm sorry, PK authentication is not enabled for your oper{} block."); return 0; } if(IsOperConfNeedSSL(oper_p) && !IsSSLClient(source_p)) { sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST)); ilog(L_FOPER, "FAILED CHALLENGE (%s) by (%s!%[email protected]%s) (%s) -- requires SSL/TLS", parv[1], source_p->name, source_p->username, source_p->host, source_p->sockhost); if(ConfigFileEntry.failed_oper_notice) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Failed CHALLENGE attempt - missing SSL/TLS by %s (%[email protected]%s)", source_p->name, source_p->username, source_p->host); } return 0; } if (oper_p->certfp != NULL) { if (source_p->certfp == NULL || strcasecmp(source_p->certfp, oper_p->certfp)) { sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST)); ilog(L_FOPER, "FAILED OPER (%s) by (%s!%[email protected]%s) (%s) -- client certificate fingerprint mismatch", parv[1], source_p->name, source_p->username, source_p->host, source_p->sockhost); if(ConfigFileEntry.failed_oper_notice) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Failed OPER attempt - client certificate fingerprint mismatch by %s (%[email protected]%s)", source_p->name, source_p->username, source_p->host); } return 0; } } if(!generate_challenge(&challenge, &(source_p->localClient->challenge), oper_p->rsa_pubkey)) { char *chal = challenge; source_p->localClient->chal_time = rb_current_time(); for(;;) { cnt = rb_strlcpy(chal_line, chal, CHALLENGE_WIDTH); sendto_one(source_p, form_str(RPL_RSACHALLENGE2), me.name, source_p->name, chal_line); if(cnt > CHALLENGE_WIDTH) chal += CHALLENGE_WIDTH - 1; else break; } sendto_one(source_p, form_str(RPL_ENDOFRSACHALLENGE2), me.name, source_p->name); rb_free(challenge); source_p->localClient->opername = rb_strdup(oper_p->name); } else sendto_one_notice(source_p, ":Failed to generate challenge."); return 0; }
/* * * parc number of arguments ('sender' counted as one!) * parv[0] pointer to 'sender' (may point to empty string) (not used) * parv[1]..parv[parc-1] * pointers to additional parameters, this is a NULL * terminated list (parv[parc] == NULL). * * *WARNING* * Numerics are mostly error reports. If there is something * wrong with the message, just *DROP* it! Don't even think of * sending back a neat error message -- big danger of creating * a ping pong error message... */ static void do_numeric(char numeric[], struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p; struct Channel *chptr; if(parc < 2 || !IsServer(source_p)) return; /* Remap low number numerics. */ if(numeric[0] == '0') numeric[0] = '1'; /* * Prepare the parameter portion of the message into 'buffer'. * (Because the buffer is twice as large as the message buffer * for the socket, no overflow can occur here... ...on current * assumptions--bets are off, if these are changed --msa) * Note: if buffer is non-empty, it will begin with SPACE. */ if(parc > 1) { char *t = buffer; /* Current position within the buffer */ int i; int tl; /* current length of presently being built string in t */ for (i = 2; i < (parc - 1); i++) { tl = ircsprintf(t, " %s", parv[i]); t += tl; } ircsprintf(t, " :%s", parv[parc - 1]); } if((target_p = find_client(parv[1])) != NULL) { if(IsMe(target_p)) { /* * We shouldn't get numerics sent to us, * any numerics we do get indicate a bug somewhere.. */ /* ugh. this is here because of nick collisions. when two servers * relink, they burst each other their nicks, then perform collides. * if there is a nick collision, BOTH servers will kill their own * nicks, and BOTH will kill the other servers nick, which wont exist, * because it will have been already killed by the local server. * * unfortunately, as we cant guarantee other servers will do the * "right thing" on a nick collision, we have to keep both kills. * ergo we need to ignore ERR_NOSUCHNICK. --fl_ */ /* quick comment. This _was_ tried. i.e. assume the other servers * will do the "right thing" and kill a nick that is colliding. * unfortunately, it did not work. --Dianora */ if(atoi(numeric) != ERR_NOSUCHNICK) sendto_realops_flags(UMODE_ALL, L_ADMIN, "*** %s(via %s) sent a %s numeric to me: %s", source_p->name, client_p->name, numeric, buffer); return; } else if(target_p->from == client_p) { /* This message changed direction (nick collision?) * ignore it. */ return; } /* csircd will send out unknown umode flag for +a (admin), drop it here. */ if((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p)) return; /* Fake it for server hiding, if its our client */ if(ConfigServerHide.hide_servers && MyClient(target_p) && !IsOper(target_p)) sendto_one(target_p, ":%s %s %s%s", me.name, numeric, parv[1], buffer); else sendto_one(target_p, ":%s %s %s%s", source_p->name, numeric, parv[1], buffer); return; } else if((chptr = hash_find_channel(parv[1])) != NULL) sendto_channel_local(ALL_MEMBERS, chptr, ":%s %s %s %s", source_p->name, numeric, chptr->chname, buffer); }
/* * m_die - DIE command handler */ int m_die(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { struct Client* acptr; int i; if (!MyClient(sptr) || !IsAnOper(sptr)) { sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (!IsOperDie(sptr)) { sendto_one(sptr,":%s NOTICE %s :You have no D flag", me.name, parv[0]); return 0; } if (parc < 2) { sendto_one(sptr,":%s NOTICE %s :Need server name /die %s", me.name,sptr->name,me.name); return 0; } else { if (irccmp(parv[1], me.name)) { sendto_one(sptr,":%s NOTICE %s :Mismatch on /die %s", me.name,sptr->name,me.name); return 0; } } for (i = 0; i <= highest_fd; i++) { if (!(acptr = local[i])) continue; if (IsClient(acptr)) { if(IsAnOper(acptr)) sendto_one(acptr, ":%s NOTICE %s :Server Terminating. %s", me.name, acptr->name, get_client_name(sptr, HIDE_IP)); else sendto_one(acptr, ":%s NOTICE %s :Server Terminating. %s", me.name, acptr->name, get_client_name(sptr, MASK_IP)); } else if (IsServer(acptr)) sendto_one(acptr, ":%s ERROR :Terminated by %s", me.name, get_client_name(sptr, MASK_IP)); } flush_connections(0); irclog(L_NOTICE, "Server terminated by %s", get_client_name(sptr, HIDE_IP)); /* * this is a normal exit, tell the os it's ok */ exit(0); /* NOT REACHED */ return 0; }
/* * m_not_oper * inputs - * output - * side effects - just returns a nastyogram to given user */ void m_not_oper(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { sendto_one(source_p, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); }
/* ** m_sendumode - Stskeeps ** parv[0] = sender prefix ** parv[1] = target ** parv[2] = message text ** Pretty handy proc.. ** Servers can use this to f.x: ** :server.unreal.net SENDUMODE F :Client connecting at server server.unreal.net port 4141 usw.. ** or for sending msgs to locops.. :P */ DLLFUNC int m_sendumode(aClient *cptr, aClient *sptr, int parc, char *parv[]) { char *message; char *p; int i; long umode_s = 0; long snomask = 0; aClient* acptr; message = (parc > 3) ? parv[3] : parv[2]; if (parc < 3) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SENDUMODE"); return 0; } if (!IsServer(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } sendto_serv_butone(IsServer(cptr) ? cptr : NULL, ":%s SMO %s :%s", parv[0], parv[1], message); for (p = parv[1]; *p; p++) { umode_s = 0; for(i = 0; i <= Usermode_highest; i++) { if (!Usermode_Table[i].flag) continue; if (Usermode_Table[i].flag == *p) { umode_s |= Usermode_Table[i].mode; break; } } if (i <= Usermode_highest) continue; for(i = 0; i <= Snomask_highest; i++) { if (Snomask_Table[i].flag == *p) { snomask |= Snomask_Table[i].mode; break; } } } if (parc > 3) for(p = parv[2]; *p; p++) { for (i = 0; i <= Snomask_highest; i++) { if (Snomask_Table[i].flag == *p) { snomask |= Snomask_Table[i].mode; break; } } } for(i = 0; i <= LastSlot; i++) if((acptr = local[i]) && IsPerson(acptr) && ((acptr->user->snomask & snomask) || (acptr->umodes & umode_s))) { sendto_one(acptr, ":%s NOTICE %s :%s", me.name, acptr->name, message); } return 0; }
/* * mo_omode - MODE command handler * parv[1] - channel */ static int mo_omode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; char params[512]; int i; int wasonchannel; /* admins only */ if(!IsOperAdmin(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin"); return 0; } /* Now, try to find the channel in question */ if(!IsChanPrefix(parv[1][0]) || !check_channel_name(parv[1])) { sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[1]); return 0; } chptr = find_channel(parv[1]); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } /* Now know the channel exists */ msptr = find_channel_membership(chptr, source_p); wasonchannel = msptr != NULL; if (is_chanop(msptr)) { sendto_one_notice(source_p, ":Use a normal MODE you idiot"); return 0; } params[0] = '\0'; for (i = 2; i < parc; i++) { if (i != 2) rb_strlcat(params, " ", sizeof params); rb_strlcat(params, parv[i], sizeof params); } sendto_wallops_flags(UMODE_WALLOP, &me, "OMODE called for [%s] [%s] by %s!%[email protected]%s", parv[1], params, source_p->name, source_p->username, source_p->host); ilog(L_MAIN, "OMODE called for [%s] [%s] by %s", parv[1], params, get_oper_name(source_p)); if(*chptr->chname != '&') sendto_server(NULL, NULL, NOCAPS, NOCAPS, ":%s WALLOPS :OMODE called for [%s] [%s] by %s!%[email protected]%s", me.name, parv[1], params, source_p->name, source_p->username, source_p->host); #if 0 set_channel_mode(client_p, source_p->servptr, chptr, msptr, parc - 2, parv + 2); #else if (parc == 4 && !strcmp(parv[2], "+o") && !irccmp(parv[3], source_p->name)) { /* Opping themselves */ if (!wasonchannel) { sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname); return 0; } sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s", me.name, parv[1], source_p->name); sendto_server(NULL, chptr, CAP_TS6, NOCAPS, ":%s TMODE %ld %s +o %s", me.id, (long) chptr->channelts, parv[1], source_p->id); msptr->flags |= CHFL_CHANOP; } else { /* Hack it so set_channel_mode() will accept */ if (wasonchannel) msptr->flags |= CHFL_CHANOP; else { add_user_to_channel(chptr, source_p, CHFL_CHANOP); msptr = find_channel_membership(chptr, source_p); } set_channel_mode(client_p, source_p, chptr, msptr, parc - 2, parv + 2); /* We know they were not opped before and they can't have opped * themselves as set_channel_mode() does not allow that * -- jilles */ if (wasonchannel) msptr->flags &= ~CHFL_CHANOP; else remove_user_from_channel(msptr); } #endif return 0; }
int build_searchopts(aClient *sptr, int parc, char *parv[]) { static char *who_oper_help[] = { "/WHO [+|-][acghilmnstuCM] [args]", "Flags are specified like channel modes,", "The flags cghimnsu all have arguments", "Flags are set to a positive check by +, a negative check by -", "The flags work as follows:", "Flag a: user is away", "Flag c <channel>: user is on <channel>,", " no wildcards accepted", "Flag g <gcos/realname>: user has string <gcos> in their GCOS,", " wildcards accepted, oper only", "Flag h <host>: user has string <host> in their hostname,", " wildcards accepted", "Flag i <ip>: user is from <ip>, wildcards and cidr accepted,", "Flag m <usermodes>: user has <usermodes> set on them", "Flag n <nick>: user has string <nick> in their nickname,", " wildcards accepted", "Flag s <server>: user is on server <server>,", " wildcards not accepted", "Flag t <seconds>: (+t) show nicks in use for more than or equal to <seconds> seconds", " (-t) show nicks in use for less than <seconds> seconds", "Flag u <user>: user has string <user> in their username,", " wildcards accepted", "Flag T <type>: user is of type <type>, where type is assigned", " by services.", "Behavior flags:", "Flag C: show first visible channel user is in", "Flag M: check for user in channels I am a member of", "Flag I: always show IPs instead of hosts", NULL }; static char *who_user_help[] = { "/WHO [+|-][achmnsuCM] [args]", "Flags are specified like channel modes,", "The flags cghimnsu all have arguments", "Flags are set to a positive check by +, a negative check by -", "The flags work as follows:", "Flag a: user is away", "Flag c <channel>: user is on <channel>,", " no wildcards accepted", "Flag h <host>: user has string <host> in their hostname,", " wildcards accepted", "Flag m <usermodes>: user has <usermodes> set on them,", " only usermodes o/O/a/A will return a result", "Flag n <nick>: user has string <nick> in their nickname,", " wildcards accepted", "Flag s <server>: user is on server <server>,", " wildcards not accepted", "Flag u <user>: user has string <user> in their username,", " wildcards accepted", "Behavior flags:", "Flag C: show first visible channel user is in", "Flag M: check for user in channels I am a member of", NULL }; char *flags, change=1, *s, *err; int args=1, i, rval; memset((char *)&wsopts, '\0', sizeof(SOpts)); /* if we got no extra arguments, send them the help. yeech. */ /* if it's /who ?, send them the help */ if(parc < 1 || parv[0][0]=='?') { /* So we don't confuse users with flags they cannot use, a different /who ? output will be given to users and opers -srd */ char **ptr = NULL; if (!IsAnOper(sptr)) ptr = who_user_help; else ptr = who_oper_help; for (; *ptr; ptr++) sendto_one(sptr, getreply(RPL_COMMANDSYNTAX), me.name, sptr->name, *ptr); sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name, "?","WHO"); return 0; } /* backwards compatibility */ else if(parv[0][0]=='0' && parv[0][1]==0) { if(parc>1 && *parv[1]=='o') { wsopts.check_umode=1; wsopts.umode_plus=1; wsopts.umodes=UMODE_o; } wsopts.host_plus=1; wsopts.host="*"; return 1; } /* if the first argument isn't a list of stuff */ else if(parv[0][0]!='+' && parv[0][0]!='-') { if(parv[0][0]=='#' || parv[0][0]=='&') { wsopts.channel=find_channel(parv[0],NullChn); if(wsopts.channel==NULL) { sendto_one(sptr, getreply(ERR_NOSUCHCHANNEL), me.name, sptr->name, parv[0]); return 0; } } else if (IsAnOper(sptr)) { int bits; bits = inet_parse_cidr(AF_INET, parv[0], &wsopts.cidr_ip, sizeof(wsopts.cidr_ip)); if (bits > 0) { wsopts.cidr_family = AF_INET; wsopts.cidr_bits = bits; wsopts.cidr_plus = 1; } else { bits = inet_parse_cidr(AF_INET6, parv[0], &wsopts.cidr_ip, sizeof(wsopts.cidr_ip)); if (bits > 0) { wsopts.cidr_family = AF_INET6; wsopts.cidr_bits = bits; wsopts.cidr_plus = 1; } else { /* * The argument could be an IPv6 address with a wildcard, a * hostname, or a nickname. */ if (strchr(parv[0], ':')) { wsopts.ip_plus = 1; wsopts.ip = parv[0]; } else if (strchr(parv[0], '.')) { wsopts.host_plus = 1; wsopts.host = parv[0]; } else { wsopts.nick_plus = 1; wsopts.nick = parv[0]; } } } } else { /* The argument could be either a hostname or a nickname. */ if (strchr(parv[0], '.')) { wsopts.host_plus = 1; wsopts.host = parv[0]; } else { wsopts.nick_plus = 1; wsopts.nick = parv[0]; } } return 1; } /* now walk the list (a lot like set_mode) and set arguments * as appropriate. */ flags=parv[0]; while(*flags) { switch(*flags) { case '+': case '-': change=(*flags=='+' ? 1 : 0); break; case 'a': if(change) wsopts.away_plus=1; /* they want here people */ else wsopts.away_plus=0; wsopts.check_away=1; break; case 'C': wsopts.show_chan = change; break; case 'M': wsopts.search_chan = change; break; case 'c': if(parv[args]==NULL || !change) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } if(*parv[args] == '@' || *parv[args] == '+') { char *cname = parv[args] + 1; if(*parv[args] == '@') { wsopts.channelflags = CHFL_CHANOP; if(*cname == '+') { wsopts.channelflags |= CHFL_VOICE; cname++; } } else wsopts.channelflags = CHFL_VOICE; wsopts.channel=find_channel(cname, NullChn); } else { wsopts.channelflags = 0; wsopts.channel=find_channel(parv[args],NullChn); } if(wsopts.channel==NULL) { sendto_one(sptr, getreply(ERR_NOSUCHCHANNEL), me.name, sptr->name, parv[args]); return 0; } wsopts.chan_plus=change; args++; break; case 'g': if(parv[args]==NULL) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } else if(!IsAnOper(sptr)) { sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } wsopts.gcos=parv[args]; wsopts.gcos_plus=change; args++; break; case 'h': if(parv[args]==NULL) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } wsopts.host=parv[args]; wsopts.host_plus=change; args++; break; case 't': if(parv[args]==NULL || (rval = strtol(parv[args], &err, 0)) == 0 || *err != '\0') { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } else if(!IsAnOper(sptr)) { sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } wsopts.ts = rval; wsopts.ts_value = change ? 2 : 1; args++; break; case 'T': if(parv[args]==NULL || (rval = strtol(parv[args], &err, 0)) == 0 || *err != '\0') { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } else if(!IsAnOper(sptr)) { sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } wsopts.client_type = rval; wsopts.client_type_plus = change ? 1 : 0; args++; break; case 'I': if(!IsAnOper(sptr)) { sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } wsopts.ip_show = change; break; case 'i': if(parv[args]==NULL) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } else if(!IsAnOper(sptr)) { sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } else { if (strchr(parv[args], '/')) { int bits; bits = inet_parse_cidr(AF_INET, parv[args], &wsopts.cidr_ip, sizeof(wsopts.cidr_ip)); if (bits > 0) wsopts.cidr_family = AF_INET; else { bits = inet_parse_cidr(AF_INET6, parv[args], &wsopts.cidr_ip, sizeof(wsopts.cidr_ip)); if (bits > 0) wsopts.cidr_family = AF_INET6; } if (bits > 0) { wsopts.cidr_bits = bits; wsopts.cidr_plus = change; } else { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } args++; } else { wsopts.ip=parv[args]; wsopts.ip_plus=change; args++; } } break; case 'm': if(parv[args]==NULL) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } s=parv[args]; while(*s) { for(i=1;user_modes[i]!=0x0;i+=2) { if(*s==(char)user_modes[i]) { wsopts.umodes|=user_modes[i-1]; break; } } if(!user_modes[i]) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } s++; } if(!IsAnOper(sptr)) /* only let users search for +/-oOaA */ wsopts.umodes=(wsopts.umodes&(UMODE_o|UMODE_O|UMODE_a|UMODE_A)); wsopts.umode_plus=change; if(wsopts.umodes) wsopts.check_umode=1; args++; break; case 'n': if(parv[args]==NULL) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } wsopts.nick=parv[args]; wsopts.nick_plus=change; args++; break; case 's': if(parv[args]==NULL || !change) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } wsopts.server=find_server(parv[args],NULL); if(wsopts.server==NULL) { sendto_one(sptr, getreply(ERR_NOSUCHSERVER), me.name, sptr->name, parv[args]); return 0; } wsopts.serv_plus=change; args++; break; case 'u': if(parv[args]==NULL) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } wsopts.user=parv[args]; wsopts.user_plus=change; args++; break; default: sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } flags++; } /* if we specified search_chan, we _must_ specify something useful * to go with it. Specifying a channel makes no sense, and no params make no * sense either, as does specifying a nick. */ if(wsopts.search_chan && !(wsopts.check_away || wsopts.gcos_plus || wsopts.host_plus || wsopts.check_umode || wsopts.serv_plus || wsopts.nick_plus || wsopts.user_plus || wsopts.ts_value || wsopts.client_type_plus || wsopts.ip_plus)) { if(parv[args]==NULL || wsopts.channel || wsopts.nick || parv[args][0] == '#' || parv[args][0] == '&') { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } if (strchr(parv[args], '.')) { wsopts.host_plus=1; wsopts.host=parv[args]; } else { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } } else /* can't show_chan if nothing else is set! */ if(wsopts.show_chan && !(wsopts.check_away || wsopts.gcos_plus || wsopts.host_plus || wsopts.check_umode || wsopts.serv_plus || wsopts.nick_plus || wsopts.user_plus || wsopts.ts_value || wsopts.client_type_plus || wsopts.ip_plus || wsopts.chan_plus || wsopts.cidr_bits)) { if(parv[args]==NULL) { sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } if (strchr(parv[args], '.')) { wsopts.host_plus=1; wsopts.host=parv[args]; } else { wsopts.nick_plus=1; wsopts.nick=parv[args]; } } if(parc > args) { /* Too many arguments */ sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO", "who"); return 0; } /* hey cool, it all worked! */ return 1; }
/* handle_special() * * inputs - client pointer * - nick stuff to grok for opers * - text to send if grok * output - none * side effects - old style [email protected] is handled here for non opers * opers are allowed username%[email protected] * all the traditional oper type messages are also parsed here. * i.e. "/msg #some.host." * However, syntax has been changed. * previous syntax "/msg #some.host.mask" * now becomes "/msg $#some.host.mask" * previous syntax of: "/msg $some.server.mask" remains * This disambiguates the syntax. * * XXX N.B. dalnet changed it to [email protected] as have other servers. * we will stick with tradition for now. * - Dianora */ static void handle_special(int p_or_n, const char *command, struct Client *source_p, const char *nick, const char *text) { struct Client *target_p = NULL; const char *server = NULL, *s = NULL; /* * user[%host]@server addressed? */ if ((server = strchr(nick, '@'))) { if ((target_p = hash_find_server(server + 1)) == NULL) { sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, server + 1); return; } if (!HasUMode(source_p, UMODE_OPER) && strchr(nick, '%')) { sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick); return; } if (!IsMe(target_p)) { sendto_one(target_p, ":%s %s %s :%s", source_p->id, command, nick, text); return; } sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick); return; } if (!HasUMode(source_p, UMODE_OPER)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES); return; } /* * The following two cases allow masks in NOTICEs * (for OPERs only) * * Armin, 8Jun90 ([email protected]) */ if (*nick == '$') { if (*(nick + 1) == '$' || *(nick + 1) == '#') ++nick; else if (MyClient(source_p)) { sendto_one_notice(source_p, &me, ":The command %s %s is no longer supported, please use $%s", command, nick, nick); return; } if ((s = strrchr(nick, '.')) == NULL) { sendto_one_numeric(source_p, &me, ERR_NOTOPLEVEL, nick); return; } while (*++s) if (*s == '.' || *s == '*' || *s == '?') break; if (*s == '*' || *s == '?') { sendto_one_numeric(source_p, &me, ERR_WILDTOPLEVEL, nick); return; } sendto_match_butone(IsServer(source_p->from) ? source_p->from : NULL, source_p, nick + 1, (*nick == '#') ? MATCH_HOST : MATCH_SERVER, "%s $%s :%s", command, nick, text); } }
int m_who(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *ac; chanMember *cm; Link *lp; int shown=0, i=0, showall=IsAnOper(sptr); char status[4]; /* drop nonlocal clients */ if(!MyClient(sptr)) return 0; if(!build_searchopts(sptr, parc-1, parv+1)) return 0; /* /who was no good */ if(wsopts.gcos!=NULL && (strchr(wsopts.gcos, '?'))==NULL && (strchr(wsopts.gcos, '*'))==NULL) gchkfn=mycmp; else gchkfn=match; if(wsopts.nick!=NULL && (strchr(wsopts.nick, '?'))==NULL && (strchr(wsopts.nick, '*'))==NULL) nchkfn=mycmp; else nchkfn=match; if(wsopts.user!=NULL && (strchr(wsopts.user, '?'))==NULL && (strchr(wsopts.user, '*'))==NULL) uchkfn=mycmp; else uchkfn=match; if(wsopts.host!=NULL && (strchr(wsopts.host, '?'))==NULL && (strchr(wsopts.host, '*'))==NULL) hchkfn=mycmp; else hchkfn=match; if(wsopts.ip!=NULL && (strchr(wsopts.ip, '?'))==NULL && (strchr(wsopts.ip, '*'))==NULL) ichkfn=mycmp; else ichkfn=match; if(wsopts.channel!=NULL) { if(IsMember(sptr,wsopts.channel) && (!(wsopts.channel->mode.mode & MODE_AUDITORIUM) || is_chan_opvoice(sptr, wsopts.channel))) showall=1; else if(SecretChannel(wsopts.channel) && IsAdmin(sptr)) showall=1; else if(!SecretChannel(wsopts.channel) && IsAnOper(sptr)) showall=1; else showall=0; if(showall || !SecretChannel(wsopts.channel)) { for(cm=wsopts.channel->members; cm; cm=cm->next) { ac=cm->cptr; i=0; if(!chk_who(ac,showall)) continue; /* If we have channel flags set, verify they match */ if(wsopts.channelflags && ((cm->flags & wsopts.channelflags) == 0)) continue; /* get rid of the pidly stuff first */ /* wow, they passed it all, give them the reply... * IF they haven't reached the max, or they're an oper */ status[i++]=(ac->user->away==NULL ? 'H' : 'G'); status[i]=(IsAnOper(ac) ? '*' : ((IsInvisible(ac) && IsOper(sptr)) ? '%' : 0)); status[((status[i]) ? ++i : i)]=((cm->flags&CHFL_CHANOP) ? '@' : ((cm->flags&CHFL_VOICE) ? '+' : 0)); status[++i]=0; sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name, wsopts.channel->chname, ac->user->username, WHO_HOST(ac), WHO_SERVER(sptr, ac), ac->name, status, WHO_HOPCOUNT(sptr, ac), ac->info); } } sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name, wsopts.channel->chname, "WHO"); return 0; } /* if (for whatever reason) they gave us a nick with no * wildcards, just do a find_person, bewm! */ else if(nchkfn==mycmp) { ac=find_person(wsopts.nick,NULL); if(ac!=NULL) { if(!chk_who(ac,1)) { sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name, wsopts.host!=NULL ? wsopts.host : wsopts.nick, "WHO"); return 0; } else { status[0]=(ac->user->away==NULL ? 'H' : 'G'); status[1]=(IsAnOper(ac) ? '*' : (IsInvisible(ac) && IsAnOper(sptr) ? '%' : 0)); status[2]=0; sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name, wsopts.show_chan ? first_visible_channel(ac, sptr) : "*", ac->user->username, WHO_HOST(ac), WHO_SERVER(sptr, ac), ac->name, status, WHO_HOPCOUNT(sptr, ac), ac->info); sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name, wsopts.host!=NULL ? wsopts.host : wsopts.nick, "WHO"); return 0; } } sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name, wsopts.host!=NULL ? wsopts.host : wsopts.nick, "WHO"); return 0; } if(wsopts.search_chan) { for(lp = sptr->user->channel; lp; lp = lp->next) { for(cm = lp->value.chptr->members; cm; cm = cm->next) { ac = cm->cptr; if(!chk_who(ac, 1)) continue; if(shown==MAXWHOREPLIES && !IsAnOper(sptr)) { sendto_one(sptr, getreply(ERR_WHOLIMEXCEED), me.name, sptr->name, MAXWHOREPLIES, "WHO"); break; } i = 0; status[i++]=(ac->user->away==NULL ? 'H' : 'G'); status[i]=(IsAnOper(ac) ? '*' : ((IsInvisible(ac) && IsOper(sptr)) ? '%' : 0)); status[((status[i]) ? ++i : i)]=((cm->flags&CHFL_CHANOP) ? '@' : ((cm->flags&CHFL_VOICE) ? '+' : 0)); status[++i]=0; sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name, lp->value.chptr->chname, ac->user->username, WHO_HOST(ac),WHO_SERVER(sptr, ac), ac->name, status, WHO_HOPCOUNT(sptr, ac), ac->info); shown++; } } } else { for(ac=client;ac;ac=ac->next) { if(!chk_who(ac,showall)) continue; /* wow, they passed it all, give them the reply... * IF they haven't reached the max, or they're an oper */ if(shown==MAXWHOREPLIES && !IsAnOper(sptr)) { sendto_one(sptr, getreply(ERR_WHOLIMEXCEED), me.name, sptr->name, MAXWHOREPLIES, "WHO"); break; /* break out of loop so we can send end of who */ } status[0]=(ac->user->away==NULL ? 'H' : 'G'); status[1]=(IsAnOper(ac) ? '*' : (IsInvisible(ac) && IsAnOper(sptr) ? '%' : 0)); status[2]=0; sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name, wsopts.show_chan ? first_visible_channel(ac, sptr) : "*", ac->user->username, WHO_HOST(ac), WHO_SERVER(sptr, ac), ac->name, status, WHO_HOPCOUNT(sptr, ac), ac->info); shown++; } } sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name, (wsopts.host!=NULL ? wsopts.host : (wsopts.nick!=NULL ? wsopts.nick : (wsopts.user!=NULL ? wsopts.user : (wsopts.gcos!=NULL ? wsopts.gcos : (wsopts.server!=NULL ? wsopts.server->name : "*"))))), "WHO"); return 0; }
int m_scan_klines(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[]) { char *host_mask = NULL, *user_mask = NULL; int list = 1, count = 0, listed_so_far = 0; int list_max = 100; int expired = 0; char *placed_by = NULL; int i; struct ConfItem *aconf; if (!HasUmode(sptr,UMODE_SEEKLINES)) { if (SeesOperMessages(sptr)) sendto_one(sptr,":%s NOTICE %s :You have no 2 umode", me.name, parv[0]); else sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (parc < 2) { if (!IsServer(sptr)) sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SCAN KLINES"); return 0; } for (i = 2; i < parc; i++) { if (!irccmp(parv[i], "no-list")) list = 0; else if (!irccmp(parv[i], "list")) list = 1; else if (!irccmp(parv[i], "not-expired")) expired = 0; else if (!irccmp(parv[i], "expired")) expired = 1; else if (i < (parc - 1)) { if (!irccmp(parv[i], "list-max")) { list_max = strtoul(parv[++i], NULL, 0); } else if (!irccmp(parv[i], "host-mask")) { host_mask = parv[++i]; } else if (!irccmp(parv[i], "user-mask")) { user_mask = parv[++i]; } else if (!irccmp(parv[i], "placed-by")) { placed_by = parv[++i]; } } } for (aconf = kline_list; aconf; aconf = aconf->kline_next) { char *p; if (aconf->status != CONF_KILL) continue; if (host_mask && !match(host_mask, aconf->host)) continue; if (user_mask && !match(user_mask, aconf->user)) continue; /* extract the user who placed the K:line */ if ((p = strchr(aconf->passwd, ';'))) { int skip = 0; *p = '\0'; skip = placed_by && !match(placed_by, aconf->passwd); *p = ';'; if (skip) continue; } /* true if: * (can expire (and has expired )) * (we want expired and have expired, or vice versa ) */ if (expired ^ (aconf->hold && (aconf->hold <= CurrentTime))) continue; count++; if (list && (list_max > ++listed_so_far)) { /* p points to the semicolon in the comment field, if there is one */ if (p) *p = '\0'; if (aconf->hold) { if (p) { /* send_markup(sptr, &me, "SCAN-KLINE", */ /* "!begin<1>%[email protected]%s!end<1> klined " */ /* "until !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>) " */ /* "by !begin<4>%s!end<4>, because: %s", */ /* aconf->user, aconf->host, aconf->hold, aconf->hold - CurrentTime, aconf->passwd, p + 2); */ send_markup(sptr, &me, "SCAN-KLINE", "%[email protected]%s klined " "until %s (%s) " "by %s, because: %s", aconf->user, aconf->host, smalldate(aconf->hold), smalltime(aconf->hold - CurrentTime), aconf->passwd, p + 2); } else { /* send_markup(sptr, &me, "SCAN-KLINE", */ /* "!begin<1>%[email protected]%s!end<1> klined " */ /* "until !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>) " */ /* "by !begin<4>%s!end<4>", */ /* aconf->user, aconf->host, aconf->hold, aconf->hold - CurrentTime, aconf->passwd); */ send_markup(sptr, &me, "SCAN-KLINE", "%[email protected]%s klined " "until %s (%s) " "by %s", aconf->user, aconf->host, smalldate(aconf->hold), smalltime(aconf->hold - CurrentTime), aconf->passwd); } } else { if (p) { /* send_markup(sptr, &me, "SCAN-KLINE", */ /* "!begin<1>%[email protected]%s!end<1> klined !begin<2>permanently!end<2> " */ /* "by !begin<4>%s!end<4>, because: %s", */ /* aconf->user, aconf->host, aconf->passwd, p + 2); */ send_markup(sptr, &me, "SCAN-KLINE", "%[email protected]%s klined permanently " "by %s, because: %s", aconf->user, aconf->host, aconf->passwd, p + 2); } else { /* send_markup(sptr, &me, "SCAN-KLINE", */ /* "!begin<1>%[email protected]%s!end<1> klined !begin<2>permanently!end<2> " */ /* "by !begin<4>%s!end<4>", */ /* aconf->user, aconf->host, aconf->passwd); */ send_markup(sptr, &me, "SCAN-KLINE", "%[email protected]%s klined permanently " "by %s", aconf->user, aconf->host, aconf->passwd); } } if (p) { *p = ';'; } } } send_markup(sptr, &me, "KLINE-END", "End of kline list"); /* send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */ send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count); return 0; }
/* ** m_whowas ** parv[0] = sender prefix ** parv[1] = nickname queried */ int m_whowas(aClient *cptr, aClient *sptr, int parc, char *parv[]) { Reg aName *wp, *wp2 = NULL; Reg int j = 0; Reg anUser *up = NULL; int max = -1; char *p = NULL, *nick, *s; if (parc < 2) { sendto_one(sptr, replies[ERR_NONICKNAMEGIVEN], ME, BadTo(parv[0])); return 1; } if (parc > 2) max = atoi(parv[2]); if (parc > 3) if (hunt_server(cptr,sptr,":%s WHOWAS %s %s :%s", 3,parc,parv)) return 3; parv[1] = canonize(parv[1]); if (!MyConnect(sptr)) max = MIN(max, 20); for (s = parv[1]; (nick = strtoken(&p, s, ",")); s = NULL) { wp = wp2 = &was[(ww_index ? ww_index : ww_size) - 1]; j = 0; do { if (mycmp(nick, wp->ww_nick) == 0) { up = wp->ww_user; sendto_one(sptr, replies[RPL_WHOWASUSER], ME, BadTo(parv[0]), wp->ww_nick, up->username, up->host, wp->ww_info); sendto_one(sptr, replies[RPL_WHOISSERVER], ME, BadTo(parv[0]), wp->ww_nick, up->server, myctime(wp->ww_logout)); j++; } if (max > 0 && j >= max) break; if (wp == was) wp = &was[ww_size - 1]; else wp--; } while (wp != wp2); if (up == NULL) { if (strlen(nick) > (size_t) NICKLEN) nick[NICKLEN] = '\0'; sendto_one(sptr, replies[ERR_WASNOSUCHNICK], ME, BadTo(parv[0]), nick); } else up = NULL; if (p) p[-1] = ','; } sendto_one(sptr, replies[RPL_ENDOFWHOWAS], ME, BadTo(parv[0]), parv[1]); return 2; }
int m_scan_idle(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[]) { struct Client *ptr, *target = NULL; char *eptr, buffer[321]; int idle_time, check_time, len = 0, count = 0; if(MyClient(sptr) && !HasUmode(sptr, UMODE_USER_AUSPEX)) { if(SeesOperMessages(sptr)) sendto_one(sptr,":%s NOTICE %s :You have no a umode", me.name, parv[0]); else sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if(parc < 3) { if (!IsServer(sptr)) sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SCAN IDLE"); return 0; } idle_time = strtoul(parv[2], &eptr, 10); if(eptr == parv[2]) return 0; /* Store the timestamp which last_sent should be >= to save time */ check_time = CurrentTime - idle_time; /* If the query is for another server, pass it on and return. */ if(parc > 3) { if(MyClient(sptr) && !HasUmode(sptr, UMODE_REMOTEINFO)) { if(SeesOperMessages(sptr)) sendto_one(sptr,":%s NOTICE %s :You have no S umode(cannot send remote)", me.name, parv[0]); else sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if(!irccmp(parv[3], "GLOBAL") || !irccmp(parv[3], "*")) sendto_serv_butone(cptr, ":%s SCAN IDLE %d *", parv[0], idle_time); else if((target = find_server(parv[3])) == NULL) { sendto_one(sptr, form_str(ERR_NOSUCHSERVER), me.name, parv[0], parv[3]); return 0; }else if(!IsMe(target)) { /* But only if the query is not on us... */ sendto_prefix_one(target, sptr, ":%s SCAN IDLE %d %s", parv[0], idle_time, target->name); return 0; } } buffer[0] = '\0'; for(ptr = local_cptr_list; ptr; ptr = ptr->next_local_client) { if(ptr->user->last_sent < check_time) continue; if(len + strlen(ptr->name) > 319) { buffer[len - 1] = '\0'; /* Strip the trailing space */ send_markup(sptr, &me, "SCAN-IDLE", "%d %s", idle_time, buffer); buffer[0] = '\0'; len = 0; } strcat(buffer, ptr->name); strcat(buffer, " "); len += strlen(ptr->name) + 1; count++; } if(buffer[0]) { buffer[len - 1] = '\0'; send_markup(sptr, &me, "SCAN-IDLE", "%d %s", idle_time, buffer); } send_markup(sptr, &me, "IDLE-END", "End of idle listing"); if(count > 0 || target || parc == 3) /* Don't give a summary for globals if no results matched */ send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count); return 0; }
/* m_knock * parv[1] = channel * * The KNOCK command has the following syntax: * :<sender> KNOCK <channel> * * If a user is not banned from the channel they can use the KNOCK * command to have the server NOTICE the channel operators notifying * they would like to join. Helpful if the channel is invite-only, the * key is forgotten, or the channel is full (INVITE can bypass each one * of these conditions. Concept by Dianora <*****@*****.**> and written by * <anonymous> */ static int m_knock(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr; char *p, *name; if(MyClient(source_p) && ConfigChannel.use_knock == 0) { sendto_one(source_p, form_str(ERR_KNOCKDISABLED), me.name, source_p->name); return 0; } name = LOCAL_COPY(parv[1]); /* dont allow one knock to multiple chans */ if((p = strchr(name, ','))) *p = '\0'; if(!IsChannelName(name)) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } if((chptr = find_channel(name)) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } if(IsMember(source_p, chptr)) { if(MyClient(source_p)) sendto_one(source_p, form_str(ERR_KNOCKONCHAN), me.name, source_p->name, name); return 0; } if(!((chptr->mode.mode & MODE_INVITEONLY) || (*chptr->mode.key) || (chptr->mode.limit && rb_dlink_list_length(&chptr->members) >= (unsigned long)chptr->mode.limit))) { sendto_one_numeric(source_p, ERR_CHANOPEN, form_str(ERR_CHANOPEN), name); return 0; } /* cant knock to a +p channel */ if(HiddenChannel(chptr)) { sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN, form_str(ERR_CANNOTSENDTOCHAN), name, "channel does not accept knocks"); return 0; } if(MyClient(source_p)) { /* don't allow a knock if the user is banned */ if(is_banned(chptr, source_p, NULL, NULL, NULL) == CHFL_BAN || is_quieted(chptr, source_p, NULL, NULL, NULL) == CHFL_BAN) { sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN, form_str(ERR_CANNOTSENDTOCHAN), name, "you are banned from this channel"); return 0; } /* local flood protection: * allow one knock per user per knock_delay * allow one knock per channel per knock_delay_channel */ if(!IsOper(source_p) && (source_p->localClient->last_knock + ConfigChannel.knock_delay) > rb_current_time()) { sendto_one(source_p, form_str(ERR_TOOMANYKNOCK), me.name, source_p->name, name, "user"); return 0; } else if((chptr->last_knock + ConfigChannel.knock_delay_channel) > rb_current_time()) { sendto_one(source_p, form_str(ERR_TOOMANYKNOCK), me.name, source_p->name, name, "channel"); return 0; } /* ok, we actually can send the knock, tell client */ source_p->localClient->last_knock = rb_current_time(); sendto_one(source_p, form_str(RPL_KNOCKDLVR), me.name, source_p->name, name); } chptr->last_knock = rb_current_time(); if(ConfigChannel.use_knock) sendto_channel_local(chptr->mode.mode & MODE_FREEINVITE ? ALL_MEMBERS : ONLY_CHANOPS, chptr, form_str(RPL_KNOCK), me.name, name, name, source_p->name, source_p->username, source_p->host); sendto_server(client_p, chptr, CAP_KNOCK|CAP_TS6, NOCAPS, ":%s KNOCK %s", use_id(source_p), name); sendto_server(client_p, chptr, CAP_KNOCK, CAP_TS6, ":%s KNOCK %s", source_p->name, name); return 0; }
/* * m_topic * parv[0] = sender prefix * parv[1] = channel name * parv[2] = new topic, if setting topic */ static int m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; char *p = NULL; if((p = strchr(parv[1], ','))) *p = '\0'; if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); if(!IsChannelName(parv[1])) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } chptr = find_channel(parv[1]); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } /* setting topic */ if(parc > 2) { msptr = find_channel_membership(chptr, source_p); if(msptr == NULL) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), parv[1]); return 0; } if((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || is_chanop(msptr)) { char topic_info[USERHOST_REPLYLEN]; ircsprintf(topic_info, "%s!%[email protected]%s", source_p->name, source_p->username, source_p->host); set_channel_topic(chptr, parv[2], topic_info, CurrentTime); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s TOPIC %s :%s", use_id(source_p), chptr->chname, chptr->topic == NULL ? "" : chptr->topic); sendto_server(client_p, chptr, NOCAPS, CAP_TS6, ":%s TOPIC %s :%s", source_p->name, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%[email protected]%s TOPIC %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); } else sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), me.name, source_p->name, parv[1]); } else if(MyClient(source_p)) { if(!IsMember(source_p, chptr) && SecretChannel(chptr)) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), parv[1]); return 0; } if(chptr->topic == NULL) sendto_one(source_p, form_str(RPL_NOTOPIC), me.name, source_p->name, parv[1]); else { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); } } return 0; }
/* * parse a buffer. * * NOTE: parse() should not be called recusively by any other functions! */ void parse(struct Client *client_p, char *pbuffer, char *bufend) { struct Client *from = client_p; char *ch; char *s; char *end; int i; int paramcount, mpara = 0; char *numeric = 0; struct Message *mptr; Debug((DEBUG_DEBUG, "Parsing %s:", pbuffer)); s_assert(!IsDead(client_p)); s_assert(client_p->localClient->fd >= 0); if(IsDead(client_p) || client_p->localClient->fd < 0) return; s_assert(bufend-pbuffer < 512); for (ch = pbuffer; *ch == ' '; ch++) /* skip spaces */ /* null statement */ ; para[0] = from->name; if(*ch == ':') { ch++; /* * Copy the prefix to 'sender' assuming it terminates * with SPACE (or NULL, which is an error, though). */ sender = ch; if((s = strchr(ch, ' '))) { *s = '\0'; s++; ch = s; } i = 0; if(*sender && IsServer(client_p)) { from = find_client(sender); if(from == NULL) { from = find_server(sender); } /* Hmm! If the client corresponding to the * prefix is not found--what is the correct * action??? Now, I will ignore the message * (old IRC just let it through as if the * prefix just wasn't there...) --msa */ if(from == NULL) { Debug((DEBUG_ERROR, "Unknown prefix (%s)(%s) from (%s)", sender, pbuffer, client_p->name)); ServerStats->is_unpf++; remove_unknown(client_p, sender, pbuffer); return; } para[0] = from->name; if(from->from != client_p) { ServerStats->is_wrdi++; Debug((DEBUG_ERROR, "Message (%s) coming from (%s)", pbuffer, client_p->name)); cancel_clients(client_p, from, pbuffer); return; } } while (*ch == ' ') ch++; } if(*ch == '\0') { ServerStats->is_empt++; Debug((DEBUG_NOTICE, "Empty message from host %s:%s", client_p->name, from->name)); return; } /* * Extract the command code from the packet. Point s to the end * of the command code and calculate the length using pointer * arithmetic. Note: only need length for numerics and *all* * numerics must have parameters and thus a space after the command * code. -avalon */ /* EOB is 3 chars long but is not a numeric */ if(*(ch + 3) == ' ' && /* ok, lets see if its a possible numeric.. */ IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2))) { mptr = (struct Message *) NULL; numeric = ch; paramcount = MAXPARA; ServerStats->is_num++; s = ch + 3; /* I know this is ' ' from above if */ *s++ = '\0'; /* blow away the ' ', and point s to next part */ } else { int ii = 0; if((s = strchr(ch, ' '))) *s++ = '\0'; mptr = hash_parse(ch); if(!mptr || !mptr->cmd) { /* * Note: Give error message *only* to recognized * persons. It's a nightmare situation to have * two programs sending "Unknown command"'s or * equivalent to each other at full blast.... * If it has got to person state, it at least * seems to be well behaving. Perhaps this message * should never be generated, though... --msa * Hm, when is the buffer empty -- if a command * code has been found ?? -Armin */ if(pbuffer[0] != '\0') { if(IsPerson(from)) sendto_one(from, ":%s %d %s %s :Unknown command", me.name, ERR_UNKNOWNCOMMAND, from->name, ch); Debug((DEBUG_ERROR, "Unknown (%s) from %s", ch, get_client_name(client_p, HIDE_IP))); } ServerStats->is_unco++; return; } paramcount = mptr->parameters; mpara = mptr->maxpara; ii = bufend - ((s) ? s : ch); mptr->bytes += ii; } end = bufend - 1; /* XXX this should be done before parse() is called */ if(*end == '\n') *end-- = '\0'; if(*end == '\r') *end = '\0'; i = 0; if(s != NULL) i = string_to_array(s, para); if(mptr == (struct Message *) NULL) { do_numeric(numeric, client_p, from, i, para); return; } if(handle_command(mptr, client_p, from, i, para) < -1) { char *p; for (p = pbuffer; p <= end; p += 8) { /* HACK HACK */ /* Its expected this nasty code can be removed * or rewritten later if still needed. */ if((unsigned long) (p + 8) > (unsigned long) end) { for (; p <= end; p++) { ilog(L_CRIT, "%02x |%c", p[0], p[0]); } } else ilog(L_CRIT, "%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); } } }
/* * mr_webirc - webirc message handler * parv[1] = password * parv[2] = fake username (we ignore this) * parv[3] = fake hostname * parv[4] = fake ip */ static int mr_webirc(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct ConfItem *aconf; const char *encr; if (!strchr(parv[4], '.') && !strchr(parv[4], ':')) { sendto_one(source_p, "NOTICE * :Invalid IP"); return 0; } aconf = find_address_conf(client_p->host, client_p->sockhost, IsGotId(client_p) ? client_p->username : "******", IsGotId(client_p) ? client_p->username : "******", (struct sockaddr *) &client_p->localClient->ip, client_p->localClient->ip.ss_family, NULL); if (aconf == NULL || !(aconf->status & CONF_CLIENT)) return 0; if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->info.name, "webirc.")) { /* XXX */ sendto_one(source_p, "NOTICE * :Not a CGI:IRC auth block"); return 0; } if (EmptyString(aconf->passwd)) { sendto_one(source_p, "NOTICE * :CGI:IRC auth blocks must have a password"); return 0; } if (EmptyString(parv[1])) encr = ""; else if (IsConfEncrypted(aconf)) encr = rb_crypt(parv[1], aconf->passwd); else encr = parv[1]; if (strcmp(encr, aconf->passwd)) { sendto_one(source_p, "NOTICE * :CGI:IRC password incorrect"); return 0; } rb_strlcpy(source_p->sockhost, parv[4], sizeof(source_p->sockhost)); if(strlen(parv[3]) <= HOSTLEN) rb_strlcpy(source_p->host, parv[3], sizeof(source_p->host)); else rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host)); rb_inet_pton_sock(parv[4], (struct sockaddr *)&source_p->localClient->ip); /* Check dlines now, klines will be checked on registration */ if((aconf = find_dline((struct sockaddr *)&source_p->localClient->ip, source_p->localClient->ip.ss_family))) { if(!(aconf->status & CONF_EXEMPTDLINE)) { exit_client(client_p, source_p, &me, "D-lined"); return 0; } } sendto_one(source_p, "NOTICE * :Congratulations, your host is reset via I:line: %s %s", parv[3], parv[4]); return 0; }
static void send_usage(aClient *cptr, char *nick) { #if defined( HAVE_GETRUSAGE ) struct rusage rus; time_t secs, rup; #ifdef hz #define hzz hz #else #ifdef HZ #define hzz HZ #else int hzz = 1; #endif #endif if (getrusage(RUSAGE_SELF, &rus) == -1) { sendto_one(cptr, ":%s NOTICE %s :Getruseage error: %s.", me.name, nick, sys_errlist[errno]); return; } secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec; rup = timeofday - me.since; if (secs == 0) secs = 1; sendto_one(cptr, ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d", me.name, RPL_STATSDEBUG, nick, secs / 60, secs % 60, rus.ru_utime.tv_sec / 60, rus.ru_utime.tv_sec % 60, rus.ru_stime.tv_sec / 60, rus.ru_stime.tv_sec % 60); sendto_one(cptr, ":%s %d %s :RSS %d ShMem %d Data %d Stack %d", me.name, RPL_STATSDEBUG, nick, rus.ru_maxrss, rus.ru_ixrss / (rup * hzz), rus.ru_idrss / (rup * hzz), rus.ru_isrss / (rup * hzz)); sendto_one(cptr, ":%s %d %s :Swaps %d Reclaims %d Faults %d", me.name, RPL_STATSDEBUG, nick, rus.ru_nswap, rus.ru_minflt, rus.ru_majflt); sendto_one(cptr, ":%s %d %s :Block in %d out %d", me.name, RPL_STATSDEBUG, nick, rus.ru_inblock, rus.ru_oublock); sendto_one(cptr, ":%s %d %s :Msg Rcv %d Send %d", me.name, RPL_STATSDEBUG, nick, rus.ru_msgrcv, rus.ru_msgsnd); sendto_one(cptr, ":%s %d %s :Signals %d Context Vol. %d Invol %d", me.name, RPL_STATSDEBUG, nick, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); #else #if defined( HAVE_TIMES ) struct tms tmsbuf; time_t secs, mins; int hzz = 1, ticpermin; int umin, smin, usec, ssec; ticpermin = hzz * 60; umin = tmsbuf.tms_utime / ticpermin; usec = (tmsbuf.tms_utime % ticpermin) / (float) hzz; smin = tmsbuf.tms_stime / ticpermin; ssec = (tmsbuf.tms_stime % ticpermin) / (float) hzz; secs = usec + ssec; mins = (secs / 60) + umin + smin; secs %= hzz; if (times(&tmsbuf) == -1) { sendto_one(cptr, ":%s %d %s :times(2) error: %s.", me.name, RPL_STATSDEBUG, nick, strerror(errno)); return; } secs = tmsbuf.tms_utime + tmsbuf.tms_stime; sendto_one(cptr, ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d", me.name, RPL_STATSDEBUG, nick, mins, secs, umin, usec, smin, ssec); #endif /* HAVE_TIMES */ #endif /* HAVE_GETRUSAGE */ sendto_one(cptr, ":%s %d %s :Reads %d Writes %d", me.name, RPL_STATSDEBUG, nick, readcalls, writecalls); /* sendto_one(cptr, ":%s %d %s :DBUF alloc %d used %d", me.name, RPL_STATSDEBUG, nick, DBufCount, DBufUsedCount); */ sendto_one(cptr, ":%s %d %s :Writes: <0 %d 0 %d <16 %d <32 %d <64 %d", me.name, RPL_STATSDEBUG, nick, writeb[0], writeb[1], writeb[2], writeb[3], writeb[4]); sendto_one(cptr, ":%s %d %s :<128 %d <256 %d <512 %d <1024 %d >1024 %d", me.name, RPL_STATSDEBUG, nick, writeb[5], writeb[6], writeb[7], writeb[8], writeb[9]); return; }