X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Firc-login.c;h=c7ff831da06740d24e94733407f45e0727111d80;hp=9d1c96df2041281fd9f91eecc21c5a26744ce2cf;hb=ff98833136dbd3dec403b8bf586a1a167943236a;hpb=50ec7a56a4e75dad25b20fdb904545143ac19ff3 diff --git a/src/ngircd/irc-login.c b/src/ngircd/irc-login.c index 9d1c96df..c7ff831d 100644 --- a/src/ngircd/irc-login.c +++ b/src/ngircd/irc-login.c @@ -2,65 +2,49 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * 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. * - * $Id: irc-login.c,v 1.6 2002/03/11 22:04:10 alex Exp $ - * - * irc-login.c: Anmeldung und Abmeldung im IRC - * - * $Log: irc-login.c,v $ - * Revision 1.6 2002/03/11 22:04:10 alex - * - Client_Destroy() hat neuen Paramter: QUITs fuer Clients verschicken? - * - * Revision 1.5 2002/03/11 17:33:40 alex - * - Log-Level von SQUIT und QUIT bei unbekannten Clients auf DEBUG herabgesetzt. - * - * Revision 1.4 2002/03/10 22:40:22 alex - * - IRC_PING() ist, wenn nicht im "strict RFC"-Mode, toleranter und akzptiert - * beliebig viele Parameter: z.B. BitchX sendet soetwas. - * - * Revision 1.3 2002/03/03 17:15:11 alex - * - Source in weitere Module fuer IRC-Befehle aufgesplitted. - * - * Revision 1.2 2002/03/02 00:49:11 alex - * - Bei der USER-Registrierung wird NICK nicht mehr sofort geforwarded, - * sondern erst dann, wenn auch ein gueltiges USER empfangen wurde. - * - * Revision 1.1 2002/02/27 23:26:21 alex - * - Modul aus irc.c bzw. irc.h ausgegliedert. + * Login and logout */ -#include -#include "global.h" +#include "portab.h" -#include +static char UNUSED id[] = "$Id: irc-login.c,v 1.33 2003/01/08 22:28:12 alex Exp $"; + +#include "imp.h" #include #include #include #include #include "ngircd.h" +#include "resolve.h" +#include "conn-func.h" #include "conf.h" -#include "irc.h" -#include "irc-write.h" +#include "client.h" +#include "channel.h" #include "log.h" #include "messages.h" +#include "parse.h" +#include "irc.h" +#include "irc-info.h" +#include "irc-write.h" -#include +#include "exp.h" #include "irc-login.h" -LOCAL BOOLEAN Hello_User( CLIENT *Client ); -LOCAL VOID Kill_Nick( CHAR *Nick, CHAR *Reason ); +LOCAL BOOLEAN Hello_User PARAMS(( CLIENT *Client )); +LOCAL VOID Kill_Nick PARAMS(( CHAR *Nick, CHAR *Reason )); -GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req ) +GLOBAL BOOLEAN +IRC_PASS( CLIENT *Client, REQUEST *Req ) { assert( Client != NULL ); assert( Req != NULL ); @@ -81,13 +65,71 @@ GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req ) } else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 ))) { + CHAR c2, c4, *type, *impl, *serverver, *flags, *ptr, *ircflags; + INT protohigh, protolow; + /* noch nicht registrierte Server-Verbindung */ Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client )); /* Passwort speichern */ Client_SetPassword( Client, Req->argv[0] ); + /* Protokollversion ermitteln */ + if( strlen( Req->argv[1] ) >= 4 ) + { + c2 = Req->argv[1][2]; + c4 = Req->argv[1][4]; + + Req->argv[1][4] = '\0'; + protolow = atoi( &Req->argv[1][2] ); + Req->argv[1][2] = '\0'; + protohigh = atoi( Req->argv[1] ); + + Req->argv[1][2] = c2; + Req->argv[1][4] = c4; + } + else protohigh = protolow = 0; + + /* Protokoll-Typ */ + if( strlen( Req->argv[1] ) > 4 ) type = &Req->argv[1][4]; + else type = NULL; + + /* IRC-Flags (nach RFC 2813) */ + if( Req->argc >= 4 ) ircflags = Req->argv[3]; + else ircflags = ""; + + /* Implementation, Version und ngIRCd-Flags */ + impl = Req->argv[2]; + ptr = strchr( impl, '|' ); + if( ptr ) *ptr = '\0'; + + if( type && ( strcmp( type, PROTOIRCPLUS ) == 0 )) + { + /* auf der anderen Seite laeuft ein Server, der + * ebenfalls das IRC+-Protokoll versteht */ + serverver = ptr + 1; + flags = strchr( serverver, ':' ); + if( flags ) + { + *flags = '\0'; + flags++; + } + else flags = ""; + Log( LOG_INFO, "Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", impl, serverver, protohigh, protolow, flags ); + } + else + { + /* auf der anderen Seite laeuft ein Server, der + * nur das Originalprotokoll unterstuetzt */ + serverver = ""; + if( strchr( ircflags, 'Z' )) flags = "Z"; + else flags = ""; + Log( LOG_INFO, "Peer announces itself as \"%s\" using protocol %d.%d (flags: \"%s\").", impl, protohigh, protolow, flags ); + } + Client_SetType( Client, CLIENT_GOTPASSSERVER ); + Client_SetFlags( Client, flags ); + return CONNECTED; } else if(( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) @@ -99,7 +141,8 @@ GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req ) } /* IRC_PASS */ -GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req ) +GLOBAL BOOLEAN +IRC_NICK( CLIENT *Client, REQUEST *Req ) { CLIENT *intr_c, *target, *c; CHAR *modes; @@ -122,7 +165,7 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req ) /* "Ziel-Client" ermitteln */ if( Client_Type( Client ) == CLIENT_SERVER ) { - target = Client_GetFromID( Req->prefix ); + target = Client_Search( Req->prefix ); if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] ); } else @@ -138,7 +181,7 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req ) * wenn wir es nicht so machen. Ob es so okay ist? Hm ... */ if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 ) return CONNECTED; #endif - + /* pruefen, ob Nick bereits vergeben. Speziallfall: der Client * will nur die Gross- und Kleinschreibung aendern. Das darf * er natuerlich machen :-) */ @@ -162,7 +205,16 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req ) else { /* Nick-Aenderung */ - Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] ); + if( Client_Conn( target ) > NONE ) + { + /* lokaler Client */ + Log( LOG_INFO, "User \"%s\" changed nick (connection %d): \"%s\" -> \"%s\".", Client_Mask( target ), Client_Conn( target ), Client_ID( target ), Req->argv[0] ); + } + else + { + /* Remote-Client */ + Log( LOG_DEBUG, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] ); + } /* alle betroffenen User und Server ueber Nick-Aenderung informieren */ if( Client_Type( Client ) == CLIENT_USER ) IRC_WriteStrClientPrefix( Client, Client, "NICK :%s", Req->argv[0] ); @@ -183,7 +235,7 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req ) if( Req->argc != 7 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); /* Nick ueberpruefen */ - c = Client_GetFromID( Req->argv[0] ); + c = Client_Search( Req->argv[0] ); if( c ) { /* Der neue Nick ist auf diesem Server bereits registriert: @@ -228,7 +280,8 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req ) } /* IRC_NICK */ -GLOBAL BOOLEAN IRC_USER( CLIENT *Client, REQUEST *Req ) +GLOBAL BOOLEAN +IRC_USER( CLIENT *Client, REQUEST *Req ) { assert( Client != NULL ); assert( Req != NULL ); @@ -258,26 +311,15 @@ GLOBAL BOOLEAN IRC_USER( CLIENT *Client, REQUEST *Req ) } /* IRC_USER */ -GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req ) +GLOBAL BOOLEAN +IRC_QUIT( CLIENT *Client, REQUEST *Req ) { CLIENT *target; assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) == CLIENT_USER ) || ( Client_Type( Client ) == CLIENT_SERVICE )) - { - /* User / Service */ - - /* Falsche Anzahl Parameter? */ - if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - if( Req->argc == 0 ) Conn_Close( Client_Conn( Client ), "Got QUIT command.", NULL, TRUE ); - else Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argv[0], TRUE ); - - return DISCONNECTED; - } - else if ( Client_Type( Client ) == CLIENT_SERVER ) + if ( Client_Type( Client ) == CLIENT_SERVER ) { /* Server */ @@ -288,7 +330,7 @@ GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req ) if( ! target ) { /* Den Client kennen wir nicht (mehr), also nichts zu tun. */ - Log( LOG_DEBUG, "Got QUIT from %s for unknown client!?", Client_ID( Client )); + Log( LOG_WARNING, "Got QUIT from %s for unknown client!?", Client_ID( Client )); return CONNECTED; } @@ -297,19 +339,29 @@ GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req ) return CONNECTED; } - else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); + else + { + /* User, Service, oder noch nicht registriert */ + + /* Falsche Anzahl Parameter? */ + if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); + + if( Req->argc == 0 ) Conn_Close( Client_Conn( Client ), "Got QUIT command.", NULL, TRUE ); + else Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argv[0], TRUE ); + + return DISCONNECTED; + } } /* IRC_QUIT */ -GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req ) +GLOBAL BOOLEAN +IRC_PING( CLIENT *Client, REQUEST *Req ) { CLIENT *target, *from; assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client )); #ifdef STRICT_RFC @@ -319,12 +371,12 @@ GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req ) if( Req->argc > 1 ) { /* es wurde ein Ziel-Client angegeben */ - target = Client_GetFromID( Req->argv[1] ); - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] ); + target = Client_Search( Req->argv[1] ); + if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] ); if( target != Client_ThisServer( )) { /* ok, forwarden */ - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix ); + if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); else from = Client; if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix ); return IRC_WriteStrClientPrefix( target, from, "PING %s :%s", Client_ID( from ), Req->argv[1] ); @@ -336,15 +388,14 @@ GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req ) } /* IRC_PING */ -GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req ) +GLOBAL BOOLEAN +IRC_PONG( CLIENT *Client, REQUEST *Req ) { CLIENT *target, *from; assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client )); if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -352,12 +403,12 @@ GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req ) /* forwarden? */ if( Req->argc == 2 ) { - target = Client_GetFromID( Req->argv[1] ); - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] ); + target = Client_Search( Req->argv[1] ); + if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] ); if( target != Client_ThisServer( )) { /* ok, forwarden */ - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix ); + if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); else from = Client; if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix ); return IRC_WriteStrClientPrefix( target, from, "PONG %s :%s", Client_ID( from ), Req->argv[1] ); @@ -365,7 +416,7 @@ GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req ) } /* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket - * aktualisiert, daher muss das hier nicht mehr gemacht werden. */ + * aktualisiert, daher muss das hier nicht mehr gemacht werden. */ if( Client_Conn( Client ) > NONE ) Log( LOG_DEBUG, "Connection %d: received PONG. Lag: %ld seconds.", Client_Conn( Client ), time( NULL ) - Conn_LastPing( Client_Conn( Client ))); else Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client )); @@ -374,7 +425,8 @@ GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req ) } /* IRC_PONG */ -LOCAL BOOLEAN Hello_User( CLIENT *Client ) +LOCAL BOOLEAN +Hello_User( CLIENT *Client ) { assert( Client != NULL ); @@ -393,9 +445,12 @@ LOCAL BOOLEAN Hello_User( CLIENT *Client ) IRC_WriteStrServers( NULL, "NICK %s 1 %s %s 1 +%s :%s", Client_ID( Client ), Client_User( Client ), Client_Hostname( Client ), Client_Modes( Client ), Client_Info( Client )); if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return FALSE; - if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE; + if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), VERSION, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return FALSE; if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return FALSE; - if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE; + if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), VERSION, USERMODES, CHANMODES )) return FALSE; + + /* Features */ + if( ! IRC_WriteStrClient( Client, RPL_ISUPPORT_MSG, Client_ID( Client ), CLIENT_NICK_LEN - 1, CHANNEL_TOPIC_LEN - 1, CLIENT_AWAY_LEN - 1, Conf_MaxJoins )) return DISCONNECTED; Client_SetType( Client, CLIENT_USER ); @@ -406,21 +461,21 @@ LOCAL BOOLEAN Hello_User( CLIENT *Client ) } /* Hello_User */ -LOCAL VOID Kill_Nick( CHAR *Nick, CHAR *Reason ) +LOCAL VOID +Kill_Nick( CHAR *Nick, CHAR *Reason ) { - CLIENT *c; + REQUEST r; assert( Nick != NULL ); assert( Reason != NULL ); - Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason ); - - /* andere Server benachrichtigen */ - IRC_WriteStrServers( NULL, "KILL %s :%s", Nick, Reason ); + r.prefix = Client_ThisServer( ); + r.argv[0] = Nick; + r.argv[1] = Reason; + r.argc = 2; - /* Ggf. einen eigenen Client toeten */ - c = Client_GetFromID( Nick ); - if( c && ( Client_Conn( c ) != NONE )) Conn_Close( Client_Conn( c ), NULL, Reason, TRUE ); + Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason ); + IRC_KILL( Client_ThisServer( ), &r ); } /* Kill_Nick */