Do not show "[#channel (500,)]" in a !myaccess list.
[srvx.git] / src / nickserv.c
index b1f0d294382812ce2a9bc8e818b070fa0a8108cd..f8941033ec820bfa388e0035707808e01ecdfc57 100644 (file)
@@ -194,8 +194,10 @@ static const struct message_entry msgtab[] = {
     { "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" },
@@ -214,6 +216,7 @@ static const struct message_entry msgtab[] = {
     { "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" },
@@ -317,6 +320,7 @@ static const struct message_entry msgtab[] = {
     { "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" },
@@ -383,7 +387,6 @@ static struct {
     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;
@@ -398,6 +401,8 @@ static struct {
     unsigned long ounregister_flags;
 } nickserv_conf;
 
+const char *titlehost_suffix = NULL;
+
 /* We have 2^32 unique account IDs to use. */
 unsigned long int highest_id = 0;
 
@@ -884,7 +889,7 @@ generate_fakehost(struct handle_info *handle)
         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;
     }
     return handle->fakehost;
@@ -1295,15 +1300,34 @@ static NICKSERV_FUNC(cmd_oregister)
     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], '@')) {
@@ -1329,12 +1353,14 @@ static NICKSERV_FUNC(cmd_oregister)
         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;
 }
 
@@ -1441,11 +1467,12 @@ static NICKSERV_FUNC(cmd_handleinfo)
         reply("NSMSG_HANDLEINFO_EPITHET", (hi->epithet ? hi->epithet : nsmsg_none));
     }
 
-    if (hi->fakeident)
-        reply("NSMSG_HANDLEINFO_FAKEIDENT", (hi->fakeident ? hi->fakeident : handle_find_message(hi, "MSG_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);
@@ -1616,6 +1643,12 @@ static NICKSERV_FUNC(cmd_rename_handle)
         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]);
@@ -2596,7 +2629,7 @@ static OPTION_FUNC(opt_title)
             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;
         }
@@ -2631,33 +2664,47 @@ static OPTION_FUNC(opt_fakehost)
     }
 
     if ((argc > 1) && oper_has_access(user, nickserv, nickserv_conf.set_fakehost_level, 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 &&
-            oper_has_access(user, nickserv, nickserv_conf.set_fakeident_level, 0)) {
-            ident = mask;
-            *host++ = '\0';
+        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 ((strlen(host) > HOSTLEN) || (host[0] == '.')) {
-            send_message(user, nickserv, "NSMSG_FAKEHOST_INVALID", HOSTLEN);
+        if (ident && strlen(ident) > USERLEN) {
+            send_message(user, nickserv, "NSMSG_FAKEIDENT_INVALID", USERLEN);
             return 0;
         }
 
-        if (ident && strlen(ident) > USERLEN) {
-            send_message(user, nickserv, "NSMSG_FAKEIDENT_INVALID", USERLEN);
+        if (host && ((strlen(host) > HOSTLEN) || (host[0] == '.'))) {
+            send_message(user, nickserv, "NSMSG_FAKEHOST_INVALID", HOSTLEN);
             return 0;
         }
 
-        free(hi->fakehost);
-        if (!strcmp(host, "*"))
-            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
-            hi->fakehost = strdup(host);
-        host = hi->fakehost;
+            host = generate_fakehost(hi);
 
         if (ident) {
             free(hi->fakeident);
@@ -2667,6 +2714,8 @@ static OPTION_FUNC(opt_fakehost)
                 hi->fakeident = strdup(ident);
             ident = hi->fakeident;
         }
+        else
+            ident = generate_fakeident(hi, NULL);
 
         apply_fakehost(hi, NULL);
     } else {
@@ -2675,9 +2724,10 @@ static OPTION_FUNC(opt_fakehost)
     }
     if (!host)
         host = (char *) user_find_message(user, "MSG_NONE");
-    send_message(user, nickserv, "NSMSG_SET_FAKEHOST", host);
-    if (ident)
-        send_message(user, nickserv, "NSMSG_SET_FAKEIDENT", ident);
+    if(ident)
+        send_message(user, nickserv, "NSMSG_SET_FAKEIDENTHOST", ident, host);
+    else
+        send_message(user, nickserv, "NSMSG_SET_FAKEHOST", host);
     return 1;
 }
 
@@ -2713,12 +2763,10 @@ static OPTION_FUNC(opt_fakeident)
 
 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]);
@@ -4019,7 +4067,7 @@ nickserv_conf_read(void)
     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) {
@@ -4270,7 +4318,7 @@ init_nickserv(const char *nick)
     dict_insert(nickserv_opt_dict, "ACCESS", opt_level);
     dict_insert(nickserv_opt_dict, "LEVEL", opt_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);