X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fngircd%2Fresolve.c;h=4a6f2e14dce2fc3e8a7e2781ee0bb75fdaa10953;hb=4db29b007689d34adeaca8cbe8676f7c2aedc2ab;hp=846e5236d40b1d630c22405a9e1477aa81622a9b;hpb=5e929effcae7a273f55a0011632b86a0811cf35f;p=ngircd-alex.git diff --git a/src/ngircd/resolve.c b/src/ngircd/resolve.c index 846e5236..4a6f2e14 100644 --- a/src/ngircd/resolve.c +++ b/src/ngircd/resolve.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: resolve.c,v 1.10 2005/03/05 12:57:14 alex Exp $"; +static char UNUSED id[] = "$Id: resolve.c,v 1.20 2005/09/11 11:42:48 fw Exp $"; #include "imp.h" #include @@ -39,30 +39,29 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.10 2005/03/05 12:57:14 alex Exp $" #include "exp.h" #include "resolve.h" +#include "io.h" #ifdef IDENTAUTH -LOCAL VOID Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, INT Sock, INT w_fd )); +static 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 )); +static void Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, int w_fd )); #endif -LOCAL VOID Do_ResolveName PARAMS(( CHAR *Host, INT w_fd )); +static void Do_ResolveName PARAMS(( char *Host, int w_fd )); #ifdef h_errno -LOCAL CHAR *Get_Error PARAMS(( INT H_Error )); +static char *Get_Error PARAMS(( int H_Error )); #endif -LOCAL RES_STAT *New_Res_Stat PARAMS(( VOID )); +static RES_STAT *New_Res_Stat PARAMS(( void )); -GLOBAL VOID -Resolve_Init( VOID ) -{ - /* Initialize module */ - - 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 @@ -77,24 +76,30 @@ Resolve_Addr( struct sockaddr_in *Addr ) * can't be forked, this functions returns NULL. */ RES_STAT *s; - INT pid; + int pid; s = New_Res_Stat( ); if( ! s ) return NULL; /* For sub-process */ pid = fork( ); - if( pid > 0 ) - { + if (pid > 0) { + 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 ) - { + } else if( pid == 0 ) { + close( s->pipe[0] ); /* Sub process */ Log_Init_Resolver( ); #ifdef IDENTAUTH @@ -103,144 +108,182 @@ Resolve_Addr( struct sockaddr_in *Addr ) Do_ResolveAddr( Addr, s->pipe[1] ); #endif Log_Exit_Resolver( ); - exit( 0 ); - } - else - { - /* Error! */ - free( s ); - Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno )); - return NULL; + exit(0); } + + Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno )); + +out: /* Error! */ + close( s->pipe[0] ); + close( s->pipe[1] ); + free( s ); +return NULL; } /* Resolve_Addr */ GLOBAL RES_STAT * -Resolve_Name( CHAR *Host ) +Resolve_Name( char *Host ) { /* Resolve hostname (asynchronous!). On errors, e.g. if the child * process can't be forked, this functions returns NULL. */ RES_STAT *s; - INT pid; + int pid; s = New_Res_Stat( ); if( ! s ) return NULL; /* Fork sub-process */ pid = fork( ); - if( pid > 0 ) - { + if (pid > 0) { + 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 ) - { + } else if( pid == 0 ) { + close( s->pipe[0] ); /* Sub process */ Log_Init_Resolver( ); Do_ResolveName( Host, s->pipe[1] ); Log_Exit_Resolver( ); - exit( 0 ); - } - else - { - /* Error! */ - free( s ); - Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno )); - return NULL; + exit(0); } + + Log( LOG_CRIT, "Resolver: Can't fork: %s!", strerror( errno )); + +out: /* Error! */ + close( s->pipe[0] ); + close( s->pipe[1] ); + free( s ); + return NULL; } /* Resolve_Name */ #ifdef IDENTAUTH -LOCAL VOID -Do_ResolveAddr( struct sockaddr_in *Addr, int Sock, INT w_fd ) +static void +Do_ResolveAddr( struct sockaddr_in *Addr, int Sock, int w_fd ) #else -LOCAL VOID -Do_ResolveAddr( struct sockaddr_in *Addr, INT w_fd ) +static void +Do_ResolveAddr( struct sockaddr_in *Addr, int w_fd ) #endif { /* 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; - INT len; + size_t len; + struct in_addr *addr; + char *ntoaptr; + array resolved_addr; #ifdef IDENTAUTH - CHAR *res; + char *res; #endif + array_init(&resolved_addr); + /* Resolve IP address */ +#ifdef DEBUG Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr )); - 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 ); - /* 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 )); + if (!array_copyb(&resolved_addr, hostname, len )) { + Log_Resolver( LOG_CRIT, "Resolver: Can't copy resolved name: %s!", strerror( errno )); close( w_fd ); return; } #ifdef IDENTAUTH - /* Do "IDENT" (aka "AUTH") lookup and write result to parent */ + /* Do "IDENT" (aka "AUTH") lookup and append result to resolved_addr array */ 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 */ - len = strlen( res ? res : "" ); - if( res != NULL ) res[len] = '\n'; - len++; - 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 ); + if (res) { + if (!array_cats(&resolved_addr, res)) + Log_Resolver(LOG_WARNING, "Resolver: Cannot copy IDENT result: %s!", strerror(errno)); + /* try to omit ident and return hostname only */ } - free( res ); + + if (!array_catb(&resolved_addr, "\n", 1)) { + close(w_fd); + Log_Resolver(LOG_CRIT, "Resolver: Cannot copy result: %s!", strerror(errno)); + array_free(&resolved_addr); + return; + } + + if (res) free(res); #endif + len = array_bytes(&resolved_addr); + if( (size_t)write( w_fd, array_start(&resolved_addr), len) != len ) + Log_Resolver( LOG_CRIT, "Resolver: Can't write result to parent: %s!", strerror( errno )); + + close(w_fd); + array_free(&resolved_addr); } /* Do_ResolveAddr */ -LOCAL VOID -Do_ResolveName( CHAR *Host, INT w_fd ) +static void +Do_ResolveName( char *Host, int w_fd ) { /* 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; + int len; Log_Resolver( LOG_DEBUG, "Now resolving \"%s\" ...", Host ); /* Resolve hostname */ h = gethostbyname( Host ); - if( h ) - { + if( h ) { addr = (struct in_addr *)h->h_addr; strlcpy( ip, inet_ntoa( *addr ), sizeof( ip )); - } - else - { + } else { #ifdef h_errno Log_Resolver( LOG_WARNING, "Can't resolve \"%s\": %s!", Host, Get_Error( h_errno )); #else @@ -253,8 +296,7 @@ Do_ResolveName( CHAR *Host, INT w_fd ) /* Write result into pipe to parent */ len = strlen( ip ); ip[len] = '\n'; len++; - if( (size_t)write( w_fd, ip, len ) != (size_t)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 ); } @@ -263,8 +305,8 @@ Do_ResolveName( CHAR *Host, INT w_fd ) #ifdef h_errno -LOCAL CHAR * -Get_Error( INT H_Error ) +static char * +Get_Error( int H_Error ) { /* Get error message for H_Error */ @@ -286,8 +328,8 @@ Get_Error( INT H_Error ) #endif -LOCAL RES_STAT * -New_Res_Stat( VOID ) +static RES_STAT * +New_Res_Stat( void ) { RES_STAT *s; @@ -308,7 +350,7 @@ New_Res_Stat( VOID ) } s->stage = 0; - s->bufpos = 0; + array_init(&s->buffer); s->pid = -1; return s;