X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fclient.c;h=37b168ff8d5dac07cb835b86eb37b366da6fcbe3;hp=0d2d4147345046b87f7f3c6e46fd018749f4da36;hb=a14eb495b75c8c2a2a32ddb6eecf50dc174f811c;hpb=55859c1befa7cd04a130f1816cb73a9629637105 diff --git a/src/ngircd/client.c b/src/ngircd/client.c index 0d2d4147..37b168ff 100644 --- a/src/ngircd/client.c +++ b/src/ngircd/client.c @@ -41,6 +41,7 @@ #include "hash.h" #include "irc-write.h" #include "log.h" +#include "match.h" #include "messages.h" #include @@ -239,9 +240,9 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen assert( Client != NULL ); - if( LogMsg ) txt = LogMsg; - else txt = FwdMsg; - if( ! txt ) txt = "Reason unknown."; + txt = LogMsg ? LogMsg : FwdMsg; + if (!txt) + txt = "Reason unknown"; /* netsplit message */ if( Client->type == CLIENT_SERVER ) { @@ -281,10 +282,15 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen Destroy_UserOrService(c, txt, FwdMsg, SendQuit); else if( c->type == CLIENT_SERVER ) { - if( c != This_Server ) - { - if( c->conn_id != NONE ) Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt ); - else Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered: %s", c->id, txt ); + if (c != This_Server) { + if (c->conn_id != NONE) + Log(LOG_NOTICE|LOG_snotice, + "Server \"%s\" unregistered (connection %d): %s.", + c->id, c->conn_id, txt); + else + Log(LOG_NOTICE|LOG_snotice, + "Server \"%s\" unregistered: %s.", + c->id, txt); } /* inform other servers */ @@ -296,13 +302,19 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen } else { - if( c->conn_id != NONE ) - { - if( c->id[0] ) Log( LOG_NOTICE, "Client \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt ); - else Log( LOG_NOTICE, "Client unregistered (connection %d): %s", c->conn_id, txt ); + if (c->conn_id != NONE) { + if (c->id[0]) + Log(LOG_NOTICE, + "Client \"%s\" unregistered (connection %d): %s.", + c->id, c->conn_id, txt); + else + Log(LOG_NOTICE, + "Client unregistered (connection %d): %s.", + c->conn_id, txt); } else { - Log(LOG_WARNING, "Unregistered unknown client \"%s\": %s", - c->id[0] ? c->id : "(No Nick)", txt ); + Log(LOG_WARNING, + "Unregistered unknown client \"%s\": %s", + c->id[0] ? c->id : "(No Nick)", txt); } } @@ -545,13 +557,14 @@ Client_ModeDel( CLIENT *Client, char Mode ) } /* Client_ModeDel */ +/** + * Search CLIENT structure of a given nick name. + * + * @return Pointer to CLIENT structure or NULL if not found. + */ GLOBAL CLIENT * Client_Search( const char *Nick ) { - /* return Client-Structure that has the corresponding Nick. - * If none is found, return NULL. - */ - char search_id[CLIENT_ID_LEN], *ptr; CLIENT *c = NULL; UINT32 search_hash; @@ -572,7 +585,39 @@ Client_Search( const char *Nick ) c = (CLIENT *)c->next; } return NULL; -} /* Client_Search */ +} + + +/** + * Serach first CLIENT structure matching a given mask of a server. + * + * The order of servers is arbitrary, but this function makes sure that the + * local server is always returned if the mask matches it. + * + * @return Pointer to CLIENT structure or NULL if no server could be found. + */ +GLOBAL CLIENT * +Client_SearchServer(const char *Mask) +{ + CLIENT *c; + + assert(Mask != NULL); + + /* First check if mask matches the local server */ + if (MatchCaseInsensitive(Mask, Client_ID(Client_ThisServer()))) + return Client_ThisServer(); + + c = My_Clients; + while (c) { + if (Client_Type(c) == CLIENT_SERVER) { + /* This is a server: check if Mask matches */ + if (MatchCaseInsensitive(Mask, c->id)) + return c; + } + c = (CLIENT *)c->next; + } + return NULL; +} /** @@ -671,7 +716,6 @@ Client_OrigUser(CLIENT *Client) { #endif - /** * Return the hostname of a client. * @param Client Pointer to client structure @@ -682,25 +726,88 @@ Client_Hostname(CLIENT *Client) { assert (Client != NULL); return Client->host; -} /* Client_Hostname */ +} +/** + * Return the cloaked hostname of a client, if set. + * @param Client Pointer to the client structure. + * @return Pointer to the cloaked hostname or NULL if not set. + */ +GLOBAL char * +Client_HostnameCloaked(CLIENT *Client) +{ + assert(Client != NULL); + return Client->cloaked; +} /** - * Get potentially cloaked hostname of a client. + * Get (potentially cloaked) hostname of a client to display it to other users. + * * If the client has not enabled cloaking, the real hostname is used. + * Please note that this function uses a global static buffer, so you can't + * nest invocations without overwriting earlier results! + * * @param Client Pointer to client structure * @return Pointer to client hostname */ GLOBAL char * -Client_HostnameCloaked(CLIENT *Client) +Client_HostnameDisplayed(CLIENT *Client) { assert(Client != NULL); - if (Client_HasMode(Client, 'x')) - return Client_ID(Client->introducer); - else + + /* Client isn't cloaked at all, return real hostname: */ + if (!Client_HasMode(Client, 'x')) return Client_Hostname(Client); -} /* Client_HostnameCloaked */ + /* Use an already saved cloaked hostname, if there is one */ + if (Client->cloaked[0]) + return Client->cloaked; + + Client_UpdateCloakedHostname(Client, NULL, NULL); + return Client->cloaked; +} + +/** + * Update (and generate, if necessary) the cloaked hostname of a client. + * + * The newly set cloaked hostname is announced in the network using METADATA + * commands to peers that support this feature. + * + * @param Client The client of which the cloaked hostname should be updated. + * @param Origin The originator of the hostname change, or NULL if this server. + * @param Hostname The new cloaked hostname, or NULL if it should be generated. + */ +GLOBAL void +Client_UpdateCloakedHostname(CLIENT *Client, CLIENT *Origin, + const char *Hostname) +{ + static char Cloak_Buffer[CLIENT_HOST_LEN]; + + assert(Client != NULL); + if (!Origin) + Origin = Client_ThisServer(); + + if (!Hostname) { + /* Generate new cloaked hostname */ + if (*Conf_CloakHostModeX) { + strlcpy(Cloak_Buffer, Client->host, CLIENT_HOST_LEN); + strlcat(Cloak_Buffer, Conf_CloakHostSalt, + CLIENT_HOST_LEN); + snprintf(Client->cloaked, sizeof(Client->cloaked), + Conf_CloakHostModeX, Hash(Cloak_Buffer)); + } else + strlcpy(Client->cloaked, Client_ID(Client->introducer), + sizeof(Client->cloaked)); + } else + strlcpy(Client->cloaked, Hostname, sizeof(Client->cloaked)); + LogDebug("Cloaked hostname of \"%s\" updated to \"%s\"", + Client_ID(Client), Client->cloaked); + + /* Inform other servers in the network */ + IRC_WriteStrServersPrefixFlag(Client_NextHop(Origin), Origin, 'M', + "METADATA %s cloakhost :%s", + Client_ID(Client), Client->cloaked); +} GLOBAL char * Client_Modes( CLIENT *Client ) @@ -792,10 +899,12 @@ Client_Mask( CLIENT *Client ) /** * Return ID of a client with cloaked hostname: "client!user@server-name" + * * This client ID is used for IRC prefixes, for example. * Please note that this function uses a global static buffer, so you can't * nest invocations without overwriting earlier results! * If the client has not enabled cloaking, the real hostname is used. + * * @param Client Pointer to client structure * @return Pointer to global buffer containing the client ID */ @@ -803,7 +912,6 @@ GLOBAL char * Client_MaskCloaked(CLIENT *Client) { static char Mask_Buffer[GETID_LEN]; - char Cloak_Buffer[GETID_LEN]; assert (Client != NULL); @@ -811,16 +919,8 @@ Client_MaskCloaked(CLIENT *Client) if (!Client_HasMode(Client, 'x')) return Client_Mask(Client); - if(*Conf_CloakHostModeX) { - strlcpy(Cloak_Buffer, Client->host, GETID_LEN); - strlcat(Cloak_Buffer, Conf_CloakHostSalt, GETID_LEN); - snprintf(Cloak_Buffer, GETID_LEN, Conf_CloakHostModeX, Hash(Cloak_Buffer)); - } else { - strncpy(Cloak_Buffer, Client_ID(Client->introducer), GETID_LEN); - } - - snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", - Client->id, Client->user, Cloak_Buffer); + snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user, + Client_HostnameDisplayed(Client)); return Mask_Buffer; } /* Client_MaskCloaked */ @@ -865,7 +965,7 @@ Client_Away( CLIENT *Client ) * the appropriate error messages. * * @param Client Client that wants to change the nickname. - * @param Nick New nick name. + * @param Nick New nickname. * @returns true if nickname is valid, false otherwise. */ GLOBAL bool @@ -887,7 +987,7 @@ Client_CheckNick(CLIENT *Client, char *Nick) if (Client_Type(Client) != CLIENT_SERVER && Client_Type(Client) != CLIENT_SERVICE) { - /* Make sure that this isn't a restricted/forbidden nick name */ + /* Make sure that this isn't a restricted/forbidden nickname */ if (Conf_NickIsBlocked(Nick)) { IRC_WriteStrClient(Client, ERR_FORBIDDENNICKNAME_MSG, Client_ID(Client), Nick); @@ -1329,7 +1429,7 @@ Client_RegisterWhowas( CLIENT *Client ) sizeof( My_Whowas[slot].id )); strlcpy( My_Whowas[slot].user, Client_User( Client ), sizeof( My_Whowas[slot].user )); - strlcpy( My_Whowas[slot].host, Client_HostnameCloaked( Client ), + strlcpy( My_Whowas[slot].host, Client_HostnameDisplayed( Client ), sizeof( My_Whowas[slot].host )); strlcpy( My_Whowas[slot].info, Client_Info( Client ), sizeof( My_Whowas[slot].info )); @@ -1369,7 +1469,7 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool if(Client->conn_id != NONE) { /* Local (directly connected) client */ Log(LOG_NOTICE, - "%s \"%s\" unregistered (connection %d): %s", + "%s \"%s\" unregistered (connection %d): %s.", Client_TypeText(Client), Client_Mask(Client), Client->conn_id, Txt); Log_ServerNotice('c', "Client exiting: %s (%s@%s) [%s]", @@ -1387,7 +1487,7 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool } } else { /* Remote client */ - LogDebug("%s \"%s\" unregistered: %s", + LogDebug("%s \"%s\" unregistered: %s.", Client_TypeText(Client), Client_Mask(Client), Txt); if(SendQuit) {