X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fresolve.c;h=8e1749a30eaa574e76dfaed2c3e9679ea47fa701;hp=aeb98ba6e923fe913f06dc5e00e58a30d185a718;hb=2e794a6943a74f2ba4f3769703e3500fe9008461;hpb=c3dfd63bf3213a5a68d890d3e7cb38fe94a55cb6 diff --git a/src/ngircd/resolve.c b/src/ngircd/resolve.c index aeb98ba6..8e1749a3 100644 --- a/src/ngircd/resolve.c +++ b/src/ngircd/resolve.c @@ -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.15 2005/07/25 09:20:10 fw Exp $"; #include "imp.h" #include @@ -27,188 +27,254 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.6 2003/04/21 10:52:51 alex Exp $"; #include #include +#ifdef IDENTAUTH +#ifdef HAVE_IDENT_H +#include +#endif +#endif + #include "conn.h" #include "defines.h" #include "log.h" #include "exp.h" #include "resolve.h" +#include "io.h" -LOCAL VOID Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, INT w_fd )); -LOCAL VOID Do_ResolveName PARAMS(( CHAR *Host, INT w_fd )); +#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 -LOCAL CHAR *Get_Error PARAMS(( INT H_Error )); +LOCAL char *Get_Error PARAMS(( int H_Error )); #endif +LOCAL RES_STAT *New_Res_Stat PARAMS(( void )); -GLOBAL VOID -Resolve_Init( VOID ) -{ - /* Modul initialisieren */ - FD_ZERO( &Resolver_FDs ); -} /* Resolve_Init */ +static void +cb_resolver(int fd, short unused) { + (void) unused; /* shut up compiler warning */ + Read_Resolver_Result(fd); +} +#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 */ - s = malloc( sizeof( RES_STAT )); - if( ! s ) - { - Log( LOG_EMERG, "Resolver: Can't allocate memory! [Resolve_Addr]" ); - return NULL; - } + int pid; - /* Pipe fuer Antwort initialisieren */ - if( pipe( s->pipe ) != 0 ) - { - free( s ); - Log( LOG_ALERT, "Resolver: Can't create output pipe: %s!", strerror( errno )); - return NULL; - } + s = New_Res_Stat( ); + if( ! s ) return NULL; - /* Sub-Prozess erzeugen */ + /* For sub-process */ pid = fork( ); if( pid > 0 ) { - /* Haupt-Prozess */ + close( s->pipe[1] ); + /* 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]; + if (!io_setnonblock( s->pipe[0] )) { + Log( LOG_DEBUG, "Could not set Non-Blocking mode for pipefd %d", s->pipe[0] ); + goto out; + } + if (!io_event_create( s->pipe[0], IO_WANTREAD, cb_resolver )) { + Log( LOG_DEBUG, "Could not add pipefd %dto event watchlist: %s", + s->pipe[0], strerror(errno) ); + goto out; + } s->pid = pid; return s; } else if( pid == 0 ) { - /* Sub-Prozess */ + close( s->pipe[0] ); + /* 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 */ - free( s ); - Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno )); - return NULL; - } + + Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno )); + +out: /* Error! */ + close( s->pipe[0] ); + free( s ); +return NULL; } /* Resolve_Addr */ GLOBAL RES_STAT * -Resolve_Name( CHAR *Host ) +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 */ - s = malloc( sizeof( RES_STAT )); - if( ! s ) - { - Log( LOG_EMERG, "Resolver: Can't allocate memory! [Resolve_Name]" ); - return NULL; - } + int pid; - /* Pipe fuer Antwort initialisieren */ - if( pipe( s->pipe ) != 0 ) - { - free( s ); - Log( LOG_ALERT, "Resolver: Can't create output pipe: %s!", strerror( errno )); - return NULL; - } + s = New_Res_Stat( ); + if( ! s ) return NULL; - /* Sub-Prozess erzeugen */ + /* Fork sub-process */ pid = fork( ); if( pid > 0 ) { - /* Haupt-Prozess */ + close( s->pipe[1] ); + /* 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]; + if (!io_setnonblock( s->pipe[0] )) { + Log( LOG_DEBUG, "Could not set Non-Blocking mode for pipefd %d", s->pipe[0] ); + goto out; + } + if (!io_event_create( s->pipe[0], IO_WANTREAD, cb_resolver )) { + Log( LOG_DEBUG, "Could not add pipefd %dto event watchlist: %s", + s->pipe[0], strerror(errno) ); + goto out; + } s->pid = pid; return s; } else if( pid == 0 ) { - /* Sub-Prozess */ + close( s->pipe[0] ); + /* Sub process */ Log_Init_Resolver( ); Do_ResolveName( Host, s->pipe[1] ); Log_Exit_Resolver( ); exit( 0 ); } - else - { - /* Fehler */ - free( s ); - Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno )); - return NULL; - } + + Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno )); + +out: /* Error! */ + close( s->pipe[0] ); + free( s ); + return NULL; } /* Resolve_Name */ -LOCAL VOID -Do_ResolveAddr( struct sockaddr_in *Addr, INT w_fd ) +#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]; + char hostname[HOST_LEN]; + char ipstr[HOST_LEN]; struct hostent *h; + size_t len; + struct in_addr *addr; + char *ntoaptr; +#ifdef IDENTAUTH + char *res; +#endif + /* Resolve IP address */ +#ifdef DEBUG Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr )); - - /* Namen aufloesen */ - h = gethostbyaddr( (CHAR *)&Addr->sin_addr, sizeof( Addr->sin_addr ), AF_INET ); - if( h ) strlcpy( hostname, h->h_name, sizeof( hostname )); - else - { +#endif + h = gethostbyaddr( (char *)&Addr->sin_addr, sizeof( Addr->sin_addr ), AF_INET ); + if (!h) { #ifdef h_errno Log_Resolver( LOG_WARNING, "Can't resolve address \"%s\": %s!", inet_ntoa( Addr->sin_addr ), Get_Error( h_errno )); #else Log_Resolver( LOG_WARNING, "Can't resolve address \"%s\"!", inet_ntoa( Addr->sin_addr )); #endif strlcpy( hostname, inet_ntoa( Addr->sin_addr ), sizeof( hostname )); + } else { + strlcpy( hostname, h->h_name, sizeof( hostname )); + + h = gethostbyname( hostname ); + if ( h ) { + if (memcmp(h->h_addr, &Addr->sin_addr, sizeof (struct in_addr))) { + addr = (struct in_addr*) h->h_addr; + strlcpy(ipstr, inet_ntoa(*addr), sizeof ipstr); + ntoaptr = inet_ntoa( Addr->sin_addr ); + Log(LOG_WARNING,"Possible forgery: %s resolved to %s (which is at ip %s!)", + ntoaptr, hostname, ipstr); + strlcpy( hostname, ntoaptr, sizeof hostname); + } + } else { + ntoaptr = inet_ntoa( Addr->sin_addr ); + Log(LOG_WARNING, "Possible forgery: %s resolved to %s (which has no ip address)", + ntoaptr, hostname); + strlcpy( hostname, ntoaptr, sizeof hostname); + } } + Log_Resolver( LOG_DEBUG, "Ok, translated %s to \"%s\".", inet_ntoa( Addr->sin_addr ), hostname ); - /* Antwort an Parent schreiben */ - if( (size_t)write( w_fd, hostname, strlen( hostname ) + 1 ) != (size_t)( strlen( hostname ) + 1 )) + /* Write resolver result into pipe to parent */ + len = strlen( hostname ); + hostname[len] = '\n'; len++; + if( (size_t)write( w_fd, hostname, len ) != (size_t)len ) { Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", strerror( errno )); close( w_fd ); return; } - Log_Resolver( LOG_DEBUG, "Ok, translated %s to \"%s\".", inet_ntoa( Addr->sin_addr ), hostname ); +#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, "Ok, IDENT lookup on socket %d done: \"%s\"", Sock, res ? res : "" ); + + /* Write IDENT result into pipe to parent */ + if (res) { + len = strlen(res); + res[len] = '\n'; + len++; + } else len = 1; + + if( (size_t)write( w_fd, res ? res : "\n", len ) != (size_t)len ) + { + Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent (IDENT): %s!", strerror( errno )); + close( w_fd ); + } + free( res ); +#endif } /* Do_ResolveAddr */ -LOCAL VOID -Do_ResolveName( CHAR *Host, 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]; + char ip[16]; struct hostent *h; struct in_addr *addr; + int len; Log_Resolver( LOG_DEBUG, "Now resolving \"%s\" ...", Host ); - /* Namen aufloesen */ + /* Resolve hostname */ h = gethostbyname( Host ); if( h ) { @@ -222,27 +288,27 @@ Do_ResolveName( CHAR *Host, INT w_fd ) #else Log_Resolver( LOG_WARNING, "Can't resolve \"%s\"!", Host ); #endif - strcpy( ip, "" ); + ip[0] = '\0'; } + if( ip[0] ) Log_Resolver( LOG_DEBUG, "Ok, translated \"%s\" to %s.", Host, ip ); - /* Antwort an Parent schreiben */ - if( (size_t)write( w_fd, ip, strlen( ip ) + 1 ) != (size_t)( strlen( ip ) + 1 )) + /* Write result into pipe to parent */ + len = strlen( ip ); + ip[len] = '\n'; len++; + if( (size_t)write( w_fd, ip, len ) != (size_t)len ) { Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", strerror( errno )); close( w_fd ); - return; } - - if( ip[0] ) Log_Resolver( LOG_DEBUG, "Ok, translated \"%s\" to %s.", Host, ip ); } /* Do_ResolveName */ #ifdef h_errno -LOCAL CHAR * -Get_Error( INT H_Error ) +LOCAL char * +Get_Error( int H_Error ) { - /* Fehlerbeschreibung fuer H_Error liefern */ + /* Get error message for H_Error */ switch( H_Error ) { @@ -262,4 +328,33 @@ Get_Error( INT H_Error ) #endif +LOCAL RES_STAT * +New_Res_Stat( void ) +{ + RES_STAT *s; + + /* Allocate memory */ + s = (RES_STAT *)malloc( sizeof( RES_STAT )); + if( ! s ) + { + Log( LOG_EMERG, "Resolver: Can't allocate memory! [Resolve_Addr]" ); + return NULL; + } + + /* Initialize pipe for result */ + if( pipe( s->pipe ) != 0 ) + { + free( s ); + Log( LOG_ALERT, "Resolver: Can't create output pipe: %s!", strerror( errno )); + return NULL; + } + + s->stage = 0; + s->bufpos = 0; + s->pid = -1; + + return s; +} /* New_Res_Stat */ + + /* -eof- */