openssh (OpenBSD) , bsdauth and tis authsrv

ArkanoiD ark at eltex.net
Tue Sep 12 21:02:26 EST 2006


nuqneH,

I've tried using TIS authsrv authentication via bsd auth and found
it quite limited. The most important restriction it does not log
ip and fqdn of the remote peer, nor the application name, to
the authentication server. It does not matter much for TIS authsrv,
but since other applications do provide such information, our
authsrv version uses it for extra authentication restrictions.
And - as tcp loopback interface is hardly considered secure -
we use unix domain sockets to talk to it instead.

I tried Mark Roth's patch, but it suffers from the similar problems
and does not support privsep api.

So i made my own, it is not very good yet (it does not take advantage
of init_ctx) but i hope i will fix that soon if you people will give 
me good advices.


-------------- next part --------------
diff -crP ssh/auth-tis.c ssh.my2/auth-tis.c
*** ssh/auth-tis.c	Thu Jan  1 03:00:00 1970
--- ssh.my2/auth-tis.c	Tue Sep 12 14:15:57 2006
***************
*** 0 ****
--- 1,598 ----
+ /*
+ **  Copyright 2006 ArkanoiD, Pitek Software Labs
+ **  Based on Mark D. Roth's module, original copyrights follow
+ */
+ /*
+ **  Copyright 2001-2003 University of Illinois Board of Trustees
+ **  Copyright 2001-2003 Mark D. Roth
+ **  All rights reserved. 
+ **
+ **  TIS authentication module for OpenSSH
+ **
+ **  Mark D. Roth <roth at uiuc.edu>
+ **  Campus Information Technologies and Educational Services
+ **  University of Illinois at Urbana-Champaign
+ */
+ 
+ #include "includes.h"
+ 
+ #include <auth.h>
+ 
+ #include "xmalloc.h"
+ #include "auth.h"
+ #include <login_cap.h>
+ #include <des.h>
+ #include <sys/stat.h>
+ #include <sys/uio.h>
+ #include <sys/un.h>
+ #include "auth-tis.h"
+ #include "monitor_wrap.h"
+ #include "log.h"
+ #include "servconf.h"
+ 
+ static ssize_t tis_recv(struct tis_connection *, u_char *, size_t);
+ static ssize_t tis_send(struct tis_connection *, u_char *, size_t);
+ static void send_fd(struct tis_connection *, int);
+ static void tis_getconf(struct tis_connection *, char *);
+ static ssize_t tis_decode(u_char *, size_t);
+ static ssize_t tis_encode(u_char *, size_t, size_t);
+ static int tis_getkey(struct tis_connection *);
+ static int tis_open(struct tis_connection *, const char *, char *);
+ static int tis_verify(struct tis_connection *, const char *, char *);
+ 
+ extern char *__progname;
+ extern ServerOptions options;
+ 
+ static struct tis_connection tc = { -1, TIS_DEFTIMEOUT, TIS_KEY, TIS_DEFPORT,
+ 				    TIS_DEFSERVER, TIS_DEFALTSERVER, NULL };
+ 
+ 
+ void *
+ tis_init_ctx(Authctxt *authctxt)
+ {
+ 	return authctxt;
+ }
+ 
+ int
+ tis_query(void *ctx, char **name, char **infotxt, 
+     u_int* numprompts, char ***prompts, u_int **echo_on)
+ {
+ 	Authctxt *authctxt = ctx;
+ 	static char challenge[1024];
+ 	char buf1[256], buf2[256]; 
+ 	char *cp;
+ 	FILE *f;
+ 
+ 	*name = xstrdup("");
+ 	*infotxt = xstrdup("");
+ 	*numprompts = 1;
+ 	*prompts = xmalloc(*numprompts * sizeof(char*));
+ 	*echo_on = xmalloc(*numprompts * sizeof(u_int));
+ 	(*echo_on)[0] = 0;
+ 
+ 	/* fake it if no account */
+ 	if (authctxt->pw == NULL)
+ 	{
+ 		(*prompts)[0] = "Password: ";
+ 		return 0;
+ 	}
+ 
+ 	/* connect to the authsrv */
+ 	if (tc.keyfile != NULL && tis_getkey(&tc) != 0) {
+ 		error("cannot read key file");
+ 		return -1;
+ 	}
+ 	if (tc.fd == -1) 
+ 	{
+ 		tis_getconf(&tc, authctxt->pw->pw_class);
+ 		if (tc.keyfile != NULL && tis_getkey(&tc) != 0)
+ 			error("cannot read encryption key");
+ 		debug2("main server %s, alternate %s", tc.server, tc.altserver);
+ 		if (tis_open(&tc, tc.server, buf1) == -1 && (tc.altserver &&
+ 		    tis_open(&tc, tc.altserver, buf1) == -1)) {
+ 			error("unable to connect to authsrv: %s",
+ 			    buf1);
+ 			return -1;
+ 		}
+ 	}
+ 
+ 	/* send authsrv username */
+ 	snprintf(buf2, sizeof(buf2), "authorize %.100s 'openssh %.128s/%.128s'",
+ 		 authctxt->user,get_canonical_hostname(options.use_dns),
+ 		 get_remote_ipaddr());
+ 	debug2("TIS get_challenge: sending to authsrv: %s", buf2);
+ 	if (tis_send(&tc,buf2,strlen(buf2)) != strlen(buf2))
+ 	{
+ 		logit("TIS authentication: tis_send() failed");
+ 		close(tc.fd);
+ 		tc.fd = -1;
+ 		return -1;
+ 	}
+ 
+ 	/* read challenge */
+ 	if (tis_recv(&tc, buf1, sizeof(buf1)) <= 0)
+ 	{
+ 		logit("TIS authentication: auth_recv() failed");
+ 		close(tc.fd);
+ 		tc.fd = -1;
+ 		return -1;
+ 	}
+ 
+ 	debug2("TIS get_challenge: received from authsrv: %s", buf1);
+ 	if (strncmp(buf1, "challenge ", 10) == 0 ||
+ 	    strncmp(buf1, "chalnecho ", 10) == 0)
+ 	{
+ 		debug2("TIS authentication: authsrv challenge: %.100s", buf1 + 10);
+ 		strlcpy(challenge, buf1 + 10, sizeof(challenge));
+ 		(*prompts)[0] = xstrdup(challenge);
+ 		return 0;
+ 	}
+ 	else if (strncmp(buf1, "password", 8) == 0)
+ 	{
+ 		logit("TIS authentication: authsrv requests user password");
+ 		(*prompts)[0] = "Password: ";
+ 		return 0;
+ 	}
+ 	else
+ 		logit("TIS authentication: unknown authsrv user");
+ 
+ 	return -1;
+ }
+ 
+ int
+ tis_respond(void *ctx, u_int numresponses, char **responses)
+ {
+ 	Authctxt *authctxt = ctx;
+ 	char buf1[256];
+ 
+ 	/* fail if no account */
+ 	if (authctxt->pw == NULL || !authctxt->valid || numresponses != 1)
+ 		return -1;
+ 
+ 	/* send response to authsrv */
+ 	snprintf(buf1, sizeof(buf1), "response '%.100s'", responses[0]);
+ 	debug2("TIS verify_response: sending to authsrv: %s", buf1);
+ 	if (tis_send(&tc, buf1, strlen(buf1)) != strlen(buf1))
+ 	{
+ 		logit("TIS authentication: auth_send() failed");
+ 		close(tc.fd);
+ 		tc.fd = -1;
+ 		return -1;
+ 	}
+ 
+ 	/* get reaction from authsrv */
+ 	if (tis_recv(&tc, buf1, sizeof(buf1)) <= 0)
+ 	{
+ 		logit("TIS authentication: auth_recv() failed");
+ 		close(tc.fd);
+ 		tc.fd = -1;
+ 		return -1;
+ 	}
+ 	debug2("TIS verify_response: received from authsrv: %.100s", buf1);
+ 
+ 	/* determine outcome */
+ 	if (strncmp(buf1, "ok", 2) == 0)
+ 	{
+ 		close(tc.fd);
+ 		tc.fd = -1;
+ 		return 0;
+ 	}
+  
+ 	return -1;
+ }
+ 
+ void
+ tis_free_ctx(void *ctx)
+ {
+ 	close(tc.fd);
+ 	tc.fd = -1;
+ }
+ 
+ KbdintDevice tis_device = {
+ 	"tis",
+ 	tis_init_ctx,
+ 	tis_query,
+ 	tis_respond,
+ 	tis_free_ctx
+ };
+ 
+ KbdintDevice mm_tis_device = {
+ 	"tis",
+ 	tis_init_ctx,
+ 	mm_tis_query,
+ 	mm_tis_respond,
+ 	tis_free_ctx
+ };
+ 
+ 
+ /*
+  * Send the file descriptor in struct tis_connection over a socketpair
+  * to the parent process to keep the connection to authsrv open.
+  */
+ void
+ send_fd(struct tis_connection *tc, int sock)
+ {
+ 	struct msghdr msg;
+ 	struct cmsghdr *cmp;
+ 	char cmsgbuf[CMSG_SPACE(sizeof(int))];
+ 
+ 	memset(&msg, 0, sizeof(msg));
+ 	msg.msg_control = cmsgbuf;
+ 	msg.msg_controllen = CMSG_LEN(sizeof(int));
+ 
+ 	cmp = CMSG_FIRSTHDR(&msg);
+ 	cmp->cmsg_len = CMSG_LEN(sizeof(int));
+ 	cmp->cmsg_level = SOL_SOCKET;
+ 	cmp->cmsg_type = SCM_RIGHTS;
+ 
+ 	*(int *)CMSG_DATA(cmp) = tc->fd;
+ 
+ 	if (sendmsg(sock, &msg, 0) < 0)
+ 		logit("sendmsg: %m");
+ }
+ 
+ /*
+  * Look up the given login class and populate struct tis_connection.
+  */
+ void
+ tis_getconf(struct tis_connection *tc, char *class)
+ {
+ 	extern login_cap_t *lc;
+ 
+ 	if ((lc = login_getclass(class)) == NULL) {
+ 		tc->port = TIS_DEFPORT;
+ 		tc->timeout = TIS_DEFTIMEOUT;
+ 		tc->server = TIS_DEFSERVER;
+ 		tc->altserver = TIS_DEFALTSERVER;
+ 		tc->keyfile = NULL;
+ 		return;
+ 	}
+ 
+ 	tc->port = login_getcapstr(lc, "tis-port", TIS_DEFPORT, TIS_DEFPORT);
+ 	tc->timeout = login_getcapnum(lc, "tis-timeout", TIS_DEFTIMEOUT,
+ 	    TIS_DEFTIMEOUT);
+ 	tc->server = login_getcapstr(lc, "tis-server", TIS_DEFSERVER,
+ 	    TIS_DEFSERVER);
+ 	tc->altserver = login_getcapstr(lc, "tis-server-alt", TIS_DEFALTSERVER, TIS_DEFALTSERVER);
+ 	tc->keyfile = login_getcapstr(lc, "tis-keyfile", NULL, NULL);
+ }
+ 
+ /*
+  * Read an ASCII string from a file and convert it to a DES key.
+  */
+ int
+ tis_getkey(struct tis_connection *tc)
+ {
+ 	size_t len;
+ 	struct stat sb;
+ 	des_cblock cblock;
+ 	char *key, *tbuf = NULL;
+ 	FILE *fp;
+ 	int error;
+ 
+ 	if ((fp = fopen(tc->keyfile, "r")) == NULL) {
+ 		logit("%s: %m", tc->keyfile);
+ 		return (-1);
+ 	}
+ 	if (fstat(fileno(fp), &sb) == -1) {
+ 		logit("%s: %m", tc->keyfile);
+ 		fclose(fp);
+ 		return (-1);
+ 	}
+ 	if (sb.st_uid != 0) {
+ 		logit("%s: not owned by root", tc->keyfile);
+ 		fclose(fp);
+ 		return (-1);
+ 	}
+ 	if (!S_ISREG(sb.st_mode)) {
+ 		logit("%s: not a regular file", tc->keyfile);
+ 		fclose(fp);
+ 		return (-1);
+ 	}
+ 	if (sb.st_mode & (S_IRWXG|S_IRWXO)) {
+ 		logit("%s: readable or writable by non-owner",
+ 		    tc->keyfile);
+ 		fclose(fp);
+ 		return (-1);
+ 	}
+ 	if ((key = fgetln(fp, &len)) == NULL || (len == 1 && key[0] == '\n')) {
+ 		if (ferror(fp))
+ 			logit("%s: %m", tc->keyfile);
+ 		else
+ 			logit("%s: empty key file", tc->keyfile);
+ 		fclose(fp);
+ 		return (-1);
+ 	}
+ 	fclose(fp);
+ 	if (key[len - 1] == '\n')
+ 		key[--len] = '\0';
+ 	else {
+ 		if ((tbuf = malloc(len + 1)) == NULL) {
+ 			logit("%s: %m", tc->keyfile);
+ 			return (-1);
+ 		}
+ 		memcpy(tbuf, key, len);
+ 		tbuf[len] = '\0';
+ 		key = tbuf;
+ 	}
+ 	des_string_to_key(key, &cblock);
+ 	error = des_set_key(&cblock, tc->keysched);
+ 	memset(key, 0, len);
+ 	memset(&cblock, 0, sizeof(cblock));
+ 	if (tbuf) free(tbuf);
+ 	return (error);
+ }
+ 
+ /*
+  * Open a connection to authsrv and read the welcom banner.
+  * Returns the file descriptor on success and -1 on error
+  * or unrecognized welcome banner.
+  */
+ int
+ tis_open(struct tis_connection *tc, const char *server, char *ebuf)
+ {
+ 	char buf[TIS_BUFSIZ];
+ 	int error;
+ 
+ 	ebuf[0] = '\0';
+ 	if (strncasecmp(server, "unix:", strlen("unix:"))) {
+ 		struct addrinfo hints, *res, *res0;
+ 		memset(&hints, 0, sizeof(hints));
+ 		hints.ai_socktype = SOCK_STREAM;
+ 		hints.ai_family = PF_UNSPEC;
+ 		hints.ai_flags = 0;
+ 		debug("talking to authsrv server %s port %s",server, tc->port);
+ 		error = getaddrinfo(server, tc->port, &hints, &res0);
+ 		if (error) {
+ 			strlcpy(ebuf, gai_strerror(error), TIS_BUFSIZ);
+ 			freeaddrinfo(res0);
+ 			return (-1);
+ 		}
+ 
+ 		/* connect to the first address that succeeds */
+ 		for (res = res0; res != NULL; res = res->ai_next) {
+ 			tc->fd = socket(res->ai_family, res->ai_socktype,
+ 		    	res->ai_protocol);
+ 			if (tc->fd != -1) {
+ 				if (connect(tc->fd, res->ai_addr, res->ai_addrlen) == 0)
+ 					break;
+ 				close(tc->fd);
+ 				tc->fd = -1;
+ 			}
+ 		}
+ 		if (res == NULL) {
+ 			strlcpy(ebuf, strerror(errno), TIS_BUFSIZ);
+ 			freeaddrinfo(res0);
+ 			tc->fd = -1;
+ 			return (-1);
+ 		}
+ 		freeaddrinfo(res0);
+ 		debug("TIS authsrv inet connection success");
+ 	} else {
+ 		struct sockaddr_un sa;
+ 		tc->fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ 		if (tc->fd != -1) {
+ 			strncpy(sa.sun_path, server + strlen("unix:"),  
+ 				sizeof(sa.sun_path));
+ 			sa.sun_family = AF_UNIX;
+ 			if (connect(tc->fd, 
+ 				    (struct sockaddr *)&sa, sizeof(sa)) < 0 ) {
+ 				close(tc->fd);
+ 				tc->fd = -1;
+ 				debug2("unix socket connection fail");
+ 				return (-1);
+ 			}
+ 		}
+ 		debug("TIS authsrv unix connection success");
+ 	}
+ 		
+ 
+ 	/* read welcome banner */
+ 	if (tis_recv(tc, buf, sizeof(buf)) == -1) {
+ 		strlcpy(ebuf, strerror(errno), TIS_BUFSIZ);
+ 		close(tc->fd);
+ 		tc->fd = -1;
+ 		return (-1);
+ 	}
+ 	if (strncmp(buf, "Authsrv ready", 13) != 0) {
+ 		strlcpy(ebuf, buf, TIS_BUFSIZ);
+ 		close(tc->fd);
+ 		tc->fd = -1;
+ 		return (-1);
+ 	}
+ 	debug("TIS authsrv connection setup success");
+ 
+ 	return (tc->fd);
+ }
+ 
+ /*
+  * Read a one-line response from authsrv.
+  * On success, returns 0.  On error, returns non-zero and calls syslog().
+  */
+ ssize_t
+ tis_recv(struct tis_connection *tc, u_char *buf, size_t bufsiz)
+ {
+ 	des_key_schedule ks;
+ 	des_cblock iv;
+ 	ssize_t len;
+ 	u_char *cp, *ep, tbuf[TIS_BUFSIZ];
+ 
+ 	for (cp = buf, ep = buf + bufsiz; cp < ep; cp++) {
+ 		alarm(tc->timeout);
+ 		len = read(tc->fd, cp, 1);
+ 		alarm(0);
+ 		if (len != 1) {
+ 			if (len == -1)
+ 				logit("error reading data from authsrv: %m");
+ 			else
+ 				logit("EOF reading data from authsrv");
+ 			return (-1);
+ 		}
+ 		if (*cp == '\n')
+ 			break;
+ 	}
+ 	if (*cp != '\n') {
+ 		logit("server response too large");
+ 		return (-1);
+ 	}
+ 	*cp = '\0';
+ 	len = cp - buf;
+ 
+ 	if (tc->keyfile != NULL) {
+ 		if ((len = tis_decode(buf, len)) < 0) {
+ 		    logit("improperly encoded data from authsrv");
+ 		    return (-1);
+ 		}
+ 		if (len > sizeof(tbuf)) {
+ 			logit("encrypted data too large to store");
+ 			return (-1);
+ 		}
+ 		memcpy(ks, tc->keysched, sizeof(ks));
+ 		memset(iv, 0, sizeof(iv));
+ 		des_ncbc_encrypt((des_cblock *)buf, (des_cblock *)tbuf,
+ 		    len, ks, &iv, DES_DECRYPT);
+ 		if (strlcpy(buf, tbuf, bufsiz) >= bufsiz) {
+ 			logit("unencrypted data too large to store");
+ 			memset(tbuf, 0, sizeof(tbuf));
+ 			return (-1);
+ 		}
+ 		memset(tbuf, 0, sizeof(tbuf));
+ 	}
+ 	return (len);
+ }
+ 
+ /*
+  * Send a line to authsrv.
+  * On success, returns 0.  On error, returns non-zero and calls syslog().
+  */
+ ssize_t
+ tis_send(struct tis_connection *tc, u_char *buf, size_t len)
+ {
+ 	struct iovec iov[2];
+ 	des_key_schedule ks;
+ 	des_cblock iv;
+ 	ssize_t nwritten;
+ 	size_t n;
+ 	u_char cbuf[TIS_BUFSIZ];
+ 
+ 	if (tc->keyfile != NULL) {
+ 		memcpy(ks, tc->keysched, sizeof(ks));
+ 		memset(iv, 0, sizeof(iv));
+ 
+ 		len++;				/* we need to encrypt the NUL */
+ 		if ((n = len % 8) != 0)
+ 			len += 8 - n;		/* make multiple of 8 bytes */
+ 		if (len * 2 > sizeof(cbuf)) {
+ 			logit("encoded data too large to store");
+ 			return (-1);
+ 		}
+ 		des_ncbc_encrypt((des_cblock *)buf, (des_cblock *)cbuf, len,
+ 		    ks, &iv, DES_ENCRYPT);
+ 		len = tis_encode(cbuf, len, sizeof(cbuf));
+ 		buf = cbuf;
+ 	}
+ 	iov[0].iov_base = buf;
+ 	iov[0].iov_len = len;
+ 	iov[1].iov_base = "\n";
+ 	iov[1].iov_len = 1;
+ 
+ 	alarm(tc->timeout);
+ 	nwritten = writev(tc->fd, iov, 2);
+ 	alarm(0);
+ 	if (nwritten != len + 1) {
+ 		if (nwritten < 0)
+ 			logit("error writing to authsrv: %m");
+ 		else
+ 			logit("short write sending to authsrv");
+ 		return (-1);
+ 	}
+ 	return (nwritten - 1);		/* don't include the newline */
+ }
+ 
+ /*
+  * Convert a stream of bytes hex digits to hex octects in place.
+  * The passed in buffer must have space for len*2 bytes
+  * plus a NUL.
+  */
+ ssize_t
+ tis_encode(u_char *buf, size_t inlen, size_t bufsiz)
+ {
+ 	u_char *in, *out;
+ 	size_t outlen;
+ 	const static char hextab[] = "0123456789ABCDEF";
+ 
+ 	outlen = inlen * 2;
+ 	if (bufsiz <= outlen)
+ 		return (-1);
+ 
+ 	/* convert from the end -> beginning so we can do it in place */
+ 	for (in = &buf[inlen - 1], out = &buf[outlen - 1]; in >= buf; in--) {
+ 		*out-- = hextab[*in & 0x0f];
+ 		*out-- = hextab[*in >> 4];
+ 	}
+ 	buf[outlen] = '\0';
+ 
+ 	return (outlen);
+ }
+ 
+ /*
+  * Convert a stream of hex digits to bytes in place.
+  */
+ ssize_t
+ tis_decode(u_char *buf, size_t len)
+ {
+ 	u_char *end, *in, *out;
+ 	int byte;
+ 
+ 	if (len & 1)
+ 		return (-1);		/* len must be even */
+ 
+ 	for (in = out = buf, end = buf + len; in < end; in += 2) {
+ 		if (in[1] >= 'A' && in[1] <= 'F')
+ 			byte = in[1] - 'A' + 10;
+ 		else
+ 			byte = in[1] - '0';
+ 		if (in[0] >= 'A' && in[0] <= 'F')
+ 			byte += (in[0] - 'A' + 10) * 16;
+ 		else
+ 			byte += (in[0] - '0') * 16;
+ 		if (byte > 0xff || byte < 0)
+ 			return (-1);
+ 		*out++ = byte;
+ 	}
+ 	*out = '\0';
+ 	return (out - buf);
+ }
+ 
+ /*
+  * Send a response string to authsrv and check the result.
+  * Returns the type of response, and an error buffer.
+  */
+ int
+ tis_verify(struct tis_connection *tc, const char *response, char *ebuf)
+ {
+ 	u_char buf[TIS_BUFSIZ];
+ 	int len;
+ 
+ 	ebuf[0] = '\0';
+ 	len = snprintf(buf, sizeof(buf), "response '%s'", response);
+ 	if (len == -1 || len >= sizeof(buf)) {
+ 		logit("response too large");
+ 		return (-1);
+ 	}
+ 	if (tis_send(tc, buf, len) < 0)
+ 		return (-1);
+ 	if (tis_recv(tc, buf, sizeof(buf)) < 0)
+ 		return (-1);
+ 	if (strncmp(buf, "ok", 2) == 0) {
+ 		if (buf[2] != '\0')
+ 			strlcpy(ebuf, buf + 3, TIS_BUFSIZ);
+ 		memset(buf, 0, sizeof(buf));
+ 		return (0);
+ 	}
+ 	strlcpy(ebuf, buf, TIS_BUFSIZ);
+ 	memset(buf, 0, sizeof(buf));
+ 	return (-1);
+ }
+ 
+ #endif /* TIS */
diff -crP ssh/auth-tis.h ssh.my2/auth-tis.h
*** ssh/auth-tis.h	Thu Jan  1 03:00:00 1970
--- ssh.my2/auth-tis.h	Tue Sep 12 13:53:39 2006
***************
*** 0 ****
--- 1,39 ----
+ /*	$OpenBSD: login_tis.h,v 1.1 2004/09/28 15:02:01 millert Exp $	*/
+ 
+ /*
+  * Copyright (c) 2004 Todd C. Miller <Todd.Miller at courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+  * copyright notice and this permission notice appear in all copies.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  */
+ 
+ #define	TIS_BUFSIZ		512	/* max size of authsrv reply */
+ 					/* XXX - only 128 for most */
+ 
+ #define	TIS_PASSWD_TIMEOUT	120	/* password prompt timeout */
+ 
+ /* default values for login.conf variables */
+ #define	TIS_DEFPORT	"7777"		/* default port to use */
+ #define	TIS_KEY		NULL		/* default keyfile */
+ #define	TIS_DEFSERVER	"unix:/var/empty/authsrv.sock"	/* default server to contact */
+ #define	TIS_DEFALTSERVER "localhost"	/* default alt server to contact */
+ #define	TIS_DEFTIMEOUT	15		/* default communications timeout */
+ 
+ struct tis_connection {
+ 	int fd;
+ 	int timeout;
+ 	char *keyfile;
+ 	char *port;
+ 	char *server;
+ 	char *altserver;
+ 	des_key_schedule keysched;
+ };
diff -crP ssh/auth2-chall.c ssh.my2/auth2-chall.c
*** ssh/auth2-chall.c	Sun Jul 17 11:17:54 2005
--- ssh.my2/auth2-chall.c	Fri Sep  8 15:10:49 2006
***************
*** 44,49 ****
--- 44,52 ----
  extern KbdintDevice skey_device;
  #endif
  #endif
