--- Makefile.orig	Mon Apr 26 11:34:13 1999
+++ Makefile	Thu Apr 22 14:23:42 1999
@@ -243,5 +243,5 @@
 
 install_prefix	=
-prefix		= /usr/local
+prefix		= /home/aland
 exec_prefix	= ${prefix}
 bindir		= ${exec_prefix}/bin
@@ -250,13 +250,13 @@
 man1dir		= $(mandir)/man1
 man8dir		= $(mandir)/man8
-etcdir		= /etc
+etcdir		= /home/aland/ssh
 piddir		= /var/run
 
 COMMERCIAL	=
 CC 		= gcc -pipe
-CFLAGS 		= -g -O2
+CFLAGS 		= -g -O2 -I/home/aland/src/libradius/src
 LDFLAGS		= 
 DEFS 		= -DHAVE_CONFIG_H $(COMMERCIAL)
-LIBS		= -lnsl -lbsd -lcrypt -L/usr/local/lib  -lutil
+LIBS		= -lnsl -lbsd -lcrypt -L/usr/local/lib  -lutil -L/home/aland/src/libradius/src -lradius
 LIBOBJS		= 
 CONFOBJS	=  idea.o
--- config.h.orig	Mon Apr 26 11:25:58 1999
+++ config.h	Mon Apr 26 11:22:45 1999
@@ -188,4 +188,7 @@
 /* #undef HAVE_TIS */
 
+/* Define this if you want to support RADIUS Authentication scheme. */
+#define HAVE_RADIUS
+
 /* Define this if you are using HPSUX.  HPUX uses non-standard shared
    memory communication for X, which seems to be enabled by the display name
--- readconf.h.orig	Mon Apr 26 11:29:18 1999
+++ readconf.h	Mon Apr 26 11:29:22 1999
@@ -87,4 +87,5 @@
   int kerberos_tgt_passing;	/* Try Kerberos tgt passing. */
   int tis_authentication;	/* Try TIS authsrv authentication. */
+  int radius_authentication;	/* Try RADIUS authsrv authentication. */
   int password_authentication;	/* Try password authentication. */
   int fallback_to_rsh;		/* Use rsh if cannot connect with ssh. */
--- servconf.h.orig	Mon Apr 26 11:25:59 1999
+++ servconf.h	Mon Apr 26 10:22:08 1999
@@ -114,4 +114,9 @@
   int allow_tcp_forwarding;
   int tis_authentication;	/* If true, permit TIS authsrv auth. */
+  int radius_authentication;	/* If true, permit RADIUS authsrv auth. */
+  char *radius_server;		/* RADIUS server:port */
+  char *radius_secret;		/* RADIUS secret */
+  int radius_timeout;		/* RADIUS timeout */
+  int radius_fake_tis;		/* sshd does RADIUS, but tells client TIS */
   int password_authentication;  /* If true, permit password authentication. */
   int permit_empty_passwd;      /* If false, do not permit empty passwords. */
--- sshconnect.c.orig	Mon Apr 26 11:25:59 1999
+++ sshconnect.c	Mon Apr 26 11:31:15 1999
@@ -1757,4 +1757,71 @@
       }
     }
+
+  /* Support for RADIUS authentication server
+     Contributed by Alan DeKok <alan@cryptocard.com>. */
+  /*
+   * Try RADIUS authentication daemon if the server supports it.
+   * First, we ask for a password and send that over.
+   * If we get SUCCESS, we're in.  If not, show the message
+   * to the user, (there MUST be a message), and ask for the response.
+   * If that fails, die horribly.
+   */
+  if ((supported_authentications & (1 << SSH_AUTH_RADIUS)) &&
+      options->radius_authentication && !options->batch_mode)
+    {
+      char prompt[80];
+      debug("RADIUS asking authentication.");
+      if (options->cipher == SSH_CIPHER_NONE)
+	log_msg("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
+      
+      if (options->password_prompt_login && options->password_prompt_host)
+	sprintf(prompt, "%.30s@%.30s's password: ", server_user, host);
+      else if (!options->password_prompt_login &&
+	       !options->password_prompt_host)
+	sprintf(prompt, "Password: ");
+      else if (options->password_prompt_login)
+	sprintf(prompt, "%.30s's password: ", server_user);
+      else
+	sprintf(prompt, "%.30s password: ", host);
+      
+      /* unlike passwords, we only do this once, instead of looping */
+      password = read_passphrase(pw->pw_uid, prompt, 0);
+      packet_start(SSH_CMSG_AUTH_RADIUS);
+      packet_put_string(password, strlen(password));
+      memset(password, 0, strlen(password));
+      xfree(password);
+      packet_send();
+      packet_write_wait();
+      
+      type = packet_read();
+      if (type == SSH_SMSG_SUCCESS)
+	return; /* Successful connection. */
+      if (type == SSH_SMSG_FAILURE) {
+	/* Authentication failure : either the authentication server is */
+	/* not accessible (or unknown) or the user is not registered on */
+	/* the authentication server. Try next authentication method. */
+	debug("User cannot be identifier on authentication server.");
+      } else if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
+	packet_disconnect("Protocol error: got %d in response to RADIUS auth request", type);
+      } else {			/* it IS a RADIUS challenge... */
+	char *challenge;
+	
+	challenge = packet_get_string(NULL);
+	password = read_passphrase(pw->pw_uid, challenge, 0);
+	packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
+	packet_put_string(password, strlen(password));
+	memset(password, 0, strlen(password));
+	xfree(password);
+	packet_send();
+	packet_write_wait();
+	
+	type = packet_read();
+	if (type == SSH_SMSG_SUCCESS)
+	  return; /* Successful connection. */
+	if (type != SSH_SMSG_FAILURE)
+	  packet_disconnect("Protocol error: got %d in response to RADIUS auth",
+			    type);
+      }
+    }
   
   /* Try password authentication if the server supports it. */
