Added optional support for IDENT lookups (configure switch "--with-ident").
authorAlexander Barton <alex@barton.de>
Sat, 27 Dec 2003 13:01:12 +0000 (13:01 +0000)
committerAlexander Barton <alex@barton.de>
Sat, 27 Dec 2003 13:01:12 +0000 (13:01 +0000)
ChangeLog
NEWS
configure.in
src/ngircd/conn.c
src/ngircd/irc-login.c
src/ngircd/resolve.c
src/ngircd/resolve.h
src/testsuite/channel-test.e
src/testsuite/mode-test.e

index 84e8a65..c9c15c1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,9 @@
 
 ngIRCd CVSHEAD
 
+  - Added optional support for "IDENT" lookups on incoming connections. You
+    have to enable this function with the ./configure switch "--with-ident".
+    The default is not to do IDENT lookups.
   - Removed "USE_" prefixes of configuration #defines.
 
 ngIRCd 0.7.6 (2003-12-05)
@@ -488,4 +491,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: ChangeLog,v 1.219 2003/12/26 15:55:07 alex Exp $
+$Id: ChangeLog,v 1.220 2003/12/27 13:01:12 alex Exp $
diff --git a/NEWS b/NEWS
index c7ecdd3..a7fa785 100644 (file)
--- a/NEWS
+++ b/NEWS
                                   -- NEWS --
 
 
+ngIRCd CVSHEAD
+
+  - Added optional support for "IDENT" lookups on incoming connections. You
+    have to enable this function with the ./configure switch "--with-ident".
+    The default is not to do IDENT lookups.
+
 ngIRCd 0.7.5 (2003-07-11)
 
   - New configuration variable "MaxConnectionsIP" to limit the number of
@@ -174,4 +180,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: NEWS,v 1.60 2003/11/07 21:32:15 alex Exp $
+$Id: NEWS,v 1.61 2003/12/27 13:01:12 alex Exp $
index 43d5734..324fd33 100644 (file)
@@ -8,7 +8,7 @@
 # (at your option) any later version.
 # Please read the file COPYING, README and AUTHORS for more information.
 #
-# $Id: configure.in,v 1.97 2003/12/26 15:55:07 alex Exp $
+# $Id: configure.in,v 1.98 2003/12/27 13:01:12 alex Exp $
 #
 
 # -- Initialisierung --
@@ -31,6 +31,7 @@ AH_TEMPLATE([ZLIB], [Define if zlib compression should be enabled])
 AH_TEMPLATE([TCPWRAP], [Define if TCP wrappers should be used])
 AH_TEMPLATE([IRCPLUS], [Define if IRC+ protocol should be used])
 AH_TEMPLATE([RENDEZVOUS], [Define if Rendezvous support should be included])
+AH_TEMPLATE([IDENTAUTH], [Define if the server should do IDENT requests])
 
 AH_TEMPLATE([TARGET_OS], [Target operating system name])
 AH_TEMPLATE([TARGET_VENDOR], [Target system vendor])
@@ -223,6 +224,22 @@ if test "$x_rendezvous_on" = "yes"; then
        AC_CHECK_HEADERS(DNSServiceDiscovery/DNSServiceDiscovery.h mach/port.h)
 fi
 
