#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAXLINE 4096
#define SIZ 500
extern int errno;
char *auth_tcpuser( register long unsigned int in,
register short unsigned int local,
register short unsigned int remote );
unsigned short auth_tcpport = 113;
void err_sys( const char *str )
{
FILE *log_file;
if( !( log_file = fopen( "./getnameauth_err.log", "a+t" ) ) )
{
perror( "can't open Error log!" );
return;
}
fprintf( log_file, "%s\n", str );
fclose( log_file );
return;
}
int main( void )
{
int n;
int int1;
int int2;
int addr;
int server_port;
struct hostent *from;
char *user;
char line[ MAXLINE ];
char addr_buff[ 64 ];
char name_buff[ 64 ];
while( ( n = read( STDIN_FILENO, line, MAXLINE ) ) > 0 )
{
line[ n ] = '\0';
if( sscanf( line, "%s %d %d %d",
&name_buff[ 0 ], &int1, &int2, &server_port ) == 4 )
{
from = gethostbyaddr( ( char* )&int1, sizeof( int1 ), AF_INET );
user = auth_tcpuser( int1, server_port, int2 );
addr = ntohl( int1 );
sprintf( addr_buff, "%d.%d.%d.%d port %d",
( addr >> 24 ) & 0xFF,
( addr >> 16 ) & 0xFF,
( addr >> 8 ) & 0xFF,
( addr ) & 0xFF,
int2 );
sprintf( line, "%s:%s:%s",
name_buff,
user,
from ? from->h_name : addr_buff );
n = strlen( line );
if( write( STDOUT_FILENO, line, n ) != n )
err_sys( "Error writing to pipe" );
}
else
{
if( write( STDOUT_FILENO, "Invalid Query\n", 14 ) != 14 )
err_sys( "Error writing to pipe" );
}
}
exit( 0 );
}
static char ruser[ SIZ ];
static char realbuf[ SIZ ];
static char *buf;
/* This was taken from public domain source that I managed to dredge up,
* I changed a little of it, but I can't claim that I wrote it all. I don't
* know who the original author is, so I can't give him/her credit. */
char *auth_tcpuser(
register long unsigned int in,
register short unsigned int local,
register short unsigned int remote )
{
struct sockaddr_in sa;
register int s;
register int buflen;
register int w;
register int saveerrno;
char ch;
unsigned short rlocal;
unsigned short rremote;
if( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
return 0;
sa.sin_family = AF_INET;
sa.sin_port = htons( auth_tcpport );
sa.sin_addr.s_addr = in;
if( connect( s, ( struct sockaddr * )&sa, sizeof( sa ) ) == -1 )
{
saveerrno = errno;
close( s );
errno = saveerrno;
return( "(Unknown)" );
}
buf = realbuf;
sprintf( buf, "%u , %u\r\n",
( unsigned int )remote,
( unsigned int )local );
/*
* note the reversed order, the example in the RFC is misleading
*/
buflen = strlen( buf );
while( ( w = write( s, buf, buflen ) ) < buflen )
if( w == -1 ) /* should we worry about 0 as well? */
{
saveerrno = errno;
close( s );
errno = saveerrno;
return( "(Send Error)" );
}
else
{
buf += w;
buflen -= w;
}
buf = realbuf;
while( ( w = read( s, &ch, 1 ) ) == 1 )
{
*buf = ch;
if( ( ch != ' ' )
&& ( ch != '\t' )
&& ( ch != '\r' ) )
++buf;
if( ( buf - realbuf == sizeof( realbuf ) - 1 )
|| ( ch == '\n' ) )
break;
}
if( w == -1 )
{
saveerrno = errno;
close( s );
errno = saveerrno;
return( "(Read Error)" );
}
*buf = '\0';
bzero( ruser, SIZ );
if( sscanf( realbuf, "%hd,%hd: USERID :%*[^:]:%s",
&rremote, &rlocal, ruser ) < 3 )
{
close( s );
errno = EOF;
/*
* Makes sense, right? well, not when USERID failed to match ERROR
* but there's no good error to return in that case
*/
fprintf( stderr, realbuf );
return( "(Auth Error)" );
}
if( ( remote != rremote )
|| ( local != rlocal ) )
{
close( s );
errno = EOF;
return( "REMOTE/LOCAL" );
}
close( s );
return ruser;
}