--- readconf.c.orig	Mon Apr 26 11:25:59 1999
+++ readconf.c	Thu Apr 22 14:36:17 1999
@@ -172,5 +172,6 @@
   oKeepAlives, oUsePrivilegedPort, oKerberosAuthentication,
   oKerberosTgtPassing, oClearAllForwardings, oNumberOfPasswordPrompts,
-  oXauthPath, oGatewayPorts, oPasswordPromptLogin, oPasswordPromptHost
+  oXauthPath, oGatewayPorts, oPasswordPromptLogin, oPasswordPromptHost,
+  oRADIUSAuthentication
 } OpCodes;
 
@@ -189,4 +190,5 @@
   { "rsaauthentication", oRSAAuthentication },
   { "tisauthentication", oTISAuthentication },
+  { "radiusauthentication", oRADIUSAuthentication },
   { "fallbacktorsh", oFallBackToRsh },
   { "usersh", oUseRsh },
@@ -341,4 +343,9 @@
     case oTISAuthentication:
       intptr = &options->tis_authentication;
+      goto parse_flag;
+      
+    case oRADIUSAuthentication:
+      intptr = &options->radius_authentication;
+      debug("RADIUS client got config");
       goto parse_flag;
       
--- servconf.c.orig	Mon Apr 26 11:25:59 1999
+++ servconf.c	Mon Apr 26 10:22:47 1999
@@ -108,4 +108,9 @@
   options->kerberos_tgt_passing = -1;
   options->tis_authentication = -1;
+  options->radius_authentication = -1;
+  options->radius_server = NULL;
+  options->radius_secret = NULL;
+  options->radius_timeout = -1;
+  options->radius_fake_tis = -1;
   options->allow_tcp_forwarding = -1;
   options->password_authentication = -1;
@@ -208,4 +213,14 @@
   if (options->tis_authentication == -1)
     options->tis_authentication = 0;
+  if (options->radius_authentication == -1)
+    options->radius_authentication = 0;
+  if (options->radius_server == NULL)
+    options->radius_server = "localhost";
+  if (options->radius_secret == NULL)
+    options->radius_secret = "testing123";
+  if (options->radius_timeout == -1)
+    options->radius_timeout = 5;
+  if (options->radius_fake_tis == -1)
+    options->radius_fake_tis = 0;
   if (options->password_authentication == -1)
     options->password_authentication = 1;
@@ -253,5 +268,7 @@
   sXauthPath, sCheckMail, sDenyGroups, sAllowGroups, sIgnoreRootRhosts,
   sAllowSHosts, sDenySHosts, sPasswordExpireWarningDays,
-  sAccountExpireWarningDays
+  sAccountExpireWarningDays,
+  sRADIUSAuthentication, sRADIUSServer, sRADIUSSecret,  sRADIUSTimeout,
+  sRADIUSFakeTIS
 #ifdef F_SECURE_COMMERCIAL
 
@@ -280,4 +297,9 @@
   { "rsaauthentication", sRSAAuthentication },
   { "tisauthentication", sTISAuthentication },
+  { "radiusauthentication", sRADIUSAuthentication },
+  { "radiusserver", sRADIUSServer },
+  { "radiussecret", sRADIUSSecret },
+  { "radiustimeout", sRADIUSTimeout },
+  { "radiusfaketis", sRADIUSFakeTIS },
   { "passwordauthentication", sPasswordAuthentication },
   { "uselogin", sUseLogin },
@@ -381,4 +403,5 @@
       linenum++;
       cp = line + strspn(line, WHITESPACE);
