home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacks & Cracks
/
Hacks_and_Cracks.iso
/
hackersclub
/
km
/
downloads
/
c_scripts
/
identdsp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-03-25
|
6KB
|
242 lines
/* $Id: identd.c,v 0.1 1994/05/22 21:41:23 qpliu Exp $
* identd.c by qpliu 1994 -- this program is in the public domain.
* RFC 1413 ident server using the linux /proc fs.
* This probably could be done much more simply with perl.
*/
/* Aug. 95 - modded by VectorX to accept a file of no more
then 14 characters on one line, called .fakeid, in the
users home directory, which will be substituted for the
actual identity of the user being looked up. Re-define
USERIDFILE and recompile to change he default lookup.
To install just compile, rename /usr/sbin/in.identd to a
backup, and replace w/this file.
*/
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <ctype.h>
#include <netinet/in.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* TIMEOUT is the number of seconds to wait before closing the connection if
* the client doesn't provide the port pairs.
*/
#define TIMEOUT 120
/* PROCINFO_PATH is where the /proc tcp information is found */
#define PROCINFO_PATH "/proc/net/tcp"
/* USERIDFILE is the file that can spoof the identd information */
#define USERIDFILE "/.fakeid"
/* PROCINFO_BUFFER_SIZE must be bigger than 80 */
#define PROCINFO_BUFFER_SIZE 2048
#define SOCKET_BUFFER_SIZE 100
unsigned short lport = 0, rport = 0;
#define INVALID_PORT 0
#define NO_USER 1
#define HIDDEN_USER 2
#define UNKNOWN_ERROR 3
char *errors[] = {
"INVALID-PORT", "NO-USER", "HIDDEN-USER", "UNKNOWN-ERROR"
};
void
error (int c)
{
char str[80];
sprintf (str, "%u , %u : ERROR : %s\r\n", lport, rport, errors[c]);
write (1, str, strlen (str));
exit (0);
}
void
main ()
{
struct sockaddr_in sin;
unsigned long here, there;
int len = sizeof (sin);
struct fd_set fdset;
struct timeval timeout;
char buffer[PROCINFO_BUFFER_SIZE > SOCKET_BUFFER_SIZE ?
PROCINFO_BUFFER_SIZE : SOCKET_BUFFER_SIZE];
char *spoofdir;
char *spoofid;
char spoofbuf[14];
int index;
enum {
have_neither, have_lport_start, have_lport,
have_comma, have_rport_start, have_both
} read_state;
int fd, spooffd, spooflen;
if (getsockname (0, (struct sockaddr *) &sin, &len) < 0) exit (0);
here = sin.sin_addr.s_addr;
if (getpeername (0, (struct sockaddr *) &sin, &len) < 0) exit (0);
there = sin.sin_addr.s_addr;
/* prepare to read ports */
FD_ZERO (&fdset);
FD_SET (0, &fdset);
timeout.tv_sec = TIMEOUT;
timeout.tv_usec = 0;
/* read ports from stdin */
read_state = have_neither;
index = 0;
while (read_state != have_both && 1 == select (1, &fdset, NULL, NULL, &timeout)) {
int i, newindex;
len = read (0, buffer + index, SOCKET_BUFFER_SIZE - index);
if (len <= 0)
exit (0);
i = index;
newindex = 0;
switch (read_state) {
case have_neither:
while (i < len + index) {
if (isdigit (buffer[i])) {
read_state = have_lport_start;
break;
}
if (!isspace (buffer[i]))
error (INVALID_PORT);
i++;
}
newindex = i;
/* fallthrough */
case have_lport_start:
while (i < len + index) {
if (!isdigit (buffer[i])) {
newindex = atoi (buffer + newindex);
if (newindex != newindex&0xffff && newindex == 0)
error (INVALID_PORT);
lport = newindex;
read_state = have_lport;
newindex = i;
break;
}
i++;
}
/* fallthrough */
case have_lport:
while (i < len + index) {
if (',' == buffer[i]) {
read_state = have_comma;
++i;
break;
}
if (!isspace (buffer[i]))
error (INVALID_PORT);
i++;
}
newindex = i;
/* fallthrough */
case have_comma:
while (i < len + index) {
if (isdigit (buffer[i])) {
read_state = have_rport_start;
break;
}
if (!isspace (buffer[i]))
error (INVALID_PORT);
i++;
}
newindex = i;
/* fallthrough */
case have_rport_start:
while (i < len + index) {
if (!isdigit (buffer[i])) {
newindex = atoi (buffer + newindex);
if (newindex != newindex&0xffff && newindex == 0)
error (INVALID_PORT);
rport = newindex;
read_state = have_both;
newindex = i;
break;
}
i++;
}
/* fallthrough */
}
index = i - newindex;
memmove (buffer, buffer + newindex, index);
FD_SET (0, &fdset);
}
if (read_state != have_both) exit (0);
/* get info from /proc/net/tcp */
fd = open (PROCINFO_PATH, O_RDONLY);
if (fd < 0)
error (UNKNOWN_ERROR);
index = 0;
/* linear search for matching addresses and ports */
while (0 < (len = read (fd, buffer + index, PROCINFO_BUFFER_SIZE - index))) {
int i, newindex;
unsigned long l_here, l_there;
unsigned short l_rport, l_lport;
int uid;
newindex = i = 0;
while (i < len + index) {
if (sscanf (buffer + i, "%*d: %lx:%hx %lx:%hx %*x %*x:%*x %*x:%*x %*x %d",
&l_here, &l_lport, &l_there, &l_rport, &uid) == 5) {
/* /proc/net/tcp displays addresses in net order and
* ports in host order--how convenient.
*/
if (here == l_here && lport == l_lport && there == l_there && rport == l_rport) {
struct passwd *p = getpwuid (uid);
if (NULL == p) error (UNKNOWN_ERROR);
spoofdir = p->pw_dir;
strcat(spoofdir, USERIDFILE);
spooffd = open(spoofdir, O_RDONLY);
if (spooffd < 0) {
sprintf (buffer, "%u , %u : USERID : UNIX : %s\r\n",
lport, rport, p->pw_name);
}
else
{
spooflen = read(spooffd, spoofbuf, sizeof(spoofbuf));
spoofid = strtok(spoofbuf, "\r\n");
sprintf (buffer, "%u , %u : USERID : UNIX : %s\r\n",
lport, rport, spoofid);
}
write (1, buffer, strlen (buffer));
exit (0);
}
}
newindex = i;
while (buffer[i++] != '\n' && i < len + index)
;
}
index = PROCINFO_BUFFER_SIZE - newindex;
memmove (buffer, buffer + newindex, index);
}
error (NO_USER);
}
/* $Log: identd.c,v $
* Revision 0.1 1994/05/22 21:41:23 qpliu
* Seems to work.
*
*/