diff --git a/Changes b/Changes index abaf297ee..d8db40abe 100644 --- a/Changes +++ b/Changes @@ -2326,3 +2326,7 @@ and patch by fbi (#4035). - Tweak: send actual channel name and not user supplied channel in KICK, reported and patch by Stealth (#3298). +- Services coders: Added support for ESVID. Instead of a number you can + now store a string (of max NICKLEN size) as service stamp. See + protoctl.txt and serverprotocol.html in doc/technical for more information. + Patch from nenotopia (#3966). diff --git a/doc/technical/protoctl.txt b/doc/technical/protoctl.txt index ef0fec5d1..f0d060f2a 100644 --- a/doc/technical/protoctl.txt +++ b/doc/technical/protoctl.txt @@ -154,3 +154,7 @@ EAUTH Early Authorization. This makes it possible for servers to authent SERVERS Informs the other server about the other servers (numerics) on this network (including our own numeric). Syntax: SERVERS=numeric1,numeric2,numeric3,etc + +ESVID This token indicates that the traditional services stamp value may take any + arbitrary value for the SVID field, such as an account name or other unique + identifier, including a traditional timestamp value. diff --git a/doc/technical/serverprotocol.html b/doc/technical/serverprotocol.html index 98b515cea..09a1579da 100644 --- a/doc/technical/serverprotocol.html +++ b/doc/technical/serverprotocol.html @@ -106,6 +106,7 @@
  • NICKCHARS : Indicates the set of enabled nickchar options (see the regular documention for info about this).
  • CHANMODES : (Not required to be sent) This is the same as the CHANMODES value in the 005 for client connections. Useful for autodetecting things like what modes are valid for ChanServ MLOCK, for example.
  • CLK : Supports an extra field in NICK for sending the cloaked host (not vhost).
  • +
  • ESVID : Supports arbitrary values instead of just numeric timestamps for the services identifier field.
  • The syntax examples here follow the conventions for TOKEN and also NS in cases of server-only messages.

    2.3 SERVER - Server Negotiation

    @@ -168,11 +169,11 @@

    3.1 NICK - User Introduction and Nick Change (TOKEN: &)

    Syntax (nick change): :oldnick & newnick :timestamp

    This format of the NICK message indicates an existing user is changing his or her nickname. If a collision occurs, see the section on Nick Collisions below. The timestamp is the new nickname's timestamp.

    -

    Syntax (normal): & nick hopcount timestamp username hostname server servicestamp :realname

    -

    Syntax (NICKv2): & nick hopcount timestamp username hostname server servicestamp +usermodes virtualhost :realname

    -

    Syntax (NICKv2+CLK): & nick hopcount timestamp username hostname server servicestamp +usermodes virtualhost cloakhost :realname -

    Syntax (NICKv2+NICKIP): & nick hopcount timestamp username hostname server servicestamp +usermodes virtualhost nickipaddr :realname

    -

    Syntax (NICKv2+NICKIP+CLK): & nick hopcount timestamp username hostname server servicestamp +usermodes virtualhost cloakhost nickipaddr :realname +

    Syntax (normal): & nick hopcount timestamp username hostname server service-identifier-token :realname

    +

    Syntax (NICKv2): & nick hopcount timestamp username hostname server service-identifier-token +usermodes virtualhost :realname

    +

    Syntax (NICKv2+CLK): & nick hopcount timestamp username hostname server service-identifier-token +usermodes virtualhost cloakhost :realname +

    Syntax (NICKv2+NICKIP): & nick hopcount timestamp username hostname server service-identifier-token +usermodes virtualhost nickipaddr :realname

    +

    Syntax (NICKv2+NICKIP+CLK): & nick hopcount timestamp username hostname server service-identifier-token +usermodes virtualhost cloakhost nickipaddr :realname

    Note: Because each server normally does its own cloak generation, Unreal does not expect to receive NICK messages with the CLK info, so do not send it. It will send this info to a server it has received a PROTOCTL CLK from however.

    This format of the NICK message introduces a new user to the network. If PROTOCTL VHP is enabled, the user's cloaked host is put in the virtualhost field, otherwise it'll be * unless the user is +t. With the addition of CLK, VHP is no longer necessary for determining the cloak host.

    3.1.1 Nick Collisions

    @@ -306,7 +307,7 @@

    Syntax (SVSMODE): :source n target +usermodes

    Syntax (SVS2MODE): :source v target +usermodes

    Judging by these commands alone, you'd think they are identical. Both commands force a usermode change to occur. This is typically used by services to set +r on a user who has successfully identified. They differ in that SVS2MODE also sends the mode change to the user, while SVSMODE does not (hidden mode change).

    -

    SVSMODE and SVS2MODE also give special treatment to usermode +d. Rather than setting the deaf mode like you might expect, SVS(2)MODE +d allows services to change a user's services stamp (which is given in the NICK message). This could allow services to set the service stamp to an easily identifiable value that could then be used to say "hey, this person identified already". The syntax of this is: +d newservicestamp and can be combined with setting other usermodes as well. The deaf mode can be set by using +d without the service stamp parameter; however, in this case you cannot set the service stamp in the same SVS(2)MODE message.

    +

    SVSMODE and SVS2MODE also give special treatment to usermode +d. Rather than setting the deaf mode like you might expect, SVS(2)MODE +d allows services to change a user's services stamp (which is given in the NICK message). This could allow services to set the service stamp to an easily identifiable value that could then be used to say "hey, this person identified already". The syntax of this is: +d newservice-identifier-token and can be combined with setting other usermodes as well. The deaf mode can be set by using +d without the service stamp parameter; however, in this case you cannot set the service stamp in the same SVS(2)MODE message.

    Note: Do NOT use SVSMODE to remove IRCop status from a user. Use the SVSO command for that instead.

    Alternatively, target can name a channel. In this case, the mode change parameter can consist of a - character, followed by any or all of: b, e, I, q, a, o, h, or v. These characters cause the corresponding lists to be cleared of all entries. For example: SVSMODE #channel -b removes ALL bans from #channel, and SVSMODE #channel -qaohv turns ALL users on #channel into normal users (removes all owner, admin, op, halfop, and voice status). In this case, the uplink will acknowledge with a MODE listing the bans, etc that were removed.

    To completely clear a channel of all modes: MODE #channel -cfijklmnprstzACGMKLNOQRSTVu (plus any added by third-party module) followed by SVSMODE #channel -beIqaohv.

    diff --git a/include/h.h b/include/h.h index 6e8a28f3d..4cd618126 100644 --- a/include/h.h +++ b/include/h.h @@ -285,7 +285,7 @@ extern int send_queued(aClient *); extern void sendto_locfailops(char *pattern, ...) __attribute__((format(printf,1,2))); extern void sendto_connectnotice(char *nick, anUser *user, aClient *sptr, int disconnect, char *comment); extern void sendto_serv_butone_nickcmd(aClient *one, aClient *sptr, char *nick, int hopcount, -long lastnick, char *username, char *realhost, char *server, long servicestamp, char *info, char *umodes, +long lastnick, char *username, char *realhost, char *server, char *svid, char *info, char *umodes, char *virthost); extern void sendto_message_one(aClient *to, aClient *from, char *sender, char *cmd, char *nick, char *msg); diff --git a/include/struct.h b/include/struct.h index 6a5e4795f..e685bd4ca 100644 --- a/include/struct.h +++ b/include/struct.h @@ -802,7 +802,15 @@ struct User { Link *silence; /* chain of silence pointer blocks */ Link *dccallow; /* chain of dccallowed entries */ char *away; /* pointer to away message */ - u_int32_t servicestamp; /* Services' time stamp variable */ + + /* + * svid: a value that is assigned by services to this user record. + * in previous versions of Unreal, this was strictly a timestamp value, + * which is less useful in the modern world of IRC where nicks are grouped to + * accounts, so it is now a string. + */ + char svid[NICKLEN + 1]; + signed char refcnt; /* Number of times this block is referenced */ unsigned short joined; /* number of channels joined */ char username[USERLEN + 1]; diff --git a/src/list.c b/src/list.c index e3e2d2f6d..f75e191d9 100644 --- a/src/list.c +++ b/src/list.c @@ -195,7 +195,7 @@ anUser *make_user(aClient *cptr) user->invited = NULL; user->silence = NULL; user->server = NULL; - user->servicestamp = 0; + strlcpy(user->svid, "*", sizeof(user->svid)); user->lopt = NULL; user->whowas = NULL; user->snomask = 0; diff --git a/src/modules/m_nick.c b/src/modules/m_nick.c index d3cf500ea..9667873b2 100644 --- a/src/modules/m_nick.c +++ b/src/modules/m_nick.c @@ -1170,7 +1170,7 @@ int _register_user(aClient *cptr, aClient *sptr, char *nick, char *username, cha /* NICKv2 Servers ! */ sendto_serv_butone_nickcmd(cptr, sptr, nick, sptr->hopcount + 1, sptr->lastnick, user->username, user->realhost, - user->server, user->servicestamp, sptr->info, + user->server, user->svid, sptr->info, (!buf || *buf == '\0' ? "+" : buf), sptr->umodes & UMODE_SETHOST ? sptr->user->virthost : NULL); diff --git a/src/modules/m_server.c b/src/modules/m_server.c index 34a510c6c..2facb0aa1 100644 --- a/src/modules/m_server.c +++ b/src/modules/m_server.c @@ -886,13 +886,13 @@ int m_server_synch(aClient *cptr, long numeric, ConfigItem_link *aconf) if (!SupportNICKv2(cptr)) { sendto_one(cptr, - "%s %s %d %ld %s %s %s %lu :%s", + "%s %s %d %ld %s %s %s %s :%s", (IsToken(cptr) ? TOK_NICK : MSG_NICK), acptr->name, acptr->hopcount + 1, acptr->lastnick, acptr->user->username, acptr->user->realhost, acptr->user->server, - (unsigned long)acptr->user->servicestamp, acptr->info); + acptr->user->svid, acptr->info); send_umode(cptr, acptr, 0, SEND_UMODES, buf); if (IsHidden(acptr) && acptr->user->virthost) sendto_one(cptr, ":%s %s %s", @@ -912,9 +912,9 @@ int m_server_synch(aClient *cptr, long numeric, ConfigItem_link *aconf) { sendto_one(cptr, ((cptr->proto & PROTO_SJB64) ? - "%s %s %d %B %s %s %b %lu %s %s %s%s%s%s:%s" + "%s %s %d %B %s %s %b %s %s %s %s%s%s%s:%s" : - "%s %s %d %lu %s %s %b %lu %s %s %s%s%s%s:%s"), + "%s %s %d %lu %s %s %b %s %s %s %s%s%s%s:%s"), (IsToken(cptr) ? TOK_NICK : MSG_NICK), acptr->name, acptr->hopcount + 1, @@ -922,7 +922,7 @@ int m_server_synch(aClient *cptr, long numeric, ConfigItem_link *aconf) acptr->user->username, acptr->user->realhost, (long)(acptr->srvptr->serv->numeric), - (unsigned long)acptr->user->servicestamp, + acptr->user->svid, (!buf || *buf == '\0' ? "+" : buf), ((IsHidden(acptr) && (acptr->umodes & UMODE_SETHOST)) ? acptr->user->virthost : "*"), SupportCLK(cptr) ? getcloak(acptr) : "", @@ -935,9 +935,9 @@ int m_server_synch(aClient *cptr, long numeric, ConfigItem_link *aconf) { sendto_one(cptr, (cptr->proto & PROTO_SJB64 ? - "%s %s %d %B %s %s %s %lu %s %s %s%s%s%s:%s" + "%s %s %d %B %s %s %s %s %s %s %s%s%s%s:%s" : - "%s %s %d %lu %s %s %s %lu %s %s %s%s%s%s:%s"), + "%s %s %d %lu %s %s %s %s %s %s %s%s%s%s:%s"), (IsToken(cptr) ? TOK_NICK : MSG_NICK), acptr->name, acptr->hopcount + 1, @@ -945,7 +945,7 @@ int m_server_synch(aClient *cptr, long numeric, ConfigItem_link *aconf) acptr->user->username, acptr->user->realhost, acptr->user->server, - (unsigned long)acptr->user->servicestamp, + acptr->user->svid, (!buf || *buf == '\0' ? "+" : buf), ((IsHidden(acptr) && (acptr->umodes & UMODE_SETHOST)) ? acptr->user->virthost : "*"), SupportCLK(cptr) ? getcloak(acptr) : "", @@ -957,7 +957,7 @@ int m_server_synch(aClient *cptr, long numeric, ConfigItem_link *aconf) } else sendto_one(cptr, - "%s %s %d %ld %s %s %s %lu %s %s %s%s:%s", + "%s %s %d %ld %s %s %s %s %s %s %s%s:%s", (IsToken(cptr) ? TOK_NICK : MSG_NICK), acptr->name, acptr->hopcount + 1, @@ -969,7 +969,7 @@ int m_server_synch(aClient *cptr, long numeric, ConfigItem_link *aconf) base64enc(acptr->srvptr-> serv->numeric) : acptr-> user->server) : acptr->user-> - server), (unsigned long)acptr->user->servicestamp, + server), acptr->user->svid, (!buf || *buf == '\0' ? "+" : buf), GetHost(acptr), diff --git a/src/modules/m_user.c b/src/modules/m_user.c index 6c9a33a79..da830fd1d 100644 --- a/src/modules/m_user.c +++ b/src/modules/m_user.c @@ -91,7 +91,7 @@ DLLFUNC CMD_FUNC(m_user) #define UFLAGS (UMODE_INVISIBLE|UMODE_WALLOP|UMODE_SERVNOTICE) char *username, *host, *server, *realname, *umodex = NULL, *virthost = NULL, *ip = NULL; - u_int32_t sstamp = 0; + char *sstamp = NULL; anUser *user; aClient *acptr; @@ -129,23 +129,20 @@ DLLFUNC CMD_FUNC(m_user) if (parc == 6 && IsServer(cptr)) { - if (isdigit(*parv[4])) - sstamp = strtoul(parv[4], NULL, 10); + sstamp = (BadPtr(parv[4])) ? "*" : parv[4]; realname = (BadPtr(parv[5])) ? "" : parv[5]; umodex = NULL; } else if (parc == 8 && IsServer(cptr)) { - if (isdigit(*parv[4])) - sstamp = strtoul(parv[4], NULL, 10); + sstamp = (BadPtr(parv[4])) ? "*" : parv[4]; realname = (BadPtr(parv[7])) ? "" : parv[7]; umodex = parv[5]; virthost = parv[6]; } else if (parc == 9 && IsServer(cptr)) { - if (isdigit(*parv[4])) - sstamp = strtoul(parv[4], NULL, 10); + sstamp = (BadPtr(parv[4])) ? "*" : parv[4]; realname = (BadPtr(parv[8])) ? "" : parv[8]; umodex = parv[5]; virthost = parv[6]; @@ -202,7 +199,9 @@ DLLFUNC CMD_FUNC(m_user) user->ip_str = strdup(Inet_ia2p(&sptr->ip)); user->server = me_hash; user_finish: - user->servicestamp = sstamp; + if (sstamp != NULL) + strlcpy(user->svid, sstamp, sizeof(user->svid)); + strlcpy(sptr->info, realname, sizeof(sptr->info)); if (sptr->name[0] && (IsServer(cptr) ? 1 : IsNotSpoof(sptr))) /* NICK and no-spoof already received, now we have USER... */ diff --git a/src/s_serv.c b/src/s_serv.c index 29886e56b..60624a46d 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -226,12 +226,14 @@ char *num = NULL; * send_proto: * sends PROTOCTL message to server, taking care of whether ZIP * should be enabled or not. + * + * ESVID added to denote support of extended SVID values. --nenolod */ void send_proto(aClient *cptr, ConfigItem_link *aconf) { char buf[1024]; - sprintf(buf, "CHANMODES=%s%s,%s%s,%s%s,%s%s NICKCHARS=%s", + sprintf(buf, "CHANMODES=%s%s,%s%s,%s%s,%s%s NICKCHARS=%s ESVID", CHPAR1, EXPAR1, CHPAR2, EXPAR2, CHPAR3, EXPAR3, CHPAR4, EXPAR4, langsinuse); #ifdef ZIP_LINKS if (aconf->options & CONNECT_ZIP) diff --git a/src/send.c b/src/send.c index f96db432f..6272aada8 100644 --- a/src/send.c +++ b/src/send.c @@ -1950,7 +1950,7 @@ void sendto_fconnectnotice(char *nick, anUser *user, aClient *sptr, int disconne void sendto_serv_butone_nickcmd(aClient *one, aClient *sptr, char *nick, int hopcount, long lastnick, char *username, char *realhost, char *server, - long servicestamp, char *info, char *umodes, char *virthost) + char *svid, char *info, char *umodes, char *virthost) { int i; aClient *cptr; @@ -1992,14 +1992,14 @@ void sendto_serv_butone_nickcmd(aClient *one, aClient *sptr, sendto_one(cptr, (cptr->proto & PROTO_SJB64) ? /* Ugly double %s to prevent excessive spaces */ - "%s %s %d %B %s %s %b %lu %s %s %s%s%s%s:%s" + "%s %s %d %B %s %s %b %s %s %s %s%s%s%s:%s" : - "%s %s %d %lu %s %s %b %lu %s %s %s%s%s%s:%s" + "%s %s %d %lu %s %s %b %s %s %s %s%s%s%s:%s" , (IsToken(cptr) ? TOK_NICK : MSG_NICK), nick, hopcount, (long)lastnick, username, realhost, (long)(sptr->srvptr->serv->numeric), - servicestamp, umodes, vhost, + svid, umodes, vhost, SupportCLK(cptr) ? getcloak(sptr) : "", SupportCLK(cptr) ? " " : "", SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "", @@ -2007,11 +2007,11 @@ void sendto_serv_butone_nickcmd(aClient *one, aClient *sptr, info); else sendto_one(cptr, - "%s %s %d %d %s %s %s %lu %s %s %s%s%s%s:%s", + "%s %s %d %d %s %s %s %s %s %s %s%s%s%s:%s", (IsToken(cptr) ? TOK_NICK : MSG_NICK), nick, hopcount, lastnick, username, realhost, SupportNS(cptr) && sptr->srvptr->serv->numeric ? base64enc(sptr->srvptr->serv->numeric) : server, - servicestamp, umodes, vhost, + svid, umodes, vhost, SupportCLK(cptr) ? getcloak(sptr) : "", SupportCLK(cptr) ? " " : "", SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "", @@ -2021,11 +2021,11 @@ void sendto_serv_butone_nickcmd(aClient *one, aClient *sptr, } else { - sendto_one(cptr, "%s %s %d %d %s %s %s %lu :%s", + sendto_one(cptr, "%s %s %d %d %s %s %s %s :%s", (IsToken(cptr) ? TOK_NICK : MSG_NICK), nick, hopcount, lastnick, username, realhost, - server, servicestamp, info); + server, svid, info); if (strcmp(umodes, "+")) { sendto_one(cptr, ":%s %s %s :%s", @@ -2081,14 +2081,14 @@ void sendto_one_nickcmd(aClient *cptr, aClient *sptr, char *umodes) sendto_one(cptr, (cptr->proto & PROTO_SJB64) ? /* Ugly double %s to prevent excessive spaces */ - "%s %s %d %B %s %s %b %lu %s %s %s%s:%s" + "%s %s %d %B %s %s %b %s %s %s %s%s:%s" : - "%s %s %d %lu %s %s %b %lu %s %s %s%s:%s" + "%s %s %d %lu %s %s %b %s %s %s %s%s:%s" , (IsToken(cptr) ? TOK_NICK : MSG_NICK), sptr->name, sptr->hopcount+1, (long)sptr->lastnick, sptr->user->username, sptr->user->realhost, (long)(sptr->srvptr->serv->numeric), - sptr->user->servicestamp, umodes, vhost, + sptr->user->svid, umodes, vhost, SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "", SupportNICKIP(cptr) ? " " : "", sptr->info); else @@ -2098,16 +2098,16 @@ void sendto_one_nickcmd(aClient *cptr, aClient *sptr, char *umodes) sptr->hopcount+1, sptr->lastnick, sptr->user->username, sptr->user->realhost, SupportNS(cptr) && sptr->srvptr->serv->numeric ? base64enc(sptr->srvptr->serv->numeric) - : sptr->user->server, sptr->user->servicestamp, umodes, vhost, + : sptr->user->server, sptr->user->svid, umodes, vhost, SupportNICKIP(cptr) ? encode_ip(sptr->user->ip_str) : "", SupportNICKIP(cptr) ? " " : "", sptr->info); } else { - sendto_one(cptr, "%s %s %d %d %s %s %s %lu :%s", + sendto_one(cptr, "%s %s %d %d %s %s %s %s :%s", (IsToken(cptr) ? TOK_NICK : MSG_NICK), sptr->name, sptr->hopcount+1, sptr->lastnick, sptr->user->username, - sptr->user->realhost, sptr->user->server, sptr->user->servicestamp, + sptr->user->realhost, sptr->user->server, sptr->user->svid, sptr->info); if (strcmp(umodes, "+")) {