fixed cmd_oauthlog (set NICKSERV_MIN_PARMS to 2)
[srvx.git] / src / nickserv.c
index 768148f4a755f6260de4be15a67535cdafd6cade..d98c369c4530ffc21f00d6688bb855a927419489 100644 (file)
@@ -48,6 +48,7 @@
 #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"
@@ -82,6 +83,7 @@
 #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"
@@ -330,6 +332,7 @@ static const struct message_entry msgtab[] = {
     { "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" },
@@ -394,6 +397,7 @@ static struct {
     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;
@@ -690,6 +694,23 @@ oper_has_access(struct userNode *user, struct userNode *bot, unsigned int min_le
     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;
+}
+
 static int
 is_valid_handle(const char *handle)
 {
@@ -1371,6 +1392,7 @@ static NICKSERV_FUNC(cmd_register)
     /* 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]);
     }
 
@@ -2010,9 +2032,25 @@ reg_allowauth_func(allowauth_func_t func)
     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)
 {
-    struct handle_info *hi = user->handle_info;
+    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;
@@ -2052,8 +2090,12 @@ static MODCMD_FUNC(cmd_authlog)
         tbl.contents[i][1] = ptr;
         if(authlog->logout_time)
             str = intervalString(intervalBuf, now - authlog->logout_time, hi);
-        else
-            str = (authlog->user ? "Never" : "Unknown");
+        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;
@@ -2793,6 +2835,8 @@ static OPTION_FUNC(opt_password)
         cryptpass(argv[1], hi->passwd);
 
     send_message(user, nickserv, "NSMSG_SET_PASSWORD", "***");
+    argv[1] = "****";
+    
     return 1;
 }
 
@@ -2925,6 +2969,24 @@ oper_try_set_access(struct userNode *user, struct userNode *bot, struct handle_i
     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;
@@ -2939,6 +3001,20 @@ static OPTION_FUNC(opt_level)
     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) {
@@ -3447,6 +3523,8 @@ nickserv_saxdb_write(struct saxdb_context *ctx) {
         }
         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);
@@ -3591,6 +3669,10 @@ static NICKSERV_FUNC(cmd_merge)
     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;
@@ -4172,6 +4254,8 @@ nickserv_db_read_authlog(UNUSED_ARG(const char *key), void *data, void *extra)
     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...
@@ -4235,6 +4319,8 @@ nickserv_db_read_handle(const char *handle, dict_t obj)
     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);
@@ -4523,6 +4609,8 @@ nickserv_conf_read(void)
     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);
@@ -4684,6 +4772,8 @@ check_user_nick(struct userNode *user) {
             next = pending->next;
             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);
                 if(prev)
                     prev->next = next;
                 else
@@ -4905,7 +4995,8 @@ init_nickserv(const char *nick)
     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, 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);
@@ -4921,6 +5012,8 @@ init_nickserv(const char *nick)
     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 (titlehost_suffix) {
         dict_insert(nickserv_opt_dict, "TITLE", opt_title);