+x_identauth_on=no
+AC_ARG_WITH(ident,
+       [  --with-ident            enable "IDENT" ("AUTH") protocol support],
+       [       if test "$withval" = "yes"; then
+                       AC_CHECK_LIB(ident, ident_id)
+                       AC_CHECK_FUNCS(ident_id, x_identauth_on=yes,
+                               AC_MSG_ERROR([Can't enable IDENT support!])
+                       )
+               fi
+       ]
+)
+if test "$x_identauth_on" = "yes"; then
+       AC_DEFINE(IDENTAUTH, 1)
+       AC_CHECK_HEADERS(ident.h)
+fi
+
 x_ircplus_on=yes
 AC_ARG_ENABLE(ircplus,
        [  --disable-ircplus       disable IRC+ protocol],
@@ -384,6 +401,12 @@ echo $ECHO_N "      IRC+ protocol: $ECHO_C"
 test "$x_ircplus_on" = "yes" \
        && echo "yes" \
        || echo "no"
-echo
+
+echo $ECHO_N "      IDENT support: $ECHO_C"
+test "$x_identauth_on" = "yes" \
+       && echo $ECHO_N "yes $ECHO_C" \
+       || echo $ECHO_N "no  $ECHO_C"
+
+echo; echo
 
 # -eof-
index 48c1f46..7b9dcdb 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: conn.c,v 1.128 2003/12/26 15:55:07 alex Exp $";
+static char UNUSED id[] = "$Id: conn.c,v 1.129 2003/12/27 13:01:12 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -1054,7 +1054,11 @@ New_Connection( INT Sock )
        /* Hostnamen ermitteln */
        strlcpy( My_Connections[idx].host, inet_ntoa( new_addr.sin_addr ), sizeof( My_Connections[idx].host ));
        Client_SetHostname( c, My_Connections[idx].host );
+#ifdef IDENTAUTH
+       s = Resolve_Addr( &new_addr, My_Connections[idx].sock );
+#else
        s = Resolve_Addr( &new_addr );
+#endif
        if( s )
        {
                /* Sub-Prozess wurde asyncron gestartet */
@@ -1579,26 +1583,26 @@ Read_Resolver_Result( INT r_fd )
 
        FD_CLR( r_fd, &Resolver_FDs );
 
-       /* Anfrage vom Parent lesen */
+       /* Read result from pipe */
        len = read( r_fd, result, HOST_LEN - 1 );
        if( len < 0 )
        {
-               /* Fehler beim Lesen aus der Pipe */
+               /* Error! */
                close( r_fd );
                Log( LOG_CRIT, "Resolver: Can't read result: %s!", strerror( errno ));
                return;
        }
        result[len] = '\0';
 
-       /* zugehoerige Connection suchen */
+       /* Search associated connection ... */
        for( i = 0; i < Pool_Size; i++ )
        {
                if(( My_Connections[i].sock != NONE ) && ( My_Connections[i].res_stat ) && ( My_Connections[i].res_stat->pipe[0] == r_fd )) break;
        }
        if( i >= Pool_Size )
        {
-               /* Opsa! Keine passende Connection gefunden!? Vermutlich
-                * wurde sie schon wieder geschlossen. */
+               /* Ops, none found? Probably the connection has already
+                * been closed. */
                close( r_fd );
 #ifdef DEBUG
                Log( LOG_DEBUG, "Resolver: Got result for unknown connection!?" );
@@ -1610,7 +1614,7 @@ Read_Resolver_Result( INT r_fd )
        Log( LOG_DEBUG, "Resolver: %s is \"%s\".", My_Connections[i].host, result );
 #endif
 
-       /* Aufraeumen */
+       /* Clean up ... */
        close( My_Connections[i].res_stat->pipe[0] );
        close( My_Connections[i].res_stat->pipe[1] );
        free( My_Connections[i].res_stat );
@@ -1618,21 +1622,37 @@ Read_Resolver_Result( INT r_fd )
 
        if( My_Connections[i].sock > NONE )
        {
-               /* Eingehende Verbindung: Hostnamen setzen */
+#ifdef IDENTAUTH
+               CHAR *ident;
+#endif
+               /* Incoming connection: set hostname */
                c = Client_GetFromConn( i );
                assert( c != NULL );
                strlcpy( My_Connections[i].host, result, sizeof( My_Connections[i].host ));
                Client_SetHostname( c, result );
+
+#ifdef IDENTAUTH
+               ident = strchr( result, 0 );
+               ident++;
+
+               /* Do we have a result of the IDENT lookup? */
+               if( *ident )
+               {
+                       Log( LOG_INFO, "IDENT lookup on connection %ld: \"%s\".", i, ident );
+                       Client_SetUser( c, ident, TRUE );
+               }
+               else Log( LOG_INFO, "IDENT lookup on connection %ld: no result.", i );
+#endif
        }
        else
        {
-               /* Ausgehende Verbindung (=Server): IP setzen */
+               /* Outgoing connection (server link!): set IP address */
                n = Conf_GetServer( i );
                if( n > NONE ) strlcpy( Conf_Server[n].ip, result, sizeof( Conf_Server[n].ip ));
                else Log( LOG_ERR, "Got resolver result for non-configured server!?" );
        }
 
-       /* Penalty-Zeit zurueck setzen */
+       /* Reset penalty time */
        Conn_ResetPenalty( i );
 } /* Read_Resolver_Result */
 
index a077f16..10188c5 100644 (file)
@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-login.c,v 1.36 2003/12/04 14:05:16 alex Exp $";
+static char UNUSED id[] = "$Id: irc-login.c,v 1.37 2003/12/27 13:01:12 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -285,6 +285,10 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
 GLOBAL BOOLEAN
 IRC_USER( CLIENT *Client, REQUEST *Req )
 {
+#ifdef IDENTAUTH
+       CHAR *ptr;
+#endif
+
        assert( Client != NULL );
        assert( Req != NULL );
 
@@ -297,6 +301,10 @@ IRC_USER( CLIENT *Client, REQUEST *Req )
                /* Falsche Anzahl Parameter? */
                if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
 
+#ifdef IDENTAUTH
+               ptr = Client_User( Client );
+               if( ! ptr || ! *ptr || *ptr == '~' )
+#endif
                Client_SetUser( Client, Req->argv[0], FALSE );
                Client_SetInfo( Client, Req->argv[3] );
 
index aeb98ba..69705db 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
  *
  * 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
@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: resolve.c,v 1.6 2003/04/21 10:52:51 alex Exp $";
+static char UNUSED id[] = "$Id: resolve.c,v 1.7 2003/12/27 13:01:12 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -27,6 +27,12 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.6 2003/04/21 10:52:51 alex Exp $";
 #include <arpa/inet.h>
 #include <netdb.h>
 
+#ifdef IDENTAUTH
+#ifdef HAVE_IDENT_H
+#include <ident.h>
+#endif
+#endif
+
 #include "conn.h"
 #include "defines.h"
 #include "log.h"
@@ -35,7 +41,12 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.6 2003/04/21 10:52:51 alex Exp $";
 #include "resolve.h"
 
 
+#ifdef IDENTAUTH
+LOCAL VOID Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, INT Sock, INT w_fd ));
+#else
 LOCAL VOID Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, INT w_fd ));
+#endif
+
 LOCAL VOID Do_ResolveName PARAMS(( CHAR *Host, INT w_fd ));
 
 #ifdef h_errno
@@ -46,23 +57,27 @@ LOCAL CHAR *Get_Error PARAMS(( INT H_Error ));
 GLOBAL VOID
 Resolve_Init( VOID )
 {
-       /* Modul initialisieren */
+       /* Initialize module */
 
        FD_ZERO( &Resolver_FDs );
 } /* Resolve_Init */
 
 
+#ifdef IDENTAUTH
+GLOBAL RES_STAT *
+Resolve_Addr( struct sockaddr_in *Addr, int Sock )
+#else
 GLOBAL RES_STAT *
 Resolve_Addr( struct sockaddr_in *Addr )
+#endif
 {
-       /* IP (asyncron!) aufloesen. Bei Fehler, z.B. wenn der
-        * Child-Prozess nicht erzeugt werden kann, wird NULL geliefert.
-        * Der Host kann dann nicht aufgeloest werden. */
+       /* Resolve IP (asynchronous!). On errors, e.g. if the child process
+        * can't be forked, this functions returns NULL. */
 
        RES_STAT *s;
        INT pid;
 
-       /* Speicher anfordern */
+       /* Allocate memory */
        s = malloc( sizeof( RES_STAT ));
        if( ! s )
        {
@@ -70,7 +85,7 @@ Resolve_Addr( struct sockaddr_in *Addr )
                return NULL;
        }
 
-       /* Pipe fuer Antwort initialisieren */
+       /* Initialize pipe for result */
        if( pipe( s->pipe ) != 0 )
        {
                free( s );
@@ -78,11 +93,11 @@ Resolve_Addr( struct sockaddr_in *Addr )
                return NULL;
        }
 
-       /* Sub-Prozess erzeugen */
+       /* For sub-process */
        pid = fork( );
        if( pid > 0 )
        {
-               /* Haupt-Prozess */
+               /* Main process */
                Log( LOG_DEBUG, "Resolver for %s created (PID %d).", inet_ntoa( Addr->sin_addr ), pid );
                FD_SET( s->pipe[0], &Resolver_FDs );
                if( s->pipe[0] > Conn_MaxFD ) Conn_MaxFD = s->pipe[0];
@@ -91,15 +106,19 @@ Resolve_Addr( struct sockaddr_in *Addr )
        }
        else if( pid == 0 )
        {
-               /* Sub-Prozess */
+               /* Sub process */
                Log_Init_Resolver( );
+#ifdef IDENTAUTH
+               Do_ResolveAddr( Addr, Sock, s->pipe[1] );
+#else
                Do_ResolveAddr( Addr, s->pipe[1] );
+#endif
                Log_Exit_Resolver( );
                exit( 0 );
        }
        else
        {
-               /* Fehler */
+               /* Error! */
                free( s );
                Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno ));
                return NULL;
@@ -110,14 +129,13 @@ Resolve_Addr( struct sockaddr_in *Addr )
 GLOBAL RES_STAT *
 Resolve_Name( CHAR *Host )
 {
-       /* Hostnamen (asyncron!) aufloesen. Bei Fehler, z.B. wenn der
-        * Child-Prozess nicht erzeugt werden kann, wird NULL geliefert.
-        * Der Host kann dann nicht aufgeloest werden. */
+       /* Resolve hostname (asynchronous!). On errors, e.g. if the child
+        * process can't be forked, this functions returns NULL. */
 
        RES_STAT *s;
        INT pid;
 
-       /* Speicher anfordern */
+       /* Allocate memory */
        s = malloc( sizeof( RES_STAT ));
        if( ! s )
        {
@@ -125,7 +143,7 @@ Resolve_Name( CHAR *Host )
                return NULL;
        }
 
-       /* Pipe fuer Antwort initialisieren */
+       /* Initialize the pipe for the result */
        if( pipe( s->pipe ) != 0 )
        {
                free( s );
@@ -133,11 +151,11 @@ Resolve_Name( CHAR *Host )
                return NULL;
        }
 
-       /* Sub-Prozess erzeugen */
+       /* Fork sub-process */
        pid = fork( );
        if( pid > 0 )
        {
-               /* Haupt-Prozess */
+               /* Main process */
                Log( LOG_DEBUG, "Resolver for \"%s\" created (PID %d).", Host, pid );
                FD_SET( s->pipe[0], &Resolver_FDs );
                if( s->pipe[0] > Conn_MaxFD ) Conn_MaxFD = s->pipe[0];
@@ -146,7 +164,7 @@ Resolve_Name( CHAR *Host )
        }
        else if( pid == 0 )
        {
-               /* Sub-Prozess */
+               /* Sub process */
                Log_Init_Resolver( );
                Do_ResolveName( Host, s->pipe[1] );
                Log_Exit_Resolver( );
@@ -154,7 +172,7 @@ Resolve_Name( CHAR *Host )
        }
        else
        {
-               /* Fehler */
+               /* Error! */
                free( s );
                Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno ));
                return NULL;
@@ -162,17 +180,26 @@ Resolve_Name( CHAR *Host )
 } /* Resolve_Name */
 
 
