Add oper::auto-login. When set to yes, opers are automatically logged in

if the oper block permits, the user does not have to send "OPER xyz".

Eg:
security-group Syzop { certfp "xyz"; }
oper Syzop {
	auto-login yes;
        mask { security-group Syzop; }
        operclass netadmin-with-override;
        class opers;
}

Then, if you connect with SSL with that certificate fingerprint,
you become IRCOp automatically.
This commit is contained in:
Bram Matthys 2022-05-26 20:57:03 +02:00
parent c183c06d06
commit d47fdbede4
No known key found for this signature in database
GPG key ID: BF8116B163EAAE98
3 changed files with 53 additions and 1 deletions
include
src

View file

@ -1635,6 +1635,7 @@ struct ConfigItem_oper {
int maxlogins;
int server_notice_colors;
int server_notice_show_event;
int auto_login;
};
/** The TLS options that are used in set::tls and otherblocks::tls-options.

View file

@ -3999,6 +3999,10 @@ int _conf_oper(ConfigFile *conf, ConfigEntry *ce)
{
oper->server_notice_show_event = config_checkval(cep->value, CFG_YESNO);
}
else if (!strcmp(cep->name, "auto-login"))
{
oper->auto_login = config_checkval(cep->value, CFG_YESNO);
}
else if (!strcmp(cep->name, "modes"))
{
oper->modes = set_usermode(cep->value);
@ -4028,7 +4032,7 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
{
char has_class = 0, has_password = 0, has_snomask = 0;
char has_modes = 0, has_require_modes = 0, has_mask = 0, has_match = 0, has_broad_match = 0;
char has_maxlogins = 0, has_operclass = 0, has_vhost = 0;
char has_maxlogins = 0, has_operclass = 0, has_vhost = 0, has_auto_login = 0;
ConfigEntry *cep;
int errors = 0;
@ -4134,6 +4138,10 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
else if (!strcmp(cep->name, "server-notice-show-event"))
{
}
else if (!strcmp(cep->name, "auto-login"))
{
has_auto_login = config_checkval(cep->value, CFG_YESNO);
}
/* oper::modes */
else if (!strcmp(cep->name, "modes"))
{
@ -4270,12 +4278,27 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce)
}
}
if (has_auto_login && has_broad_match)
{
config_error("%s:%i: your oper block for '%s' has auto-login but is completely unrestricted (mask *@*)!",
ce->file->filename, ce->line_number, ce->value);
errors++;
} else
if (!has_password && has_broad_match)
{
config_error("%s:%i: your oper block for '%s' has no password and is completely unrestricted (mask *@*)!",
ce->file->filename, ce->line_number, ce->value);
errors++;
}
/* The rest should NOT be in an 'else'... */
if (has_password && has_auto_login)
{
config_error("%s:%i: You have auto-login enabled for your oper block '%s' but you also have a password set. "
"Remove the password if you want to use auto-login.",
ce->file->filename, ce->line_number, ce->value);
errors++;
}
if (!has_mask && !has_match)
{
config_error_missing(ce->file->filename, ce->line_number,

View file

@ -34,6 +34,7 @@ ModuleHeader MOD_HEADER
/* Forward declarations */
CMD_FUNC(cmd_oper);
int _make_oper(Client *client, const char *operblock_name, const char *operclass, ConfigItem_class *clientclass, long modes, const char *snomask, const char *vhost);
int oper_connect(Client *client);
MOD_TEST()
{
@ -46,6 +47,7 @@ MOD_INIT()
{
MARK_AS_OFFICIAL_MODULE(modinfo);
CommandAdd(modinfo->handle, MSG_OPER, cmd_oper, MAXPARA, CMD_USER);
HookAdd(modinfo->handle, HOOKTYPE_LOCAL_CONNECT, 0, oper_connect);
return MOD_SUCCESS;
}
@ -348,3 +350,29 @@ CMD_FUNC(cmd_oper)
log_data_string("warn_type", "OUTDATED_TLS_PROTOCOL_OR_CIPHER"));
}
}
int oper_connect(Client *client)
{
ConfigItem_oper *e;
if (IsOper(client))
return 0;
for (e = conf_oper; e; e = e->next)
{
if (e->auto_login && user_allowed_by_security_group(client, e->match))
{
/* Ideally we would check all the criteria that cmd_oper does.
* I'm taking a shortcut for now that is not ideal...
*/
const char *parx[3];
parx[0] = NULL;
parx[1] = e->name;
parx[2] = NULL;
do_cmd(client, NULL, "OPER", 3, parx);
return 0;
}
}
return 0;
}