+
       if (!*cp || *cp == '#')
 	continue;
@@ -579,4 +602,34 @@
 	case sTISAuthentication:
 	  intptr = &options->tis_authentication;
+	  goto parse_flag;
+	  
+	case sRADIUSAuthentication:
+	  intptr = &options->radius_authentication;
+	  goto parse_flag;
+	  
+	case sRADIUSServer:
+	  charptr = &options->radius_server;
+	parse_text:
+	  cp = strtok(NULL, WHITESPACE);
+	  if (!cp)
+	    {
+	      fprintf(stderr, "%s line %d: missing text.\n",
+		      filename, linenum);
+	      exit(1);
+	    }
+	  if (*charptr == NULL)
+	    *charptr = xstrdup(cp);
+	  break;
+
+	case sRADIUSSecret:
+	  charptr = &options->radius_secret;
+	  goto parse_text;
+	  
+	case sRADIUSTimeout:
+	  intptr = &options->radius_timeout;
+	  goto parse_int;
+	  
+	case sRADIUSFakeTIS:
+	  intptr = &options->radius_fake_tis;
 	  goto parse_flag;
 	  
--- ssh.h.orig	Mon Apr 26 11:25:59 1999
+++ ssh.h	Mon Apr 26 11:09:52 1999
@@ -327,4 +327,5 @@
 /* If you add new methods add them after this using random number between 16-31
    so if someone else adds also new methods you dont use same number. */
+#define SSH_AUTH_RADIUS		29
 
 /* Protocol flags.  These are bit masks. */
@@ -402,4 +403,7 @@
    you dont use same numbers */
 
+/* Support for RADIUS authentication server
+   Contributed by Alan DeKok <alan@cryptocard.com>. */
+#define SSH_CMSG_AUTH_RADIUS			111	/* authentication */
 
 /* define this and debug() will print local hostname */
--- sshd.c.orig	Mon Apr 26 11:25:59 1999
+++ sshd.c	Mon Apr 26 11:12:00 1999
@@ -490,4 +490,11 @@
 #endif
 
+#ifdef HAVE_RADIUS
+/* Support for RADIUS authentication server
+   Contributed by Alan DeKok <alan@cryptocard.com>. */
+#include "radius.h"
+#include "libradius.h"
+#endif
+
 #if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
 #include <login_cap.h>
@@ -1441,4 +1448,18 @@
     auth_mask |= 1 << SSH_AUTH_TIS;
 #endif
+#ifdef HAVE_RADIUS
+  if (options.radius_authentication) {
+    auth_mask |= 1 << SSH_AUTH_RADIUS;
+
+    /*
+     *  For old clients: the server is NOT doing TIS, but
+     * is faking out TIS for the old clients.
+     */
+    if (!options.tis_authentication &&
+	options.radius_fake_tis) {
+      auth_mask |= 1 << SSH_AUTH_TIS;
+    }
+  }
+#endif
 #ifdef KERBEROS
 #ifdef KRB5
@@ -2212,4 +2233,6 @@
     }
 
+  debug("trying to authenticate...");
+
   /* Loop until the user has been authenticated or the connection is closed. */
   while (!authenticated)
@@ -2217,5 +2240,4 @@
       /* Get a packet from the client. */
       type = packet_read();
-      
       /* Process the packet. */
       switch (type)