+#ifdef IDENTAUTH
+LOCAL VOID
+Do_ResolveAddr( struct sockaddr_in *Addr, int Sock, INT w_fd )
+#else
 LOCAL VOID
 Do_ResolveAddr( struct sockaddr_in *Addr, INT w_fd )
+#endif
 {
-       /* Resolver Sub-Prozess: IP aufloesen und Ergebnis in Pipe schreiben. */
+       /* Resolver sub-process: resolve IP address and write result into
+        * pipe to parent. */
 
        CHAR hostname[HOST_LEN];
        struct hostent *h;
+#ifdef IDENTAUTH
+       CHAR *res;
+#endif
 
        Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr ));
 
-       /* Namen aufloesen */
+       /* Resolve IP address */
        h = gethostbyaddr( (CHAR *)&Addr->sin_addr, sizeof( Addr->sin_addr ), AF_INET );
        if( h ) strlcpy( hostname, h->h_name, sizeof( hostname ));
        else
@@ -185,13 +212,30 @@ Do_ResolveAddr( struct sockaddr_in *Addr, INT w_fd )
                strlcpy( hostname, inet_ntoa( Addr->sin_addr ), sizeof( hostname ));
        }
 
-       /* Antwort an Parent schreiben */
+#ifdef IDENTAUTH
+       /* Do "IDENT" (aka "AUTH") lookup and write result to parent */
+       Log_Resolver( LOG_DEBUG, "Doing IDENT lookup on socket %d ...", Sock );
+       res = ident_id( Sock, 10 );
+       Log_Resolver( LOG_DEBUG, "IDENT lookup on socket %d done.", Sock );
+#endif
+
+       /* Write result into pipe to parent */
        if( (size_t)write( w_fd, hostname, strlen( hostname ) + 1 ) != (size_t)( strlen( hostname ) + 1 ))
        {
                Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", strerror( errno ));
                close( w_fd );
                return;
        }
