]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/proto-p10.c
Fix for SF bug #2423717. Invalid automode choices with a string will now show the...
[irc/evilnet/x3.git] / src / proto-p10.c
index f68dd8c65ff4c6ae05178c27eb4aeddbef83a15d..d9944d7bd835b8586ae945397a65f4785a2c9753 100644 (file)
@@ -5,7 +5,7 @@
  *
  * x3 is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -29,6 +29,7 @@
 /* Full commands. */
 #define CMD_ACCOUNT            "ACCOUNT"
 #define CMD_ADMIN               "ADMIN"
+#define CMD_ALIST               "ALIST"
 #define CMD_ASLL               "ASLL"
 #define CMD_AWAY                "AWAY"
 #define CMD_BURST               "BURST"
 #define CMD_SERVSET             "SERVSET"
 #define CMD_SET                        "SET"
 #define CMD_SETTIME             "SETTIME"
+#define CMD_SGLINE              "SGLINE"
 #define CMD_SHUN               "SHUN"
 #define CMD_SILENCE             "SILENCE"
+#define CMD_SMO                 "SMO"
+#define CMD_SNO                 "SNO"
+#define CMD_SSHUN              "SSHUN"
 #define CMD_SQUERY              "SQUERY"
 #define CMD_SQUIT               "SQUIT"
 #define CMD_STATS               "STATS"
 #define CMD_SVSJOIN             "SVSJOIN"
 #define CMD_SVSNICK             "SVSNICK"
 #define CMD_SVSPART             "SVSPART"
+#define CMD_SVSQUIT             "SVSQUIT"
 #define CMD_SWHOIS              "SWHOIS"
 #define CMD_TIME                "TIME"
 #define CMD_TOPIC               "TOPIC"
 /* Tokenized commands. */
 #define TOK_ACCOUNT            "AC"
 #define TOK_ADMIN               "AD"
+#define TOK_ALIST               "AL"
 #define TOK_ASLL               "LL"
 #define TOK_AWAY                "A"
 #define TOK_BURST               "B"
 #define TOK_SERVSET             "SERVSET"
 #define TOK_SET                        "SET"
 #define TOK_SETTIME             "SE"
+#define TOK_SGLINE              "SGL"
 #define TOK_SHUN               "SU"
 #define TOK_SILENCE             "U"
+#define TOK_SMO                 "SMO"
+#define TOK_SNO                 "SNO"
+#define TOK_SSHUN              "SSU"
 #define TOK_SQUERY              "SQUERY"
 #define TOK_SQUIT               "SQ"
 #define TOK_STATS               "R"
 #define TOK_SVSJOIN             "SJ"
 #define TOK_SVSNICK             "SN"
 #define TOK_SVSPART             "SP"
+#define TOK_SVSQUIT             "SX"
 #define TOK_SWHOIS              "SW"
 #define TOK_TIME                "TI"
 #define TOK_TOPIC               "T"
 #define P10_SERVSET             TYPE(SERVSET)
 #define P10_SET                        TYPE(SET)
 #define P10_SETTIME             TYPE(SETTIME)
+#define P10_SGLINE              TYPE(SGLINE)
 #define P10_SHUN               TYPE(SHUN)
 #define P10_SILENCE             TYPE(SILENCE)
+#define P10_SMO                 TYPE(SMO)
+#define P10_SNO                 TYPE(SNO)
+#define P10_SSHUN              TYPE(SSHUN)
 #define P10_SQUERY              TYPE(SQUERY)
 #define P10_SQUIT               TYPE(SQUIT)
 #define P10_STATS               TYPE(STATS)
 #define P10_SVSJOIN             TYPE(SVSJOIN)
 #define P10_SVSNICK             TYPE(SVSNICK)
 #define P10_SVSPART             TYPE(SVSPART)
+#define P10_SVSQUIT            TYPE(SVSQUIT)
 #define P10_SWHOIS              TYPE(SWHOIS)
 #define P10_TIME                TYPE(TIME)
 #define P10_TOPIC               TYPE(TOPIC)
@@ -475,7 +492,7 @@ irc_server(struct server *srv)
     }
 }
 
-static void
+void
 irc_p10_pton(irc_in_addr_t *ip, const char *input)
 {
     if (strlen(input) == 6) {
@@ -502,7 +519,7 @@ irc_p10_pton(irc_in_addr_t *ip, const char *input)
     }
 }
 