@@ -2429,4 +2451,11 @@
 	  debug("TIS Authentication...");
 	  if (!options.tis_authentication) {
+#ifdef HAVE_RADIUS
+	    /* ONLY if TIS is off do we fake TIS */
+	    if (options.radius_fake_tis) {
+	      debug("RADIUS faking TIS Authentication...");
+	      goto radius_authentication;	/* yuck, I know... */
+	    }
+#endif
 	    packet_get_all();
 	    log_msg("Tis authsrv authentication disabled.");
@@ -2558,4 +2587,162 @@
 	  break;	/* TIS authsrv authentication not supported */
 #endif
+
+#ifdef HAVE_RADIUS
+#ifndef HAVE_TIS
+	  /* RADIUS and NOT TIS means that we can fake TIS out */
+	case SSH_CMSG_AUTH_TIS:
+#endif
+	case SSH_CMSG_AUTH_RADIUS:
+	  /* Support for RADIUS authentication server
+	     Contributed by Alan DeKok <alan@cryptocard.com>. */
+	radius_authentication:
+	  debug("RADIUS Authentication...");
+	  if (!options.radius_authentication) {
+	    packet_get_all();
+	    log_msg("RADIUS authsrv authentication disabled.");
+	    break;
+
+	    /* otherwise do straightforward RADIUS */
+	  } else {
+	    char buf[128];
+	    char mapping[128];
+	    int rad_auth;
+	    char *key, *value, *resp;
+	    int tries = 0;
+	    char state[256];
+	    int state_len = 0;
+
+	    AUTH_HDR *request, *reply;
+	    char *server, *port;
+
+	    server = xstrdup(options.radius_server);
+	    port = strchr(server, ':');
+	    if (port) {
+	      *(port++) = '\0';
+	    }
+
+	    debug("RADIUS server = %s", server);
+	    debug("RADIUS port = %s", port);
+	    debug("RADIUS secret = %s", options.radius_secret);
+	    debug("RADIUS timeout = %d", options.radius_timeout);
+
+	    if (!options.radius_fake_tis) {
+	      /* check the password */
+	      password = packet_get_string(NULL);
+	    } else {
+	      password = xstrdup("fakeTIS");
+	    }
+	      
+	    request = lrad_packet_create(PW_ACCESS_REQUEST);
+	    reply = lrad_packet_create(PW_RESERVED);
+	    if (!request || !reply) {
+	      log_msg("out of memory");
+	      packet_start(SSH_SMSG_FAILURE);
+	      packet_send();
+	      packet_write_wait();
+	      goto radius_exit;
+	    }
+	    
+	  radius_repeat:
+	    /* add User name and password to the request */
+	    lrad_attr_add(request, PW_USER_NAME, user, -1);
+	    lrad_attr_add_password(request, PW_PASSWORD, password, 
+				   options.radius_secret);
+	    if (tries > 0 ) {
+	      lrad_attr_add(request, PW_STATE, state, state_len);
+	    }
+
+	    rad_auth = lrad_client_send_recv(request, reply, server, port,
+					     options.radius_timeout);
+	    if (rad_auth <= 0) {
+	      log_msg("Cannot connect to authentication server");
+	      packet_start(SSH_SMSG_FAILURE);
+	      packet_send();
+	      packet_write_wait();
+
+	      goto radius_exit;
+	    }
+	    debug("RADIUS server response = %d", reply->code);
+
+	    if (reply->code == PW_ACCESS_ACCEPT) {
+
+	       /* this should NEVER happen */
+	      if ((tries == 0) &&
+		  options.radius_fake_tis) {
+		debug("RADIUS server accepted our fake password for %s: authentication failed");
+		goto radius_exit;
+	      }
+
+	      authentication_type = SSH_AUTH_RADIUS;
+	      authenticated = 1;
+	      goto radius_exit;
+
+	      /* only allow an Access-Challenge once */
+	    } else if ((tries == 0) &&
+		       (reply->code == PW_ACCESS_CHALLENGE)) {
+	      RADIUS_ATTR *attr;
+	      char challenge[256];
+	      
+	      tries++;
+	      attr = lrad_attr_fetch(reply, PW_STATE);
+	      if (!attr) {
+		debug("RADIUS server sent no State for %s: authentication failed",user);
+		goto radius_exit;
+	      }
+
+	      /* ensure we save the state */
+	      state_len = attr->length - 2;
+	      memcpy(state, attr->data, state_len);
+
+	      /* get rid of the old password, first */
+	      memset(password, 0, strlen(password));
+	      xfree(password);
+
+	      /* grab the challenge string (from a Reply-Message) */
+	      attr = lrad_attr_fetch(reply, PW_REPLY_MESSAGE);
+	      if (!attr) {
+		debug("RADIUS server sent no Reply-Message for %s: authentication failed",user);
+		goto radius_exit;
+	      }
+	      memcpy(challenge, attr->data, attr->length - 2);
+	      challenge[attr->length - 2] = '\0';
+	      
+	      packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
+	      packet_put_string(challenge, attr->length - 2);
+	      packet_send();
+	      packet_write_wait();
+	      
+	      type = packet_read();
+	      if (type != SSH_CMSG_AUTH_TIS_RESPONSE) {
+		packet_get_all();
+		log_msg("Protocol error: got %d in response to RADIUS challenge",
+			type);
+		break;
+	      }
+
+	      /* refresh the RADIUS request packet */
+	      request->id++;
+	      lrad_random_vector(request->vector);
+	      request->length = htons(AUTH_HDR_LEN);
+	      
+	      password = packet_get_string(NULL);
+	      goto radius_repeat;
+	      
+	    } else {		/* Access-Reject, or something else */
+	      debug("RADIUS authentication for %s failed",user);
+
+	    radius_exit:
+	      memset(password, 0, strlen(password));
+	      xfree(password);
+
+	      lrad_free(request, 0);
+	      lrad_free(reply, 0);
+	      xfree(server);
+	      break;
+	    }
+	  }
+	  break;	/* RADIUS authsrv authentication not supported */
+#endif
+
 	case SSH_CMSG_AUTH_PASSWORD:
 	  if (!options.password_authentication)
