Cover V03, I04
Article
Listing 1
Listing 2
Listing 3
Listing 4
Listing 5
Listing 6
Sidebar 1

jul94.tar


Listing 1: snklogin.c

/*  Listing 1
* snklogin.c - front end to standard login program
* which first authenticates the user using the
* SecureNet encryption key.
* Mark Dapoz   Wed Dec  2 15:41:47 MET 1992
*/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include <signal.h>
#include <setjmp.h>
#include <syslog.h>
#include <pwd.h>
#include "snk.h"
#include "pathnames.h"
#include "des.h"

char snkkey[8];
int pflag=0, iflag=0, hflag=0;
char *from_host = "unknown host";
char *from_ip   = "location unknown";
char *user      = NULL;

jmp_buf env;

main(argc, argv)
int argc;
char **argv;
{

char challenge[9], response[9], snkkey[8], reply[16];
char id[16], in_id[9], *p, message[1024];;
unsigned int oct1, oct2, oct3, oct4,
oct5, oct6, oct7, oct8, cksum;
register int ch;
int i;
int secured=0;
extern char *optarg;
extern int optind;
FILE *in_file;
extern int timeout();
char *real_ipinfo();
char *auth_class=NULL;
int quit();

/* list of hostnames that we allow through */
char *hosts_allow[] = {     "viceroy.bsc.no",
"traine.bsc.no",
"overlord.bsc.no",
NULL };

/* list of ip addresses that we allow through */
char *ip_addr_allow[] = {   "129.177.80.6",
"129.177.80.64",
"129.177.80.5",
NULL };

signal(SIGALRM, timeout);
/* just die if anything goes wrong */
signal(SIGHUP, quit);
signal(SIGINT, quit);
signal(SIGQUIT, quit);
signal(SIGILL, quit);
signal(SIGABRT, quit);
signal(SIGSEGV, quit);

signal(SIGTERM, quit);

/* zero out the snkkey first */
for (i=0; i<= 7; i++)
snkkey[i] = NULL;

/* send messages to syslog */
openlog(argv[0], LOG_PID | LOG_CONS, LOG_AUTH);

while ((ch = getopt(argc, argv, "c:h:i:p")) != EOF) {
switch((char)ch) {
case 'c':
auth_class=optarg;
break;
case 'h':
hflag++;
from_host=optarg;
break;
case 'i':
iflag++;
from_ip=optarg;
break;
case 'p':
pflag++;
break;
case '?':
default:
break;
}
}
argc -= optind;
argv += optind;
if (argc)
user=argv[0];

/* check for hosts we allow directly in */
if (hflag)
secured+=allow(from_host, hosts_allow);
if (iflag)
secured+=allow(from_ip, ip_addr_allow);
/* restricted access line (remote) */
if (auth_class) {
struct passwd *pw=getpwnam(user);

if (pw && !strcmp(pw->pw_class, auth_class))
secured++;
}

sprintf(message, "Connection from %s (%s)\n",
from_host, from_ip);
fprintf(stderr, "%s", message);
syslog(LOG_NOTICE, message);
/* let some people straight through */
if (secured) {
syslog(LOG_NOTICE,
"Direct access allowed from %s (%s) for %s",
from_host, from_ip, user ? user : "(unknown)");
start_login(secured);
syslog(LOG_ERR,"Can't start login process: %m");
fprintf(stderr,"Problems starting %s...",
_PATH_LOGIN);
quit();
}

/* open the key file */
if ((in_file = fopen(_PATH_KEYFILE, "r")) == NULL) {
perror("keyfile");
syslog(LOG_ERR,"Can't open key file: %m");
fprintf(stderr,"Can't open the key file...");
quit();
}

/* SNK userid supplied on command line */
if (user) {
for (p=user; isalpha(*p) | isdigit(*p); p++);
*p='\0';
strncpy(id,user,sizeof(id));
} else {    /* prompt and get the SNK userid */
for(id[0]='\0'; !strlen(id);) {
fprintf(stderr,"\nSNK login: ");
fflush(stderr);
if(setjmp(env) == 0) {
alarm(SNKTIMEOUT);
if (!fgets(id, sizeof(id), stdin))
quit();
alarm(0);
for (p=id; isalpha(*p) | is-
digit(*p); p++);
*p='\0';
} else {
fprintf(stderr,"Timeout...");
quit();
}
}
}

/* get the key associated with the userid and
put the key into snkkey */
while (fgets(message, sizeof(message), in_file) != NULL) {
sscanf(message, "%9s %o %o %o %o %o %o %o %o %x",
in_id, &oct1, &oct2, &oct3, &oct4,
&oct5, &oct6, &oct7, &oct8, &cksum);
if (strlen(in_id) && strncmp(in_id, "#", 1)) {
if ((ismatch(in_id, id))) {

snkkey[0] = oct1;
snkkey[1] = oct2;
snkkey[2] = oct3;
snkkey[3] = oct4;
snkkey[4] = oct5;
snkkey[5] = oct6;
snkkey[6] = oct7;
snkkey[7] = oct8;
break;

}
}
*in_id='\0';
}
fclose(in_file);

/* compute the challenge/response, give them the
challenge, and get the response from the user */
installkey(snkkey, pkey);
buildsnk(pkey, challenge, response);
fprintf(stderr,"Challenge is: %s\nEnter Response: ",
challenge);

if(setjmp(env) == 0) {
alarm(SNKTIMEOUT);
fgets(reply, sizeof(reply), stdin);
alarm(0);
for (p=reply; isalpha(*p) | isdigit(*p); p++);
*p='\0';
} else {
fprintf(stderr,"Timeout...");
quit();
}
for(i=0; i<=7; i++)
if(islower(reply[i]))
reply[i]=toupper(reply[i]);

/* if the reply the user gives doesn't match with the
response we compute, they're out of here! */
if ((strncmp(response, reply, 8)) != 0) {
syslog(LOG_NOTICE,
"Failed SNK login for %s from %s (%s).", id,
from_host, from_ip);
fprintf(stderr,"Incorrect response...");
quit();
} else {
start_login(secured);
syslog(LOG_ERR,"Can't start login process: %m");
fprintf(stderr,"Problems starting %s...",
_PATH_LOGIN);
}
quit();
}