-static void
+void
 irc_p10_ntop(char *output, const irc_in_addr_t *ip)
 {
     if (!irc_in_addr_is_valid(*ip)) {
@@ -584,6 +601,15 @@ irc_user(struct userNode *user)
             modes[modelen++] = 'f';
         if (IsHiddenHost(user))
             modes[modelen++] = 'x';
+        if (IsBotM(user))
+            modes[modelen++] = 'B';
+        if (IsHideChans(user))
+            modes[modelen++] = 'n';
+        if (IsHideIdle(user))
+            modes[modelen++] = 'I';
+        if (IsXtraOp(user))
+            modes[modelen++] = 'X';
+
         modes[modelen] = 0;
 
         /* we don't need to put the + in modes because it's in the format string. */
@@ -744,6 +770,12 @@ irc_eob_ack(void)
     }
 }
 
+void
+irc_rpong(const char *from1, const char *from2, const char *pingtime, const char *clientinfo)
+{
+    putsock("%s " P10_RPONG " %s %s %s :%s", self->numeric, from1, from2, pingtime, clientinfo);
+}
+
 void
 irc_ping(const char *payload)
 {
@@ -792,8 +824,8 @@ irc_introduce(const char *passwd)
 void
 irc_gline(struct server *srv, struct gline *gline, int silent)
 {
-    putsock("%s " P10_GLINE " %s +%s %ld :%s<%s> %s",
-            self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, silent ? "AUTO " : "", gline->issuer, gline->reason);
+    putsock("%s " P10_GLINE " %s +%s %ld %ld :%s<%s> %s",
+            self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, now, silent ? "AUTO " : "", gline->issuer, gline->reason);
 }
 
 void
@@ -1009,6 +1041,12 @@ irc_svspart(struct userNode *from, struct userNode *who, struct chanNode *to)
     putsock("%s " P10_SVSPART " %s %s", from->uplink->numeric, who->numeric, to->name);
 }
 
