/* * mo_version - oper message handler * * parv[0] = sender prefix * parv[1] = servername */ int mo_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client *acptr; if (MyConnect(sptr) && parc > 1) { if (!(acptr = find_match_server(parv[1]))) { send_reply(sptr, ERR_NOSUCHSERVER, parv[1]); return 0; } parv[1] = cli_name(acptr); } if (hunt_server_cmd(sptr, CMD_VERSION, cptr, feature_int(FEAT_HIS_REMOTE), ":%C", 1, parc, parv) == HUNTED_ISME) { send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me), debug_serveropts()); send_supported(sptr); } return 0; }
/* * ms_rping - server message handler * -- by Run * * parv[0] = sender (sptr->name thus) * if sender is a person: (traveling towards start server) * parv[1] = pinged server[mask] * parv[2] = start server (current target) * parv[3] = optional remark * if sender is a server: (traveling towards pinged server) * parv[1] = pinged server (current target) * parv[2] = original sender (person) * parv[3] = start time in s * parv[4] = start time in us * parv[5] = the optional remark */ int ms_rping(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client* destination = 0; assert(0 != cptr); assert(0 != sptr); assert(IsServer(cptr)); /* * shouldn't happen */ if (!IsPrivileged(sptr)) return 0; if (IsServer(sptr)) { if (parc < 6) { /* * PROTOCOL ERROR */ return need_more_params(sptr, "RPING"); } if ((destination = FindNServer(parv[1]))) { /* * if it's not for me, pass it on */ if (IsMe(destination)) sendcmdto_one(&me, CMD_RPONG, sptr, "%s %s %s %s :%s", cli_name(sptr), parv[2], parv[3], parv[4], parv[5]); else sendcmdto_one(sptr, CMD_RPING, destination, "%C %s %s %s :%s", destination, parv[2], parv[3], parv[4], parv[5]); } } else { if (parc < 3) { return need_more_params(sptr, "RPING"); } /* * Haven't made it to the start server yet, if I'm not the start server * pass it on. */ if (hunt_server_cmd(sptr, CMD_RPING, cptr, 1, "%s %C :%s", 2, parc, parv) != HUNTED_ISME) return 0; /* * otherwise ping the destination from here */ if ((destination = find_match_server(parv[1]))) { assert(IsServer(destination) || IsMe(destination)); sendcmdto_one(&me, CMD_RPING, destination, "%C %C %s :%s", destination, sptr, militime(0, 0), parv[3]); } else send_reply(sptr, ERR_NOSUCHSERVER, parv[1]); } return 0; }
/* * mo_rping - oper message handler * -- by Run * * * Receive: * RPING blah.* * RPING blah.* :<start time> * RPING blah.* server.* :<start time> * * parv[0] = sender (sptr->name thus) * parv[1] = pinged server name or mask (required) * parv[2] = start server name or mask (optional, defaults to me) * parv[3] = client start time (optional) * * Send: NumNick(sptr) RPING blah.* server.net :<start time> (hunt_server) * NumServ(&me) RPING NumServ(blah.bar.net) NumNick(sptr) :<start time> (here) */ int mo_rping(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client* acptr = 0; const char* start_time = "<No client start time>"; assert(0 != cptr); assert(0 != sptr); assert(cptr == sptr); assert(IsAnOper(sptr)); if (parc < 2) return need_more_params(sptr, "RPING"); if (parc > 2) { if ((acptr = find_match_server(parv[2])) && !IsMe(acptr)) { parv[2] = cli_name(acptr); if (3 == parc) { /* * const_cast<char*>(start_time); */ parv[parc++] = (char*) start_time; } hunt_server_cmd(sptr, CMD_RPING, cptr, 1, "%s %C :%s", 2, parc, parv); return 0; } else start_time = parv[2]; } if ((acptr = find_match_server(parv[1]))) { assert(IsServer(acptr) || IsMe(acptr)); sendcmdto_one(&me, CMD_RPING, acptr, "%C %C %s :%s", acptr, sptr, militime(0, 0), start_time); } else send_reply(sptr, ERR_NOSUCHSERVER, parv[1]); return 0; }
/* * m_oper - generic message handler */ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct ConfItem* aconf; char* name; char* password; assert(0 != cptr); assert(cptr == sptr); if ((parc > 3) && feature_bool(FEAT_REMOTE_OPER)) { struct Client *srv; if (!string_has_wildcards(parv[1])) srv = FindServer(parv[1]); else srv = find_match_server(parv[1]); if (!srv) return send_reply(sptr, ERR_NOOPERHOST); if (IsMe(srv)) { parv[1] = parv[2]; parv[2] = parv[3]; } else { sendcmdto_one(sptr, CMD_OPER, srv, "%C %s %s", srv, parv[2], parv[3]); return 0; } } name = parc > 1 ? parv[1] : 0; password = parc > 2 ? parv[2] : 0; if (EmptyString(name) || EmptyString(password)) return need_more_params(sptr, "OPER"); if (can_oper(cptr, sptr, name, password, &aconf)) do_oper(cptr, sptr, aconf); return 0; }
/* * mo_version - oper message handler * * parv[0] = sender prefix * parv[1] = servername */ int mo_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client *acptr; if (MyConnect(sptr) && parc > 1) { if (!(acptr = find_match_server(parv[1]))) { send_reply(sptr, ERR_NOSUCHSERVER, parv[1]); return 0; } parv[1] = cli_name(acptr); } if (hunt_server_cmd(sptr, CMD_VERSION, cptr, feature_int(FEAT_HIS_REMOTE), ":%C", 1, parc, parv) == HUNTED_ISME) { send_reply(sptr, RPL_VERSION, version, cvs_version, debugmode, cli_name(&me), debug_serveropts()); #ifdef USE_SSL #ifdef DEBUGMODE sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Headers: %s", sptr, OPENSSL_VERSION_TEXT); #endif sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Library: %s", sptr, SSLeay_version(SSLEAY_VERSION)); #endif #ifdef USE_GEOIP sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :GeoIP %s", sptr, geoip_version()); #endif #ifdef USE_MMDB sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :MaxMindDB %s", sptr, geoip_libmmdb_version()); #endif send_supported(sptr); } return 0; }
/* * ms_svsnoop * * parv[0] = sender prefix * parv[1] = server * parv[2] = +/- * * Ported From Ultimate IRCd */ int ms_svsnoop(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct ConfItem *aconf; struct Client *server = 0; char c; char* cp; if (!IsServer(sptr) || parc < 3) return 0; /* this could be done with hunt_server_cmd but its a bucket of shit */ if (!string_has_wildcards(parv[1])) server = FindServer(parv[1]); else server = find_match_server(parv[1]); if (!server) return 0; if (server == &me) { cp = parv[2]; c = *cp; if (c == '+') { for(aconf = GlobalConfList; aconf; aconf = aconf->next) { if (aconf->status & CONF_OPERATOR) aconf->status |= CONF_ILLEGAL; } SetServerNoop(&me); } else { rehash (&me, 2); ClearServerNoop(&me); } } sendcmdto_serv_butone(sptr, CMD_SVSNOOP, cptr, "%s %s", parv[1], parv[2]); return 0; }
/* * mo_gline - oper message handler * * parv[0] = Sender prefix * parv[1] = [[+|-]<G-line mask>] * * Local (to me) style: * * parv[2] = [Expiration offset] * parv[3] = [Comment] * * Global (or remote local) style: * * parv[2] = [target] * parv[3] = [Expiration offset] * parv[4] = [Comment] * */ int mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { struct Client *acptr = 0; struct Gline *agline; unsigned int flags = 0; time_t expire_off; char *mask = parv[1], *target = 0, *reason; if (parc < 2) return gline_list(sptr, 0); if (*mask == '!') { mask++; if (HasPriv(sptr, PRIV_WIDE_GLINE)) flags |= GLINE_OPERFORCE; } if (*mask == '+') { flags |= GLINE_ACTIVE; mask++; } else if (*mask == '-') mask++; else return gline_list(sptr, mask); if (parc == 4) { expire_off = atoi(parv[2]); reason = parv[3]; flags |= GLINE_LOCAL; } else if (parc > 4) { target = parv[2]; expire_off = atoi(parv[3]); reason = parv[4]; } else return need_more_params(sptr, "GLINE"); if (target) { if (!(target[0] == '*' && target[1] == '\0')) { if (!(acptr = find_match_server(target))) return send_reply(sptr, ERR_NOSUCHSERVER, target); /* manually propagate, since we don't set it */ if (!IsMe(acptr)) { if (!feature_bool(FEAT_CONFIG_OPERCMDS)) return send_reply(sptr, ERR_DISABLED, "GLINE"); if (!HasPriv(sptr, PRIV_GLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); sendcmdto_one(sptr, CMD_GLINE, acptr, "%C %s%c%s %s %Tu :%s", acptr, flags & GLINE_OPERFORCE ? "!" : "", flags & GLINE_ACTIVE ? '+' : '-', mask, parv[3], TStime(), reason); return 0; } flags |= GLINE_LOCAL; } } if (!(flags & GLINE_LOCAL) && !feature_bool(FEAT_CONFIG_OPERCMDS)) return send_reply(sptr, ERR_DISABLED, "GLINE"); if (!HasPriv(sptr, (flags & GLINE_LOCAL ? PRIV_LOCAL_GLINE : PRIV_GLINE))) return send_reply(sptr, ERR_NOPRIVILEGES); agline = gline_find(mask, GLINE_ANY | GLINE_EXACT); if (agline) { if (GlineIsLocal(agline) && !(flags & GLINE_LOCAL)) /* global over local */ gline_free(agline); else { if (!GlineLastMod(agline)) /* force mods to Uworld-set G-lines local */ flags |= GLINE_LOCAL; if (flags & GLINE_ACTIVE) return gline_activate(cptr, sptr, agline, GlineLastMod(agline) ? TStime() : 0, flags); else return gline_deactivate(cptr, sptr, agline, GlineLastMod(agline) ? TStime() : 0, flags); } } return gline_add(cptr, sptr, mask, reason, expire_off, TStime(), flags); }
/* * mo_zline - oper message handler * * parv[0] = Sender prefix * parv[1] = [[+|-]<Z-line mask>] * * For other parameters, see doc/readme.zline. */ int mo_zline(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { struct Client *acptr = 0; struct Zline *azline = 0; unsigned int flags = 0; enum ZlineAction action = ZLINE_MODIFY; time_t expire = 0; char *mask = parv[1], *target = 0, *reason = 0, *end; if (parc < 2) return zline_list(sptr, 0); if (*mask == '!') { mask++; if (HasPriv(sptr, PRIV_WIDE_ZLINE)) flags |= ZLINE_OPERFORCE; } switch (*mask) { /* handle +, -, <, and > */ case '+': /* activate the Z-line */ action = ZLINE_ACTIVATE; mask++; break; case '-': /* deactivate the Z-line */ action = ZLINE_DEACTIVATE; mask++; break; case '>': /* locally activate the Z-line */ action = ZLINE_LOCAL_ACTIVATE; mask++; break; case '<': /* locally deactivate the Z-line */ action = ZLINE_LOCAL_DEACTIVATE; mask++; break; } /* OK, let's figure out the parameters... */ switch (action) { case ZLINE_MODIFY: /* no specific action on the Z-line... */ if (parc == 2) /* user wants a listing of a specific Z-line */ return zline_list(sptr, mask); else if (parc < 4) /* must have target and expire, minimum */ return need_more_params(sptr, "ZLINE"); target = parv[2]; /* get the target... */ if (is_timestamp(parv[3])) { expire = strtol(parv[3], &end, 10) + TStime(); /* and the expiration */ if (*end != '\0') return send_reply(sptr, SND_EXPLICIT | ERR_BADEXPIRE, "%s :Bad expire time", parv[3]); } else expire = ParseInterval(parv[3]) + TStime(); flags |= ZLINE_EXPIRE; /* remember that we got an expire time */ if (parc > 4) { /* also got a reason... */ reason = parv[parc - 1]; flags |= ZLINE_REASON; } /* target is not global, interpolate action and require reason */ if (target[0] != '*' || target[1] != '\0') { if (!reason) /* have to have a reason for this */ return need_more_params(sptr, "ZLINE"); action = ZLINE_ACTIVATE; } break; case ZLINE_LOCAL_ACTIVATE: /* locally activate a Z-line */ case ZLINE_LOCAL_DEACTIVATE: /* locally deactivate a Z-line */ if (parc > 2) { /* if target is available, pick it */ target = parv[2]; if (target[0] == '*' && target[1] == '\0') return send_reply(sptr, ERR_NOSUCHSERVER, target); } break; case ZLINE_ACTIVATE: /* activating/adding a Z-line */ case ZLINE_DEACTIVATE: /* deactivating/removing a Z-line */ if (parc < 3) return need_more_params(sptr, "ZLINE"); if (parc > 3) { /* get expiration and target */ reason = parv[parc - 1]; if (is_timestamp(parv[parc - 2])) { expire = strtol(parv[parc - 2], &end, 10) + TStime(); if (*end != '\0') return send_reply(sptr, SND_EXPLICIT | ERR_BADEXPIRE, "%s :Bad expire time", parv[parc - 2]); } else expire = ParseInterval(parv[parc - 2]) + TStime(); flags |= ZLINE_EXPIRE | ZLINE_REASON; /* remember that we got 'em */ if (parc > 4) /* also have a target! */ target = parv[2]; } else { target = parv[2]; /* target has to be present, and has to be '*' */ if (target[0] != '*' || target[1] != '\0') return need_more_params(sptr, "ZLINE"); } break; } /* Is there no mask left? */ if (mask[0] == '\0') return need_more_params(sptr, "ZLINE"); /* Now let's figure out which is the target server */ if (!target) /* no target, has to be me... */ acptr = &me; /* if it's not '*', look up the server */ else if ((target[0] != '*' || target[1] != '\0') && !(acptr = find_match_server(target))) return send_reply(sptr, ERR_NOSUCHSERVER, target); /* Z-line deprecation notice */ sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Use of Z-line is deprecated. " " Please use G-line instead.", sptr); /* Now, is the Z-line local or global? */ if (action == ZLINE_LOCAL_ACTIVATE || action == ZLINE_LOCAL_DEACTIVATE || !acptr) flags |= ZLINE_GLOBAL; else /* it's some form of local Z-line */ flags |= ZLINE_LOCAL; /* If it's a local activate/deactivate and server isn't me, propagate it */ if ((action == ZLINE_LOCAL_ACTIVATE || action == ZLINE_LOCAL_DEACTIVATE) && !IsMe(acptr)) { /* check for permissions... */ if (!feature_bool(FEAT_CONFIG_OPERCMDS)) return send_reply(sptr, ERR_DISABLED, "ZLINE"); else if (!HasPriv(sptr, PRIV_ZLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); Debug((DEBUG_DEBUG, "I am forwarding a local change to a global zline " "to a remote server; target %s, mask %s, operforce %s, action %c", cli_name(acptr), mask, flags & ZLINE_OPERFORCE ? "YES" : "NO", action == ZLINE_LOCAL_ACTIVATE ? '>' : '<')); sendcmdto_one(sptr, CMD_ZLINE, acptr, "%C %s%c%s", acptr, flags & ZLINE_OPERFORCE ? "!" : "", action == ZLINE_LOCAL_ACTIVATE ? '>' : '<', mask); return 0; /* all done */ } /* Next, try to find the Z-line... */ if ((flags & ZLINE_GLOBAL) || IsMe(acptr)) /* don't bother if it's not me! */ azline = zline_find(mask, flags | ZLINE_ANY | ZLINE_EXACT); /* We now have all the pieces to tell us what we've got; let's put * it all together and convert the rest of the arguments. */ /* Handle the local Z-lines first... */ if (flags & ZLINE_LOCAL) { assert(acptr); /* normalize the action, first */ if (action == ZLINE_LOCAL_ACTIVATE || action == ZLINE_MODIFY) action = ZLINE_ACTIVATE; else if (action == ZLINE_LOCAL_DEACTIVATE) action = ZLINE_DEACTIVATE; /* If it's not for us, forward */ /* UPDATE NOTE: Once all servers are updated to u2.10.12.11, the * format string in this sendcmdto_one() may be updated to omit * <lastmod> for ZLINE_ACTIVATE and to omit <expire>, <lastmod>, * and <reason> for ZLINE_DEACTIVATE. */ if (!IsMe(acptr)) { /* check for permissions... */ if (!feature_bool(FEAT_CONFIG_OPERCMDS)) return send_reply(sptr, ERR_DISABLED, "ZLINE"); else if (!HasPriv(sptr, PRIV_ZLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); Debug((DEBUG_DEBUG, "I am forwarding a local Z-line to a remote " "server; target %s, mask %s, operforce %s, action %c, " "expire %Tu, reason %s", target, mask, flags & ZLINE_OPERFORCE ? "YES" : "NO", action == ZLINE_ACTIVATE ? '+' : '-', expire, reason)); sendcmdto_one(sptr, CMD_ZLINE, acptr, "%C %s%c%s %Tu %Tu :%s", acptr, flags & ZLINE_OPERFORCE ? "!" : "", action == ZLINE_ACTIVATE ? '+' : '-', mask, expire - TStime(), TStime(), reason); return 0; /* all done */ } /* check local Z-line permissions... */ if (!HasPriv(sptr, PRIV_LOCAL_ZLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); /* let's handle activation... */ if (action == ZLINE_ACTIVATE) { if (azline) /* Z-line already exists, so let's ignore it... */ return 0; /* OK, create the local Z-line */ Debug((DEBUG_DEBUG, "I am creating a local Z-line here; target %s, " "mask %s, operforce %s, action %s, expire %Tu, reason: %s", target, mask, flags & ZLINE_OPERFORCE ? "YES" : "NO", action == ZLINE_ACTIVATE ? "+" : "-", expire, reason)); return zline_add(cptr, sptr, mask, reason, expire, 0, 0, flags | ZLINE_ACTIVE); } else { /* OK, it's a deactivation/destruction */ if (!azline) /* Z-line doesn't exist, so let's complain... */ return send_reply(sptr, ERR_NOSUCHZLINE, mask); /* Let's now destroy the Z-line */ Debug((DEBUG_DEBUG, "I am destroying a local Z-line here; target %s, " "mask %s, operforce %s, action %s", target, mask, flags & ZLINE_OPERFORCE ? "YES" : "NO", action == ZLINE_ACTIVATE ? "+" : "-")); return zline_destroy(cptr, sptr, azline); } } /* can't modify a Z-line that doesn't exist... * (and if we are creating a new one, we need a reason and expiration) */ if (!azline && (action == ZLINE_MODIFY || action == ZLINE_LOCAL_ACTIVATE || action == ZLINE_LOCAL_DEACTIVATE || !reason || !expire)) return send_reply(sptr, ERR_NOSUCHZLINE, mask); /* check for Z-line permissions... */ if (action == ZLINE_LOCAL_ACTIVATE || action == ZLINE_LOCAL_DEACTIVATE) { /* only need local privileges for locally-limited status changes */ if (!HasPriv(sptr, PRIV_LOCAL_ZLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); } else { /* global privileges required */ if (!feature_bool(FEAT_CONFIG_OPERCMDS)) return send_reply(sptr, ERR_DISABLED, "ZLINE"); else if (!HasPriv(sptr, PRIV_ZLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); } Debug((DEBUG_DEBUG, "I have a global Z-line I am acting upon now; " "target %s, mask %s, operforce %s, action %s, expire %Tu, " "reason: %s; zline %s! (fields present: %s %s)", target, mask, flags & ZLINE_OPERFORCE ? "YES" : "NO", action == ZLINE_ACTIVATE ? "+" : (action == ZLINE_DEACTIVATE ? "-" : (action == ZLINE_LOCAL_ACTIVATE ? ">" : (action == ZLINE_LOCAL_DEACTIVATE ? "<" : "(MODIFY)"))), expire, reason, azline ? "EXISTS" : "does not exist", flags & ZLINE_EXPIRE ? "expire" : "", flags & ZLINE_REASON ? "reason" : "")); if (azline) /* modifying an existing Z-line */ return zline_modify(cptr, sptr, azline, action, reason, expire, TStime(), 0, flags); assert(action != ZLINE_LOCAL_ACTIVATE); assert(action != ZLINE_LOCAL_DEACTIVATE); assert(action != ZLINE_MODIFY); /* create a new Z-line */ return zline_add(cptr, sptr, mask, reason, expire, TStime(), 0, flags | ((action == ZLINE_ACTIVATE) ? ZLINE_ACTIVE : 0)); }
int m_challenge(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { #ifdef USE_SSL struct ConfItem *aconf; RSA *rsa_public_key; BIO *file = NULL; char *challenge = NULL; char *name; char *tmpname; char chan[CHANNELLEN-1]; char* join[2]; int nl; struct Flags old_mode = cli_flags(sptr); if (!MyUser(sptr)) return 0; if (parc < 2) return need_more_params(sptr, "CHALLENGE"); if (parc > 2) { /* This is a remote OPER Request */ struct Client *srv; if (!string_has_wildcards(parv[1])) srv = FindServer(parv[1]); else srv = find_match_server(parv[1]); if (!feature_bool(FEAT_REMOTE_OPER)) return send_reply(sptr, ERR_NOOPERHOST); if (!srv) return send_reply(sptr, ERR_NOOPERHOST); if (IsMe(srv)) { parv[1] = parv[2]; } else { sendcmdto_one(sptr, CMD_CHALLENGE, srv, "%C %s", srv, parv[2]); return 0; } } /* if theyre an oper, reprint oper motd and ignore */ if (IsOper(sptr)) { send_reply(sptr, RPL_YOUREOPER); if (feature_bool(FEAT_OPERMOTD)) m_opermotd(sptr, sptr, 1, parv); } if (*parv[1] == '+') { /* Ignore it if we aren't expecting this... -A1kmm */ if (cli_user(sptr)->response == NULL) return 0; if (ircd_strcmp(cli_user(sptr)->response, ++parv[1])) { send_reply(sptr, ERR_PASSWDMISMATCH); sendto_allops(&me, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) (Password Incorrect)", parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr)); tmpname = strdup(cli_user(sptr)->auth_oper); failed_challenge_notice(sptr, tmpname, "challenge failed"); return 0; } name = strdup(cli_user(sptr)->auth_oper); aconf = find_conf_exact(cli_user(sptr)->auth_oper, cli_user(sptr)->realusername, MyUser(sptr) ? cli_sockhost(sptr) : cli_user(sptr)->realhost, CONF_OPS); if (!aconf) aconf = find_conf_exact(cli_user(sptr)->auth_oper, cli_user(sptr)->realusername, ircd_ntoa((const char*) &(cli_ip(sptr))), CONF_OPS); if (!aconf) aconf = find_conf_cidr(cli_user(sptr)->auth_oper, cli_user(sptr)->realusername, cli_ip(sptr), CONF_OPS); if (!aconf) { send_reply(sptr, ERR_NOOPERHOST); sendto_allops(&me, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) (No O:line)", parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr)); return 0; } if (CONF_LOCOP == aconf->status) { ClearOper(sptr); SetLocOp(sptr); } else { /* * prevent someone from being both oper and local oper */ ClearLocOp(sptr); if (!feature_bool(FEAT_OPERFLAGS) || !(aconf->port & OFLAG_ADMIN)) { /* Global Oper */ SetOper(sptr); ClearAdmin(sptr); } else { /* Admin */ SetOper(sptr); OSetGlobal(sptr); SetAdmin(sptr); } ++UserStats.opers; } cli_handler(cptr) = OPER_HANDLER; if (!feature_bool(FEAT_OPERFLAGS) || (aconf->port & OFLAG_WHOIS)) { OSetWhois(sptr); } if (!feature_bool(FEAT_OPERFLAGS) || (aconf->port & OFLAG_IDLE)) { OSetIdle(sptr); } if (!feature_bool(FEAT_OPERFLAGS) || (aconf->port & OFLAG_XTRAOP)) { OSetXtraop(sptr); } if (!feature_bool(FEAT_OPERFLAGS) || (aconf->port & OFLAG_HIDECHANS)) { OSetHideChans(sptr); } SetFlag(sptr, FLAG_WALLOP); SetFlag(sptr, FLAG_SERVNOTICE); SetFlag(sptr, FLAG_DEBUG); if (!IsAdmin(sptr)) cli_oflags(sptr) = aconf->port; set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD); client_set_privs(sptr, aconf); cli_max_sendq(sptr) = 0; /* Get the sendq from the oper's class */ send_umode_out(cptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE)); send_reply(sptr, RPL_YOUREOPER); if (IsAdmin(sptr)) { sendto_allops(&me, SNO_OLDSNO, "%s (%s@%s) is now an IRC Administrator", parv[0], cli_user(sptr)->username, cli_sockhost(sptr)); /* Autojoin admins to admin channel and oper channel (if enabled) */ if (feature_bool(FEAT_AUTOJOIN_ADMIN)) { if (feature_bool(FEAT_AUTOJOIN_ADMIN_NOTICE)) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, feature_str(FEAT_AUTOJOIN_ADMIN_NOTICE_VALUE)); ircd_strncpy(chan, feature_str(FEAT_AUTOJOIN_ADMIN_CHANNEL), CHANNELLEN-1); join[0] = cli_name(sptr); join[1] = chan; m_join(sptr, sptr, 2, join); } if (feature_bool(FEAT_AUTOJOIN_OPER) && IsOper(sptr)) { if (feature_bool(FEAT_AUTOJOIN_OPER_NOTICE)) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, feature_str(FEAT_AUTOJOIN_OPER_NOTICE_VALUE)); ircd_strncpy(chan, feature_str(FEAT_AUTOJOIN_OPER_CHANNEL), CHANNELLEN-1); join[0] = cli_name(sptr); join[1] = chan; m_join(sptr, sptr, 2, join); } } else { sendto_allops(&me, SNO_OLDSNO, "%s (%s@%s) is now an IRC Operator (%c)", parv[0], cli_user(sptr)->username, cli_sockhost(sptr), IsOper(sptr) ? 'O' : 'o'); if (feature_bool(FEAT_AUTOJOIN_OPER) && IsOper(sptr)) { if (feature_bool(FEAT_AUTOJOIN_OPER_NOTICE)) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, feature_str(FEAT_AUTOJOIN_OPER_NOTICE_VALUE)); ircd_strncpy(chan, feature_str(FEAT_AUTOJOIN_OPER_CHANNEL), CHANNELLEN-1); join[0] = cli_name(sptr); join[1] = chan; m_join(sptr, sptr, 2, join); } } if (feature_bool(FEAT_OPERMOTD)) m_opermotd(sptr, sptr, 1, parv); log_write(LS_OPER, L_INFO, 0, "OPER (%s) by (%#C)", name, sptr); ircd_snprintf(0, cli_user(sptr)->response, BUFSIZE+1, "%s", ""); return 0; } ircd_snprintf(0, cli_user(sptr)->response, BUFSIZE+1, "%s", ""); ircd_snprintf(0, cli_user(sptr)->auth_oper, NICKLEN+1, "%s", ""); aconf = find_conf_exact(parv[1], cli_user(sptr)->realusername, cli_user(sptr)->realhost, CONF_OPS); if (!aconf) aconf = find_conf_exact(parv[1], cli_user(sptr)->realusername, ircd_ntoa((const char*) &(cli_ip(sptr))), CONF_OPS); if (!aconf) aconf = find_conf_cidr(parv[1], cli_user(sptr)->realusername, cli_ip(sptr), CONF_OPS); if (aconf == NULL) { send_reply(sptr, ERR_NOOPERHOST); failed_challenge_notice(sptr, parv[1], "No o:line"); sendto_allops(&me, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) (No O:line)", parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr)); return 0; } if (!(aconf->port & OFLAG_RSA)) { send_reply(sptr, RPL_NO_CHALL); return 0; } if (!verify_sslclifp(sptr, aconf)) { sendto_allops(&me, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) (SSL Fingerprint Missmatch)", parv[0], cli_user(sptr)->realusername, cli_user(sptr)->realhost); send_reply(sptr, ERR_SSLCLIFP); return 0; } if ((file = BIO_new_file(aconf->passwd, "r")) == NULL) { send_reply(sptr, RPL_NO_KEY); return 0; } rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL); if (rsa_public_key == NULL) return send_reply(sptr, RPL_INVALID_KEY); if (!generate_challenge(&challenge, rsa_public_key, sptr)) { Debug((DEBUG_DEBUG, "generating challenge sum (%s)", challenge)); send_reply(sptr, RPL_RSACHALLENGE, challenge); ircd_snprintf(0, cli_user(sptr)->auth_oper, NICKLEN + 1, "%s", aconf->name); } nl = BIO_set_close(file, BIO_CLOSE); BIO_free(file); return 1; #else return 1; #endif }
static void do_trace(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { int i; struct Client *acptr; struct Client *acptr2; const struct ConnectionClass* cl; char* tname; int doall; int *link_s; int *link_u; int cnt = 0; int wilds; int dow; if (parc < 2 || BadPtr(parv[1])) { /* just "TRACE" without parameters. Must be from local client */ parc = 1; acptr = &me; tname = cli_name(&me); i = HUNTED_ISME; } else if (parc < 3 || BadPtr(parv[2])) { /* No target specified. Make one before propagating. */ parc = 2; tname = parv[1]; if ((acptr = find_match_server(parv[1])) || ((acptr = FindClient(parv[1])) && !MyUser(acptr))) { if (IsUser(acptr)) parv[2] = cli_name(cli_user(acptr)->server); else parv[2] = cli_name(acptr); parc = 3; parv[3] = 0; if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, IsServer(acptr), "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH) return; } else i = HUNTED_ISME; } else { /* Got "TRACE <tname> :<target>" */ parc = 3; if (MyUser(sptr) || Protocol(cptr) < 10) acptr = find_match_server(parv[2]); else acptr = FindNServer(parv[2]); if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, 0, "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH) return; tname = parv[1]; } if (i == HUNTED_PASS) { if (!acptr) acptr = next_client(GlobalClientList, tname); else acptr = cli_from(acptr); send_reply(sptr, RPL_TRACELINK, version, debugmode, tname, acptr ? cli_name(cli_from(acptr)) : "<No_match>"); return; } doall = (parv[1] && (parc > 1)) ? !match(tname, cli_name(&me)) : 1; wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?'); dow = wilds || doall; /* Don't give (long) remote listings to lusers */ if (dow && !MyConnect(sptr) && !IsAnOper(sptr)) { send_reply(sptr, RPL_TRACEEND); return; } link_s = MyCalloc(2 * maxconnections, sizeof(link_s[0])); link_u = link_s + maxconnections; if (doall) { for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) { if (IsUser(acptr)) link_u[cli_fd(cli_from(acptr))]++; else if (IsServer(acptr)) link_s[cli_fd(cli_from(acptr))]++; } } /* report all direct connections */ for (i = 0; i <= HighestFd; i++) { const char *conClass; if (!(acptr = LocalClientArray[i])) /* Local Connection? */ continue; if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsOper(sptr)) && !IsAnOper(acptr) && (acptr != sptr)) continue; if (!doall && wilds && match(tname, cli_name(acptr))) continue; if (!dow && 0 != ircd_strcmp(tname, cli_name(acptr))) continue; conClass = get_client_class(acptr); switch (cli_status(acptr)) { case STAT_CONNECTING: send_reply(sptr, RPL_TRACECONNECTING, conClass, cli_name(acptr)); cnt++; break; case STAT_HANDSHAKE: send_reply(sptr, RPL_TRACEHANDSHAKE, conClass, cli_name(acptr)); cnt++; break; case STAT_ME: break; case STAT_UNKNOWN: case STAT_UNKNOWN_USER: send_reply(sptr, RPL_TRACEUNKNOWN, conClass, get_client_name(acptr, HIDE_IP)); cnt++; break; case STAT_UNKNOWN_SERVER: send_reply(sptr, RPL_TRACEUNKNOWN, conClass, "Unknown Server"); cnt++; break; case STAT_USER: /* Only opers see users if there is a wildcard but anyone can see all the opers. */ if ((IsAnOper(sptr) && (MyUser(sptr) || !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr)) { if (IsAnOper(acptr)) send_reply(sptr, RPL_TRACEOPERATOR, conClass, get_client_name(acptr, SHOW_IP), CurrentTime - cli_lasttime(acptr)); else send_reply(sptr, RPL_TRACEUSER, conClass, get_client_name(acptr, SHOW_IP), CurrentTime - cli_lasttime(acptr)); cnt++; } break; /* * Connection is a server * * Serv <class> <nS> <nC> <name> <ConnBy> <last> <age> * * class Class the server is in * nS Number of servers reached via this link * nC Number of clients reached via this link * name Name of the server linked * ConnBy Who established this link * last Seconds since we got something from this link * age Seconds this link has been alive * * Additional comments etc...... -Cym-<*****@*****.**> */ case STAT_SERVER: if (cli_serv(acptr)->user) { if (!cli_serv(acptr)->by[0] || !(acptr2 = findNUser(cli_serv(acptr)->by)) || (cli_user(acptr2) != cli_serv(acptr)->user)) acptr2 = NULL; send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i], link_u[i], cli_name(acptr), acptr2 ? cli_name(acptr2) : "*", cli_serv(acptr)->user->username, cli_serv(acptr)->user->host, CurrentTime - cli_lasttime(acptr), CurrentTime - cli_serv(acptr)->timestamp); } else send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i], link_u[i], cli_name(acptr), (*(cli_serv(acptr))->by) ? cli_serv(acptr)->by : "*", "*", cli_name(&me), CurrentTime - cli_lasttime(acptr), CurrentTime - cli_serv(acptr)->timestamp); cnt++; break; default: /* We actually shouldn't come here, -msa */ send_reply(sptr, RPL_TRACENEWTYPE, get_client_name(acptr, HIDE_IP)); cnt++; break; } } /* * Add these lines to summarize the above which can get rather long * and messy when done remotely - Avalon */ if (IsAnOper(sptr) && doall) { for (cl = get_class_list(); cl; cl = cl->next) { if (Links(cl) > 1) send_reply(sptr, RPL_TRACECLASS, ConClass(cl), Links(cl) - 1); } } send_reply(sptr, RPL_TRACEEND); MyFree(link_s); }
/* * mo_jupe - oper message handler * * parv[0] = Send prefix * parv[1] = [[+|-]<server name>] * * Local (to me) style: * * parv[2] = [Expiration offset] * parv[3] = [Comment] * * Global (or remote local) style: * * parv[2] = [target] * parv[3] = [Expiration offset] * parv[4] = [Comment] * */ int mo_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client *acptr = 0; struct Jupe *ajupe; unsigned int flags = 0; time_t expire_off; char *server = parv[1], *target = 0, *reason; if (parc < 2) return jupe_list(sptr, 0); if (*server == '+') { flags |= JUPE_ACTIVE; server++; } else if (*server == '-') server++; else return jupe_list(sptr, server); if (!feature_bool(FEAT_CONFIG_OPERCMDS)) return send_reply(sptr, ERR_DISABLED, "JUPE"); if (parc == 4) { expire_off = atoi(parv[2]); reason = parv[3]; flags |= JUPE_LOCAL; } else if (parc > 4) { target = parv[2]; expire_off = atoi(parv[3]); reason = parv[4]; } else return need_more_params(sptr, "JUPE"); if (target) { if (!(target[0] == '*' && target[1] == '\0')) { if (!(acptr = find_match_server(target))) return send_reply(sptr, ERR_NOSUCHSERVER, target); if (!IsMe(acptr)) { /* manually propagate, since we don't set it */ if (!HasPriv(sptr, PRIV_JUPE)) return send_reply(sptr, ERR_NOPRIVILEGES); sendcmdto_one(sptr, CMD_JUPE, acptr, "%C %c%s %s %Tu :%s", acptr, flags & JUPE_ACTIVE ? '+' : '-', server, parv[3], TStime(), reason); return 0; } else if (!HasPriv(sptr, PRIV_LOCAL_JUPE)) return send_reply(sptr, ERR_NOPRIVILEGES); flags |= JUPE_LOCAL; } else if (!HasPriv(sptr, PRIV_JUPE)) return send_reply(sptr, ERR_NOPRIVILEGES); } ajupe = jupe_find(server); if (ajupe) { if (JupeIsLocal(ajupe) && !(flags & JUPE_LOCAL)) /* global over local */ jupe_free(ajupe); else { if (flags & JUPE_ACTIVE) return jupe_activate(cptr, sptr, ajupe, TStime(), flags); else return jupe_deactivate(cptr, sptr, ajupe, TStime(), flags); } } return jupe_add(cptr, sptr, server, reason, expire_off, TStime(), flags); }
/** Handle a CONNECT message from an operator. * * \a parv has the following elements: * \li \a parv[1] is the server that should initiate the connection * \li \a parv[2] is the port number to connect on (zero for the default) * \li \a parv[3] is the server to connect to * * See @ref m_functions for discussion of the arguments. * @param[in] cptr Client that sent us the message. * @param[in] sptr Original source of message. * @param[in] parc Number of arguments. * @param[in] parv Argument vector. */ int mo_connect(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { unsigned short port; unsigned short tmpport; const char* rule; struct ConfItem* aconf; struct Client* acptr; struct Jupe* ajupe; assert(0 != cptr); assert(cptr == sptr); assert(IsAnOper(sptr)); if (parc < 2) return need_more_params(sptr, "CONNECT"); if (parc > 3) { /* * if parc > 3, we are trying to connect two remote * servers to each other */ if (IsLocOp(sptr)) { /* * Only allow LocOps to make local CONNECTS --SRB */ return send_reply(cptr, ERR_NOPRIVILEGES); } else { struct Client* acptr2; struct Client* acptr3; if (!(acptr3 = find_match_server(parv[3]))) { return send_reply(sptr, ERR_NOSUCHSERVER, parv[3]); } /* * Look for closest matching server * needed for "/connect blah 4400 *"? */ for (acptr2 = acptr3; acptr2 != &me; acptr2 = cli_serv(acptr2)->up) { if (!match(parv[3], cli_name(acptr2))) acptr3 = acptr2; } parv[3] = cli_name(acptr3); if (hunt_server_cmd(sptr, CMD_CONNECT, cptr, 1, "%s %s :%C", 3, parc, parv) != HUNTED_ISME) return 0; } } /* * need to find the conf entry first so we can use the server name from * the conf entry instead of parv[1] to find out if the server is already * present below. --Bleep */ if (0 == (aconf = conf_find_server(parv[1]))) { sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Host %s not listed " "in ircd.conf", sptr, parv[1]); return 0; } /* * use aconf->name to look up the server, see above */ if ((acptr = FindServer(aconf->name))) { sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Server %s already " "exists from %s", sptr, parv[1], cli_name(cli_from(acptr))); return 0; } /* * Evaluate connection rules... If no rules found, allow the * connect. Otherwise stop with the first true rule (ie: rules * are ored together. Oper connects are effected only by D * lines (CRULEALL) not d lines (CRULEAUTO). */ if ((rule = conf_eval_crule(aconf->name, CRULE_ALL))) { sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Disallowed by rule: %s", sptr, rule); return 0; } /* * Check to see if the server is juped; if it is, disallow the connect */ if ((ajupe = jupe_find(aconf->name)) && JupeIsActive(ajupe)) { sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Server %s is juped: %s", sptr, JupeServer(ajupe), JupeReason(ajupe)); return 0; } /* * Get port number from user, if given. If not specified, * use the default from configuration structure. If missing * from there, then use the precompiled default. */ port = aconf->address.port; if (parc > 2) { assert(0 != parv[2]); if (0 == (port = atoi(parv[2]))) { sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Invalid port number", sptr); return 0; } } if (0 == port && 0 == (port = feature_int(FEAT_SERVER_PORT))) { sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: missing port number", sptr); return 0; } tmpport = aconf->address.port; aconf->address.port = port; if (connect_server(aconf, sptr)) { sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Connecting to %s.", sptr, aconf->name); } else { sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Connection to %s failed", sptr, aconf->name); } aconf->address.port = tmpport; return 0; }