+ #ifdef TIS
+ extern KbdintDevice tis_device;
+ #endif
  
  KbdintDevice *devices[] = {
  #ifdef BSD_AUTH
***************
*** 53,58 ****
--- 56,64 ----
  	&skey_device,
  #endif
  #endif
+ #ifdef TIS
+ 	&tis_device,
+ #endif
  	NULL
  };
  
***************
*** 319,330 ****
--- 325,343 ----
  #ifdef SKEY
  	extern KbdintDevice mm_skey_device;
  #endif
+ #ifdef TIS
+ 	extern KbdintDevice mm_tis_device;
+ #endif
  	/* As long as SSHv1 has devices[0] hard coded this is fine */
  #ifdef BSD_AUTH
  	devices[0] = &mm_bsdauth_device;
  #else
  #ifdef SKEY
  	devices[0] = &mm_skey_device;
+ #else
+ #ifdef TIS
+ 	devices[0] = &mm_tis_device;
+ #endif
  #endif
  #endif
  }
diff -crP ssh/monitor.c ssh.my2/monitor.c
*** ssh/monitor.c	Mon Feb 20 20:02:44 2006
--- ssh.my2/monitor.c	Mon Sep 11 15:24:09 2006
***************
*** 116,121 ****
--- 116,123 ----
  int mm_answer_bsdauthrespond(int, Buffer *);
  int mm_answer_skeyquery(int, Buffer *);
  int mm_answer_skeyrespond(int, Buffer *);
