/* 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_VALID_NICK_REGEX "valid_nick_regex"
#define KEY_DB_BACKUP_FREQ "db_backup_freq"
#define KEY_MODOPER_LEVEL "modoper_level"
+#define KEY_MODSTAFF_LEVEL "modstaff_level"
#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_HANDLE_EXPIRE_FREQ "handle_expire_freq"
#define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq"
-#define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
+#define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay"
#define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay"
#define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay"
#define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay"
#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_MAX_AUTHLOG_LEN "max_authlog_len"
#define KEY_ID "id"
#define KEY_PASSWD "passwd"
#define KEY_NICKS "nicks"
#define KEY_MASKS "masks"
#define KEY_OPSERV_LEVEL "opserv_level"
+#define KEY_STAFF_LEVEL "staff_level"
#define KEY_FLAGS "flags"
#define KEY_REGISTER_ON "register"
#define KEY_LAST_SEEN "lastseen"
#define KEY_INFO "info"
+#define KEY_DEVNULL "devnull"
+#define KEY_WEBSITE "website"
#define KEY_USERLIST_STYLE "user_style"
#define KEY_SCREEN_WIDTH "screen_width"
#define KEY_LAST_AUTHED_HOST "last_authed_host"
#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 KEY_NOTE_SETTER "setter"
#define KEY_NOTE_NOTE "note"
#define KEY_KARMA "karma"
+#define KEY_AUTHLOG "authlog"
+#define KEY_AUTHLOG_LOGIN_TIME "login_time"
+#define KEY_AUTHLOG_LOGOUT_TIME "logout_time"
+#define KEY_AUTHLOG_HOSTMASK "hostmask"
+#define KEY_AUTHLOG_QUIT_REASON "quit_reason"
-#define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
+#define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
#define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME)
#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_STAMPED_AUTHCOOKIE", "You have already authenticated to an account once this session; you may not use a cookie to authenticate to another account." },
{ "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_TITLE_TRUNCATED_RENAME", "That account name combined with the user's title would result in a truncated host; please choose a shorter account name." },
{ "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_FAKEMASK_INVALID", "Fake ident@hosts 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_COOKIE_ALLOWAUTH", " Cookie: There is currently an allowauth cookie issued for this account" },
{ "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", " Cookie: There is currently an unknown cookie issued for this account" },
{ "NSMSG_HANDLEINFO_INFOLINE", " Infoline: %s" },
+ { "NSMSG_HANDLEINFO_DEVNULL", " DevNull Class: %s" },
+ { "NSMSG_HANDLEINFO_WEBSITE", " Website: %s" },
+ { "NSMSG_HANDLEINFO_ACCESS", " Access: %i" },
{ "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_SETTING_LIST", "$b$N account settings:$b" },
{ "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." },
{ "NSMSG_SET_INFO", "$bINFO: $b%s" },
+ { "NSMSG_SET_DEVNULL", "$bDEVNULL: $b%s" },
+ { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" },
+ { "NSMSG_SET_WEBSITE", "$bWEBSITE: $b%s" },
{ "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" },
{ "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" },
{ "NSMSG_SET_COLOR", "$bCOLOR: $b%s" },
{ "NSMSG_SET_MAXLOGINS", "$bMAXLOGINS: $b%d" },
{ "NSMSG_SET_LANGUAGE", "$bLANGUAGE: $b%s" },
{ "NSMSG_SET_LEVEL", "$bLEVEL: $b%d" },
+ { "NSMSG_SET_STAFFLEVEL", "$bSTAFF_LEVEL: $b%d" },
{ "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 handle_expire_delay;
unsigned long nochan_handle_expire_delay;
unsigned long modoper_level;
+ unsigned long modstaff_level;
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;
- const char *titlehost_suffix;
regex_t valid_handle_regex;
regex_t valid_nick_regex;
dict_t weak_password_dict;
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;
unsigned long ounregister_inactive;
unsigned long ounregister_flags;
+ unsigned int max_authlog_len;
} nickserv_conf;
+struct pendingLOCUser {
+ struct handle_info *handle_info;
+ unsigned long time;
+ struct authlogEntry *authlog;
+ struct pendingLOCUser *next;
+};
+
+const char *titlehost_suffix = NULL;
+static struct pendingLOCUser *pendingLOCUsers = NULL;
+
/* We have 2^32 unique account IDs to use. */
unsigned long int highest_id = 0;
{
char *out = mask, *temp;
if ((temp = strchr(mask, '!'))) {
- temp++;
- while (*temp) *out++ = *temp++;
- *out++ = 0;
+ temp++;
+ while (*temp) *out++ = *temp++;
+ *out++ = 0;
}
return mask;
}
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;
+ hi->website = NULL;
+ hi->devnull = NULL;
dict_insert(nickserv_id_dict, strdup(id_base64), hi);
-#endif
return hi;
}
}
/* Remove ni from the nick_info linked list. */
if (ni == ni->owner->nicks) {
- ni->owner->nicks = ni->next;
+ ni->owner->nicks = ni->next;
} else {
- last = ni->owner->nicks;
- next = last->next;
- while (next != ni) {
- last = next;
- next = last->next;
- }
- last->next = next->next;
+ last = ni->owner->nicks;
+ next = last->next;
+ while (next != ni) {
+ last = next;
+ next = last->next;
+ }
+ last->next = next->next;
}
dict_remove(nickserv_nick_dict, ni->nick);
}
reg_unreg_func(unreg_func_t func)
{
if (unreg_func_used == unreg_func_size) {
- if (unreg_func_size) {
- unreg_func_size <<= 1;
- unreg_func_list = realloc(unreg_func_list, unreg_func_size*sizeof(unreg_func_t));
- } else {
- unreg_func_size = 8;
- unreg_func_list = malloc(unreg_func_size*sizeof(unreg_func_t));
- }
+ if (unreg_func_size) {
+ unreg_func_size <<= 1;
+ unreg_func_list = realloc(unreg_func_list, unreg_func_size*sizeof(unreg_func_t));
+ } else {
+ unreg_func_size = 8;
+ unreg_func_list = malloc(unreg_func_size*sizeof(unreg_func_t));
+ }
}
unreg_func_list[unreg_func_used++] = func;
}
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->devnull);
+ free(hi->website);
+ free(hi->fakeident);
if (hi->cookie) {
timeq_del(hi->cookie->expires, nickserv_free_cookie, hi->cookie, 0);
nickserv_free_cookie(hi->cookie);
if (!hil->used)
dict_remove(nickserv_email_dict, hi->email_addr);
}
+ struct authlogEntry *authlog, *next;
+ for(authlog = hi->authlog; authlog; authlog = next) {
+ next = authlog->next;
+ struct pendingLOCUser *pending, *prev_pending = NULL;
+ for(pending = pendingLOCUsers; pending; pending = pending->next) {
+ if(pending->authlog == authlog) {
+ if(prev_pending)
+ prev_pending->next = pending->next;
+ else
+ pendingLOCUsers = pending->next;
+ free(pending);
+ break;
+ }
+ prev_pending = pending;
+ }
+ free((char *) authlog->hostmask);
+ if(authlog->quit_reason)
+ free((char *) authlog->quit_reason);
+ free(authlog);
+ }
free(hi);
}
}
if (!IsOper(user) && (!IsHelping(user) || min_level)) {
- if (!quiet)
+ if (!quiet)
send_message(user, bot, "NSMSG_NO_ACCESS");
- return 0;
+ return 0;
}
if (HANDLE_FLAGGED(user->handle_info, OPER_SUSPENDED)) {
- if (!quiet)
+ if (!quiet)
send_message(user, bot, "MSG_OPER_SUSPENDED");
- return 0;
+ return 0;
}
if (user->handle_info->opserv_level < min_level) {
- if (!quiet)
+ if (!quiet)
send_message(user, bot, "NSMSG_NO_ACCESS");
- return 0;
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+staff_has_access(struct userNode *user, struct userNode *bot, unsigned int min_level, unsigned int quiet) {
+ if (!user->handle_info) {
+ if (!quiet)
+ send_message(user, bot, "MSG_AUTHENTICATE");
+ return 0;
+ }
+
+ if (user->handle_info->staff_level < min_level) {
+ if (!quiet)
+ send_message(user, bot, "NSMSG_NO_ACCESS");
+ return 0;
}
return 1;
return 0;
/* check against maximum length */
if (strlen(handle) > NICKSERV_HANDLE_LEN)
- return 0;
+ return 0;
/* for consistency, only allow account names that could be nicks */
if (!is_valid_nick(handle))
return 0;
}
static int
-is_valid_email_addr(const char *email)
+is_valid_email_addr(const char *org_email)
{
- return strchr(email, '@') != NULL;
+ char email[strlen(org_email)+1];
+ strcpy(email, org_email);
+ //validate email address
+ //1st check: there need to be one @
+ char *p1 = strchr(email, '@');
+ if(!p1 || strchr(p1+1, '@')) return 0;
+ *p1 = '\0';
+ //2nd check: username (bevore @) must be at least 1 char long and out of part_chars
+ char *part_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._%+-";
+ int i;
+ if(p1 - email == 0) return 0;
+ for(i = 0; i < (p1 - email); i++) {
+ if(!strchr(part_chars, email[i])) return 0;
+ }
+ //3rd check: there need to be at least 1 dot in the domain part and all characters out of part_chars
+ part_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-";
+ char *p2 = NULL;
+ p1++;
+ i = 0;
+ while(*p1) {
+ if(*p1 == '.') {
+ if(!i) return 0;
+ i = 0;
+ p2 = p1;
+ } else if(!strchr(part_chars, *p1))
+ return 0;
+ else
+ i++;
+ p1++;
+ }
+ if(!p2) return 0;
+ //4th check: TLD must be <= 5 chars, no special chars
+ i = 0;
+ p2++;
+ while(*p2) {
+ if(!isalpha(*p2))
+ return 0;
+ else
+ i++;
+ p2++;
+ }
+ if(i > 5) return 0;
+ return 1;
}
static const char *
return 0;
}
if (IsLocal(target)) {
- if (IsService(target))
+ if (IsService(target))
send_message(user, service, "NSMSG_USER_IS_SERVICE", target->nick);
- else
+ else
send_message(user, service, "MSG_USER_AUTHENTICATE", target->nick);
return 0;
}
if (!(hi = smart_get_handle_info(nickserv, user, target)))
return 0;
if (HANDLE_FLAGGED(user->handle_info, OPER_SUSPENDED)) {
- send_message(user, nickserv, "MSG_OPER_SUSPENDED");
- return 0;
+ send_message(user, nickserv, "MSG_OPER_SUSPENDED");
+ return 0;
}
return oper_outranks(user, hi) ? hi : NULL;
}
unsigned int ii;
/* If no hostmasks on the account, allow it. */
- if (!hi->masks->used)
+ if (!hi->masks->used || IsDummy(user))
return 1;
/* If any hostmask matches, allow it. */
for (ii=0; ii<hi->masks->used; ii++)
return 1;
/* If they are allowauthed to this account, allow it (removing the aa). */
if (dict_find(nickserv_allow_auth_dict, user->nick, NULL) == hi) {
- dict_remove(nickserv_allow_auth_dict, user->nick);
- return 2;
+ dict_remove(nickserv_allow_auth_dict, user->nick);
+ return 2;
}
/* The user is not allowed to use this account. */
return 0;
return 0;
}
for (i=0; i<len; i++) {
- if (isdigit(pass[i]))
+ if (isdigit(pass[i]))
cnt_digits++;
- if (isupper(pass[i]))
+ if (isupper(pass[i]))
cnt_upper++;
- if (islower(pass[i]))
+ if (islower(pass[i]))
cnt_lower++;
}
if ((cnt_lower < nickserv_conf.password_min_lower)
- || (cnt_upper < nickserv_conf.password_min_upper)
- || (cnt_digits < nickserv_conf.password_min_digits)) {
+ || (cnt_upper < nickserv_conf.password_min_upper)
+ || (cnt_digits < nickserv_conf.password_min_digits)) {
if (user)
send_message(user, nickserv, "NSMSG_PASSWORD_READABLE", nickserv_conf.password_min_digits, nickserv_conf.password_min_upper, nickserv_conf.password_min_lower);
return 0;
reg_auth_func(auth_func_t func)
{
if (auth_func_used == auth_func_size) {
- if (auth_func_size) {
- auth_func_size <<= 1;
- auth_func_list = realloc(auth_func_list, auth_func_size*sizeof(auth_func_t));
- } else {
- auth_func_size = 8;
- auth_func_list = malloc(auth_func_size*sizeof(auth_func_t));
- }
+ if (auth_func_size) {
+ auth_func_size <<= 1;
+ auth_func_list = realloc(auth_func_list, auth_func_size*sizeof(auth_func_t));
+ } else {
+ auth_func_size = 8;
+ auth_func_list = malloc(auth_func_size*sizeof(auth_func_t));
+ }
}
auth_func_list[auth_func_used++] = func;
}
rf_list[rf_list_used++] = func;
}
-static char *
+char *
generate_fakehost(struct handle_info *handle)
{
extern const char *hidden_host_suffix;
return buffer;
} else if (handle->fakehost[0] == '.') {
/* A leading dot indicates the stored value is actually a title. */
- snprintf(buffer, sizeof(buffer), "%s.%s.%s", handle->handle, handle->fakehost+1, nickserv_conf.titlehost_suffix);
+ snprintf(buffer, sizeof(buffer), "%s.%s.%s", handle->handle, handle->fakehost+1, titlehost_suffix);
+ return buffer;
+ } else if (handle->fakehost[0] == '$') {
+ /* A leading $ indicates the stored value begins with the user handle. */
+ snprintf(buffer, sizeof(buffer), "%s%s", handle->handle, handle->fakehost+1);
return buffer;
}
return handle->fakehost;
}
-static void
-apply_fakehost(struct handle_info *handle)
+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;
+}
+
+void
+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
return;
if (user->handle_info) {
- struct userNode *other;
+ struct userNode *other;
- if (IsHelper(user))
+ if (IsHelper(user))
userList_remove(&curr_helpers, user);
- /* remove from next_authed linked list */
- if (user->handle_info->users == user) {
- user->handle_info->users = user->next_authed;
- } else {
- for (other = user->handle_info->users;
- other->next_authed != user;
- other = other->next_authed) ;
- other->next_authed = user->next_authed;
- }
+ /* remove from next_authed linked list */
+ if (user->handle_info->users == user) {
+ user->handle_info->users = user->next_authed;
+ } 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)
HANDLE_CLEAR_FLAG(user->handle_info, HELPING);
/* record them as being last seen at this time */
- user->handle_info->lastseen = now;
+ user->handle_info->lastseen = now;
/* and record their hostmask */
snprintf(user->handle_info->last_quit_host, sizeof(user->handle_info->last_quit_host), "%s@%s", user->ident, user->hostname);
}
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;
for (other = hi->users; other; other = other->next_authed)
send_message(other, nickserv, "NSMSG_CLONE_AUTH", user->nick, user->ident, user->hostname);
}
- user->next_authed = hi->users;
- hi->users = user;
- hi->lastseen = now;
- if (IsHelper(user))
+ user->next_authed = hi->users;
+ hi->users = user;
+ hi->lastseen = now;
+ 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))
timeq_del(0, nickserv_reclaim_p, user, TIMEQ_IGNORE_WHEN);
} else {
/* We cannot clear the user's account ID, unfortunately. */
- user->next_authed = NULL;
+ user->next_authed = NULL;
}
}
char crypted[MD5_CRYPT_LENGTH];
if ((hi = dict_find(nickserv_handle_dict, handle, NULL))) {
- send_message(user, nickserv, "NSMSG_HANDLE_EXISTS", handle);
- return 0;
+ send_message(user, nickserv, "NSMSG_HANDLE_EXISTS", handle);
+ return 0;
}
if (!is_secure_password(handle, passwd, user))
int no_auth;
if (!IsOper(user) && !dict_size(nickserv_handle_dict)) {
- /* Require the first handle registered to belong to someone +o. */
- reply("NSMSG_REQUIRE_OPER");
- return 0;
+ /* Require the first handle registered to belong to someone +o. */
+ reply("NSMSG_REQUIRE_OPER");
+ return 0;
}
if (user->handle_info) {
if (IsRegistering(user)) {
reply("NSMSG_ALREADY_REGISTERING");
- return 0;
+ return 0;
}
if (IsStamped(user)) {
return 0;
/* Add any masks they should get. */
if (nickserv_conf.default_hostmask) {
- string_list_append(hi->masks, strdup("*@*"));
+ nickserv_addmask(NULL, hi, strdup("*@*"));
} else {
- string_list_append(hi->masks, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
+ nickserv_addmask(NULL, hi, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
if (irc_in_addr_is_valid(user->ip) && !irc_pton(&ip, NULL, user->hostname))
- string_list_append(hi->masks, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_BYIP|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
+ nickserv_addmask(NULL, hi, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_BYIP|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
}
/* If they're the first to register, give them level 1000. */
if (dict_size(nickserv_handle_dict) == 1) {
hi->opserv_level = 1000;
+ hi->staff_level = 1000;
reply("NSMSG_ROOT_HANDLE", argv[1]);
}
char *mask;
struct userNode *settee;
struct handle_info *hi;
+ const char *pass, *email;
NICKSERV_MIN_PARMS(3);
+ pass = argv[2];
+ argv[2] = "****";
+
if (!is_valid_handle(argv[1])) {
reply("NSMSG_BAD_HANDLE", argv[1]);
return 0;
}
- if (argc < 4) {
+ if (argc < 5 || !nickserv_conf.email_enabled) {
+ email = NULL;
+ } else {
+ const char *str;
+ email = argv[4];
+ if (!is_valid_email_addr(email)) {
+ send_message(user, nickserv, "NSMSG_BAD_EMAIL_ADDR");
+ return 0;
+ }
+ if ((str = mail_prohibited_address(email))) {
+ send_message(user, nickserv, "NSMSG_EMAIL_PROHIBITED", email, str);
+ return 0;
+ }
+ }
+
+ if (argc < 4 || !strcmp(argv[3], "*")) {
mask = NULL;
settee = NULL;
} else if (strchr(argv[3], '@')) {
- mask = canonicalize_hostmask(strdup(argv[3]));
- if (argc > 4) {
- settee = GetUserH(argv[4]);
- if (!settee) {
- reply("MSG_NICK_UNKNOWN", argv[4]);
+ mask = canonicalize_hostmask(strdup(argv[3]));
+ if (argc > 4) {
+ settee = GetUserH(argv[4]);
+ if (!settee) {
+ reply("MSG_NICK_UNKNOWN", argv[4]);
free(mask);
- return 0;
- }
- } else {
- settee = NULL;
- }
+ return 0;
+ }
+ } else {
+ settee = NULL;
+ }
} else if ((settee = GetUserH(argv[3]))) {
- mask = generate_hostmask(settee, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT);
+ mask = generate_hostmask(settee, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT);
} else {
- reply("NSMSG_REGISTER_BAD_NICKMASK", argv[3]);
- return 0;
+ reply("NSMSG_REGISTER_BAD_NICKMASK", argv[3]);
+ return 0;
}
if (settee && settee->handle_info) {
reply("NSMSG_USER_PREV_AUTH", settee->nick);
free(mask);
return 0;
}
- if (!(hi = nickserv_register(user, settee, argv[1], argv[2], 0))) {
+ if (!(hi = nickserv_register(user, settee, argv[1], pass, 0))) {
free(mask);
return 0;
}
if (mask)
string_list_append(hi->masks, mask);
+ if (email)
+ nickserv_set_email_addr(hi, email);
return 1;
}
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("NSMSG_HANDLEINFO_LASTSEEN", buff);
+ intervalString(buff, now - hi->lastseen, user->handle_info);
+ reply("NSMSG_HANDLEINFO_LASTSEEN", buff);
} else {
- reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
+ reply("NSMSG_HANDLEINFO_LASTSEEN_NOW");
}
reply("NSMSG_HANDLEINFO_INFOLINE", (hi->infoline ? hi->infoline : nsmsg_none));
+ if ((oper_has_access(user, cmd->parent->bot, 200, 1)) || IsNetworkHelper(user))
+ reply("NSMSG_HANDLEINFO_DEVNULL", (hi->devnull ? hi->devnull : nsmsg_none));
+ if (user->handle_info && HANDLE_FLAGGED(user->handle_info, BOT))
+ reply("NSMSG_HANDLEINFO_WEBSITE", (hi->website ? hi->website : nsmsg_none));
+ if(hi->opserv_level > 0 && user->handle_info && HANDLE_FLAGGED(user->handle_info, BOT))
+ reply("NSMSG_HANDLEINFO_ACCESS", hi->opserv_level);
if (HANDLE_FLAGGED(hi, FROZEN))
reply("NSMSG_HANDLEINFO_VACATION");
reply(type);
}
- if (oper_has_access(user, cmd->parent->bot, 0, 1) || IsSupport(user)) {
+ 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");
} else {
}
if (hi->flags) {
- unsigned long flen = 1;
- char flags[34]; /* 32 bits possible plus '+' and '\0' */
- flags[0] = '+';
- for (i=0, flen=1; handle_flags[i]; i++)
- if (hi->flags & 1 << i)
+ unsigned long flen = 1;
+ char flags[34]; /* 32 bits possible plus '+' and '\0' */
+ flags[0] = '+';
+ for (i=0, flen=1; handle_flags[i]; i++)
+ if (hi->flags & 1 << i)
flags[flen++] = handle_flags[i];
- flags[flen] = 0;
- reply("NSMSG_HANDLEINFO_FLAGS", flags);
+ flags[flen] = 0;
+ reply("NSMSG_HANDLEINFO_FLAGS", flags);
} else {
- reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none);
+ reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none);
}
if (HANDLE_FLAGGED(hi, SUPPORT_HELPER)
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);
reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN");
if (nickserv_conf.disable_nicks) {
- /* nicks disabled; don't show anything about registered nicks */
+ /* nicks disabled; don't show anything about registered nicks */
} else if (hi->nicks) {
- struct nick_info *ni, *next_ni;
- for (ni = hi->nicks; ni; ni = next_ni) {
- herelen = strlen(ni->nick);
- if (pos + herelen + 1 > ArrayLength(buff)) {
- next_ni = ni;
- goto print_nicks_buff;
- } else {
- next_ni = ni->next;
- }
- memcpy(buff+pos, ni->nick, herelen);
- pos += herelen; buff[pos++] = ' ';
- if (!next_ni) {
- print_nicks_buff:
- buff[pos-1] = 0;
- reply("NSMSG_HANDLEINFO_NICKS", buff);
- pos = 0;
- }
- }
+ struct nick_info *ni, *next_ni;
+ for (ni = hi->nicks; ni; ni = next_ni) {
+ herelen = strlen(ni->nick);
+ if (pos + herelen + 1 > ArrayLength(buff)) {
+ next_ni = ni;
+ goto print_nicks_buff;
+ } else {
+ next_ni = ni->next;
+ }
+ memcpy(buff+pos, ni->nick, herelen);
+ pos += herelen; buff[pos++] = ' ';
+ if (!next_ni) {
+ print_nicks_buff:
+ buff[pos-1] = 0;
+ reply("NSMSG_HANDLEINFO_NICKS", buff);
+ pos = 0;
+ }
+ }
} else {
- reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none);
+ reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none);
}
if (hi->masks->used) {
}
if (hi->channels) {
- struct userData *channel, *next;
- char *name;
-
- for (channel = hi->channels; channel; channel = next) {
- next = channel->u_next;
- name = channel->channel->channel->name;
- herelen = strlen(name);
- if (pos + herelen + 7 > ArrayLength(buff)) {
- next = channel;
+ struct userData *chan, *next;
+ char *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 = chan;
goto print_chans_buff;
- }
- if (IsUserSuspended(channel))
+ }
+ if (IsUserSuspended(chan))
buff[pos++] = '-';
- pos += sprintf(buff+pos, "%d:%s ", channel->access, name);
- if (next == NULL) {
- print_chans_buff:
- buff[pos-1] = 0;
- reply("NSMSG_HANDLEINFO_CHANNELS", buff);
- pos = 0;
- }
- }
+ pos += sprintf(buff+pos, "%d:%s ", chan->access, name);
+ if (next == NULL) {
+ print_chans_buff:
+ buff[pos-1] = 0;
+ reply("NSMSG_HANDLEINFO_CHANNELS", buff);
+ pos = 0;
+ }
+ }
} else {
- reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none);
+ reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none);
}
for (target = hi->users; target; target = next_un) {
- herelen = strlen(target->nick);
- if (pos + herelen + 1 > ArrayLength(buff)) {
- next_un = target;
- goto print_cnick_buff;
- } else {
- next_un = target->next_authed;
- }
- memcpy(buff+pos, target->nick, herelen);
- pos += herelen; buff[pos++] = ' ';
- if (!next_un) {
- print_cnick_buff:
- buff[pos-1] = 0;
- reply("NSMSG_HANDLEINFO_CURRENT", buff);
- pos = 0;
- }
+ herelen = strlen(target->nick);
+ if (pos + herelen + 1 > ArrayLength(buff)) {
+ next_un = target;
+ goto print_cnick_buff;
+ } else {
+ next_un = target->next_authed;
+ }
+ memcpy(buff+pos, target->nick, herelen);
+ pos += herelen; buff[pos++] = ' ';
+ if (!next_un) {
+ print_cnick_buff:
+ buff[pos-1] = 0;
+ reply("NSMSG_HANDLEINFO_CURRENT", buff);
+ pos = 0;
+ }
}
- return 1;
+ return 1 | ((hi != user->handle_info) ? CMD_LOG_STAFF : 0);
}
static NICKSERV_FUNC(cmd_userinfo)
NICKSERV_MIN_PARMS(2);
if (!(target = GetUserH(argv[1]))) {
- reply("MSG_NICK_UNKNOWN", argv[1]);
- return 0;
+ reply("MSG_NICK_UNKNOWN", argv[1]);
+ return 0;
}
if (target->handle_info)
- reply("NSMSG_USERINFO_AUTHED_AS", target->nick, target->handle_info->handle);
+ reply("NSMSG_USERINFO_AUTHED_AS", target->nick, target->handle_info->handle);
else
- reply("NSMSG_USERINFO_NOT_AUTHED", target->nick);
+ reply("NSMSG_USERINFO_NOT_AUTHED", target->nick);
return 1;
}
NICKSERV_MIN_PARMS(2);
if (!(ni = get_nick_info(argv[1]))) {
- reply("MSG_NICK_UNKNOWN", argv[1]);
- return 0;
+ reply("MSG_NICK_UNKNOWN", argv[1]);
+ return 0;
}
reply("NSMSG_NICKINFO_OWNER", ni->nick, ni->owner->handle);
return 1;
reply("NSMSG_HANDLE_EXISTS", argv[2]);
return 0;
}
+ if (hi->fakehost && hi->fakehost[0] == '.' &&
+ (strlen(argv[2]) + strlen(hi->fakehost+1) +
+ strlen(titlehost_suffix) + 2) > HOSTLEN) {
+ send_message(user, nickserv, "NSMSG_TITLE_TRUNCATED_RENAME");
+ return 0;
+ }
dict_remove2(nickserv_handle_dict, old_handle = hi->handle, 1);
hi->handle = strdup(argv[2]);
reply("NSMSG_HANDLE_CHANGED", old_handle, hi->handle);
global_message(MESSAGE_RECIPIENT_STAFF, msgbuf);
free(old_handle);
+ apply_fakehost(hi, NULL);
return 1;
}
failpw_func_list[failpw_func_used++] = func;
}
+static struct authlogEntry *authlog_add(struct handle_info *hi, struct userNode *user, const char *mask) {
+ if(!hi || (!user && !mask)) return NULL;
+ if(!mask)
+ mask = generate_hostmask(user, GENMASK_USENICK|GENMASK_STRICT_IDENT|GENMASK_NO_HIDING|GENMASK_STRICT_HOST);
+ struct authlogEntry *authlog, *next, *prev = NULL;
+ authlog = malloc(sizeof(*authlog));
+ authlog->login_time = now;
+ authlog->logout_time = 0;
+ authlog->hostmask = mask;
+ authlog->quit_reason = NULL;
+ authlog->user = user;
+ authlog->next = hi->authlog;
+ hi->authlog = authlog;
+ unsigned int i = 0;
+ for(authlog = hi->authlog; authlog; authlog = next) {
+ i++;
+ next = authlog->next;
+ if(i > nickserv_conf.max_authlog_len) {
+ struct pendingLOCUser *pending, *prev_pending = NULL;
+ for(pending = pendingLOCUsers; pending; pending = pending->next) {
+ if(pending->authlog == authlog) {
+ if(prev_pending)
+ prev_pending->next = pending->next;
+ else
+ pendingLOCUsers = pending->next;
+ free(pending);
+ break;
+ }
+ prev_pending = pending;
+ }
+ free((char *) authlog->hostmask);
+ if(authlog->quit_reason)
+ free((char *) authlog->quit_reason);
+ if(prev)
+ prev->next = authlog->next;
+ else
+ hi->authlog = authlog->next;
+ free(authlog);
+ } else
+ prev = authlog;
+ }
+ return hi->authlog;
+}
+
static NICKSERV_FUNC(cmd_auth)
{
int pw_arg, used, maxlogins;
return 1;
}
}
+ if (HANDLE_FLAGGED(hi, AUTOHIDE)) {
+ //ok we have a fakehost set... but we need to set mode +x
+ irc_svsmode(nickserv,user,"+x");
+ }
set_user_handle_info(user, hi, 1);
if (nickserv_conf.email_required && !hi->email_addr)
cryptpass(passwd, hi->passwd);
if (!hi->masks->used) {
irc_in_addr_t ip;
- string_list_append(hi->masks, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
+ nickserv_addmask(NULL, hi, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
if (irc_in_addr_is_valid(user->ip) && irc_pton(&ip, NULL, user->hostname))
- string_list_append(hi->masks, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_BYIP|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
+ nickserv_addmask(NULL, hi, generate_hostmask(user, GENMASK_OMITNICK|GENMASK_BYIP|GENMASK_NO_HIDING|GENMASK_ANY_IDENT));
}
+ authlog_add(hi, user, NULL);
argv[pw_arg] = "****";
reply("NSMSG_AUTH_SUCCESS");
return 1;
}
+struct handle_info *checklogin(const char *user, const char *pass, UNUSED_ARG(const char *numeric), const char *hostmask, const char *ipmask)
+{
+ struct handle_info *hi;
+ unsigned int match = 0, ii = 0;
+ hi = dict_find(nickserv_handle_dict, user, NULL);
+ if(!hi)
+ return NULL;
+ /* If no hostmasks on the account, allow it. */
+ if (hi->masks->used) {
+ /* If any hostmask matches, allow it. */
+ for (ii=0; ii<hi->masks->used; ii++)
+ if (match_ircglob(hostmask, hi->masks->list[ii]) || match_ircglob(ipmask, hi->masks->list[ii])) {
+ match = 1;
+ break;
+ }
+ if(!match)
+ return NULL;
+ }
+ if(!checkpass(pass, hi->passwd))
+ return NULL;
+ if (HANDLE_FLAGGED(hi, SUSPENDED))
+ return NULL;
+ char *ptr = malloc(strlen(hostmask)+1);
+ strcpy(ptr, hostmask);
+ struct authlogEntry *authlog = authlog_add(hi, NULL, ptr);
+ struct pendingLOCUser *pending;
+ if(authlog && (pending = malloc(sizeof(*pending)))) {
+ pending->handle_info = hi;
+ pending->time = now;
+ pending->authlog = authlog;
+ pending->next = pendingLOCUsers;
+ pendingLOCUsers = pending;
+ }
+ return hi;
+}
+
+char *getfakehost(const char *user)
+{
+ struct handle_info *hi;
+ hi = dict_find(nickserv_handle_dict, user, NULL);
+ if(!hi)
+ return 0;
+ return generate_fakehost(hi);
+}
+
static allowauth_func_t *allowauth_func_list;
static unsigned int allowauth_func_size = 0, allowauth_func_used = 0;
allowauth_func_list[allowauth_func_used++] = func;
}
+static int cmd_authlog_func(struct userNode *user, struct svccmd *cmd, struct handle_info *hi);
+
+static MODCMD_FUNC(cmd_authlog)
+{
+ return cmd_authlog_func(user, cmd, user->handle_info);
+}
+
+static MODCMD_FUNC(cmd_oauthlog) {
+ struct handle_info *hi;
+
+ NICKSERV_MIN_PARMS(2);
+
+ if (!(hi = get_victim_oper(user, argv[1])))
+ return 0;
+
+ return cmd_authlog_func(user, cmd, hi);
+}
+
+static int cmd_authlog_func(struct userNode *user, struct svccmd *cmd, struct handle_info *hi) {
+ struct helpfile_table tbl;
+ struct authlogEntry *authlog;
+ int i = 0;
+
+ for(authlog = hi->authlog; authlog; authlog = authlog->next) {
+ i++;
+ }
+
+ tbl.length = i+1;
+ tbl.width = 4;
+ tbl.flags = 0;
+ tbl.flags = TABLE_NO_FREE;
+ tbl.contents = malloc(tbl.length * sizeof(tbl.contents[0]));
+ tbl.contents[0] = malloc(tbl.width * sizeof(tbl.contents[0][0]));
+ tbl.contents[0][0] = "Hostmask";
+ tbl.contents[0][1] = "Login";
+ tbl.contents[0][2] = "Logout";
+ tbl.contents[0][3] = "Quit Reason";
+
+ if(!tbl.length) {
+ table_send(cmd->parent->bot, user->nick, 0, NULL, tbl);
+ reply("MSG_NONE");
+ free(tbl.contents[0]);
+ free(tbl.contents);
+ return 0;
+ }
+
+ char *str, *ptr;
+ char intervalBuf[INTERVALLEN];
+ i = 0;
+ for(authlog = hi->authlog; authlog; authlog = authlog->next) {
+ tbl.contents[++i] = malloc(tbl.width * sizeof(tbl.contents[0][0]));
+ tbl.contents[i][0] = authlog->hostmask;
+ str = intervalString(intervalBuf, now - authlog->login_time, hi);
+ ptr = malloc(strlen(str)+1);
+ strcpy(ptr, str);
+ tbl.contents[i][1] = ptr;
+ if(authlog->logout_time)
+ str = intervalString(intervalBuf, now - authlog->logout_time, hi);
+ else if(!authlog->user)
+ str = "Unknown";
+ else {
+ sprintf(intervalBuf, "Never (%s)", authlog->user->nick);
+ str = intervalBuf;
+ }
+ ptr = malloc(strlen(str)+1);
+ strcpy(ptr, str);
+ tbl.contents[i][2] = ptr;
+ tbl.contents[i][3] = (authlog->quit_reason ? authlog->quit_reason : "-");
+ }
+
+ table_send(cmd->parent->bot, user->nick, 0, NULL, tbl);
+ for(i = 1; i < tbl.length; ++i)
+ {
+ free((char *) tbl.contents[i][1]);
+ free((char *) tbl.contents[i][2]);
+ free(tbl.contents[i]);
+ }
+ free(tbl.contents[0]);
+ free(tbl.contents);
+
+ return 0;
+}
+
static NICKSERV_FUNC(cmd_allowauth)
{
struct userNode *target;
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;
}
ni = dict_find(nickserv_nick_dict, nick, NULL);
if (ni) {
- reply("NSMSG_NICK_EXISTS", nick);
- return 0;
+ reply("NSMSG_NICK_EXISTS", nick);
+ return 0;
}
register_nick(nick, target);
reply("NSMSG_OREGNICK_SUCCESS", nick, target->handle);
}
ni = dict_find(nickserv_nick_dict, user->nick, NULL);
if (ni) {
- reply("NSMSG_NICK_EXISTS", user->nick);
- return 0;
+ reply("NSMSG_NICK_EXISTS", user->nick);
+ return 0;
}
register_nick(user->nick, user->handle_info);
reply("NSMSG_REGNICK_SUCCESS", user->nick);
if (!is_secure_password(hi->handle, new_pass, user)) return 0;
if (!checkpass(old_pass, hi->passwd)) {
argv[1] = "BADPASS";
- reply("NSMSG_PASSWORD_INVALID");
- return 0;
+ reply("NSMSG_PASSWORD_INVALID");
+ return 0;
}
cryptpass(new_pass, hi->passwd);
argv[1] = "****";
char *new_mask = canonicalize_hostmask(strdup(mask));
for (i=0; i<hi->masks->used; i++) {
if (!irccasecmp(new_mask, hi->masks->list[i])) {
- send_message(user, nickserv, "NSMSG_ADDMASK_ALREADY", new_mask);
+ if(user)
+ send_message(user, nickserv, "NSMSG_ADDMASK_ALREADY", new_mask);
free(new_mask);
return 0;
}
}
string_list_append(hi->masks, new_mask);
- send_message(user, nickserv, "NSMSG_ADDMASK_SUCCESS", new_mask);
+ if(user)
+ send_message(user, nickserv, "NSMSG_ADDMASK_SUCCESS", new_mask);
return 1;
}
{
unsigned int i;
for (i=0; i<hi->masks->used; i++) {
- if (!strcmp(del_mask, hi->masks->list[i])) {
- char *old_mask = hi->masks->list[i];
- if (hi->masks->used == 1 && !force) {
- send_message(user, nickserv, "NSMSG_DELMASK_NOTLAST");
- return 0;
- }
- hi->masks->list[i] = hi->masks->list[--hi->masks->used];
- send_message(user, nickserv, "NSMSG_DELMASK_SUCCESS", old_mask);
- free(old_mask);
- return 1;
- }
+ if (!strcmp(del_mask, hi->masks->list[i])) {
+ char *old_mask = hi->masks->list[i];
+ if (hi->masks->used == 1 && !force) {
+ send_message(user, nickserv, "NSMSG_DELMASK_NOTLAST");
+ return 0;
+ }
+ hi->masks->list[i] = hi->masks->list[--hi->masks->used];
+ send_message(user, nickserv, "NSMSG_DELMASK_SUCCESS", old_mask);
+ free(old_mask);
+ return 1;
+ }
}
send_message(user, nickserv, "NSMSG_DELMASK_NOT_FOUND");
return 0;
unsigned long added, removed, flag;
for (added=removed=nn=0; str[nn]; nn++) {
- switch (str[nn]) {
- case '+': add = 1; break;
- case '-': add = 0; break;
- default:
- if (!(pos = handle_inverse_flags[(unsigned char)str[nn]])) {
- send_message(user, bot, "NSMSG_INVALID_FLAG", str[nn]);
- return 0;
- }
+ switch (str[nn]) {
+ case '+': add = 1; break;
+ case '-': add = 0; break;
+ default:
+ if (!(pos = handle_inverse_flags[(unsigned char)str[nn]])) {
+ send_message(user, bot, "NSMSG_INVALID_FLAG", str[nn]);
+ return 0;
+ }
if (user && (user->handle_info->opserv_level < flag_access_levels[pos-1])) {
/* cheesy avoidance of looking up the flag name.. */
send_message(user, bot, "NSMSG_FLAG_PRIVILEGED", str[nn]);
return 0;
}
flag = 1 << (pos - 1);
- if (add)
+ if (add)
added |= flag, removed &= ~flag;
- else
+ else
removed |= flag, added &= ~flag;
- break;
- }
+ break;
+ }
}
*padded = added;
*premoved = removed;
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);
}
unsigned int i;
char *set_display[] = {
"INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE",
- "EMAIL", "MAXLOGINS", "LANGUAGE"
+ "EMAIL", "MAXLOGINS", "LANGUAGE", "DEVNULL"
};
send_message(user, nickserv, "NSMSG_SETTING_LIST");
/* Do this so options are presented in a consistent order. */
for (i = 0; i < ArrayLength(set_display); ++i)
- if ((opt = dict_find(nickserv_opt_dict, set_display[i], NULL)))
- opt(user, hi, override, 0, NULL);
+ if ((opt = dict_find(nickserv_opt_dict, set_display[i], NULL)))
+ opt(user, hi, override, 0, NULL);
}
static NICKSERV_FUNC(cmd_set)
hi = user->handle_info;
if (argc < 2) {
- set_list(user, hi, 0);
- return 1;
+ set_list(user, hi, 0);
+ return 1;
}
if (!(opt = dict_find(nickserv_opt_dict, argv[1], NULL))) {
- reply("NSMSG_INVALID_OPTION", argv[1]);
+ reply("NSMSG_INVALID_OPTION", argv[1]);
return 0;
}
return opt(user, hi, 0, argc-1, argv+1);
return 0;
if (argc < 3) {
- set_list(user, hi, 0);
- return 1;
+ set_list(user, hi, 0);
+ return 1;
}
if (!(opt = dict_find(nickserv_opt_dict, argv[2], NULL))) {
- reply("NSMSG_INVALID_OPTION", argv[2]);
+ reply("NSMSG_INVALID_OPTION", argv[2]);
return 0;
}
{
const char *info;
if (argc > 1) {
- if ((argv[1][0] == '*') && (argv[1][1] == 0)) {
+ if ((argv[1][0] == '*') && (argv[1][1] == 0)) {
free(hi->infoline);
hi->infoline = NULL;
- } else {
- hi->infoline = strdup(unsplit_string(argv+1, argc-1, NULL));
- }
+ } else {
+ hi->infoline = strdup(unsplit_string(argv+1, argc-1, NULL));
+ }
}
info = hi->infoline ? hi->infoline : user_find_message(user, "MSG_NONE");
return 1;
}
+static OPTION_FUNC(opt_devnull)
+{
+ const char *devnull;
+
+ if (argc > 1) {
+ if (!override) {
+ send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
+ }
+ if ((argv[1][0] == '*') && (argv[1][1] == 0)) {
+ free(hi->devnull);
+ hi->devnull = NULL;
+ } else {
+ devnull = unsplit_string(argv+1, argc-1, NULL);
+ if(devnull_check(devnull) == 1) {
+ if(hi->devnull)
+ free(hi->devnull);
+ hi->devnull = strdup(devnull);
+ }
+ }
+ }
+
+ devnull = hi->devnull ? hi->devnull : user_find_message(user, "MSG_NONE");
+ send_message(user, nickserv, "NSMSG_SET_DEVNULL", devnull);
+ return 1;
+}
+
+void nickserv_devnull_delete(char *name) {
+ dict_iterator_t it;
+ struct handle_info *hi;
+
+ for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) {
+ hi = iter_data(it);
+ if (hi->devnull && !irccasecmp(name, hi->devnull)) {
+ free(hi->devnull);
+ hi->devnull = NULL;
+ }
+ }
+}
+
+void nickserv_devnull_rename(char *oldname, char *newname) {
+ dict_iterator_t it;
+ struct handle_info *hi;
+
+ for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) {
+ hi = iter_data(it);
+ if (hi->devnull && !irccasecmp(oldname, hi->devnull)) {
+ hi->devnull = strdup(newname);
+ }
+ }
+}
+
+static OPTION_FUNC(opt_website)
+{
+ const char *website;
+
+ if (argc > 1) {
+ if (!HANDLE_FLAGGED(user->handle_info, BOT)) {
+ send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
+ }
+ if ((argv[1][0] == '*') && (argv[1][1] == 0)) {
+ free(hi->website);
+ hi->website = NULL;
+ } else {
+ website = unsplit_string(argv+1, argc-1, NULL);
+ hi->website = strdup(website);
+ }
+ }
+ if (HANDLE_FLAGGED(user->handle_info, BOT)) {
+ website = hi->website ? hi->website : user_find_message(user, "MSG_NONE");
+ send_message(user, nickserv, "NSMSG_SET_WEBSITE", website);
+ }
+ return 1;
+}
+
static OPTION_FUNC(opt_width)
{
if (argc > 1)
- hi->screen_width = strtoul(argv[1], NULL, 0);
+ hi->screen_width = strtoul(argv[1], NULL, 0);
if ((hi->screen_width > 0) && (hi->screen_width < MIN_LINE_SIZE))
hi->screen_width = MIN_LINE_SIZE;
static OPTION_FUNC(opt_tablewidth)
{
if (argc > 1)
- hi->table_width = strtoul(argv[1], NULL, 0);
+ hi->table_width = strtoul(argv[1], NULL, 0);
if ((hi->table_width > 0) && (hi->table_width < MIN_LINE_SIZE))
hi->table_width = MIN_LINE_SIZE;
static OPTION_FUNC(opt_color)
{
if (argc > 1) {
- if (enabled_string(argv[1]))
- HANDLE_SET_FLAG(hi, MIRC_COLOR);
+ if (enabled_string(argv[1]))
+ HANDLE_SET_FLAG(hi, MIRC_COLOR);
else if (disabled_string(argv[1]))
- HANDLE_CLEAR_FLAG(hi, MIRC_COLOR);
- else {
- send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]);
- return 0;
- }
+ HANDLE_CLEAR_FLAG(hi, MIRC_COLOR);
+ else {
+ send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]);
+ return 0;
+ }
}
send_message(user, nickserv, "NSMSG_SET_COLOR", user_find_message(user, HANDLE_FLAGGED(hi, MIRC_COLOR) ? "MSG_ON" : "MSG_OFF"));
static OPTION_FUNC(opt_privmsg)
{
if (argc > 1) {
- if (enabled_string(argv[1]))
- HANDLE_SET_FLAG(hi, USE_PRIVMSG);
+ if (enabled_string(argv[1]))
+ HANDLE_SET_FLAG(hi, USE_PRIVMSG);
else if (disabled_string(argv[1]))
- HANDLE_CLEAR_FLAG(hi, USE_PRIVMSG);
- else {
- send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]);
- return 0;
- }
+ HANDLE_CLEAR_FLAG(hi, USE_PRIVMSG);
+ else {
+ send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]);
+ return 0;
+ }
}
send_message(user, nickserv, "NSMSG_SET_PRIVMSG", user_find_message(user, HANDLE_FLAGGED(hi, USE_PRIVMSG) ? "MSG_ON" : "MSG_OFF"));
return 1;
}
+static OPTION_FUNC(opt_autohide)
+{
+ if (argc > 1) {
+ if (enabled_string(argv[1]))
+ HANDLE_SET_FLAG(hi, AUTOHIDE);
+ else if (disabled_string(argv[1]))
+ HANDLE_CLEAR_FLAG(hi, AUTOHIDE);
+ else {
+ send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]);
+ return 0;
+ }
+ }
+
+ send_message(user, nickserv, "NSMSG_SET_AUTOHIDE", user_find_message(user, HANDLE_FLAGGED(hi, AUTOHIDE) ? "MSG_ON" : "MSG_OFF"));
+ return 1;
+}
+
static OPTION_FUNC(opt_style)
{
char *style;
if (argc > 1) {
- if (!irccasecmp(argv[1], "Zoot"))
- hi->userlist_style = HI_STYLE_ZOOT;
- else if (!irccasecmp(argv[1], "def"))
- hi->userlist_style = HI_STYLE_DEF;
+ if (!irccasecmp(argv[1], "Zoot"))
+ hi->userlist_style = HI_STYLE_ZOOT;
+ else if (!irccasecmp(argv[1], "def"))
+ hi->userlist_style = HI_STYLE_DEF;
}
switch (hi->userlist_style) {
case HI_STYLE_DEF:
- style = "def";
- break;
+ style = "def";
+ break;
case HI_STYLE_ZOOT:
default:
- style = "Zoot";
+ style = "Zoot";
}
send_message(user, nickserv, "NSMSG_SET_STYLE", style);
static OPTION_FUNC(opt_password)
{
if (!override) {
- send_message(user, nickserv, "NSMSG_USE_CMD_PASS");
- return 0;
+ send_message(user, nickserv, "NSMSG_USE_CMD_PASS");
+ return 0;
}
if (argc > 1)
- cryptpass(argv[1], hi->passwd);
+ cryptpass(argv[1], hi->passwd);
send_message(user, nickserv, "NSMSG_SET_PASSWORD", "***");
+ argv[1] = "****";
+
return 1;
}
unsigned int ii, flen;
if (!override) {
- send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
- return 0;
+ send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
}
if (argc > 1)
- nickserv_apply_flags(user, hi, argv[1]);
+ nickserv_apply_flags(user, hi, argv[1]);
for (ii = flen = 0; handle_flags[ii]; ii++)
if (hi->flags & (1 << ii))
return 1;
}
+int
+oper_try_set_staff_access(struct userNode *user, struct userNode *bot, struct handle_info *target, unsigned int new_level) {
+ if (!oper_has_access(user, bot, nickserv_conf.modstaff_level, 0))
+ return 0;
+ if ((user->handle_info->opserv_level < target->opserv_level)
+ || ((user->handle_info->opserv_level == target->opserv_level)
+ && (user->handle_info->opserv_level < 1000))) {
+ send_message(user, bot, "MSG_USER_OUTRANKED", target->handle);
+ return 0;
+ }
+ if (target->staff_level == new_level)
+ return 0;
+ log_module(NS_LOG, LOG_INFO, "Account %s setting staff level for account %s to %d (from %d).",
+ user->handle_info->handle, target->handle, new_level, target->staff_level);
+ target->staff_level = new_level;
+ return 1;
+}
+
static OPTION_FUNC(opt_level)
{
int res;
if (!override) {
- send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
- return 0;
+ send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
}
res = (argc > 1) ? oper_try_set_access(user, nickserv, hi, strtoul(argv[1], NULL, 0)) : 0;
return res;
}
+static OPTION_FUNC(opt_staff_level)
+{
+ int res;
+
+ if (!override) {
+ send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
+ }
+
+ res = (argc > 1) ? oper_try_set_staff_access(user, nickserv, hi, strtoul(argv[1], NULL, 0)) : 0;
+ send_message(user, nickserv, "NSMSG_SET_STAFFLEVEL", hi->staff_level);
+ return res;
+}
+
static OPTION_FUNC(opt_epithet)
{
if (!override) {
return 0;
}
if ((strlen(user->handle_info->handle) + strlen(title) +
- strlen(nickserv_conf.titlehost_suffix) + 2) > HOSTLEN) {
+ strlen(titlehost_suffix) + 2) > HOSTLEN) {
send_message(user, nickserv, "NSMSG_TITLE_TRUNCATED");
return 0;
}
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] == '.')) {
+ if(strlen(argv[1]) >= sizeof(mask)) {
+ send_message(user, nickserv, "NSMSG_FAKEMASK_INVALID", USERLEN + HOSTLEN + 1);
+ return 0;
+ }
+
+ safestrncpy(mask, argv[1], sizeof(mask));
+
+ if ((host = strrchr(mask, '@')) && host != mask) {
+ /* If ident@host was used and the user doesn't have access to set idents, do not change anything. */
+ if (!oper_has_access(user, nickserv, nickserv_conf.set_fakeident_level, 0)) {
+ host = NULL;
+ ident = NULL;
+ } else {
+ ident = mask;
+ *host++ = '\0';
+ }
+ } else {
+ ident = NULL;
+ host = mask;
+ }
+
+ if (ident && strlen(ident) > USERLEN) {
+ send_message(user, nickserv, "NSMSG_FAKEIDENT_INVALID", USERLEN);
+ return 0;
+ }
+
+ if (host && ((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 (host && host[0]) {
+ free(hi->fakehost);
+ if (!strcmp(host, "*"))
+ hi->fakehost = NULL;
+ else
+ hi->fakehost = strdup(host);
+ host = hi->fakehost;
+ }
+ else
+ host = generate_fakehost(hi);
+
+ if (ident) {
+ free(hi->fakeident);
+ if (!strcmp(ident, "*"))
+ hi->fakeident = NULL;
+ else
+ hi->fakeident = strdup(ident);
+ ident = hi->fakeident;
+ }
else
- hi->fakehost = strdup(fake);
- fake = hi->fakehost;
- apply_fakehost(hi);
+ 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;
}
static NICKSERV_FUNC(cmd_reclaim)
{
- struct handle_info *hi;
struct nick_info *ni;
struct userNode *victim;
NICKSERV_MIN_PARMS(2);
- hi = user->handle_info;
ni = dict_find(nickserv_nick_dict, argv[1], 0);
if (!ni) {
reply("NSMSG_UNKNOWN_NICK", argv[1]);
nick = (argc < 2) ? user->nick : (const char*)argv[1];
ni = dict_find(nickserv_nick_dict, nick, NULL);
if (!ni) {
- reply("NSMSG_UNKNOWN_NICK", nick);
- return 0;
+ reply("NSMSG_UNKNOWN_NICK", nick);
+ return 0;
}
if (hi != ni->owner) {
- reply("NSMSG_NOT_YOUR_NICK", nick);
- return 0;
+ reply("NSMSG_NOT_YOUR_NICK", nick);
+ return 0;
}
reply("NSMSG_UNREGNICK_SUCCESS", ni->nick);
delete_nick(ni);
NICKSERV_MIN_PARMS(2);
if (!(ni = get_nick_info(argv[1]))) {
- reply("NSMSG_NICK_NOT_REGISTERED", argv[1]);
- return 0;
+ reply("NSMSG_NICK_NOT_REGISTERED", argv[1]);
+ return 0;
}
if (!oper_outranks(user, ni->owner))
return 0;
nickserv_unregister_handle(hi, user);
return 1;
} else {
- log_module(NS_LOG, LOG_INFO, "Account '%s' tried to unregister with the wrong password.", hi->handle);
- reply("NSMSG_PASSWORD_INVALID");
+ log_module(NS_LOG, LOG_INFO, "Account '%s' tried to unregister with the wrong password.", hi->handle);
+ reply("NSMSG_PASSWORD_INVALID");
return 0;
}
}
hi = get_victim_oper(user, argv[1]);
if (!hi)
return 0;
- duration = ParseInterval(argv[2]);
+ if(!strcmp(argv[2], "0"))
+ duration = 0;
+ else if(!(duration = ParseInterval(argv[2])))
+ {
+ reply("MSG_INVALID_DURATION", argv[2]);
+ return 0;
+ }
if (duration > 2*365*86400) {
reply("NSMSG_EXCESSIVE_DURATION", argv[2]);
return 0;
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->devnull)
+ saxdb_write_string(ctx, KEY_DEVNULL, hi->devnull);
+ if (hi->website)
+ saxdb_write_string(ctx, KEY_WEBSITE, hi->website);
if (hi->last_quit_host[0])
saxdb_write_string(ctx, KEY_LAST_QUIT_HOST, hi->last_quit_host);
saxdb_write_int(ctx, KEY_LAST_SEEN, hi->lastseen);
}
if (hi->opserv_level)
saxdb_write_int(ctx, KEY_OPSERV_LEVEL, hi->opserv_level);
+ if (hi->staff_level)
+ saxdb_write_int(ctx, KEY_STAFF_LEVEL, hi->staff_level);
if (hi->language != lang_C)
saxdb_write_string(ctx, KEY_LANGUAGE, hi->language->name);
saxdb_write_string(ctx, KEY_PASSWD, hi->passwd);
flags[0] = hi->userlist_style;
flags[1] = 0;
saxdb_write_string(ctx, KEY_USERLIST_STYLE, flags);
+ if(hi->authlog) {
+ saxdb_start_record(ctx, KEY_AUTHLOG, 0);
+ struct authlogEntry *authlog;
+ int i = 0;
+ for(authlog = hi->authlog; authlog; authlog = authlog->next) {
+ saxdb_start_record(ctx, strtab(++i), 0);
+ saxdb_write_int(ctx, KEY_AUTHLOG_LOGIN_TIME, authlog->login_time);
+ saxdb_write_int(ctx, KEY_AUTHLOG_LOGOUT_TIME, authlog->logout_time);
+ saxdb_write_string(ctx, KEY_AUTHLOG_HOSTMASK, authlog->hostmask);
+ if(authlog->quit_reason)
+ saxdb_write_string(ctx, KEY_AUTHLOG_QUIT_REASON, authlog->quit_reason);
+ saxdb_end_record(ctx);
+ }
+ saxdb_end_record(ctx); //END KEY_AUTHLOG
+ }
saxdb_end_record(ctx);
}
return 0;
if (hi_from->opserv_level > hi_to->opserv_level)
hi_to->opserv_level = hi_from->opserv_level;
+ /* Do they get a staff level promotion? */
+ if (hi_from->staff_level > hi_to->staff_level)
+ hi_to->staff_level = hi_from->staff_level;
+
/* What about last seen time? */
if (hi_from->lastseen > hi_to->lastseen)
hi_to->lastseen = hi_from->lastseen;
*/
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);
return 1;
}
+#define NICKSERV_DISCRIM_FIELDS_AUTH 0x01
+#define NICKSERV_DISCRIM_FIELDS_EMAIL 0x02
+#define NICKSERV_DISCRIM_FIELDS_SEEN 0x04
+#define NICKSERV_DISCRIM_FIELDS_ACCESS 0x08
+#define NICKSERV_DISCRIM_FIELDS_FAKEHOST 0x10
+#define NICKSERV_DISCRIM_FIELDS_WEBSITE 0x20
+#define NICKSERV_DISCRIM_FIELDS_DEVNULL 0x40
+
+#define NICKSERV_DISCRIM_FIELD_COUNT 7
+
struct nickserv_discrim {
+ unsigned int show_fields;
+ struct helpfile_table *output_table;
+ int output_table_pos;
+ unsigned int output_table_free_fields;
+
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 *website;
+ const char *devnullclass;
const char *handlemask;
const char *emailmask;
};
-typedef void (*discrim_search_func)(struct userNode *source, struct handle_info *hi);
+typedef void (*discrim_search_func)(struct userNode *source, struct handle_info *hi, struct nickserv_discrim *discrim);
struct discrim_apply_info {
struct nickserv_discrim *discrim;
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;
discrim->limit = strtoul(argv[++i], NULL, 0);
} else if (!irccasecmp(argv[i], "flags")) {
nickserv_modify_handle_flags(user, nickserv, argv[++i], &discrim->flags_on, &discrim->flags_off);
+ } else if (!irccasecmp(argv[i], "fields")) {
+ char *fields = argv[++i];
+ char *delimiter = strstr(fields, ",");
+ while(1) {
+ if(delimiter)
+ *delimiter = '\0';
+ if(!irccasecmp(fields, "auth"))
+ discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_AUTH;
+ else if(!irccasecmp(fields, "email"))
+ discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_EMAIL;
+ else if(!irccasecmp(fields, "seen"))
+ discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_SEEN;
+ else if(!irccasecmp(fields, "access"))
+ discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_ACCESS;
+ else if(!irccasecmp(fields, "fakehost"))
+ discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_FAKEHOST;
+ else if(!irccasecmp(fields, "website") && IsBot(user))
+ discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_WEBSITE;
+ else if(!irccasecmp(fields, "devnull"))
+ discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_DEVNULL;
+ else {
+ send_message(user, nickserv, "MSG_INVALID_FIELD", fields);
+ goto fail;
+ }
+ if(delimiter) {
+ *delimiter = ',';
+ fields = delimiter+1;
+ if(*fields) {
+ delimiter = strstr(fields, ",");
+ continue;
+ }
+ }
+ break;
+ }
} else if (!irccasecmp(argv[i], "registered")) {
const char *cmp = argv[++i];
if (cmp[0] == '<') {
goto fail;
}
discrim->hostmask_type = SUPERSET;
- } else if (!irccasecmp(argv[i], "lastquit") || !irccasecmp(argv[i], "lastauth")) {
- if (i == argc - 1) {
- send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]);
- goto fail;
- }
- discrim->hostmask_type = LASTQUIT;
+ } else if (!irccasecmp(argv[i], "lastquit") || !irccasecmp(argv[i], "lastauth")) {
+ if (i == argc - 1) {
+ send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]);
+ goto fail;
+ }
+ discrim->hostmask_type = LASTQUIT;
} else {
i--;
discrim->hostmask_type = SUPERSET;
} 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], "website")) {
+ if (!irccasecmp(argv[++i], "*")) {
+ discrim->website = 0;
+ } else {
+ discrim->website = argv[i];
+ }
+ } else if (!irccasecmp(argv[i], "devnull")) {
+ if (!irccasecmp(argv[++i], "*")) {
+ discrim->devnullclass = 0;
+ } else {
+ discrim->devnullclass = 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->website && (!hi->website || !match_ircglob(hi->website, discrim->website)))
+ || (discrim->devnullclass && (!hi->devnull || !match_ircglob(hi->devnull, discrim->devnullclass)))
|| (discrim->emailmask && (!hi->email_addr || !match_ircglob(hi->email_addr, discrim->emailmask)))
|| (discrim->min_level > hi->opserv_level)
|| (discrim->max_level < hi->opserv_level)
&& !irccasecmp(discrim->hostmask, mask)) break;
else if ((discrim->hostmask_type == SUPERSET)
&& (match_ircglobs(mask, discrim->hostmask))) break;
- else if ((discrim->hostmask_type == LASTQUIT)
- && (match_ircglobs(discrim->hostmask, hi->last_quit_host))) break;
+ else if ((discrim->hostmask_type == LASTQUIT)
+ && (match_ircglobs(discrim->hostmask, hi->last_quit_host))) break;
}
if (i==hi->masks->used) return 0;
}
it = next) {
next = iter_next(it);
if (nickserv_discrim_match(discrim, iter_data(it))) {
- dsf(source, iter_data(it));
+ dsf(source, iter_data(it), discrim);
matched++;
}
}
}
static void
-search_print_func(struct userNode *source, struct handle_info *match)
+search_print_func(struct userNode *source, struct handle_info *match, struct nickserv_discrim *discrim)
{
- send_message(source, nickserv, "NSMSG_SEARCH_MATCH", match->handle);
+ if(discrim->show_fields) {
+ //custom fields
+ if(discrim->output_table) {
+ discrim->output_table->contents[++discrim->output_table_pos] = malloc(discrim->output_table->width * sizeof(discrim->output_table->contents[0][0]));
+ int i = 0;
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_AUTH)
+ discrim->output_table->contents[discrim->output_table_pos][i++] = match->handle;
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_EMAIL)
+ discrim->output_table->contents[discrim->output_table_pos][i++] = (match->email_addr ? match->email_addr : "*");
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_SEEN) {
+ char *seen;
+ char seenBuf[INTERVALLEN];
+ if(match->users) {
+ seen = "Here";
+ } else if(match->lastseen == 0) {
+ seen = "Never";
+ } else {
+ seen = intervalString(seenBuf, now - match->lastseen, source->handle_info);
+ }
+ discrim->output_table_free_fields |= 1 << i;
+ discrim->output_table->contents[discrim->output_table_pos][i++] = strdup(seen);
+ }
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_ACCESS)
+ discrim->output_table->contents[discrim->output_table_pos][i++] = strtab(match->opserv_level);
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_FAKEHOST)
+ discrim->output_table->contents[discrim->output_table_pos][i++] = (match->fakehost ? match->fakehost : "*");
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_WEBSITE)
+ discrim->output_table->contents[discrim->output_table_pos][i++] = (match->website ? match->website : "*");
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_DEVNULL)
+ discrim->output_table->contents[discrim->output_table_pos][i++] = (match->devnull ? match->devnull : "*");
+
+ }
+ } else
+ send_message(source, nickserv, "NSMSG_SEARCH_MATCH", match->handle);
}
static void
-search_count_func(UNUSED_ARG(struct userNode *source), UNUSED_ARG(struct handle_info *match))
+search_count_func(UNUSED_ARG(struct userNode *source), UNUSED_ARG(struct handle_info *match), UNUSED_ARG(struct nickserv_discrim *discrim))
{
}
static void
-search_unregister_func (struct userNode *source, struct handle_info *match)
+search_unregister_func (struct userNode *source, struct handle_info *match, UNUSED_ARG(struct nickserv_discrim *discrim))
{
if (oper_has_access(source, nickserv, match->opserv_level, 0))
nickserv_unregister_handle(match, source);
discrim->limit = INT_MAX;
matches = nickserv_discrim_search(discrim, action, user);
-
+
+ if(discrim->show_fields) {
+ int width = 0;
+ int ii;
+ for(ii = 0; ii < NICKSERV_DISCRIM_FIELD_COUNT; ii++) {
+ if(discrim->show_fields & (1 << ii)) width++;
+ }
+ discrim->output_table = malloc(sizeof(discrim->output_table[0]));
+ discrim->output_table->length = matches+1;
+ discrim->output_table->width = width;
+ discrim->output_table->flags = TABLE_NO_FREE;
+ discrim->output_table->contents = malloc(discrim->output_table->length * sizeof(discrim->output_table->contents[0]));
+ discrim->output_table->contents[0] = malloc(discrim->output_table->width * sizeof(discrim->output_table->contents[0][0]));
+
+ ii = 0;
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_AUTH)
+ discrim->output_table->contents[0][ii++] = "Auth";
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_EMAIL)
+ discrim->output_table->contents[0][ii++] = "EMail";
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_SEEN)
+ discrim->output_table->contents[0][ii++] = "Seen";
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_ACCESS)
+ discrim->output_table->contents[0][ii++] = "Access";
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_FAKEHOST)
+ discrim->output_table->contents[0][ii++] = "Fakehost";
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_WEBSITE)
+ discrim->output_table->contents[0][ii++] = "Website";
+ if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_DEVNULL)
+ discrim->output_table->contents[0][ii++] = "DevNull";
+
+ nickserv_discrim_search(discrim, action, user);
+
+ table_send(nickserv, user->nick, 0, NULL, *discrim->output_table);
+
+ for(ii = 1; ii < discrim->output_table->length; ++ii) {
+ int ij;
+ for(ij = 0; ij < NICKSERV_DISCRIM_FIELD_COUNT; ij++) {
+ if(discrim->output_table_free_fields & (1 << ij))
+ free((char*)discrim->output_table->contents[ii][ij]);
+ }
+ free(discrim->output_table->contents[ii]);
+ }
+ free(discrim->output_table->contents[0]);
+ free(discrim->output_table->contents);
+ free(discrim->output_table);
+ }
if (matches)
reply("MSG_MATCH_COUNT", matches);
else
reply("MSG_NO_MATCHES");
+
free(discrim);
return 0;
}
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 int
+nickserv_db_read_authlog(UNUSED_ARG(const char *key), void *data, void *extra)
+{
+ struct record_data *rd = data;
+ struct handle_info *hi = extra;
+ const char *str;
+ struct authlogEntry *authlog;
+ authlog = malloc(sizeof(*authlog));
+
+ str = database_get_data(rd->d.object, KEY_AUTHLOG_LOGIN_TIME, RECDB_QSTRING);
+ authlog->login_time = str ? strtoul(str, NULL, 0) : 0;
+
+ str = database_get_data(rd->d.object, KEY_AUTHLOG_LOGOUT_TIME, RECDB_QSTRING);
+ authlog->logout_time = str ? strtoul(str, NULL, 0) : 0;
+
+ str = database_get_data(rd->d.object, KEY_AUTHLOG_HOSTMASK, RECDB_QSTRING);
+ authlog->hostmask = str ? strdup(str) : NULL;
+
+ str = database_get_data(rd->d.object, KEY_AUTHLOG_QUIT_REASON, RECDB_QSTRING);
+ authlog->quit_reason = str ? strdup(str) : NULL;
+
+ authlog->user = NULL;
+
+ authlog->next = NULL;
+
+ //append it to the end of the list...
+ struct authlogEntry *authlog_entry;
+ if(!hi->authlog) {
+ hi->authlog = authlog;
+ } else {
+ for(authlog_entry = hi->authlog; authlog_entry; authlog_entry = authlog_entry->next) {
+ if(!authlog_entry->next) {
+ authlog_entry->next = authlog;
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
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);
hi->language = language_find(str ? str : "C");
str = database_get_data(obj, KEY_OPSERV_LEVEL, RECDB_QSTRING);
hi->opserv_level = str ? strtoul(str, NULL, 0) : 0;
+ str = database_get_data(obj, KEY_STAFF_LEVEL, RECDB_QSTRING);
+ hi->staff_level = str ? strtoul(str, NULL, 0) : 0;
str = database_get_data(obj, KEY_INFO, RECDB_QSTRING);
if (str)
hi->infoline = strdup(str);
+ str = database_get_data(obj, KEY_WEBSITE, RECDB_QSTRING);
+ if (str)
+ hi->website = strdup(str);
+ str = database_get_data(obj, KEY_DEVNULL, RECDB_QSTRING);
+ if (str)
+ hi->devnull = 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)
last_note = note;
}
}
+ if ((subdb = database_get_data(obj, KEY_AUTHLOG, RECDB_OBJECT)))
+ dict_foreach(subdb, nickserv_db_read_authlog, hi);
}
static int
stop.tv_sec -= start.tv_sec;
stop.tv_usec -= start.tv_usec;
if (stop.tv_usec < 0) {
- stop.tv_sec -= 1;
- stop.tv_usec += 1000000;
+ 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')
dict_iterator_t it;
if (!(conf_node = conf_get_data(NICKSERV_CONF_NAME, RECDB_OBJECT))) {
- log_module(NS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME);
- return;
+ log_module(NS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME);
+ return;
}
str = database_get_data(conf_node, KEY_VALID_HANDLE_REGEX, RECDB_QSTRING);
if (!str)
nickserv_conf.db_backup_frequency = str ? ParseInterval(str) : 7200;
str = database_get_data(conf_node, KEY_MODOPER_LEVEL, RECDB_QSTRING);
nickserv_conf.modoper_level = str ? strtoul(str, NULL, 0) : 900;
+ str = database_get_data(conf_node, KEY_MODSTAFF_LEVEL, RECDB_QSTRING);
+ nickserv_conf.modstaff_level = str ? strtoul(str, NULL, 0) : 800;
str = database_get_data(conf_node, KEY_SET_EPITHET_LEVEL, RECDB_QSTRING);
nickserv_conf.set_epithet_level = str ? strtoul(str, NULL, 0) : 1;
str = database_get_data(conf_node, KEY_SET_TITLE_LEVEL, RECDB_QSTRING);
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);
nickserv_conf.default_maxlogins = str ? strtoul(str, NULL, 0) : 2;
str = database_get_data(conf_node, "hard_maxlogins", RECDB_QSTRING);
nickserv_conf.hard_maxlogins = str ? strtoul(str, NULL, 0) : 10;
+ str = database_get_data(conf_node, KEY_MAX_AUTHLOG_LEN, RECDB_QSTRING);
+ nickserv_conf.max_authlog_len = str ? strtoul(str, NULL, 0) : 30;
str = database_get_data(conf_node, KEY_OUNREGISTER_INACTIVE, RECDB_QSTRING);
nickserv_conf.ounregister_inactive = str ? ParseInterval(str) : 86400*28;
str = database_get_data(conf_node, KEY_OUNREGISTER_FLAGS, 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;
str = database_get_data(conf_node, KEY_EMAIL_SEARCH_LEVEL, RECDB_QSTRING);
nickserv_conf.email_search_level = str ? strtoul(str, NULL, 0) : 600;
str = database_get_data(conf_node, KEY_TITLEHOST_SUFFIX, RECDB_QSTRING);
- nickserv_conf.titlehost_suffix = str ? str : "example.net";
+ titlehost_suffix = str ? str : "example.net";
str = conf_get_data("server/network", RECDB_QSTRING);
nickserv_conf.network_name = str ? str : "some IRC network";
if (!nickserv_conf.auth_policer_params) {
nickserv_reclaim(user, ni, nickserv_conf.auto_reclaim_action);
}
-static int
+static void
check_user_nick(struct userNode *user) {
+ //check if this user is a pending LOC user
+ if(pendingLOCUsers) {
+ struct pendingLOCUser *pending, *next, *prev = NULL;
+ int remove;
+ for(pending = pendingLOCUsers; pending; pending = next) {
+ next = pending->next;
+ remove = 0;
+ if(user->handle_info == pending->handle_info) {
+ pending->authlog->user = user;
+ free((char*) pending->authlog->hostmask);
+ pending->authlog->hostmask = generate_hostmask(user, GENMASK_USENICK|GENMASK_STRICT_IDENT|GENMASK_NO_HIDING|GENMASK_STRICT_HOST);
+ remove = 1;
+ } else if(now - pending->time > 10)
+ remove = 1;
+ if(remove) {
+ if(prev)
+ prev->next = next;
+ else
+ pendingLOCUsers = next;
+ free(pending);
+ }
+ }
+ }
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);
}
}
}
void
-nickserv_remove_user(struct userNode *user, UNUSED_ARG(struct userNode *killer), UNUSED_ARG(const char *why))
+nickserv_remove_user(struct userNode *user, UNUSED_ARG(struct userNode *killer), const char *why)
{
+ if(user->handle_info) {
+ //check if theres an open authlog entry
+ struct authlogEntry *authlog;
+ for(authlog = user->handle_info->authlog; authlog; authlog = authlog->next) {
+ if(authlog->user == user) {
+ authlog->user = NULL;
+ authlog->logout_time = now;
+ authlog->quit_reason = strdup(why);
+ break;
+ }
+ }
+ }
dict_remove(nickserv_allow_auth_dict, user->nick);
timeq_del(0, nickserv_reclaim_p, user, TIMEQ_IGNORE_WHEN);
set_user_handle_info(user, NULL, 0);
regfree(&nickserv_conf.valid_handle_regex);
if (nickserv_conf.valid_nick_regex_set)
regfree(&nickserv_conf.valid_nick_regex);
+ struct pendingLOCUser *pending, *next;
+ for(pending = pendingLOCUsers; pending; pending = next) {
+ next = pending->next;
+ free(pending);
+ }
+ pendingLOCUsers = NULL;
}
void
{
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("DELNOTE", cmd_delnote, 0, 1, 0);
nickserv_define_func("NOTES", cmd_notes, 0, 1, 0);
if (!nickserv_conf.disable_nicks) {
- /* nick management commands */
- nickserv_define_func("REGNICK", cmd_regnick, -1, 1, 0);
- nickserv_define_func("OREGNICK", cmd_oregnick, 0, 1, 0);
- nickserv_define_func("UNREGNICK", cmd_unregnick, -1, 1, 0);
- nickserv_define_func("OUNREGNICK", cmd_ounregnick, 0, 1, 0);
- nickserv_define_func("NICKINFO", cmd_nickinfo, -1, 1, 0);
+ /* nick management commands */
+ nickserv_define_func("REGNICK", cmd_regnick, -1, 1, 0);
+ nickserv_define_func("OREGNICK", cmd_oregnick, 0, 1, 0);
+ nickserv_define_func("UNREGNICK", cmd_unregnick, -1, 1, 0);
+ nickserv_define_func("OUNREGNICK", cmd_ounregnick, 0, 1, 0);
+ nickserv_define_func("NICKINFO", cmd_nickinfo, -1, 1, 0);
nickserv_define_func("RECLAIM", cmd_reclaim, -1, 1, 0);
}
if (nickserv_conf.email_enabled) {
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);
+ nickserv_define_func("AUTHLOG", cmd_authlog, -1, 1, 0);
+ nickserv_define_func("OAUTHLOG", cmd_oauthlog, 0, 1, 0);
/* other options */
dict_insert(nickserv_opt_dict, "INFO", opt_info);
dict_insert(nickserv_opt_dict, "WIDTH", opt_width);
dict_insert(nickserv_opt_dict, "COLOR", opt_color);
dict_insert(nickserv_opt_dict, "PRIVMSG", opt_privmsg);
dict_insert(nickserv_opt_dict, "STYLE", opt_style);
+ dict_insert(nickserv_opt_dict, "AUTOHIDE", opt_autohide);
dict_insert(nickserv_opt_dict, "PASS", opt_password);
dict_insert(nickserv_opt_dict, "PASSWORD", opt_password);
dict_insert(nickserv_opt_dict, "FLAGS", opt_flags);
+ dict_insert(nickserv_opt_dict, "WEBSITE", opt_website);
+ dict_insert(nickserv_opt_dict, "DEVNULL", opt_devnull);
dict_insert(nickserv_opt_dict, "ACCESS", opt_level);
dict_insert(nickserv_opt_dict, "LEVEL", opt_level);
+ dict_insert(nickserv_opt_dict, "STAFF", opt_staff_level);
+ dict_insert(nickserv_opt_dict, "STAFF_LEVEL", opt_staff_level);
dict_insert(nickserv_opt_dict, "EPITHET", opt_epithet);
- if (nickserv_conf.titlehost_suffix) {
+ if (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);