timeout(sig)
int sig;
{
signal(sig, SIG_IGN);
signal(SIGALRM, timeout);
longjmp(env, 1);
}

/* check if something is on the list */
allow(who, list)
char *who;
char *list[];
{
char *p;

for (p=*list; p; p=*(++list)) {
if (!strcmp(who, p))
return(1);
}
return(0);
}

int ismatch (s1, s2)
char *s1, *s2;
{
if (strlen(s1) != strlen(s2))
return(0);
return(!strncmp(s1, s1, 8));
}

quit()
{
fprintf(stderr,"closing connection\n");
fflush(stderr);
exit(1);
}

/* start a normal login process */
start_login(secure)
int secure;
{
register char **argv;
char **addarg();

argv = addarg(0, "login");
if (hflag) {
argv = addarg(argv, "-h");
argv = addarg(argv, from_host);
}
if (pflag)
argv = addarg(argv, "-p");
if (user) {
if (secure) {   /* only allow one login attempt */
argv = addarg(argv, "-m");
argv = addarg(argv, "1");
}
argv = addarg(argv, user);
} else
if (user=getenv("USER"))
/* special login id */
if (strcmp(SNKLOGIN, user))
argv = addarg(argv, user);

fprintf(stderr, "\n");
execv(_PATH_LOGIN, argv);
}

char **addarg(argv, val)
register char **argv;
register char *val;
{
register char **cpp;

if (argv == NULL) {
/*
* 10 entries, a leading length, and a null
*/
argv = (char **)malloc(sizeof(*argv) * 12);
if (argv == NULL)
return(NULL);
*argv++ = (char *)10;
*argv = (char *)0;
}
for (cpp = argv; *cpp; cpp++)
;
if (cpp == &argv[(int)argv[-1]]) {
--argv;
*argv = (char *)((int)(*argv) + 10);
argv = (char **)realloc(argv, (int)(*argv) + 2);
if (argv == NULL)
return(NULL);
argv++;
cpp = &argv[(int)argv[-1] - 10];
}
*cpp++ = val;
*cpp = 0;
return(argv);
}

/* end of snklogin.c */