+ int mm_answer_tisquery(int, Buffer *);
+ int mm_answer_tisrespond(int, Buffer *);
  int mm_answer_keyallowed(int, Buffer *);
  int mm_answer_keyverify(int, Buffer *);
  int mm_answer_pty(int, Buffer *);
***************
*** 134,139 ****
--- 136,143 ----
  int mm_answer_gss_checkmic(int, Buffer *);
  #endif
  
+ extern u_int tis_query();
+ extern u_int tis_respond();
  static Authctxt *authctxt;
  static BIGNUM *ssh1_challenge = NULL;	/* used for ssh1 rsa auth */
  
***************
*** 177,182 ****
--- 181,190 ----
      {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
      {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
  #endif
+ #ifdef TIS
+     {MONITOR_REQ_TISQUERY, MON_ISAUTH, mm_answer_tisquery},
+     {MONITOR_REQ_TISRESPOND, MON_AUTH, mm_answer_tisrespond},
+ #endif
      {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
      {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
  #ifdef GSSAPI
***************
*** 214,219 ****
--- 222,231 ----
      {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
      {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
  #endif
+ #ifdef TIS
+     {MONITOR_REQ_TISQUERY, MON_ISAUTH, mm_answer_tisquery},
+     {MONITOR_REQ_TISRESPOND, MON_AUTH, mm_answer_tisrespond},
+ #endif
      {0, 0, NULL}
  };
  
***************
*** 736,741 ****
--- 748,808 ----
  	mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m);
  
  	auth_method = "skey";
+ 
+ 	return (authok != 0);
+ }
+ #endif
+ 
+ #ifdef TIS
+ int
+ mm_answer_tisquery(int sock, Buffer *m)
+ {
+ 	char *name, *infotxt;
+ 	u_int numprompts;
+ 	u_int *echo_on;
+ 	char **prompts;
+ 	u_int success;
+ 
+ 	success = tis_query(authctxt, &name, &infotxt, &numprompts,
+ 	    &prompts, &echo_on) < 0 ? 0 : 1;
+ 
+ 	buffer_clear(m);
+ 	buffer_put_int(m, success);
+ 	if (success)
+ 		buffer_put_cstring(m, prompts[0]);
+ 
+ 	debug3("%s: sending challenge success: %u", __func__, success);
+ 	mm_request_send(sock, MONITOR_ANS_TISQUERY, m);
+ 
+ 	if (success) {
+ 		xfree(name);
+ 		xfree(infotxt);
+ 		xfree(prompts);
+ 		xfree(echo_on);
+ 	}
+ 
+ 	return (0);
+ }
+ 
+ int
+ mm_answer_tisrespond(int sock, Buffer *m)
+ {
+ 	char *response;
+ 	int authok;
+ 
+ 	response = buffer_get_string(m, NULL);
+ 	authok = options.challenge_response_authentication && 
+ 	    (tis_respond(authctxt, 1, &response) == 0);
+ 	debug3("%s: <%s> = <%d>", __func__, response, authok);
+ 	xfree(response);
+ 
+ 	buffer_clear(m);
+ 	buffer_put_int(m, authok);
+ 
+ 	debug3("%s: sending authenticated: %d", __func__, authok);
+ 	mm_request_send(sock, MONITOR_ANS_TISRESPOND, m);
+ 
+ 	auth_method = "tis";
  
  	return (authok != 0);
  }
diff -crP ssh/monitor.h ssh.my2/monitor.h
*** ssh/monitor.h	Mon Nov 17 14:06:07 2003
--- ssh.my2/monitor.h	Fri Sep  8 15:34:26 2006
***************
*** 39,44 ****
--- 39,46 ----
  	MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
  	MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
  	MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
+ 	MONITOR_REQ_TISQUERY, MONITOR_ANS_TISQUERY,
+ 	MONITOR_REQ_TISRESPOND, MONITOR_ANS_TISRESPOND,
  	MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
  	MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
  	MONITOR_REQ_KEYEXPORT,
diff -crP ssh/monitor_wrap.c ssh.my2/monitor_wrap.c
*** ssh/monitor_wrap.c	Tue May 24 21:32:43 2005
--- ssh.my2/monitor_wrap.c	Fri Sep  8 15:45:37 2006
***************
*** 849,854 ****
--- 849,913 ----
  }
  #endif /* SKEY */
  
+ #ifdef TIS
+ int
+ mm_tis_query(void *ctx, char **name, char **infotxt,
+    u_int *numprompts, char ***prompts, u_int **echo_on)
+ {
+ 	Buffer m;
+ 	int len;
+ 	u_int success;
+ 	char *p, *challenge;
+ 
+ 	debug3("%s: entering", __func__);
+ 
+ 	buffer_init(&m);
+ 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TISQUERY, &m);
+ 
+ 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_TISQUERY,
+ 	    &m);
+ 	success = buffer_get_int(&m);
+ 	if (success == 0) {
+ 		debug3("%s: no challenge", __func__);
+ 		buffer_free(&m);
+ 		return (-1);
+ 	}
+ 	/* Get the challenge, and format the response */
+ 	challenge  = buffer_get_string(&m, NULL);
+ 	buffer_free(&m);
+ 
+ 	mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
+ 	(*prompts)[0] = challenge;
+ 
+ 	debug3("%s: received challenge: %s", __func__, challenge);
+ 
+ 	return (0);
+ }
+ 
+ int
+ mm_tis_respond(void *ctx, u_int numresponses, char **responses)
+ {
+ 	Buffer m;
+ 	int authok;
+ 
+ 	debug3("%s: entering", __func__);
+ 	if (numresponses != 1)
+ 		return (-1);
+ 
+ 	buffer_init(&m);
+ 	buffer_put_cstring(&m, responses[0]);
+ 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TISRESPOND, &m);
+ 
+ 	mm_request_receive_expect(pmonitor->m_recvfd,
+ 	    MONITOR_ANS_TISRESPOND, &m);
+ 
+ 	authok = buffer_get_int(&m);
+ 	buffer_free(&m);
+ 
+ 	return ((authok == 0) ? -1 : 0);
+ }
+ #endif /* TIS */
+ 
  void
  mm_ssh1_session_id(u_char session_id[16])
  {
diff -crP ssh/monitor_wrap.h ssh.my2/monitor_wrap.h
*** ssh/monitor_wrap.h	Mon Jun 21 21:36:31 2004
--- ssh.my2/monitor_wrap.h	Fri Sep  8 15:36:21 2006
***************
*** 90,95 ****
--- 90,99 ----
  int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
  int mm_skey_respond(void *, u_int, char **);
  
+ /* tis */
+ int mm_tis_query(void *, char **, char **, u_int *, char ***, u_int **);
+ int mm_tis_respond(void *, u_int, char **);
+ 
  /* zlib allocation hooks */
  
  void *mm_zalloc(struct mm_master *, u_int, u_int);


More information about the openssh-unix-dev mailing list