/**********************************************************************
* PTlink IRC Services is (C) Copyright PTlink IRC Software 1999-2005 *
* http://software.pt-link.net *
* This program is distributed under GNU Public License *
* Please read the file COPYING for copyright information. *
**********************************************************************
Description: nickserv set command
* $Id: ns_set.c,v 1.15 2005/10/18 16:25:06 jpinto Exp $
*/
#include "nickserv.h"
#include "module.h"
#include "dbconf.h"
#include "encrypt.h"
#include "my_sql.h"
#include "email.h"
#include "nsmacros.h"
#include "ns_group.h" /* is_sadmin */
#include "lang/common.lh"
#include "lang/ns_set.lh"
#include "lang/ns_register.lh"
SVS_Module mod_info =
/* module, version, description */
{"ns_set", "2.4", "nickserv set/sset command" };
/* Change Log
2.4 - Added support for th USEMSG setting
2.3 - #1 : Replace NS AUTOJOIN with CS AJOIN ADD/DEL
2.2 - #12: sset vhost should check for a valid hostname
2.1 - 0000329: option to set a favorite link (to be used for links exchange)
0000327: sadmins SSET nick vhost to set a virtual hostname
2.0 - 0000287: ns_getpass and ns_getsec to recover password and security code
0000276: nick password expire option
0000272: move nickserv security info to a specific table
0000265: remove nickserv cache system
1.4 - 0000269: potential crash on ns set email
1.3 - 0000246: help display with group filter
1.2 - 0000224: SSET on password sets and a nickserv notice
- 0000243: protected nick set option
1.1 - don't check for emails count when setting to the same email
0000227: nickserv SSET PASSWORD not working
0000225: unable to reSET email address with 3 nicks registered
*/
/* external functions we need */
ServiceUser* (*nickserv_suser)(void);
u_int32_t (*find_group)(char *name);
int (*check_nick_security)
(u_int32_t snid, IRC_User *u, char* pass, char* email, int flags);
int (*forbidden_email)(char *email);
MOD_REQUIRES
MOD_FUNC(dbconf_get)
MOD_FUNC(nickserv_suser)
MOD_FUNC(check_nick_security)
MOD_FUNC(is_sadmin)
MOD_FUNC(find_group)
EMAIL_FUNCTIONS
MOD_END
MOD_OPTIONS
MOD_FUNC(forbidden_email)
MOD_END
/* internal functions */
void set_command(IRC_User *u, IRC_User *s, char* tnick, u_int32_t tsnid, char *option, char *value, int is_sset);
void ns_set(IRC_User *s, IRC_User *u);
void ns_sset(IRC_User *s, IRC_User *u); /* sadmin set */
/* Remote config */
static int StrongPasswords;
static int NickSecurityCode;
static int SecurityCodeLenght;
static int MaxNicksPerEmail;
DBCONF_REQUIRES
DBCONF_GET("nickserv", StrongPasswords)
DBCONF_GET("nickserv", NickSecurityCode)
DBCONF_GET("nickserv", SecurityCodeLenght)
DBCONF_GET("nickserv", MaxNicksPerEmail)
DBCONF_END
/* this is called before load and at services rehash */
int mod_rehash(void)
{
if(dbconf_get(dbconf_requires) < 0 )
{
errlog("Error reading dbconf!");
return -1;
}
return 0;
}
ServiceUser* nsu;
int ns_log;
char *setemail_emails[MAX_LANGS];
int mod_load(void)
{
nsu = nickserv_suser();
ns_log = log_handle("nickserv");
if(email_load("setemail", setemail_emails) < 0)
return -1;
suser_add_cmd(nsu, "SET", ns_set, SET_SUMMARY, SET_HELP);
suser_add_cmd_g(nsu, "SSET", ns_sset, SSET_SUMMARY, SSET_HELP,
find_group("Admin"));
return 0;
}
void
mod_unload(void)
{
suser_del_mod_cmds(nsu, &mod_info);
email_free(setemail_emails);
}
#define FLAG_SET(x,y) \
{ \
if(IsNull(value)) \
send_lang(u, s, VALUE_ON_OR_OFF); \
else \
if(strcasecmp(value,"on") == 0) \
{ \
log_log(ns_log, mod_info.name, "%s %s %s %s %s", \
u->nick, is_sset ? "SSET" : "SET", tnick, y, value); \
if(u->snid == tsnid) u->flags |= (x); \
send_lang(u, s, OPTION_X_ON, (y)); \
sql_execute("UPDATE nickserv SET flags=(flags | %d) "\
"WHERE snid=%d", (x), tsnid);\
} else \
if(strcasecmp(value,"off") == 0) \
{ \
log_log(ns_log, mod_info.name, "%s %s %s %s %s", \
u->nick, is_sset ? "SSET" : "SET", tnick, y, value); \
if(u->snid == tsnid) u->flags &= ~(x); \
send_lang(u, s, OPTION_X_OFF, (y)); \
sql_execute("UPDATE nickserv SET flags=(flags & ~%d) " \
"WHERE snid=%d", (x), tsnid);\
} else \
send_lang(u, s, VALUE_ON_OR_OFF); \
}
#define STRING_SET(x,y,z) \
{ \
if(IsNull(value)) \
{ \
log_log(ns_log, mod_info.name, "%s %s %s %s", \
u->nick, is_sset ? "SSET" : "SET", tnick, option);\
send_lang(u, s, (y)); \
} \
else \
{ \
log_log(ns_log, mod_info.name, "%s %s %s %s %s", \
u->nick, is_sset ? "SSET" : "SET", tnick, option, value);\
send_lang(u, s, (z), value); \
} \
sql_execute("UPDATE nickserv SET %s=%s "\
"WHERE snid=%d", (x), sql_str(value), tsnid);\
}
/* handles a set command */
void set_command(IRC_User *u, IRC_User *s, char* tnick, u_int32_t tsnid, char *option, char *value, int is_sset)
{
int li;
if(strcasecmp(option,"URL") == 0)
{
#if 0
if(value && strncasecmp(value, "http://", 7))
send_lang(u, s, URL_NEEDS_HTTP);
else
#endif
STRING_SET("url", URL_UNSET, URL_CHANGED_TO_X)
}
else if(strcasecmp(option,"FAVLINK") == 0)
{
#if 0
if(value && strncasecmp(value, "http://", 7))
send_lang(u, s, URL_NEEDS_HTTP);
else
{
#endif
if(NickSecurityCode && !IsAuthenticated(u))
send_lang(u, s, NEEDS_AUTH_NICK);
else
STRING_SET("favlink", FAVLINK_UNSET, FAVLINK_CHANGED_TO_X)
#if 0
}
#endif
}
else if(strcasecmp(option,"LOCATION") == 0)
STRING_SET("location", LOCATION_UNSET, LOCATION_CHANGED_TO_X)
else if(strcasecmp(option,"IMID") == 0)
STRING_SET("imid", IMID_UNSET, IMID_CHANGED_TO_X)
else if(strcasecmp(option,"PRIVATE") == 0)
FLAG_SET(NFL_PRIVATE, "PRIVATE")
else if(strcasecmp(option,"NONEWS") == 0)
FLAG_SET(NFL_NONEWS, "NONEWS")
else if(strcasecmp(option,"PROTECTED") == 0)
FLAG_SET(NFL_PROTECTED, "PROTECTED")
else if(strcasecmp(option,"HIDEEMAIL") == 0)
FLAG_SET(NFL_HIDEEMAIL, "HIDEEMAIL")
else if(strcasecmp(option,"USEMSG") == 0)
FLAG_SET(NFL_USEMSG, "USEMSG")
else if(strcasecmp(option,"EMAIL") == 0)
{
int diff = 1;
char *email = NULL;
char *securitycode = strtok(NULL, " ");
if(value && forbidden_email && (forbidden_email(value) > 0))
{
send_lang(u, s, FORBIDDEN_EMAIL);
return;
}
if(sql_singlequery("SELECT email FROM nickserv WHERE snid=%d",
tsnid) && sql_field(0))
email = strdup(sql_field(0));
if(sql_singlequery("SELECT securitycode FROM nickserv_security WHERE snid=%d",
tsnid) && sql_field(0) && securitycode)
{
diff = memcmp(hex_bin(sql_field(0)), encrypted_password(securitycode), 16);
if(diff != 0)
diff = strcasecmp(sql_field(0), securitycode);
}
if(!is_sset && NickSecurityCode && IsAuthenticated(u))
{
if(IsNull(securitycode))
{
FREE(email);
send_lang(u, s, SET_EMAIL_SECURITY_REQUIRED);
return;
}
else if(diff != 0)
{
FREE(email);
send_lang(u, s, INVALID_SECURITY_CODE);
return;
}
}
if(IsNull(value))
send_lang(u, s, CANT_EMAIL_UNSET);
else if((email && strcasecmp(value, email)) &&
MaxNicksPerEmail && (reg_count_for_email(value) >= MaxNicksPerEmail))
send_lang(u, s, ALREADY_X_WITH_EMAIL, MaxNicksPerEmail);
else
{
if(!is_email(value))
send_lang(u, s, INVALID_EMAIL);
else
{
securitycode = malloc(SecurityCodeLenght+1);
rand_string(securitycode, SecurityCodeLenght, SecurityCodeLenght);
sql_execute("UPDATE nickserv SET email=%s, flags = (flags & ~%d)"
" WHERE snid=%d", sql_str(value), NFL_AUTHENTIC, tsnid);
sql_execute("UPDATE nickserv_security SET securitycode='%s'"
" WHERE snid=%d",
hex_str(encrypted_password(securitycode),16), tsnid);
u->flags &= ~NFL_AUTHENTIC;
if(NickSecurityCode)
{
email_init_symbols();
email_add_symbol("nick", u->nick);
email_add_symbol("email", value);
email_add_symbol("securitycode", securitycode);
if(tsnid == u->snid)
u->flags &= ~NFL_AUTHENTIC;
send_lang(u, s, EMAIL_REQUEST_TO_X, value);
email_send(setemail_emails[u->lang]);
irc_SvsMode(u, s, "-r");
}
else
send_lang(u, s, EMAIL_CHANGED_TO_X, value);
free(securitycode);
log_log(ns_log, mod_info.name, "%s %s %s %s %s",
u->nick, is_sset ? "SSET" : "SET", tnick, option, value);
}
FREE(email);
}
}
else
if(strcasecmp(option,"LANGUAGE") == 0)
{
if(value)
{
lang2index(value, li);
}
else
li = -1;
if(li==-1)
{
send_lang(u, s, INVALID_LANGUAGE_X, value ? value : "");
}
else
{
u->lang = li;
send_lang(u, s, LANGUAGE_CHANGED_TO_X, value);
sql_execute("UPDATE nickserv SET lang=%d WHERE snid=%d",
li, tsnid);
}
}
else
if(strcasecmp(option,"PASSWORD") == 0)
{
if(IsNull(value))
send_lang(u, s, MANDATORY_PASSWORD);
else
if(StrongPasswords && is_weak_passwd(value))
send_lang(u, s, WEAK_PASSWORD);
else
{
sql_execute("UPDATE nickserv_security SET pass='%s', t_lset_pass=%d "
"WHERE snid=%d", hex_str(encrypted_password(value), 16), (int) irc_CurrentTime,
tsnid);
if(!is_sset)
send_lang(u, s, PASSWORD_CHANGED_TO_X, value);
else
send_lang(u, s, PASSWORD_CHANGED_FOR_X_TO_X, tnick, value);
log_log(ns_log, mod_info.name, "%s %s %s %s ******",
u->nick, is_sset ? "SSET" : "SET", tnick, option);
if(u->snid == tsnid);
{
char *email = NULL;
if(sql_singlequery("SELECT email FROM nickserv WHERE snid=%d", tsnid))
email = sql_field(0);
check_nick_security(tsnid, u, NULL, email, u->flags);
}
}
}
else if(is_sset == 0)
send_lang(u, s, UNKNOWN_OPTION_X, option);
else
if(strcasecmp(option,"NOEXPIRE") == 0)
FLAG_SET(NFL_NOEXPIRE, "NOEXPIRE")
else
if(strcasecmp(option, "VHOST") == 0)
{
if(value && !irc_IsValidHostname(value))
send_lang(u, s, NS_SET_INVALID_HOST_X, value);
else
STRING_SET("vhost", VHOST_UNSET, VHOST_CHANGED_TO_X)
}
else
send_lang(u, s, UNKNOWN_OPTION_X, option);
}
#undef STRING_SET
#undef FLAG_SET
/* s = service the command was sent to
u = user the command was sent from */
void ns_set(IRC_User *s, IRC_User *u)
{
u_int32_t source_snid;
char *option, *value;
CHECK_IF_IDENTIFIED_NICK
option = strtok(NULL, " ");
if(!IsNull(option) && (strcasecmp(option, "LOCATION") == 0))
value = strtok(NULL, "");
else
value = strtok(NULL, " ");
if(IsNull(option))
{
send_lang(u, s, NICK_SET_SYNTAX);
return;
}
set_command(u, s, u->nick, u->snid, option, value, 0);
}
#undef STRING_SET
/* s = service the command was sent to
u = user the command was sent from */
void ns_sset(IRC_User *s, IRC_User *u)
{
u_int32_t source_snid;
u_int32_t tsnid;
char *nick, *option = NULL, *value = NULL;
nick = strtok(NULL, " ");
if(nick)
option = strtok(NULL, " ");
CHECK_IF_IDENTIFIED_NICK
if(!IsNull(nick) && !IsNull(option) && (strcasecmp(option,"LOCATION")==0))
value = strtok(NULL, "");
else
value = strtok(NULL, " ");
if(IsNull(nick) || IsNull(option))
send_lang(u, s, NICK_SSET_SYNTAX);
else
if(!is_sadmin(source_snid))
send_lang(u, s, ONLY_FOR_SADMINS);
else
if( (tsnid = nick2snid(nick)) == 0 )
send_lang(u, s, NICK_X_NOT_REGISTERED, nick);
else
{
set_command(u, s, nick,tsnid, option, value, 1);
}
}
syntax highlighted by Code2HTML, v. 0.9.1