+void
+irc_svsquit(struct userNode *from, struct userNode *who, char *reason)
+{
+    putsock("%s " P10_SVSQUIT " %s :%s", from->uplink->numeric, who->numeric, reason);
+}
+
 void
 irc_kick(struct userNode *who, struct userNode *target, struct chanNode *channel, const char *msg)
 {
@@ -1116,6 +1154,11 @@ void
 irc_mark(struct userNode *user, char *mark)
 {
     char *host = user->hostname;
+
+    /* TODO: Allow mark overwrite. If they are marked, and their fakehost is oldmark.hostname, update it to newmark.hostname so mark can be called multiple times. Probably requires ircd modification also */
+    if(user->mark)
+        return;
+
     /* if the mark will put us over the  host length, clip some off the left hand side
      * to make room...
      */
@@ -1123,8 +1166,12 @@ irc_mark(struct userNode *user, char *mark)
         host += 1 + ( (strlen(host) + 1 + strlen(mark)) - HOSTLEN );
     putsock("%s " CMD_MARK " %s DNSBL +m %s.%s", self->numeric, user->nick, mark, host);
     putsock("%s " CMD_MARK " %s DNSBL_DATA %s", self->numeric, user->nick, mark);
+
+    /* Save it in the user */
+    user->mark = strdup(mark);
+
     /* If they are not otherwise marked, mark their host with fakehost */
-    if(!IsFakeHost(user) && !IsSetHost(user) && !IsHiddenHost(user))
+    if(!IsFakeHost(user) && !IsSetHost(user) && !(IsHiddenHost(user) && user->handle_info) )
     {
         struct modeNode *mn = NULL;
         char fakehost[HOSTLEN];
@@ -1295,6 +1342,19 @@ static CMD_FUNC(cmd_eob_ack)
     return 1;
 }
 
+static CMD_FUNC(cmd_rping)
+{
+    struct server *dest;
+
+    if (!(dest = GetServerN(argv[1])))
+        return 1; /* if its a jupe or something, return 1 so its silently ignored */
+
+    if (dest == self)
+        irc_rpong(argv[2], argv[3], argv[4], argv[5]);
+
+    return 1;
+}
+
 static CMD_FUNC(cmd_ping)
 {
     struct server *srv;
@@ -1452,7 +1512,22 @@ static CMD_FUNC(cmd_account)
     
     if(!strcmp(argv[2],"C"))
     {
-        if((hi = loc_auth(argv[4], argv[5])))
+        if((hi = loc_auth(argv[4], argv[5], NULL)))
+        {
+            /* Return a AC A */
+            putsock("%s " P10_ACCOUNT " %s A %s %lu", self->numeric, server->numeric , argv[3], hi->registered);
+
+        }
+        else
+        {
+            /* Return a AC D */
+            putsock("%s " P10_ACCOUNT " %s D %s", self->numeric, server->numeric , argv[3]);
+        }
+        return 1;
+    }
+    else if(!strcmp(argv[2],"H")) /* New enhanced (host) version of C */
+    {
+        if((hi = loc_auth(argv[5], argv[6], argv[4] )))
         {
             /* Return a AC A */
             putsock("%s " P10_ACCOUNT " %s A %s %lu", self->numeric, server->numeric , argv[3], hi->registered);
@@ -1497,7 +1572,9 @@ static struct {
   P(BADCHAN),        P(LOCAL_BADCHAN),  P(SEE_CHAN),      P(PROPAGATE),
   P(DISPLAY),        P(SEE_OPERS),      P(WIDE_GLINE),    P(FORCE_OPMODE),
   P(FORCE_LOCAL_OPMODE), P(REMOTEREHASH), P(CHECK), P(SEE_SECRET_CHAN),
-  P(SHUN),           P(LOCAL_SHUN),     P(WIDE_SHUN),
+  P(SHUN),           P(LOCAL_SHUN),     P(WIDE_SHUN),     P(ZLINE),
+  P(LOCAL_ZLINE),    P(WIDE_ZLINE),     P(LIST_CHAN),     P(WHOIS_NOTICE),
+  P(HIDE_IDLE),      P(XTRAOP),         P(HIDE_CHANNELS),
 #undef P
   { 0, 0 }
 };
@@ -1603,6 +1680,7 @@ static CMD_FUNC(cmd_burst)
     static char exemptlist[MAXLEN], banlist[MAXLEN];
     unsigned int next = 3, res = 1;
     int ctype = 0, echeck = 0, bcheck = 0;
+    struct chanData *cData;
     struct chanNode *cNode;
     struct userNode *un;
     struct modeNode *mNode;
@@ -1686,6 +1764,15 @@ static CMD_FUNC(cmd_burst)
         irc_burst(cNode);
     }
     cNode = AddChannel(argv[1], in_timestamp, modes, banlist, exemptlist);
+    cData = cNode->channel_info;
+
+    if (!cData) {
+        if (cNode->modes & MODE_REGISTERED) {
+            irc_join(opserv, cNode);
+            irc_mode(opserv, cNode, "-z");
+            irc_part(opserv, cNode, "");
+        }
+    }
 
     /* Burst channel members in now. */
     for (user = members, sep = *members, mode = 0; sep; user = end) {
@@ -1742,20 +1829,40 @@ static CMD_FUNC(cmd_mark)
 
     if(argc < 4)
         return 0;
-    target = GetUserH(argv[1]);
-    if(!target) {
-        log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose mark is changing.", argv[1]);
-        return 0;
-    }
     if(!strcasecmp(argv[2], "DNSBL")) {
         /* DNSBL <modes> */
         return 1;
     }
     else if(!strcasecmp(argv[2], "DNSBL_DATA")) {
         /* DNSBL_DATA name */
+        target = GetUserH(argv[1]);
+        if(!target) {
+            log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose dnsbl mark is changing.", argv[1]);
+            return 0;
+        }
+        target->mark = strdup(argv[3]);
         return 1;
         
     }
+    else if(!strcasecmp(argv[2], "CVERSION")) {
+        /* DNSBL_DATA name */
+        target = GetUserH(argv[1]);
+        if(!target) {
+            log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose version mark is changing.", argv[1]);
+            return 0;
+        }
+
+        char *version = unsplit_string(argv + 3, argc - 3, NULL);
+        if(!version)
+            version = "";
+
+        target->version_reply = strdup(version);
+
+        if(match_ircglob(version, "WebTV;*"))
+            target->no_notice = true; /* webbies cant see notices */
+
+        return 1;
+    }
     /* unknown type of mark */
     return 1;
 }
@@ -1945,17 +2052,29 @@ static CMD_FUNC(cmd_num_topic)
 
 static CMD_FUNC(cmd_num_gline)
 {
-    if (argc < 6)
-        return 0;
-    gline_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0, 0);
+    if (argc < 7) {
+        if (argc < 6)
+            return 0;
+        else
+            gline_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0, 0);
+    } else {
+        if (argv[5] == "+")
+          gline_add(origin, argv[3], atoi(argv[4])-now, argv[6], now, 0, 0);
+    }
     return 1;
 }
 
 static CMD_FUNC(cmd_num_shun)
 {
-    if (argc < 6)
-        return 0;
-    shun_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0);
+    if (argc < 7) {
+        if (argc < 6)
+            return 0;
+        else
+            shun_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0);
+    } else {
+        if (argv[5] == "+")
+            shun_add(origin, argv[3], atoi(argv[4])-now, argv[6], now, 0);
+    }
     return 1;
 }
 
