Implement account login support
authorFederico G. Schwindt <fgsch@lodoss.net>
Thu, 22 Aug 2013 13:40:30 +0000 (14:40 +0100)
committerFederico G. Schwindt <fgsch@lodoss.net>
Sun, 25 Aug 2013 04:24:08 +0000 (05:24 +0100)
This is done via the `accountname' METADATA command and used to
automatically identify users after netsplits or across service
restarts.

doc/Protocol.txt
src/ngircd/client.c
src/ngircd/client.h
src/ngircd/irc-metadata.c

index 59fa617afaaa91f0f0b6b6338785e11c4c240bf8..ae290dd1d86f09d8f1ea971a0730ab7f7152e214 100644 (file)
@@ -224,6 +224,7 @@ new server link", <serverflag> "M"), even if it doesn't support the given
 
 The following <key> names are defined:
 
+ - "accountname": the account name of a client (can't be empty)
  - "host": the hostname of a client (can't be empty)
  - "cloakhost": the cloaked hostname of a client
  - "info": info text ("real name") of a client
index cf0720b9942e81631a84fc0900fb259903b8ac99..32690288529499097c0b6d88c1127774202f51bd 100644 (file)
@@ -124,6 +124,8 @@ Client_Exit( void )
        {
                cnt++;
                next = (CLIENT *)c->next;
+               if (c->account_name)
+                       free(c->account_name);
                free( c );
                c = next;
        }
@@ -318,6 +320,8 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
                                }
                        }
 
+                       if (c->account_name)
+                               free(c->account_name);
                        if (c->cloaked)
                                free(c->cloaked);
                        free( c );
@@ -454,6 +458,21 @@ Client_SetFlags( CLIENT *Client, const char *Flags )
 } /* Client_SetFlags */
 
 
+GLOBAL void
+Client_SetAccountName(CLIENT *Client, const char *AccountName)
+{
+       assert(Client != NULL);
+
+       if (Client->account_name)
+               free(Client->account_name);
+
+       if (*AccountName)
+               Client->account_name = strdup(AccountName);
+       else
+               Client->account_name = NULL;
+}
+
+
 GLOBAL void
 Client_SetAway( CLIENT *Client, const char *Txt )
 {
@@ -973,6 +992,14 @@ Client_Away( CLIENT *Client )
 } /* Client_Away */
 
 
+GLOBAL char *
+Client_AccountName(CLIENT *Client)
+{
+       assert(Client != NULL);
+       return Client->account_name;
+}
+
+
 /**
  * Make sure that a given nickname is valid.
  *
@@ -1611,6 +1638,14 @@ Client_Announce(CLIENT * Client, CLIENT * Prefix, CLIENT * User)
                                return DISCONNECTED;
                }
 
+               if (Client_AccountName(User)) {
+                       if (!IRC_WriteStrClientPrefix(Client, Prefix,
+                                       "METADATA %s accountname :%s",
+                                       Client_ID(User),
+                                       Client_AccountName(User)))
+                               return DISCONNECTED;
+               }
+
                if (Conn_GetCertFp(Client_Conn(User))) {
                        if (!IRC_WriteStrClientPrefix(Client, Prefix,
                                        "METADATA %s certfp :%s",
index 6d5298fc174453af18cc59381b5c6926ed94b37b..702f114cf0f484d773f6d237d81a2152cbbb03f5 100644 (file)
@@ -59,6 +59,7 @@ typedef struct _CLIENT
        bool oper_by_me;                /* client is local IRC operator on this server? */
        char away[CLIENT_AWAY_LEN];     /* AWAY text (valid if mode 'a' is set) */
        char flags[CLIENT_FLAGS_LEN];   /* flags of the client */
+       char *account_name;             /* login account (for services) */
        int capabilities;               /* enabled IRC capabilities */
 } CLIENT;
 
@@ -123,6 +124,7 @@ GLOBAL int Client_MyToken PARAMS(( CLIENT *Client ));
 GLOBAL CLIENT *Client_TopServer PARAMS(( CLIENT *Client ));
 GLOBAL CLIENT *Client_NextHop PARAMS(( CLIENT *Client ));
 GLOBAL char *Client_Away PARAMS(( CLIENT *Client ));
+GLOBAL char *Client_AccountName PARAMS((CLIENT *Client));
 GLOBAL time_t Client_StartTime PARAMS(( CLIENT *Client ));
 
 GLOBAL bool Client_HasMode PARAMS(( CLIENT *Client, char Mode ));
@@ -141,6 +143,7 @@ GLOBAL void Client_SetModes PARAMS(( CLIENT *Client, const char *Modes ));
 GLOBAL void Client_SetFlags PARAMS(( CLIENT *Client, const char *Flags ));
 GLOBAL void Client_SetIntroducer PARAMS(( CLIENT *Client, CLIENT *Introducer ));
 GLOBAL void Client_SetAway PARAMS(( CLIENT *Client, const char *Txt ));
+GLOBAL void Client_SetAccountName PARAMS((CLIENT *Client, const char *AccountName));
 
 GLOBAL bool Client_ModeAdd PARAMS(( CLIENT *Client, char Mode ));
 GLOBAL bool Client_ModeDel PARAMS(( CLIENT *Client, char Mode ));
index 9a1398acd1de9503aae26ea5923793bd8f290154..b52512ab92afe5d08a47ff16777f04f774bb3b0a 100644 (file)
@@ -96,6 +96,8 @@ IRC_METADATA(CLIENT *Client, REQUEST *Req)
                Client_SetInfo(target, Req->argv[2]);
        else if (*Req->argv[2] && strcasecmp(Req->argv[1], "user") == 0)
                Client_SetUser(target, Req->argv[2], true);
+       else if (strcasecmp(Req->argv[1], "accountname") == 0)
+               Client_SetAccountName(target, Req->argv[2]);
        else if (*Req->argv[2] && strcasecmp(Req->argv[1], "certfp") == 0)
                Conn_SetCertFp(Client_Conn(target), Req->argv[2]);
        else