/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops |~'~.VxvxV.~'~*
* ------------------------------------------------------------------------ *
* IDENT protocol userid lookup module *
****************************************************************************/
/* Donated to Realms of Despair by Tricops, author unknown. */
#if defined( macintosh )
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <arpa/telnet.h>
#include <errno.h>
#include <netdb.h>
#include "mud.h"
extern int maxdesc;
extern int write args( ( int fd, char *buf, int nbyte ) );
extern int read args( ( int fd, char *buf, int nbyte ) );
extern int close args( ( int fd ) );
void nonblock args( ( int s ) );
void start_auth args( ( struct descriptor_data *d ) );
void read_auth args( ( struct descriptor_data *d ) );
void send_auth args( ( struct descriptor_data *d ) );
/*
* Initiate an IDENT commention
*/
void start_auth( struct descriptor_data *d )
{
struct sockaddr_in sock;
struct servent *serv;
int err, tlen;
d->auth_fd = socket( AF_INET, SOCK_STREAM, 0 );
err = errno;
if ( d->auth_fd < 0 && err == EAGAIN )
bug( "Can't allocate fd for authorization check", 0 );
nonblock( d->auth_fd );
tlen = sizeof( sock );
getpeername( d->descriptor, ( struct sockaddr * )&sock, &tlen );
serv = getservbyname( "ident", "tcp" );
if ( !serv )
sock.sin_port = htons( 113 );
else
sock.sin_port = serv->s_port;
sock.sin_family = AF_INET;
if ( connect( d->auth_fd, ( struct sockaddr *)&sock, sizeof(sock)) == -1
&& errno != EINPROGRESS )
{
/* Identd Denied */
/* bug( "Unable to verify userid", 9 ); */
close( d->auth_fd );
d->auth_fd = -1;
d->auth_state = 0;
return;
}
d->auth_state |= ( FLAG_WRAUTH|FLAG_AUTH ); /* Successful, but not sent */
if ( d->auth_fd > maxdesc ) maxdesc = d->auth_fd;
return;
}
/* send_auth */
void send_auth( struct descriptor_data *d )
{
struct sockaddr_in us, them;
char authbuf[32];
int ulen, tlen, z;
tlen = ulen = sizeof( us );
if ( getsockname( d->descriptor, ( struct sockaddr *)&us, &ulen )
|| getpeername( d->descriptor, ( struct sockaddr *)&them, &tlen ) )
{
bug( "auth getsockname error", 0 );
goto authsenderr;
}
/* compose request */
sprintf( authbuf, "%u , %u\r\n",
(unsigned int)ntohs(them.sin_port),
(unsigned int)ntohs(us.sin_port));
z = write( d->auth_fd, authbuf, strlen( authbuf ) );
if ( z != strlen( authbuf ) )
{
if (d->atimes >= 19)
{
/* sprintf( log_buf, "auth request, broken pipe [%d/%d]", z, errno );
log_string(log_buf); */
perror("send_auth");
}
authsenderr:
close( d->auth_fd );
if ( d->auth_fd == maxdesc ) maxdesc--;
d->auth_fd = -1;
d->auth_state &= ~FLAG_AUTH; /* Failure/Continue */
d->auth_inc = 0;
if ( d->atimes < 20 ) d->atimes++;
}
d->auth_state &= ~FLAG_WRAUTH; /* Successfully sent request */
return;
}
/* read_auth */
void read_auth( struct descriptor_data *d )
{
char *s, *t;
int len; /* length read */
char ruser[20], system[8]; /* remote userid */
u_short remp = 0, locp = 0; /* remote port, local port */
*system = *ruser = '\0';
/*
* Can't allow any other reads from client fd while waiting on the
* authfd to return a full valid string. Use the client's input buffer
* to buffer the authd reply. May take more than one read.
*/
if ( ( len = read( d->auth_fd, d->abuf + d->auth_inc,
sizeof( d->abuf ) - 1 - d->auth_inc ) ) >= 0 )
{
d->auth_inc += len;
d->abuf[d->auth_inc] = '\0';
}
if ( ( len > 0 ) && ( d->auth_inc != ( sizeof( d->abuf ) - 1 ) )
&& (sscanf( d->abuf, "%hd , %hd : USERID : %*[^:]: %10s",
&remp, &locp, ruser ) == 3 ) )
{
s = rindex( d->abuf, ':');
*s++ = '\0';
for ( t = ( rindex( d->abuf, ':' ) + 1 ); *t; t++ )
if ( !isspace(*t) )
break;
strncpy( system, t, sizeof( system ) );
for ( t = ruser; *s && ( t < ruser + sizeof( ruser ) ); s++ )
if ( !isspace( *s ) && *s != ':' )
*t++ = *s;
*t = '\0';
sprintf( log_buf, "auth reply ok, incoming user: [%s]", ruser );
log_string_plus( log_buf, LOG_COMM, LEVEL_GOD );
/* STRFREE(d->user);
d->user = STRALLOC(ruser);*/
}
else if ( len != 0 )
{
if (!index( d->abuf, '\n' ) && !index( d->abuf, '\r' ) ) return;
sprintf( log_buf, "bad auth reply: %s", d->abuf );
log_string_plus( log_buf, LOG_COMM, LEVEL_GOD );
ruser[0] = '\0';
}
close( d->auth_fd );
if ( d->auth_fd == maxdesc )
--maxdesc;
d->auth_inc = 0;
*d->abuf = '\0';
d->auth_fd = -1;
d->auth_state = 0;
if (ruser[0] == '\0' )
strcpy(ruser, "(no auth)" );
STRFREE(d->user);
d->user = STRALLOC(ruser);
return;
}
void nonblock( int s )
{
if ( fcntl( s, F_SETFL, FNDELAY ) == -1 )
{
perror( "Noblock" );
exit(2);
}
}
/*
int workaround( struct descriptor_data *d )
{
BAN_DATA *tmp;
char *nicnamehost;
sprintf( log_buf, "%s!%s@%s", d->name, d->user, d->host );
nicknamehost = str_dup( log_buf );
for ( tmp = ncsa_list; tmp; tmp = tmp->next )
{
if ( !match( tmp->user, nicknamehost ) )
{
FREE( nicknamehost );
write_to_descriptor( d->descriptor, "NCSA telnet patch loaded.\n" );
return 1;
}
}
FREE(nicknamehost);
return 0;
}
*/