@@ -2016,7 +2135,7 @@ static CMD_FUNC(cmd_svspart)
 
     if (argc < 3)
         return 0;
-    user = GetUserH(argv[1]);
+    user = GetUserN(argv[1]);
     if (!user)
         return 0;
     parse_foreach(argv[2], part_helper, NULL, NULL, NULL, user);
@@ -2205,6 +2324,34 @@ static CMD_FUNC(cmd_gline)
         return 0;
 }
 
+static CMD_FUNC(cmd_sgline)
+{
+    struct server *sender;
+
+    if (argc < 4)
+        return 0;
+
+    if (!(sender = GetServerH(origin)))
+        return 0;
+
+    gline_add(origin, argv[1], strtoul(argv[2], NULL, 0), argv[argc-1], now, 1, 0);
+    return 1;
+}
+
+static CMD_FUNC(cmd_sshun)
+{
+    struct server *sender;
+
+    if (argc < 4)
+        return 0;
+
+    if (!(sender = GetServerH(origin)))
+        return 0;
+
+    shun_add(origin, argv[1], strtoul(argv[2], NULL, 0), argv[argc-1], now, 1);
+    return 1;
+}
+
 static CMD_FUNC(cmd_shun)
 {
     if (argc < 3)
@@ -2378,8 +2525,12 @@ init_parse(void)
     dict_insert(irc_func_dict, TOK_WHOIS, cmd_whois);
     dict_insert(irc_func_dict, CMD_GLINE, cmd_gline);
     dict_insert(irc_func_dict, TOK_GLINE, cmd_gline);
+    dict_insert(irc_func_dict, CMD_SGLINE, cmd_sgline);
+    dict_insert(irc_func_dict, TOK_SGLINE, cmd_sgline);
     dict_insert(irc_func_dict, CMD_SHUN, cmd_shun);
     dict_insert(irc_func_dict, TOK_SHUN, cmd_shun);
+    dict_insert(irc_func_dict, CMD_SSHUN, cmd_sshun);
+    dict_insert(irc_func_dict, TOK_SSHUN, cmd_sshun);
     dict_insert(irc_func_dict, CMD_OPMODE, cmd_opmode);
     dict_insert(irc_func_dict, TOK_OPMODE, cmd_opmode);
     dict_insert(irc_func_dict, CMD_CLEARMODE, cmd_clearmode);
@@ -2388,6 +2539,15 @@ init_parse(void)
     dict_insert(irc_func_dict, TOK_VERSION, cmd_version);
     dict_insert(irc_func_dict, CMD_ADMIN, cmd_admin);
     dict_insert(irc_func_dict, TOK_ADMIN, cmd_admin);
+    dict_insert(irc_func_dict, CMD_SMO, cmd_dummy);
+    dict_insert(irc_func_dict, TOK_SMO, cmd_dummy);
+    dict_insert(irc_func_dict, CMD_SNO, cmd_dummy);
+    dict_insert(irc_func_dict, TOK_SNO, cmd_dummy);
+
+    dict_insert(irc_func_dict, CMD_RPING, cmd_rping);
+    dict_insert(irc_func_dict, TOK_RPING, cmd_rping);
+    dict_insert(irc_func_dict, CMD_RPONG, cmd_dummy);
+    dict_insert(irc_func_dict, TOK_RPONG, cmd_dummy);
 
     /* In P10, DESTRUCT doesn't do anything except be broadcast to servers.
      * Apparently to obliterate channels from any servers that think they
@@ -2418,6 +2578,9 @@ init_parse(void)
     dict_insert(irc_func_dict, TOK_EXEMPT, cmd_dummy);
     dict_insert(irc_func_dict, CMD_PRIVS, cmd_privs);
     dict_insert(irc_func_dict, TOK_PRIVS, cmd_privs);
+    /* ignore ALIST for now */
+    dict_insert(irc_func_dict, TOK_ALIST, cmd_dummy);
+    dict_insert(irc_func_dict, CMD_ALIST, cmd_dummy);
     /* Ignore remote luser */
     dict_insert(irc_func_dict, TOK_LUSERS, cmd_dummy);
     /* We have reliable clock!  Always!  Wraaa! */
@@ -2427,6 +2590,7 @@ init_parse(void)
     /* ignore /trace and /motd commands targetted at us */
     dict_insert(irc_func_dict, TOK_TRACE, cmd_dummy);
     dict_insert(irc_func_dict, TOK_MOTD, cmd_dummy);
+    dict_insert(irc_func_dict, TOK_UPING, cmd_dummy);
 
     /* handle topics */
     dict_insert(irc_func_dict, "331", cmd_num_topic);
@@ -2735,6 +2899,8 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char *
 {
     struct userNode *oldUser, *uNode;
     unsigned int n, ignore_user;
+    char *tstr;
+    int type;
 
     if ((strlen(numeric) < 3) || (strlen(numeric) > 5)) {
         log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): numeric %s wrong length!", uplink, nick, numeric);
@@ -2783,11 +2949,15 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char *
     safestrncpy(uNode->numeric, numeric, sizeof(uNode->numeric));
     irc_p10_pton(&uNode->ip, realip);
 
-    if (irc_in_addr_is_ipv4(uNode->ip)) {
-      make_virtip((char*)irc_ntoa(&uNode->ip), (char*)irc_ntoa(&uNode->ip), uNode->cryptip);
-      make_virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost);
-    } else if (irc_in_addr_is_ipv6(uNode->ip)) {
-      make_ipv6virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost);
+    tstr = conf_get_data("server/type", RECDB_QSTRING);
+    type = atoi(tstr);
+    if (type > 6) {
+      if (irc_in_addr_is_ipv4(uNode->ip)) {
+        make_virtip((char*)irc_ntoa(&uNode->ip), (char*)irc_ntoa(&uNode->ip), uNode->cryptip);
+        make_virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost);
+      } else if (irc_in_addr_is_ipv6(uNode->ip)) {
+        make_ipv6virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost);
+      }
     }
 
     if (!uNode->crypthost && uNode->cryptip)