+#ifdef IDENTAUTH
+       if( (size_t)write( w_fd, res ? res : "", strlen( res ? res : "" ) + 1 ) != (size_t)( strlen( res ? res : "" ) + 1 ))
+       {
+               Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent (IDENT): %s!", strerror( errno ));
+               close( w_fd );
+               free( res );
+               return;
+       }
+       free( res );
+#endif
 
        Log_Resolver( LOG_DEBUG, "Ok, translated %s to \"%s\".", inet_ntoa( Addr->sin_addr ), hostname );
 } /* Do_ResolveAddr */
@@ -200,7 +244,8 @@ Do_ResolveAddr( struct sockaddr_in *Addr, INT w_fd )
 LOCAL VOID
 Do_ResolveName( CHAR *Host, INT w_fd )
 {
-       /* Resolver Sub-Prozess: Name aufloesen und Ergebnis in Pipe schreiben. */
+       /* Resolver sub-process: resolve name and write result into pipe
+        * to parent. */
 
        CHAR ip[16];
        struct hostent *h;
@@ -208,7 +253,7 @@ Do_ResolveName( CHAR *Host, INT w_fd )
 
        Log_Resolver( LOG_DEBUG, "Now resolving \"%s\" ...", Host );
 
-       /* Namen aufloesen */
+       /* Resolve hostname */
        h = gethostbyname( Host );
        if( h )
        {
@@ -225,7 +270,7 @@ Do_ResolveName( CHAR *Host, INT w_fd )
                strcpy( ip, "" );
        }
 
-       /* Antwort an Parent schreiben */
+       /* Write result into pipe to parent */
        if( (size_t)write( w_fd, ip, strlen( ip ) + 1 ) != (size_t)( strlen( ip ) + 1 ))
        {
                Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", strerror( errno ));
@@ -242,7 +287,7 @@ Do_ResolveName( CHAR *Host, INT w_fd )
 LOCAL CHAR *
 Get_Error( INT H_Error )
 {
-       /* Fehlerbeschreibung fuer H_Error liefern */
+       /* Get error message for H_Error */
 
        switch( H_Error )
        {
index f823110..716dd51 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
  *
  * 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
@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: resolve.h,v 1.5 2003/04/21 10:53:10 alex Exp $
+ * $Id: resolve.h,v 1.6 2003/12/27 13:01:12 alex Exp $
  *
  * Asynchronous resolver (header)
  */
@@ -37,7 +37,12 @@ GLOBAL fd_set Resolver_FDs;
 
 GLOBAL VOID Resolve_Init PARAMS(( VOID ));
 
+#ifdef IDENTAUTH
+GLOBAL RES_STAT *Resolve_Addr PARAMS(( struct sockaddr_in *Addr, int Sock ));
+#else
 GLOBAL RES_STAT *Resolve_Addr PARAMS(( struct sockaddr_in *Addr ));
+#endif
+
 GLOBAL RES_STAT *Resolve_Name PARAMS(( CHAR *Host ));
 
 
index 19bed86..240abf6 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: channel-test.e,v 1.2 2002/09/09 21:26:00 alex Exp $
+# $Id: channel-test.e,v 1.3 2003/12/27 13:01:12 alex Exp $
 
 spawn telnet localhost 6789
 expect {
@@ -16,7 +16,7 @@ expect {
 send "join #channel\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* JOIN :#channel"
+       "@* JOIN :#channel"
 }
 expect {
        timeout { exit 1 }
@@ -26,13 +26,17 @@ expect {
 send "topic #channel :Test-Topic\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* TOPIC #channel :Test-Topic"
+       "@* TOPIC #channel :Test-Topic"
 }
 
 send "who #channel\r"
 expect {
        timeout { exit 1 }
-       "352 nick #channel ~user * nick H@ :0 User"
+       "352 nick #channel"
+}
+expect {
+       timeout { exit 1 }
+       "* nick H@ :0 User"
 }
 expect {
        timeout { exit 1 }
@@ -62,7 +66,7 @@ expect {
 send "part #channel\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* PART #channel :nick"
+       "@* PART #channel :nick"
 }
 
 send "quit\r"
index db56408..b8fff01 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: mode-test.e,v 1.4 2002/12/15 15:52:34 alex Exp $
+# $Id: mode-test.e,v 1.5 2003/12/27 13:01:12 alex Exp $
 
 spawn telnet localhost 6789
 expect {
@@ -16,7 +16,7 @@ expect {
 send "mode nick +i\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* MODE nick +i"
+       "@* MODE nick +i"
 }
 
 send "mode nick\r"
@@ -28,7 +28,7 @@ expect {
 send "mode nick -i\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* MODE nick -i"
+       "@* MODE nick -i"
 }
 
 send "oper TestOp 123\r"
@@ -50,7 +50,7 @@ expect {
 send "join #channel\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* JOIN :#channel"
+       "@* JOIN :#channel"
 }
 expect {
        timeout { exit 1 }
@@ -60,7 +60,7 @@ expect {
 send "mode #channel +tn\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* MODE #channel +tn"
+       "@* MODE #channel +tn"
 }
 
 send "mode #channel\r"
@@ -72,31 +72,31 @@ expect {
 send "mode #channel +v nick\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* MODE #channel +v nick"
+       "@* MODE #channel +v nick"
 }
 
 send "mode #channel +I nick1\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* MODE #channel +I nick1!*@*"
+       "@* MODE #channel +I nick1!*@*"
 }
 
 send "mode #channel +b nick2@domain\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* MODE #channel +b nick2!*@domain"
+       "@* MODE #channel +b nick2!*@domain"
 }
 
 send "mode #channel +I nick3!user\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* MODE #channel +I nick3!user@*"
+       "@* MODE #channel +I nick3!user@*"
 }
 
 send "mode #channel -vo nick nick\r"
 expect {
        timeout { exit 1 }
-       ":nick!~user@* MODE #channel -vo nick nick"
+       "@* MODE #channel -vo nick nick"
 }
 
 send "quit\r"