X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fngircd%2Fclient.c;h=7e28e8fb1035006d540e9f3e4b7ba7d720944662;hb=391aa8d1f714d5dc2fc1b47ec466082169ef2177;hp=f73a2d1ef0b46242bbeed67a8f0a64608b46ab34;hpb=575485eb82698a926d38634be2b3e4dce4a5dfd6;p=ngircd-alex.git diff --git a/src/ngircd/client.c b/src/ngircd/client.c index f73a2d1e..7e28e8fb 100644 --- a/src/ngircd/client.c +++ b/src/ngircd/client.c @@ -7,16 +7,17 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. - * - * Client management. */ - #define __client_c__ - #include "portab.h" +/** + * @file + * Client management. + */ + #include "imp.h" #include #include @@ -43,10 +44,8 @@ #include - #define GETID_LEN (CLIENT_NICK_LEN-1) + 1 + (CLIENT_USER_LEN-1) + 1 + (CLIENT_HOST_LEN-1) + 1 - static CLIENT *This_Server, *My_Clients; static WHOWAS My_Whowas[MAX_WHOWAS]; @@ -93,7 +92,7 @@ Client_Init( void ) This_Server->hops = 0; gethostname( This_Server->host, CLIENT_HOST_LEN ); - if (!Conf_NoDNS) { + if (Conf_DNS) { h = gethostbyname( This_Server->host ); if (h) strlcpy(This_Server->host, h->h_name, sizeof(This_Server->host)); } @@ -187,7 +186,6 @@ Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer, assert(Idx >= NONE); assert(Introducer != NULL); - assert(Hostname != NULL); client = New_Client_Struct(); if (!client) @@ -314,13 +312,30 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen } /* Client_Destroy */ +/** + * Set client hostname. + * + * If global hostname cloaking is in effect, don't set the real hostname + * but the configured one. + * + * @param Client The client of which the hostname should be set. + * @param Hostname The new hostname. + */ GLOBAL void Client_SetHostname( CLIENT *Client, const char *Hostname ) { - assert( Client != NULL ); - assert( Hostname != NULL ); + assert(Client != NULL); + assert(Hostname != NULL); - strlcpy( Client->host, Hostname, sizeof( Client->host )); + if (strlen(Conf_CloakHost)) { + LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"", + Client_ID(Client), Client->host, Conf_CloakHost); + strlcpy(Client->host, Conf_CloakHost, sizeof(Client->host)); + } else { + LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"", + Client_ID(Client), Client->host, Hostname); + strlcpy(Client->host, Hostname, sizeof(Client->host)); + } } /* Client_SetHostname */ @@ -332,6 +347,11 @@ Client_SetID( CLIENT *Client, const char *ID ) strlcpy( Client->id, ID, sizeof( Client->id )); + if (Conf_CloakUserToNick) { + strlcpy( Client->user, ID, sizeof( Client->user )); + strlcpy( Client->info, ID, sizeof( Client->info )); + } + /* Hash */ Client->hash = Hash( Client->id ); } /* Client_SetID */ @@ -345,7 +365,9 @@ Client_SetUser( CLIENT *Client, const char *User, bool Idented ) assert( Client != NULL ); assert( User != NULL ); - if (Idented) { + if (Conf_CloakUserToNick) { + strlcpy(Client->user, Client->id, sizeof(Client->user)); + } else if (Idented) { strlcpy(Client->user, User, sizeof(Client->user)); } else { Client->user[0] = '~'; @@ -363,7 +385,8 @@ Client_SetUser( CLIENT *Client, const char *User, bool Idented ) * @param User User name to set. */ GLOBAL void -Client_SetOrigUser(CLIENT UNUSED *Client, const char UNUSED *User) { +Client_SetOrigUser(CLIENT UNUSED *Client, const char UNUSED *User) +{ assert(Client != NULL); assert(User != NULL); @@ -381,7 +404,10 @@ Client_SetInfo( CLIENT *Client, const char *Info ) assert( Client != NULL ); assert( Info != NULL ); - strlcpy(Client->info, Info, sizeof(Client->info)); + if (Conf_CloakUserToNick) + strlcpy(Client->info, Client->id, sizeof(Client->info)); + else + strlcpy(Client->info, Info, sizeof(Client->info)); } /* Client_SetInfo */ @@ -552,17 +578,19 @@ Client_Search( const char *Nick ) } /* Client_Search */ +/** + * Get client structure ("introducer") identfied by a server token. + * @return CLIENT structure or NULL if none could be found. + */ GLOBAL CLIENT * Client_GetFromToken( CLIENT *Client, int Token ) { - /* Client-Struktur, die den entsprechenden Introducer (=Client) - * und das gegebene Token hat, liefern. Wird keine gefunden, - * so wird NULL geliefert. */ - CLIENT *c; assert( Client != NULL ); - assert( Token > 0 ); + + if (!Token) + return NULL; c = My_Clients; while (c) { @@ -752,7 +780,7 @@ Client_NextHop( CLIENT *Client ) * Return ID of a client: "client!user@host" * 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 erlier results! + * nest invocations without overwriting earlier results! * @param Client Pointer to client structure * @return Pointer to global buffer containing the client ID */ @@ -777,7 +805,7 @@ 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 erlier results! + * 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 @@ -831,23 +859,37 @@ Client_Away( CLIENT *Client ) } /* Client_Away */ +/** + * Make sure that a given nickname is valid. + * + * If the nickname is not valid for the given client, this function sends back + * the appropriate error messages. + * + * @param Client Client that wants to change the nickname. + * @param Nick New nick name. + * @returns true if nickname is valid, false otherwise. + */ GLOBAL bool -Client_CheckNick( CLIENT *Client, char *Nick ) +Client_CheckNick(CLIENT *Client, char *Nick) { - assert( Client != NULL ); - assert( Nick != NULL ); - - if (! Client_IsValidNick( Nick )) - { - IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick ); + assert(Client != NULL); + assert(Nick != NULL); + + if (!Client_IsValidNick(Nick)) { + if (strlen(Nick ) >= Conf_MaxNickLength) + IRC_WriteStrClient(Client, ERR_NICKNAMETOOLONG_MSG, + Client_ID(Client), Nick, + Conf_MaxNickLength - 1); + else + IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG, + Client_ID(Client), Nick); return false; } - /* Nick bereits vergeben? */ - if( Client_Search( Nick )) - { - /* den Nick gibt es bereits */ - IRC_WriteStrClient( Client, ERR_NICKNAMEINUSE_MSG, Client_ID( Client ), Nick ); + /* Nickname already registered? */ + if (Client_Search(Nick)) { + IRC_WriteStrClient(Client, ERR_NICKNAMEINUSE_MSG, + Client_ID(Client), Nick); return false; } @@ -1003,23 +1045,31 @@ Client_MyMaxUserCount( void ) } /* Client_MyMaxUserCount */ +/** + * Check that a given nickname is valid. + * + * @param Nick the nickname to check. + * @returns true if nickname is valid, false otherwise. + */ GLOBAL bool -Client_IsValidNick( const char *Nick ) +Client_IsValidNick(const char *Nick) { const char *ptr; static const char goodchars[] = ";0123456789-"; - assert( Nick != NULL ); + assert (Nick != NULL); - if( Nick[0] == '#' ) return false; - if( strchr( goodchars, Nick[0] )) return false; - if( strlen( Nick ) >= Conf_MaxNickLength) return false; + if (strchr(goodchars, Nick[0])) + return false; + if (strlen(Nick ) >= Conf_MaxNickLength) + return false; ptr = Nick; - while( *ptr ) - { - if (( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return false; - if ( *ptr > '}' ) return false; + while (*ptr) { + if (*ptr < 'A' && !strchr(goodchars, *ptr )) + return false; + if (*ptr > '}') + return false; ptr++; } @@ -1059,6 +1109,39 @@ Client_StartTime(CLIENT *Client) } /* Client_Uptime */ +/** + * Reject a client when logging in. + * + * This function is called when a client isn't allowed to connect to this + * server. Possible reasons are bad server password, bad PAM password, + * or that the client is G/K-Line'd. + * + * After calling this function, the client isn't connected any more. + * + * @param Client The client to reject. + * @param Reason The reason why the client has been rejected. + * @param InformClient If true, send the exact reason to the client. + */ +GLOBAL void +Client_Reject(CLIENT *Client, const char *Reason, bool InformClient) +{ + char info[COMMAND_LEN]; + + assert(Client != NULL); + assert(Reason != NULL); + + if (InformClient) + snprintf(info, sizeof(info), "Access denied: %s", Reason); + else + strcpy(info, "Access denied: Bad password?"); + + Log(LOG_ERR, + "User \"%s\" rejected (connection %d): %s!", + Client_Mask(Client), Client_Conn(Client), Reason); + Conn_Close(Client_Conn(Client), Reason, info, true); +} + + static unsigned long Count( CLIENT_TYPE Type ) { @@ -1176,6 +1259,10 @@ Client_RegisterWhowas( CLIENT *Client ) assert( Client != NULL ); + /* Don't register WHOWAS information when "MorePrivacy" is enabled. */ + if (Conf_MorePrivacy) + return; + now = time(NULL); /* Don't register clients that were connected less than 30 seconds. */ if( now - Client->starttime < 30 ) @@ -1274,4 +1361,26 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool } /* Destroy_UserOrService */ +#ifdef DEBUG + +GLOBAL void +Client_DebugDump(void) +{ + CLIENT *c; + + Log(LOG_DEBUG, "Client status:"); + c = My_Clients; + while (c) { + Log(LOG_DEBUG, + " - %s: type=%d, host=%s, user=%s, conn=%d, start=%ld, flags=%s", + Client_ID(c), Client_Type(c), Client_Hostname(c), + Client_User(c), Client_Conn(c), Client_StartTime(c), + Client_Flags(c)); + c = (CLIENT *)c->next; + } +} /* Client_DumpClients */ + +#endif + + /* -eof- */