@@ -2874,6 +3044,12 @@ DelUser(struct userNode* user, struct userNode *killer, int announce, const char
         user->version_reply = NULL;
     }
 
+    /* clean up mark */
+    if(user->mark) {
+        free(user->mark);
+        user->mark = NULL;
+    }
+
     /* clean up geoip data if any */
     if(user->country_code) free(user->country_code);
     if(user->city) free(user->city);
@@ -2932,6 +3108,34 @@ void mod_usermode(struct userNode *user, const char *mode_change) {
        case 'd': do_user_mode(FLAGS_DEAF); break;
        case 'k': do_user_mode(FLAGS_SERVICE); break;
        case 'g': do_user_mode(FLAGS_GLOBAL); break;
+       case 'B': do_user_mode(FLAGS_BOT); break;
+       case 'n': do_user_mode(FLAGS_HIDECHANS); break;
+       case 'I': do_user_mode(FLAGS_HIDEIDLE); break;
+       case 'X': do_user_mode(FLAGS_XTRAOP); break;
+       case 'C': do_user_mode(FLAGS_CLOAKHOST);
+           if (*word) {
+               char cloakhost[MAXLEN];
+               unsigned int ii;
+               for (ii=0; (*word != ' ') && (*word != '\0'); )
+                   cloakhost[ii++] = *word++;
+               cloakhost[ii] = 0;
+               while (*word == ' ')
+                   word++;
+               safestrncpy(user->crypthost, cloakhost, sizeof(user->crypthost));
+           }
+           break;
+       case 'c': do_user_mode(FLAGS_CLOAKIP);
+           if (*word) {
+               char cloakip[MAXLEN];
+               unsigned int ii;
+               for (ii=0; (*word != ' ') && (*word != '\0'); )
+                   cloakip[ii++] = *word++;
+               cloakip[ii] = 0;
+               while (*word == ' ')
+                   word++;
+               safestrncpy(user->cryptip, cloakip, sizeof(user->cryptip));
+           }
+           break;
        // sethost - reed/apples
        // case 'h': do_user_mode(FLAGS_HELPER); break;
        // I check if there's an 'h' in the first part, and if there,