/* nickserv.c - Nick/authentication service
- * Copyright 2000-2006 srvx Development Team
+ * Copyright 2000-2008 srvx Development Team
*
* This file is part of srvx.
*
#define KEY_SET_EPITHET_LEVEL "set_epithet_level"
#define KEY_SET_TITLE_LEVEL "set_title_level"
#define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level"
+#define KEY_SET_FAKEIDENT_LEVEL "set_fakeident_level"
#define KEY_TITLEHOST_SUFFIX "titlehost_suffix"
#define KEY_FLAG_LEVELS "flag_levels"
#define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq"
#define KEY_EMAIL_SEARCH_LEVEL "email_search_level"
#define KEY_OUNREGISTER_INACTIVE "ounregister_inactive"
#define KEY_OUNREGISTER_FLAGS "ounregister_flags"
+#define KEY_HANDLE_TS_MODE "account_timestamp_mode"
#define KEY_ID "id"
#define KEY_PASSWD "passwd"
#define KEY_TABLE_WIDTH "table_width"
#define KEY_MAXLOGINS "maxlogins"
#define KEY_FAKEHOST "fakehost"
+#define KEY_FAKEIDENT "fakeident"
#define KEY_NOTES "notes"
#define KEY_NOTE_EXPIRES "expires"
#define KEY_NOTE_SET "set"
#define OPTION_FUNC(NAME) int NAME(struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[])
typedef OPTION_FUNC(option_func_t);
-DEFINE_LIST(handle_info_list, struct handle_info*);
+DEFINE_LIST(handle_info_list, struct handle_info*)
#define NICKSERV_MIN_PARMS(N) do { \
if (argc < N) { \
{ "NSMSG_COOKIE_LIVE", "Account $b%s$b already has a cookie active. Please either finish using that cookie, wait for it to expire, or auth to the account and use the $bdelcookie$b command." },
{ "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." },
{ "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." },
+ { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." },
{ "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." },
{ "NSMSG_BAD_COOKIE", "That cookie is not the right one. Please make sure you are copying it EXACTLY from the email; it is case-sensitive, so $bABC$b is different from $babc$b." },
{ "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." },
{ "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." },
{ "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." },
{ "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." },
+ { "NSMSG_ATE_COOKIE_FOREIGN", "I ate the cookie for account $b%s$b. It may now have another." },
{ "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." },
{ "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." },
{ "NSMSG_REGISTER_BAD_NICKMASK", "Could not recognize $b%s$b as either a current nick or a hostmask." },
{ "NSMSG_TITLE_INVALID", "Titles cannot contain any dots; please choose another." },
{ "NSMSG_TITLE_TRUNCATED", "That title combined with the user's account name would result in a truncated host; please choose a shorter title." },
{ "NSMSG_FAKEHOST_INVALID", "Fake hosts must be shorter than %d characters and cannot start with a dot." },
+ { "NSMSG_FAKEIDENT_INVALID", "Fake idents must be shorter than %d characters." },
{ "NSMSG_HANDLEINFO_ON", "Account information for $b%s$b:" },
{ "NSMSG_HANDLEINFO_ID", " Account ID: %lu" },
{ "NSMSG_HANDLEINFO_REGGED", " Registered on: %s" },
{ "NSMSG_HANDLEINFO_INFOLINE", " Infoline: %s" },
{ "NSMSG_HANDLEINFO_FLAGS", " Flags: %s" },
{ "NSMSG_HANDLEINFO_EPITHET", " Epithet: %s" },
+ { "NSMSG_HANDLEINFO_FAKEIDENT", " Fake ident: %s" },
{ "NSMSG_HANDLEINFO_FAKEHOST", " Fake host: %s" },
+ { "NSMSG_HANDLEINFO_FAKEIDENTHOST", " Fake host: %s@%s" },
{ "NSMSG_HANDLEINFO_LAST_HOST", " Last quit hostmask: %s" },
{ "NSMSG_HANDLEINFO_NO_NOTES", " Notes: None" },
{ "NSMSG_HANDLEINFO_NOTE_EXPIRES", " Note %d (%s ago by %s, expires %s): %s" },
{ "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." },
{ "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." },
{ "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." },
- { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T".%03lu seconds)." },
+ { "NSMSG_DB_MERGED", "$N merged DB from %s (in %lu.%03lu seconds)." },
{ "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." },
{ "NSMSG_BAD_HANDLE", "Account $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." },
{ "NSMSG_BAD_NICK", "Nickname $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." },
{ "NSMSG_SET_EPITHET", "$bEPITHET: $b%s" },
{ "NSMSG_SET_TITLE", "$bTITLE: $b%s" },
{ "NSMSG_SET_FAKEHOST", "$bFAKEHOST: $b%s" },
+ { "NSMSG_SET_FAKEIDENT", "$bFAKEIDENT: $b%s" },
+ { "NSMSG_SET_FAKEIDENTHOST", "$bFAKEHOST: $b%s@%s" },
{ "NSMSG_INVALID_KARMA", "$b%s$b is not a valid karma modifier." },
{ "NSMSG_SET_KARMA", "$bKARMA: $b%d$b" },
{ "NSEMAIL_ACTIVATION_SUBJECT", "Account verification for %s" },
{ "NSEMAIL_ALLOWAUTH_BODY", "This email has been sent to let you authenticate (auth) to account %5$s on %1$s. Your cookie is %2$s.\nTo auth to that account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this authorization, you do not need to do anything. Please contact the %1$s staff if you have questions." },
{ "CHECKPASS_YES", "Yes." },
{ "CHECKPASS_NO", "No." },
+ { "CHECKEMAIL_NOT_SET", "No email set." },
+ { "CHECKEMAIL_YES", "Yes." },
+ { "CHECKEMAIL_NO", "No." },
{ NULL, NULL }
};
static void nickserv_reclaim_p(void *data);
static int nickserv_addmask(struct userNode *user, struct handle_info *hi, const char *mask);
+enum handle_ts_mode {
+ TS_IGNORE,
+ TS_IRCU
+};
+
static struct {
unsigned int disable_nicks : 1;
unsigned int valid_handle_regex_set : 1;
unsigned long set_epithet_level;
unsigned long set_title_level;
unsigned long set_fakehost_level;
+ unsigned long set_fakeident_level;
unsigned long handles_per_email;
unsigned long email_search_level;
const char *network_name;
struct policer_params *auth_policer_params;
enum reclaim_action reclaim_action;
enum reclaim_action auto_reclaim_action;
+ enum handle_ts_mode handle_ts_mode;
unsigned long auto_reclaim_delay;
unsigned char default_maxlogins;
unsigned char hard_maxlogins;
}
static struct handle_info *
-register_handle(const char *handle, const char *passwd, UNUSED_ARG(unsigned long id))
+register_handle(const char *handle, const char *passwd, unsigned long id)
{
struct handle_info *hi;
-#ifdef WITH_PROTOCOL_BAHAMUT
char id_base64[IDLEN + 1];
do
{
id = 0;
}
} while(!id);
-#endif
hi = calloc(1, sizeof(*hi));
hi->userlist_style = HI_DEFAULT_STYLE;
hi->infoline = NULL;
dict_insert(nickserv_handle_dict, hi->handle, hi);
-#ifdef WITH_PROTOCOL_BAHAMUT
hi->id = id;
dict_insert(nickserv_id_dict, strdup(id_base64), hi);
-#endif
return hi;
}
free_handle_info(void *vhi)
{
struct handle_info *hi = vhi;
-
-#ifdef WITH_PROTOCOL_BAHAMUT
char id[IDLEN + 1];
inttobase64(id, hi->id, IDLEN);
dict_remove(nickserv_id_dict, id);
-#endif
free_string_list(hi->masks);
assert(!hi->users);
free(hi->infoline);
free(hi->epithet);
free(hi->fakehost);
+ free(hi->fakeident);
if (hi->cookie) {
timeq_del(hi->cookie->expires, nickserv_free_cookie, hi->cookie, 0);
nickserv_free_cookie(hi->cookie);
return handle->fakehost;
}
+static char *
+generate_fakeident(struct handle_info *handle, struct userNode *user)
+{
+ static char buffer[USERLEN+1];
+
+ if (!handle->fakeident) {
+ if (!user)
+ return NULL;
+ safestrncpy(buffer, user->ident, sizeof(buffer));
+ return buffer;
+ }
+ return handle->fakeident;
+}
+
static void
-apply_fakehost(struct handle_info *handle)
+apply_fakehost(struct handle_info *handle, struct userNode *user)
{
struct userNode *target;
- char *fake;
+ char *fakehost, *fakeident;
if (!handle->users)
return;
- fake = generate_fakehost(handle);
- for (target = handle->users; target; target = target->next_authed)
- assign_fakehost(target, fake, 1);
+
+ fakehost = generate_fakehost(handle);
+
+ if (user) {
+ fakeident = generate_fakeident(handle, user);
+ assign_fakehost(user, fakehost, fakeident, 0, 1);
+ return;
+ }
+
+ for (target = handle->users; target; target = target->next_authed) {
+ fakeident = generate_fakeident(handle, target);
+ assign_fakehost(target, fakehost, fakeident, 0, 1);
+ }
}
static void
/* remove from next_authed linked list */
if (user->handle_info->users == user) {
user->handle_info->users = user->next_authed;
- } else {
+ } else if (user->handle_info->users != NULL) {
for (other = user->handle_info->users;
other->next_authed != user;
other = other->next_authed) ;
other->next_authed = user->next_authed;
+ } else {
+ /* No users authed to the account - can happen if they get
+ * killed for authing. */
}
/* if nobody left on old handle, and they're not an oper, remove !god */
if (!user->handle_info->users && !user->handle_info->opserv_level)
user->handle_info = hi;
if (hi && !hi->users && !hi->opserv_level)
HANDLE_CLEAR_FLAG(hi, HELPING);
- for (n=0; n<auth_func_used; n++)
+ for (n=0; n<auth_func_used; n++) {
auth_func_list[n](user, old_info);
+ if (user->dead)
+ return;
+ }
if (hi) {
struct nick_info *ni;
user->next_authed = hi->users;
hi->users = user;
hi->lastseen = now;
- if (IsHelper(user))
+ if (IsHelper(user) && !userList_contains(&curr_helpers, user))
userList_append(&curr_helpers, user);
- if (hi->fakehost || old_info)
- apply_fakehost(hi);
+ if (hi->fakehost || hi->fakeident || old_info)
+ apply_fakehost(hi, user);
if (stamp) {
-#ifdef WITH_PROTOCOL_BAHAMUT
- /* Stamp users with their account ID. */
- char id[IDLEN + 1];
- inttobase64(id, hi->id, IDLEN);
-#elif WITH_PROTOCOL_P10
- /* Stamp users with their account name. */
- char *id = hi->handle;
-#else
- const char *id = "???";
-#endif
if (!nickserv_conf.disable_nicks) {
- struct nick_info *ni;
- for (ni = hi->nicks; ni; ni = ni->next) {
- if (!irccasecmp(user->nick, ni->nick)) {
+ struct nick_info *ni2;
+ for (ni2 = hi->nicks; ni2; ni2 = ni2->next) {
+ if (!irccasecmp(user->nick, ni2->nick)) {
user->modes |= FLAGS_REGNICK;
break;
}
}
}
- StampUser(user, id);
+ StampUser(user, hi->handle, hi->registered, hi->id);
}
if ((ni = get_nick_info(user->nick)) && (ni->owner == hi))
struct userNode *target, *next_un;
struct handle_info *hi;
const char *nsmsg_none;
+ time_t feh;
if (argc < 2) {
if (!(hi = user->handle_info)) {
nsmsg_none = handle_find_message(hi, "MSG_NONE");
reply("NSMSG_HANDLEINFO_ON", hi->handle);
-#ifdef WITH_PROTOCOL_BAHAMUT
- reply("NSMSG_HANDLEINFO_ID", hi->id);
-#endif
- reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi->registered));
+ feh = hi->registered;
+ reply("NSMSG_HANDLEINFO_REGGED", ctime(&feh));
if (!hi->users) {
intervalString(buff, now - hi->lastseen, user->handle_info);
reply(type);
}
+ if (oper_has_access(user, cmd->parent->bot, 601, 1))
+ reply("NSMSG_HANDLEINFO_ID", hi->id);
+
if (oper_has_access(user, cmd->parent->bot, 0, 1) || IsStaff(user)) {
if (!hi->notes) {
reply("NSMSG_HANDLEINFO_NO_NOTES");
reply("NSMSG_HANDLEINFO_EPITHET", (hi->epithet ? hi->epithet : nsmsg_none));
}
- if (hi->fakehost)
- reply("NSMSG_HANDLEINFO_FAKEHOST", (hi->fakehost ? hi->fakehost : handle_find_message(hi, "MSG_NONE")));
+ if (hi->fakeident && hi->fakehost)
+ reply("NSMSG_HANDLEINFO_FAKEIDENTHOST", hi->fakeident, hi->fakehost);
+ else if (hi->fakeident)
+ reply("NSMSG_HANDLEINFO_FAKEIDENT", hi->fakeident);
+ else if (hi->fakehost)
+ reply("NSMSG_HANDLEINFO_FAKEHOST", hi->fakehost);
if (hi->last_quit_host[0])
reply("NSMSG_HANDLEINFO_LAST_HOST", hi->last_quit_host);
}
if (hi->channels) {
- struct userData *channel, *next;
+ struct userData *chan, *next;
char *name;
- for (channel = hi->channels; channel; channel = next) {
- next = channel->u_next;
- name = channel->channel->channel->name;
+ for (chan = hi->channels; chan; chan = next) {
+ next = chan->u_next;
+ name = chan->channel->channel->name;
herelen = strlen(name);
if (pos + herelen + 7 > ArrayLength(buff)) {
- next = channel;
+ next = chan;
goto print_chans_buff;
}
- if (IsUserSuspended(channel))
+ if (IsUserSuspended(chan))
buff[pos++] = '-';
- pos += sprintf(buff+pos, "%d:%s ", channel->access, name);
+ pos += sprintf(buff+pos, "%d:%s ", chan->access, name);
if (next == NULL) {
print_chans_buff:
buff[pos-1] = 0;
}
}
- return 1;
+ return 1 | ((hi != user->handle_info) ? CMD_LOG_STAFF : 0);
}
static NICKSERV_FUNC(cmd_userinfo)
return 1;
}
+static NICKSERV_FUNC(cmd_odelcookie)
+{
+ struct handle_info *hi;
+
+ NICKSERV_MIN_PARMS(2);
+
+ if (!(hi = get_victim_oper(user, argv[1])))
+ return 0;
+
+ if (!hi->cookie) {
+ reply("NSMSG_NO_COOKIE_FOREIGN", hi->handle);
+ return 0;
+ }
+
+ nickserv_eat_cookie(hi->cookie);
+ reply("NSMSG_ATE_COOKIE_FOREIGN", hi->handle);
+ return 1;
+}
+
+
static NICKSERV_FUNC(cmd_resetpass)
{
struct handle_info *hi;
struct channelList *schannels;
unsigned int ii;
schannels = chanserv_support_channels();
- for (uNode = hi->users; uNode; uNode = uNode->next_authed) {
- for (ii = 0; ii < schannels->used; ++ii)
- if (GetUserMode(schannels->list[ii], uNode))
- break;
- if (ii < schannels->used)
+ for (ii = 0; ii < schannels->used; ++ii)
+ if (find_handle_in_channel(schannels->list[ii], hi, NULL))
break;
- }
- if (!uNode)
+ if (ii == schannels->used)
HANDLE_CLEAR_FLAG(hi, HELPING);
}
hi->fakehost[0] = '.';
strcpy(hi->fakehost+1, title);
}
- apply_fakehost(hi);
+ apply_fakehost(hi, NULL);
} else if (hi->fakehost && (hi->fakehost[0] == '.'))
title = hi->fakehost + 1;
else
static OPTION_FUNC(opt_fakehost)
{
- const char *fake;
+ char mask[USERLEN + HOSTLEN + 2];
+ char *host, *ident;
if (!override) {
send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
}
if ((argc > 1) && oper_has_access(user, nickserv, nickserv_conf.set_fakehost_level, 0)) {
- fake = argv[1];
- if ((strlen(fake) > HOSTLEN) || (fake[0] == '.')) {
+ safestrncpy(mask, argv[1], sizeof(mask));
+
+ if ((host = strrchr(mask, '@')) && host != mask &&
+ oper_has_access(user, nickserv, nickserv_conf.set_fakeident_level, 0)) {
+ ident = mask;
+ *host++ = '\0';
+ } else {
+ ident = NULL;
+ host = mask;
+ }
+
+ if ((strlen(host) > HOSTLEN) || (host[0] == '.')) {
send_message(user, nickserv, "NSMSG_FAKEHOST_INVALID", HOSTLEN);
return 0;
}
- free(hi->fakehost);
- if (!strcmp(fake, "*"))
- hi->fakehost = NULL;
+
+ if (ident && strlen(ident) > USERLEN) {
+ send_message(user, nickserv, "NSMSG_FAKEIDENT_INVALID", USERLEN);
+ return 0;
+ }
+
+ if (host[0]) {
+ free(hi->fakehost);
+ if (!strcmp(host, "*"))
+ hi->fakehost = NULL;
+ else
+ hi->fakehost = strdup(host);
+ host = hi->fakehost;
+ }
else
- hi->fakehost = strdup(fake);
- fake = hi->fakehost;
- apply_fakehost(hi);
+ host = generate_fakehost(hi);
+
+ if (ident) {
+ free(hi->fakeident);
+ if (!strcmp(ident, "*"))
+ hi->fakeident = NULL;
+ else
+ hi->fakeident = strdup(ident);
+ ident = hi->fakeident;
+ }
+ else
+ ident = generate_fakeident(hi, NULL);
+
+ apply_fakehost(hi, NULL);
+ } else {
+ host = generate_fakehost(hi);
+ ident = generate_fakeident(hi, NULL);
+ }
+ if (!host)
+ host = (char *) user_find_message(user, "MSG_NONE");
+ if(ident)
+ send_message(user, nickserv, "NSMSG_SET_FAKEIDENTHOST", ident, host);
+ else
+ send_message(user, nickserv, "NSMSG_SET_FAKEHOST", host);
+ return 1;
+}
+
+static OPTION_FUNC(opt_fakeident)
+{
+ const char *ident;
+
+ if (!override) {
+ send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
+ }
+
+ if ((argc > 1) && oper_has_access(user, nickserv, nickserv_conf.set_fakeident_level, 0)) {
+ ident = argv[1];
+ if (strlen(ident) > USERLEN) {
+ send_message(user, nickserv, "NSMSG_FAKEIDENT_INVALID", USERLEN);
+ return 0;
+ }
+ free(hi->fakeident);
+ if (!strcmp(ident, "*"))
+ hi->fakeident = NULL;
+ else
+ hi->fakeident = strdup(ident);
+ ident = hi->fakeident;
+ apply_fakehost(hi, NULL);
} else
- fake = generate_fakehost(hi);
- if (!fake)
- fake = user_find_message(user, "MSG_NONE");
- send_message(user, nickserv, "NSMSG_SET_FAKEHOST", fake);
+ ident = generate_fakeident(hi, NULL); /* NULL if no fake ident set */
+ if (!ident)
+ ident = user_find_message(user, "MSG_NONE");
+ send_message(user, nickserv, "NSMSG_SET_FAKEIDENT", ident);
return 1;
}
for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) {
hi = iter_data(it);
-#ifdef WITH_PROTOCOL_BAHAMUT
- assert(hi->id);
-#endif
+ assert(hi->id != 0);
saxdb_start_record(ctx, iter_key(it), 0);
if (hi->cookie) {
struct handle_cookie *cookie = hi->cookie;
saxdb_write_string(ctx, KEY_EPITHET, hi->epithet);
if (hi->fakehost)
saxdb_write_string(ctx, KEY_FAKEHOST, hi->fakehost);
+ if (hi->fakeident)
+ saxdb_write_string(ctx, KEY_FAKEIDENT, hi->fakeident);
if (hi->flags) {
int ii, flen;
flags[flen] = 0;
saxdb_write_string(ctx, KEY_FLAGS, flags);
}
-#ifdef WITH_PROTOCOL_BAHAMUT
saxdb_write_int(ctx, KEY_ID, hi->id);
-#endif
if (hi->infoline)
saxdb_write_string(ctx, KEY_INFO, hi->infoline);
if (hi->last_quit_host[0])
*/
if (hi_from->fakehost && !hi_to->fakehost)
hi_to->fakehost = strdup(hi_from->fakehost);
+ if (hi_from->fakeident && !hi_to->fakeident)
+ hi_to->fakeident = strdup(hi_from->fakeident);
/* Notify of success. */
sprintf(buffer, "%s (%s) merged account %s into %s.", user->nick, user->handle_info->handle, hi_from->handle, hi_to->handle);
struct nickserv_discrim {
unsigned long flags_on, flags_off;
- time_t min_registered, max_registered;
- time_t lastseen;
+ unsigned long min_registered, max_registered;
+ unsigned long lastseen;
unsigned int limit;
int min_level, max_level;
int min_karma, max_karma;
const char *nickmask;
const char *hostmask;
const char *fakehostmask;
+ const char *fakeidentmask;
const char *handlemask;
const char *emailmask;
};
discrim->max_level = INT_MAX;
discrim->limit = 50;
discrim->min_registered = 0;
- discrim->max_registered = INT_MAX;
- discrim->lastseen = LONG_MAX;
+ discrim->max_registered = ULONG_MAX;
+ discrim->lastseen = ULONG_MAX;
discrim->min_karma = INT_MIN;
discrim->max_karma = INT_MAX;
} else {
discrim->fakehostmask = argv[i];
}
+ } else if (!irccasecmp(argv[i], "fakeident")) {
+ if (!irccasecmp(argv[++i], "*")) {
+ discrim->fakeidentmask = 0;
+ } else {
+ discrim->fakeidentmask = argv[i];
+ }
} else if (!irccasecmp(argv[i], "handlemask") || !irccasecmp(argv[i], "accountmask")) {
if (!irccasecmp(argv[++i], "*")) {
discrim->handlemask = 0;
|| (discrim->lastseen < (hi->users?now:hi->lastseen))
|| (discrim->handlemask && !match_ircglob(hi->handle, discrim->handlemask))
|| (discrim->fakehostmask && (!hi->fakehost || !match_ircglob(hi->fakehost, discrim->fakehostmask)))
+ || (discrim->fakeidentmask && (!hi->fakeident || !match_ircglob(hi->fakeident, discrim->fakeidentmask)))
|| (discrim->emailmask && (!hi->email_addr || !match_ircglob(hi->email_addr, discrim->emailmask)))
|| (discrim->min_level > hi->opserv_level)
|| (discrim->max_level < hi->opserv_level)
return 1;
}
+static MODCMD_FUNC(cmd_checkemail)
+{
+ struct handle_info *hi;
+
+ NICKSERV_MIN_PARMS(3);
+ if (!(hi = modcmd_get_handle_info(user, argv[1]))) {
+ return 0;
+ }
+ if (!hi->email_addr)
+ reply("CHECKEMAIL_NOT_SET");
+ else if (!irccasecmp(argv[2], hi->email_addr))
+ reply("CHECKEMAIL_YES");
+ else
+ reply("CHECKEMAIL_NO");
+ return 1;
+}
+
+
static void
nickserv_db_read_handle(const char *handle, dict_t obj)
{
struct string_list *masks, *slist;
struct handle_info *hi;
struct userNode *authed_users;
- struct userData *channels;
- unsigned long int id;
+ struct userData *channel_list;
+ unsigned long id;
unsigned int ii;
dict_t subdb;
}
if ((hi = get_handle_info(handle))) {
authed_users = hi->users;
- channels = hi->channels;
+ channel_list = hi->channels;
hi->users = NULL;
hi->channels = NULL;
dict_remove(nickserv_handle_dict, hi->handle);
} else {
authed_users = NULL;
- channels = NULL;
+ channel_list = NULL;
}
hi = register_handle(handle, str, id);
if (authed_users) {
authed_users = authed_users->next_authed;
}
}
- hi->channels = channels;
+ hi->channels = channel_list;
masks = database_get_data(obj, KEY_MASKS, RECDB_STRING_LIST);
hi->masks = masks ? string_list_copy(masks) : alloc_string_list(1);
str = database_get_data(obj, KEY_MAXLOGINS, RECDB_QSTRING);
if (str)
hi->infoline = strdup(str);
str = database_get_data(obj, KEY_REGISTER_ON, RECDB_QSTRING);
- hi->registered = str ? (time_t)strtoul(str, NULL, 0) : now;
+ hi->registered = str ? strtoul(str, NULL, 0) : now;
str = database_get_data(obj, KEY_LAST_SEEN, RECDB_QSTRING);
- hi->lastseen = str ? (time_t)strtoul(str, NULL, 0) : hi->registered;
+ hi->lastseen = str ? strtoul(str, NULL, 0) : hi->registered;
str = database_get_data(obj, KEY_KARMA, RECDB_QSTRING);
hi->karma = str ? strtoul(str, NULL, 0) : 0;
/* We want to read the nicks even if disable_nicks is set. This is so
str = database_get_data(obj, KEY_FAKEHOST, RECDB_QSTRING);
if (str)
hi->fakehost = strdup(str);
+ str = database_get_data(obj, KEY_FAKEIDENT, RECDB_QSTRING);
+ if (str)
+ hi->fakeident = strdup(str);
/* Read the "cookie" sub-database (if it exists). */
subdb = database_get_data(obj, KEY_COOKIE, RECDB_OBJECT);
if (subdb) {
const char *setter;
const char *text;
const char *set;
- const char *id;
+ const char *note_id;
dict_t notedb;
- id = iter_key(it);
+ note_id = iter_key(it);
notedb = GET_RECORD_OBJECT((struct record_data*)iter_data(it));
if (!notedb) {
- log_module(NS_LOG, LOG_ERROR, "Malformed note %s for account %s; ignoring note.", id, hi->handle);
+ log_module(NS_LOG, LOG_ERROR, "Malformed note %s for account %s; ignoring note.", note_id, hi->handle);
continue;
}
expires = database_get_data(notedb, KEY_NOTE_EXPIRES, RECDB_QSTRING);
text = database_get_data(notedb, KEY_NOTE_NOTE, RECDB_QSTRING);
set = database_get_data(notedb, KEY_NOTE_SET, RECDB_QSTRING);
if (!setter || !text || !set) {
- log_module(NS_LOG, LOG_ERROR, "Missing field(s) from note %s for account %s; ignoring note.", id, hi->handle);
+ log_module(NS_LOG, LOG_ERROR, "Missing field(s) from note %s for account %s; ignoring note.", note_id, hi->handle);
continue;
}
note = calloc(1, sizeof(*note) + strlen(text));
note->next = NULL;
note->expires = expires ? strtoul(expires, NULL, 10) : 0;
note->set = strtoul(set, NULL, 10);
- note->id = strtoul(id, NULL, 10);
+ note->id = strtoul(note_id, NULL, 10);
safestrncpy(note->setter, setter, sizeof(note->setter));
strcpy(note->note, text);
if (last_note)
stop.tv_sec -= 1;
stop.tv_usec += 1000000;
}
- reply("NSMSG_DB_MERGED", argv[1], stop.tv_sec, stop.tv_usec/1000);
+ reply("NSMSG_DB_MERGED", argv[1], (unsigned long)stop.tv_sec, (unsigned long)stop.tv_usec/1000);
return 1;
}
expire_handles(UNUSED_ARG(void *data))
{
dict_iterator_t it, next;
- time_t expiry;
+ unsigned long expiry;
struct handle_info *hi;
for (it=dict_first(nickserv_handle_dict); it; it=next) {
log_module(NS_LOG, LOG_ERROR, "Unable to open dictionary file %s: %s", fname, strerror(errno));
return;
}
- while (!feof(file)) {
- fgets(line, sizeof(line), file);
+ while (fgets(line, sizeof(line), file)) {
if (!line[0])
continue;
if (line[strlen(line)-1] == '\n')
nickserv_conf.set_title_level = str ? strtoul(str, NULL, 0) : 900;
str = database_get_data(conf_node, KEY_SET_FAKEHOST_LEVEL, RECDB_QSTRING);
nickserv_conf.set_fakehost_level = str ? strtoul(str, NULL, 0) : 1000;
+ str = database_get_data(conf_node, KEY_SET_FAKEIDENT_LEVEL, RECDB_QSTRING);
+ nickserv_conf.set_fakeident_level = str ? strtoul(str, NULL, 0) : 1000;
str = database_get_data(conf_node, KEY_HANDLE_EXPIRE_FREQ, RECDB_QSTRING);
if (!str)
str = database_get_data(conf_node, KEY_ACCOUNT_EXPIRE_FREQ, RECDB_QSTRING);
if(pos)
nickserv_conf.ounregister_flags |= 1 << (pos - 1);
}
+ str = database_get_data(conf_node, KEY_HANDLE_TS_MODE, RECDB_QSTRING);
+ if (!str)
+ nickserv_conf.handle_ts_mode = TS_IGNORE;
+ else if (!irccasecmp(str, "ircu"))
+ nickserv_conf.handle_ts_mode = TS_IRCU;
+ else
+ nickserv_conf.handle_ts_mode = TS_IGNORE;
if (!nickserv_conf.disable_nicks) {
str = database_get_data(conf_node, "reclaim_action", RECDB_QSTRING);
nickserv_conf.reclaim_action = str ? reclaim_action_from_string(str) : RECLAIM_NONE;
nickserv_reclaim(user, ni, nickserv_conf.auto_reclaim_action);
}
-static int
+static void
check_user_nick(struct userNode *user) {
struct nick_info *ni;
user->modes &= ~FLAGS_REGNICK;
if (!(ni = get_nick_info(user->nick)))
- return 0;
+ return;
if (user->handle_info == ni->owner) {
user->modes |= FLAGS_REGNICK;
irc_regnick(user);
- return 0;
+ return;
}
if (nickserv_conf.warn_nick_owned)
send_message(user, nickserv, "NSMSG_RECLAIM_WARN", ni->nick, ni->owner->handle);
if (nickserv_conf.auto_reclaim_action == RECLAIM_NONE)
- return 0;
+ return;
if (nickserv_conf.auto_reclaim_delay)
timeq_add(now + nickserv_conf.auto_reclaim_delay, nickserv_reclaim_p, user);
else
nickserv_reclaim(user, ni, nickserv_conf.auto_reclaim_action);
- return 0;
-}
-
-int
-handle_new_user(struct userNode *user)
-{
- return check_user_nick(user);
}
void
-handle_account(struct userNode *user, const char *stamp)
+handle_account(struct userNode *user, const char *stamp, unsigned long timestamp, unsigned long serial)
{
- struct handle_info *hi;
+ struct handle_info *hi = NULL;
-#ifdef WITH_PROTOCOL_P10
- hi = dict_find(nickserv_handle_dict, stamp, NULL);
-#else
- hi = dict_find(nickserv_id_dict, stamp, NULL);
-#endif
+ if (stamp != NULL)
+ hi = dict_find(nickserv_handle_dict, stamp, NULL);
+ if ((hi == NULL) && (serial != 0)) {
+ char id[IDLEN + 1];
+ inttobase64(id, serial, IDLEN);
+ hi = dict_find(nickserv_id_dict, id, NULL);
+ }
if (hi) {
+ if ((nickserv_conf.handle_ts_mode == TS_IRCU)
+ && (timestamp != hi->registered)) {
+ return;
+ }
if (HANDLE_FLAGGED(hi, SUSPENDED)) {
return;
}
set_user_handle_info(user, hi, 0);
} else {
- log_module(MAIN_LOG, LOG_WARNING, "%s had unknown account stamp %s.", user->nick, stamp);
+ log_module(MAIN_LOG, LOG_WARNING, "%s had unknown account stamp %s:%lu:%lu.", user->nick, stamp, timestamp, serial);
}
}
{
unsigned int i;
NS_LOG = log_register_type("NickServ", "file:nickserv.log");
- reg_new_user_func(handle_new_user);
+ reg_new_user_func(check_user_nick);
reg_nick_change_func(handle_nick_change);
reg_del_user_func(nickserv_remove_user);
reg_account_func(handle_account);
nickserv_define_func("RESETPASS", cmd_resetpass, -1, 0, 1);
nickserv_define_func("COOKIE", cmd_cookie, -1, 0, 1);
nickserv_define_func("DELCOOKIE", cmd_delcookie, -1, 1, 0);
+ nickserv_define_func("ODELCOOKIE", cmd_odelcookie, 0, 1, 0);
dict_insert(nickserv_opt_dict, "EMAIL", opt_email);
}
nickserv_define_func("GHOST", cmd_ghost, -1, 1, 0);
nickserv_define_func("SEARCH UNREGISTER", NULL, 800, 1, 0);
nickserv_define_func("MERGEDB", cmd_mergedb, 999, 1, 0);
nickserv_define_func("CHECKPASS", cmd_checkpass, 601, 1, 0);
+ nickserv_define_func("CHECKEMAIL", cmd_checkemail, 0, 1, 0);
/* other options */
dict_insert(nickserv_opt_dict, "INFO", opt_info);
dict_insert(nickserv_opt_dict, "WIDTH", opt_width);
if (nickserv_conf.titlehost_suffix) {
dict_insert(nickserv_opt_dict, "TITLE", opt_title);
dict_insert(nickserv_opt_dict, "FAKEHOST", opt_fakehost);
+ dict_insert(nickserv_opt_dict, "FAKEIDENT", opt_fakeident);
}
dict_insert(nickserv_opt_dict, "MAXLOGINS", opt_maxlogins);
dict_insert(nickserv_opt_dict, "LANGUAGE", opt_language);