commit 3af0ece2bcf550cccd7b647c111ce503c2faa459 from: Federico G. Schwindt date: Sun Aug 25 04:24:08 2013 UTC Implement account login support This is done via the `accountname' METADATA command and used to automatically identify users after netsplits or across service restarts. commit - a9ffbdea3f3e245326eaa4242f97803b6edad522 commit + 3af0ece2bcf550cccd7b647c111ce503c2faa459 blob - 59fa617afaaa91f0f0b6b6338785e11c4c240bf8 blob + ae290dd1d86f09d8f1ea971a0730ab7f7152e214 --- doc/Protocol.txt +++ doc/Protocol.txt @@ -224,6 +224,7 @@ new server link", "M"), even if it doesn' The following 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 blob - cf0720b9942e81631a84fc0900fb259903b8ac99 blob + 32690288529499097c0b6d88c1127774202f51bd --- src/ngircd/client.c +++ src/ngircd/client.c @@ -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, co } } + if (c->account_name) + free(c->account_name); if (c->cloaked) free(c->cloaked); free( c ); @@ -455,6 +459,21 @@ Client_SetFlags( CLIENT *Client, const char *Flags ) 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 ) { /* Set AWAY reason of client */ @@ -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, CLIE 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", blob - 6d5298fc174453af18cc59381b5c6926ed94b37b blob + 702f114cf0f484d773f6d237d81a2152cbbb03f5 --- src/ngircd/client.h +++ src/ngircd/client.h @@ -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, c 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 )); blob - 9a1398acd1de9503aae26ea5923793bd8f290154 blob + b52512ab92afe5d08a47ff16777f04f774bb3b0a --- src/ngircd/irc-metadata.c +++ src/ngircd/irc-metadata.c @@ -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