/* ** m_oper ** parv[0] = sender prefix ** parv[1] = oper name ** parv[2] = oper password */ static void m_oper(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct ConfItem *conf; struct AccessItem *aconf = NULL; const char *name = parv[1]; const char *password = parv[2]; if (EmptyString(password) && EmptyString(source_p->certfp)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "OPER"); return; } /* end the grace period */ if (!IsFloodDone(source_p)) flood_endgrace(source_p); if ((conf = find_exact_name_conf(OPER_TYPE, source_p, name, NULL, NULL)) == NULL) { sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name); conf = find_exact_name_conf(OPER_TYPE, NULL, name, NULL, NULL); failed_oper_notice(source_p, name, (conf != NULL) ? "host mismatch" : "no oper {} block"); return; } aconf = (struct AccessItem *)map_to_conf(conf); if (match_conf_password(password, source_p->certfp, aconf)) { if (attach_conf(source_p, conf) != 0) { sendto_one(source_p, ":%s NOTICE %s :Can't attach conf!", me.name, source_p->name); failed_oper_notice(source_p, name, "can't attach conf!"); return; } oper_up(source_p); ilog(LOG_TYPE_OPER, "OPER %s by %s!%s@%s", name, source_p->name, source_p->username, source_p->host); } else { sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name); failed_oper_notice(source_p, name, "password mismatch"); } }
/* SET AUTOCONN */ static void quote_autoconn(struct Client *source_p, const char *arg, int newval) { if (!EmptyString(arg)) { struct MaskItem *conf = find_exact_name_conf(CONF_SERVER, NULL, arg, NULL, NULL); if (conf) { if (newval) SetConfAllowAutoConn(conf); else ClearConfAllowAutoConn(conf); sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s has changed AUTOCONN for %s to %i", get_oper_name(source_p), arg, newval); sendto_one_notice(source_p, &me, ":AUTOCONN for %s is now set to %i", arg, newval); } else sendto_one_notice(source_p, &me, ":Cannot find %s", arg); } else sendto_one_notice(source_p, &me, ":Please specify a server name!"); }
/* find_password_conf() * * inputs - name * - pointer to source_p * output - pointer to oper conf or NULL * side effects - NONE */ static struct ConfItem * find_password_conf(const char *name, struct Client *source_p) { struct ConfItem *conf; if ((conf = find_exact_name_conf(OPER_TYPE, name, source_p->username, source_p->host )) != NULL) { return(conf); } else if ((conf = find_exact_name_conf(OPER_TYPE, name, source_p->username, source_p->localClient->sockhost)) != NULL) { return(conf); } return(NULL); }
static void resv_remove(struct Client *source_p, const char *name) { unsigned int type_int = CONF_CRESV; const char *type_str = "channel"; struct MaskItem *conf = NULL; if (!IsChanPrefix(*name)) { type_int = CONF_NRESV; type_str = "nick"; } if ((conf = find_exact_name_conf(type_int, NULL, name, NULL, NULL)) == NULL) { if (IsClient(source_p)) sendto_one_notice(source_p, &me, ":A RESV does not exist for %s: %s", type_str, name); return; } if (!IsConfDatabase(conf)) { if (IsClient(source_p)) sendto_one_notice(source_p, &me, ":The RESV for %s: %s is in ircd.conf and must be removed by hand.", type_str, name); return; } conf_free(conf); if (IsClient(source_p)) sendto_one_notice(source_p, &me, ":The RESV has been removed on %s: %s", type_str, name); sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s has removed the RESV for %s: %s", get_oper_name(source_p), type_str, name); ilog(LOG_TYPE_RESV, "%s removed RESV for [%s]", get_oper_name(source_p), name); }
static void resv_remove(struct Client *source_p, const char *name) { unsigned int type = CONF_CRESV; struct MaskItem *conf = NULL; if (!IsChanPrefix(*name)) type = CONF_NRESV; if ((conf = find_exact_name_conf(type, NULL, name, NULL, NULL)) == NULL) { if (IsClient(source_p)) sendto_one_notice(source_p, &me, ":No RESV for %s", name); return; } if (!IsConfDatabase(conf)) { if (IsClient(source_p)) sendto_one_notice(source_p, &me, ":The RESV for %s is in ircd.conf and must be removed by hand", name); return; } conf_free(conf); if (IsClient(source_p)) sendto_one_notice(source_p, &me, ":RESV for [%s] is removed", name); sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s has removed the RESV for: [%s]", get_oper_name(source_p), name); ilog(LOG_TYPE_RESV, "%s removed RESV for [%s]", get_oper_name(source_p), name); }
/* * m_challenge - generate RSA challenge for wouldbe oper * parv[0] = sender prefix * parv[1] = operator to challenge for, or +response * */ static void m_challenge(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *challenge = NULL; struct ConfItem *conf = NULL; struct AccessItem *aconf = NULL; /* if theyre an oper, reprint oper motd and ignore */ if(IsOper(source_p)) { sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, parv[0]); send_message_file(source_p, &ConfigFileEntry.opermotd); return; } if(*parv[1] == '+') { /* Ignore it if we aren't expecting this... -A1kmm */ if(source_p->localClient->response == NULL) return; if(svsnoop) { sendto_one(source_p, ":%s NOTICE %s :*** This server is in NOOP mode, you cannot /oper", me.name, source_p->name); failed_challenge_notice(source_p, source_p->localClient->auth_oper, "This server is in NOOP mode"); log_oper_action(LOG_FAILED_OPER_TYPE, source_p, "%s\n", source_p->localClient->auth_oper); return; } if(irccmp(source_p->localClient->response, ++parv[1])) { sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name); failed_challenge_notice(source_p, source_p->localClient->auth_oper, "challenge failed"); return; } conf = find_exact_name_conf(OPER_TYPE, source_p->localClient->auth_oper, source_p->username, source_p->host); if(conf == NULL) conf = find_exact_name_conf(OPER_TYPE, source_p->localClient->auth_oper, source_p->username, source_p->realhost); if(conf == NULL) conf = find_exact_name_conf(OPER_TYPE, source_p->localClient->auth_oper, source_p->username, source_p->sockhost); if(conf == NULL) { sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, parv[0]); log_oper_action(LOG_FAILED_OPER_TYPE, source_p, "%s\n", source_p->localClient->auth_oper); return; } if(attach_conf(source_p, conf) != 0) { sendto_one(source_p, ":%s NOTICE %s :Can't attach conf!", me.name, source_p->name); failed_challenge_notice(source_p, conf->name, "can't attach conf!"); log_oper_action(LOG_FAILED_OPER_TYPE, source_p, "%s\n", source_p->localClient->auth_oper); return; } oper_up(source_p); ilog(L_TRACE, "OPER %s by %s!%s@%s", source_p->localClient->auth_oper, source_p->name, source_p->username, source_p->realhost); log_oper_action(LOG_OPER_TYPE, source_p, "%s\n", source_p->localClient->auth_oper); MyFree(source_p->localClient->response); MyFree(source_p->localClient->auth_oper); source_p->localClient->response = NULL; source_p->localClient->auth_oper = NULL; return; } MyFree(source_p->localClient->response); MyFree(source_p->localClient->auth_oper); source_p->localClient->response = NULL; source_p->localClient->auth_oper = NULL; if((conf = find_conf_exact(OPER_TYPE, parv[1], source_p->username, source_p->host)) != NULL) aconf = map_to_conf(conf); else if((conf = find_conf_exact(OPER_TYPE, parv[1], source_p->username, source_p->realhost)) != NULL) aconf = map_to_conf(conf); else if((conf = find_conf_exact(OPER_TYPE, parv[1], source_p->username, source_p->sockhost)) != NULL) aconf = map_to_conf(conf); if(aconf == NULL) { sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, parv[0]); conf = find_exact_name_conf(OPER_TYPE, parv[1], NULL, NULL); failed_challenge_notice(source_p, parv[1], (conf != NULL) ? "host mismatch" : "no oper {} block"); log_oper_action(LOG_FAILED_OPER_TYPE, source_p, "%s\n", parv[1]); return; } if(aconf->rsa_public_key == NULL) { sendto_one(source_p, ":%s NOTICE %s :I'm sorry, PK authentication " "is not enabled for your oper{} block.", me.name, parv[0]); return; } if(!generate_challenge(&challenge, &(source_p->localClient->response), aconf->rsa_public_key)) sendto_one(source_p, form_str(RPL_RSACHALLENGE), me.name, parv[0], challenge); DupString(source_p->localClient->auth_oper, conf->name); MyFree(challenge); }
static void remove_resv(struct Client *source_p, const char *name) { struct ConfItem *conf = NULL; int services = 0; if(IsServices(source_p)) services = 1; if(IsChanPrefix(*name)) { struct ResvChannel *resv_p; if(resv_channel_list.head == NULL || !(resv_p = hash_find_resv(name))) { if(!services) sendto_one(source_p, ":%s NOTICE %s :A RESV does not exist for channel: %s", me.name, source_p->name, name); return; } if(resv_p->conf) { if(!services) sendto_one(source_p, ":%s NOTICE %s :The RESV for channel: %s is in ircd.conf and must be removed by hand.", me.name, source_p->name, name); return; } delete_channel_resv(resv_p); remove_conf_line(CRESV_TYPE, source_p, name, NULL); if(!services) { sendto_one(source_p, ":%s NOTICE %s :The RESV has been removed on channel: %s", me.name, source_p->name, name); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has removed the RESV for channel: %s", get_oper_name(source_p), name); } } else { struct MatchItem *resv_p = NULL; if((conf = find_exact_name_conf(NRESV_TYPE, name, NULL, NULL, NULL)) == NULL) { if(!services) sendto_one(source_p, ":%s NOTICE %s :A RESV does not exist for nick: %s", me.name, source_p->name, name); return; } resv_p = map_to_conf(conf); if(resv_p->action) { if(!services) sendto_one(source_p, ":%s NOTICE %s :The RESV for nick: %s is in ircd.conf and must be removed by hand.", me.name, source_p->name, name); return; } delete_conf_item(conf); remove_conf_line(NRESV_TYPE, source_p, name, NULL); if(!services) { sendto_one(source_p, ":%s NOTICE %s :The RESV has been removed on nick: %s", me.name, source_p->name, name); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has removed the RESV for nick: %s", get_oper_name(source_p), name); } } }
/* * m_challenge - generate RSA challenge for wouldbe oper * parv[0] = sender prefix * parv[1] = operator to challenge for, or +response * */ static void m_challenge(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *challenge = NULL; struct MaskItem *conf = NULL; if (*parv[1] == '+') { /* Ignore it if we aren't expecting this... -A1kmm */ if (source_p->localClient->response == NULL) return; if (irccmp(source_p->localClient->response, ++parv[1])) { sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name); failed_challenge_notice(source_p, source_p->localClient->auth_oper, "challenge failed"); return; } conf = find_exact_name_conf(CONF_OPER, source_p, source_p->localClient->auth_oper, NULL, NULL); if (conf == NULL) { /* XXX: logging */ sendto_one (source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name); return; } if (attach_conf(source_p, conf) != 0) { sendto_one(source_p,":%s NOTICE %s :Can't attach conf!", me.name, source_p->name); failed_challenge_notice(source_p, conf->name, "can't attach conf!"); return; } ++conf->count; oper_up(source_p); ilog(LOG_TYPE_OPER, "OPER %s by %s!%s@%s", source_p->localClient->auth_oper, source_p->name, source_p->username, source_p->host); MyFree(source_p->localClient->response); MyFree(source_p->localClient->auth_oper); source_p->localClient->response = NULL; source_p->localClient->auth_oper = NULL; return; } MyFree(source_p->localClient->response); MyFree(source_p->localClient->auth_oper); source_p->localClient->response = NULL; source_p->localClient->auth_oper = NULL; conf = find_exact_name_conf(CONF_OPER, source_p, parv[1], NULL, NULL); if (!conf) { sendto_one (source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name); conf = find_exact_name_conf(CONF_OPER, NULL, parv[1], NULL, NULL); failed_challenge_notice(source_p, parv[1], (conf != NULL) ? "host mismatch" : "no oper {} block"); return; } if (conf->rsa_public_key == NULL) { sendto_one (source_p, ":%s NOTICE %s :I'm sorry, PK authentication " "is not enabled for your oper{} block.", me.name, source_p->name); return; } if (!generate_challenge(&challenge, &(source_p->localClient->response), conf->rsa_public_key)) sendto_one(source_p, form_str(RPL_RSACHALLENGE), me.name, source_p->name, challenge); source_p->localClient->auth_oper = xstrdup(conf->name); MyFree(challenge); }
/*! \brief OPER command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = oper name * - parv[2] = oper password */ static int m_oper(struct Client *source_p, int parc, char *parv[]) { struct MaskItem *conf = NULL; const char *const opername = parv[1]; const char *const password = parv[2]; if (EmptyString(password)) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "OPER"); return 0; } /* end the grace period */ if (!IsFloodDone(source_p)) flood_endgrace(source_p); if ((conf = find_exact_name_conf(CONF_OPER, source_p, opername, NULL, NULL)) == NULL) { sendto_one_numeric(source_p, &me, ERR_NOOPERHOST); conf = find_exact_name_conf(CONF_OPER, NULL, opername, NULL, NULL); failed_oper_notice(source_p, opername, (conf != NULL) ? "host mismatch" : "no operator {} block"); return 0; } if (IsConfSSL(conf) && !HasUMode(source_p, UMODE_SSL)) { sendto_one_numeric(source_p, &me, ERR_NOOPERHOST); failed_oper_notice(source_p, opername, "requires SSL/TLS"); return 0; } if (!EmptyString(conf->certfp)) { if (EmptyString(source_p->certfp) || strcasecmp(source_p->certfp, conf->certfp)) { sendto_one_numeric(source_p, &me, ERR_NOOPERHOST); failed_oper_notice(source_p, opername, "client certificate fingerprint mismatch"); return 0; } } if (match_conf_password(password, conf)) { if (attach_conf(source_p, conf)) { sendto_one_notice(source_p, &me, ":Can't attach conf!"); failed_oper_notice(source_p, opername, "can't attach conf!"); return 0; } user_oper_up(source_p); ilog(LOG_TYPE_OPER, "OPER %s by %s!%s@%s", opername, source_p->name, source_p->username, source_p->host); } else { sendto_one_numeric(source_p, &me, ERR_PASSWDMISMATCH); failed_oper_notice(source_p, opername, "password mismatch"); } return 0; }