patch for TIS (skey/opie) *and* passwd auth via PAM
Hein Roehrig
hein at acm.org
Mon Aug 28 03:37:14 EST 2000
Hello,
appended is a patch that makes it possible to use PAM both for
password authentication and TIS (i.e. s/key or opie or any other
interactive challenge/response scheme). I have developed this starting
from the patch at http://www.debian.org/Bugs/db/61/61906.html on
Debian with openssh-2.1.1p4-3. After configuring ssh with
--with-pam-tis, there are two PAM services, "sshd" and "sshd-tis"
(resp. "ssh" and "ssh-tis" on Debian); /etc/pam.d/ssh-tis could
contain for example
------------
#%PAM-1.0
auth required pam_nologin.so
auth required pam_opie.so
auth required pam_env.so # [1]
account required pam_unix.so
session required pam_unix.so
session optional pam_lastlog.so # [1]
session optional pam_motd.so # [1]
session optional pam_mail.so standard # [1]
password required pam_unix.so
------------
I.e, the only change to the default /etc/pam.d/ssh is unix -> opie in
line 3.
I hope this patch will allow using ssh with OPIE on Debian; I am
looking forward to your comments. If in principle this approach is ok,
what changes are needed to get this patch into the development tree? I
know that my C indenting is not the same as in the rest of the source,
where do I find the official indentation style?
Thanks,
Hein
diff -urN -x *~ openssh-2.1.1p4/acconfig.h openssh-2.1.1p4-hein/acconfig.h
--- openssh-2.1.1p4/acconfig.h Sat Jul 15 06:59:14 2000
+++ openssh-2.1.1p4-hein/acconfig.h Sun Aug 27 12:13:36 2000
@@ -30,6 +30,9 @@
/* Define if you want to disable PAM support */
#undef DISABLE_PAM
+/* Define if you want TIS authentication through PAM */
+#undef PAM_TIS
+
/* Define if you want to enable AIX4's authenticate function */
#undef WITH_AIXAUTHENTICATE
diff -urN -x *~ openssh-2.1.1p4/auth-pam.c openssh-2.1.1p4-hein/auth-pam.c
--- openssh-2.1.1p4/auth-pam.c Sun Jul 9 14:42:33 2000
+++ openssh-2.1.1p4-hein/auth-pam.c Sun Aug 27 18:05:44 2000
@@ -33,12 +33,15 @@
#include "ssh.h"
#include "xmalloc.h"
#include "servconf.h"
+#include "packet.h"
RCSID("$Id: auth-pam.c,v 1.11 2000/07/09 12:42:33 djm Exp $");
#define NEW_AUTHTOK_MSG \
"Warning: You password has expired, please change it now"
+static void start_pam2(struct passwd *pw, int auth_type);
+
/* Callbacks */
static int pamconv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr);
@@ -53,6 +56,7 @@
static struct pam_handle_t *pamh = NULL;
static const char *pampasswd = NULL;
static char *pam_msg = NULL;
+static int current_auth_type=-1;
/* PAM conversation function. This is really a kludge to get the password */
/* into PAM and to pick up any messages generated by PAM into pamconv_msg */
@@ -61,6 +65,7 @@
{
struct pam_response *reply;
int count;
+ int dlen, plen, type;
/* PAM will free this later */
reply = malloc(num_msg * sizeof(*reply));
@@ -70,13 +75,58 @@
for(count = 0; count < num_msg; count++) {
switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
- if (pampasswd == NULL) {
- free(reply);
- return PAM_CONV_ERR;
+ if (current_auth_type==SSH_CMSG_AUTH_TIS && pampasswd==NULL) {
+ /* TIS */
+ int prompt_len;
+ char *prompt;
+ debug("send SSH_SMSG_AUTH_TIS_CHALLENGE in PAM");
+ /* send all previous PAM_TEXT_INFO messages plus
+ the current prompt */
+ prompt_len=((pam_msg!=NULL)?strlen(pam_msg):0) +
+ strlen(msg[count]->msg);
+ prompt=xmalloc(prompt_len + 1);
+ if (pam_msg!=NULL) {
+ strcpy(prompt, pam_msg);
+ xfree(pam_msg);
+ pam_msg=NULL;
+ } else
+ *prompt='\0';
+ strcat(prompt, msg[count]->msg);
+ /* cut off Response: from the prompt because the
+ SSH client already prints this */
+ if (prompt_len >= sizeof("Response: ") - 1 &&
+ 0==strcasecmp(prompt + prompt_len - sizeof("\nResponse: ") + 1,
+ "\nResponse: ")) {
+ prompt[prompt_len - sizeof("\nResponse: ") + 1]='\0';
+ }
+ packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
+ packet_put_string(prompt, prompt_len);
+ xfree(prompt);
+ packet_send();
+ packet_write_wait();
+ type = packet_read(&plen);
+ if (type == SSH_CMSG_AUTH_TIS_RESPONSE) {
+ debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE in PAM");
+ pampasswd = packet_get_string(&dlen);
+ packet_integrity_check(plen, 4 + dlen, type);
+ } else {
+ free(reply);
+ return PAM_CONV_ERR;
+ }
+ reply[count].resp_retcode = PAM_SUCCESS;
+ reply[count].resp = xstrdup(pampasswd);
+ xfree((void*)pampasswd);
+ pampasswd=NULL;
+ } else {
+ /* password or second TIS attempt */
+ if (pampasswd == NULL) {
+ free(reply);
+ return PAM_CONV_ERR;
}
reply[count].resp_retcode = PAM_SUCCESS;
reply[count].resp = xstrdup(pampasswd);
- break;
+ }
+ break;
case PAM_TEXT_INFO:
reply[count].resp_retcode = PAM_SUCCESS;
reply[count].resp = xstrdup("");
@@ -123,29 +173,34 @@
}
}
-/* Attempt password authentation using PAM */
-int auth_pam_password(struct passwd *pw, const char *password)
+/* Attempt authentication using PAM */
+int auth_pam_password(struct passwd *pw, const char *password, int auth_type)
{
extern ServerOptions options;
int pam_retval;
+ if (auth_type != current_auth_type) {
+ finish_pam();
+ start_pam2(pw, auth_type);
+ }
+
/* deny if no user. */
if (pw == NULL)
return 0;
if (pw->pw_uid == 0 && options.permit_root_login == 2)
return 0;
- if (*password == '\0' && options.permit_empty_passwd == 0)
+ if (password!=NULL && *password == '\0' && options.permit_empty_passwd == 0)
return 0;
pampasswd = password;
pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
if (pam_retval == PAM_SUCCESS) {
- debug("PAM Password authentication accepted for user \"%.100s\"",
+ debug("PAM authentication accepted for user \"%.100s\"",
pw->pw_name);
return 1;
} else {
- debug("PAM Password authentication for \"%.100s\" failed: %s",
+ debug("PAM authentication for \"%.100s\" failed: %s",
pw->pw_name, PAM_STRERROR((pam_handle_t *)pamh, pam_retval));
return 0;
}
@@ -234,11 +289,34 @@
/* Start PAM authentication for specified account */
void start_pam(struct passwd *pw)
{
+ start_pam2(pw, SSH_CMSG_AUTH_PASSWORD);
+}
+
+
+/* Start PAM authentication for specified account */
+static void start_pam2(struct passwd *pw, int auth_type)
+{
int pam_retval;
+ const char *service=NULL;
- debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
+ switch (auth_type) {
+ case SSH_CMSG_AUTH_PASSWORD :
+ service=SSHD_PAM_SERVICE;
+ break;
+ case SSH_CMSG_AUTH_TIS :
+ service=SSHD_PAM_TIS_SERVICE;
+ break;
+ default:
+ fatal("PAM attempted for unsupported authentication type\n");
+ }
+
+ current_auth_type=auth_type;
+
+ debug("Starting up PAM service %.200s with username \"%.200s\"",
+ service,
+ pw->pw_name);
- pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv,
+ pam_retval = pam_start(service, pw->pw_name, &conv,
(pam_handle_t**)&pamh);
if (pam_retval != PAM_SUCCESS) {
diff -urN -x *~ openssh-2.1.1p4/auth-pam.h openssh-2.1.1p4-hein/auth-pam.h
--- openssh-2.1.1p4/auth-pam.h Thu Jan 27 00:55:38 2000
+++ openssh-2.1.1p4-hein/auth-pam.h Sun Aug 27 17:27:46 2000
@@ -5,7 +5,7 @@
void start_pam(struct passwd *pw);
void finish_pam(void);
-int auth_pam_password(struct passwd *pw, const char *password);
+int auth_pam_password(struct passwd *pw, const char *password, int auth_type);
char **fetch_pam_environment(void);
int do_pam_account(char *username, char *remote_user);
void do_pam_session(char *username, const char *ttyname);
diff -urN -x *~ openssh-2.1.1p4/auth1.c openssh-2.1.1p4-hein/auth1.c
--- openssh-2.1.1p4/auth1.c Sat Jul 8 02:44:14 2000
+++ openssh-2.1.1p4-hein/auth1.c Sun Aug 27 17:27:53 2000
@@ -40,7 +40,11 @@
static char buf[1024];
switch (type) {
case SSH_CMSG_AUTH_PASSWORD:
+#ifdef USE_PAM
+ return "pam-password";
+#else
return "password";
+#endif
case SSH_CMSG_AUTH_RSA:
return "rsa";
case SSH_CMSG_AUTH_RHOSTS_RSA:
@@ -55,6 +59,11 @@
case SSH_CMSG_AUTH_TIS_RESPONSE:
return "s/key";
#endif
+#ifdef PAM_TIS
+ case SSH_CMSG_AUTH_TIS:
+ case SSH_CMSG_AUTH_TIS_RESPONSE:
+ return "pam-tis";
+#endif
}
snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
return buf;
@@ -307,7 +316,7 @@
#ifdef USE_PAM
/* Do PAM auth with password */
- authenticated = auth_pam_password(pw, password);
+ authenticated = auth_pam_password(pw, password, SSH_CMSG_AUTH_PASSWORD);
#elif defined(HAVE_OSF_SIA)
/* Do SIA auth with password */
if (sia_validate_user(NULL, saved_argc, saved_argv,
@@ -355,6 +364,26 @@
xfree(response);
}
break;
+#elif defined(PAM_TIS)
+ case SSH_CMSG_AUTH_TIS:
+ debug("rcvd SSH_CMSG_AUTH_TIS");
+ if (!options.tis_authentication) {
+ verbose("TIS authentication disabled.");
+ break;
+ }
+ authenticated = auth_pam_password(pw, NULL, SSH_CMSG_AUTH_TIS);
+ break;
+ case SSH_CMSG_AUTH_TIS_RESPONSE:
+ debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
+ if (!options.tis_authentication) {
+ verbose("TIS authentication disabled.");
+ break;
+ } else {
+ char *response = packet_get_string(&dlen);
+ authenticated = auth_pam_password(pw, response, SSH_CMSG_AUTH_TIS);
+ xfree(response);
+ }
+ break;
#else
case SSH_CMSG_AUTH_TIS:
/* TIS Authentication is unsupported */
@@ -503,7 +532,7 @@
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif /* KRB4 */
#ifdef USE_PAM
- auth_pam_password(pw, "")) {
+ auth_pam_password(pw, "", SSH_CMSG_AUTH_PASSWORD)) {
#elif defined(HAVE_OSF_SIA)
(sia_validate_user(NULL, saved_argc, saved_argv,
get_canonical_hostname(), pw->pw_name, NULL, 0, NULL,
diff -urN -x *~ openssh-2.1.1p4/auth2.c openssh-2.1.1p4-hein/auth2.c
--- openssh-2.1.1p4/auth2.c Tue Jul 11 09:31:38 2000
+++ openssh-2.1.1p4-hein/auth2.c Sun Aug 27 17:39:22 2000
@@ -102,6 +102,9 @@
#ifdef SKEY
options.skey_authentication = 0;
#endif
+#ifdef PAM_TIS
+ options.tis_authentication = 0;
+#endif
#ifdef KRB4
options.kerberos_authentication = 0;
#endif
@@ -257,7 +260,7 @@
packet_done();
#ifdef USE_PAM
- return auth_pam_password(pw, "");
+ return auth_pam_password(pw, "", SSH_CMSG_AUTH_PASSWORD);
#elif defined(HAVE_OSF_SIA)
return(sia_validate_user(NULL, saved_argc, saved_argv,
get_canonical_hostname(), pw->pw_name, NULL, 0, NULL,
@@ -284,7 +287,7 @@
packet_done();
if (options.password_authentication &&
#ifdef USE_PAM
- auth_pam_password(pw, password) == 1)
+ auth_pam_password(pw, password, SSH_CMSG_AUTH_PASSWORD) == 1)
#elif defined(HAVE_OSF_SIA)
sia_validate_user(NULL, saved_argc, saved_argv,
get_canonical_hostname(), pw->pw_name, NULL, 0,
diff -urN -x *~ openssh-2.1.1p4/configure.in openssh-2.1.1p4-hein/configure.in
--- openssh-2.1.1p4/configure.in Sat Jul 15 06:59:14 2000
+++ openssh-2.1.1p4-hein/configure.in Sun Aug 27 12:31:26 2000
@@ -306,6 +306,18 @@
)
fi
+PAM_TIS_MSG="no"
+AC_ARG_WITH(pam-tis,
+ [ --with-pam-tis Enable PAM for TIS support ],
+ [
+ if test "x$withval" = "xyes" ; then
+ pam_tis=1
+ AC_DEFINE(PAM_TIS)
+ PAM_TIS_MSG="yes"
+ fi
+ ]
+)
+
# The big search for OpenSSL
AC_ARG_WITH(ssl-dir,
[ --with-ssl-dir=PATH Specify path to OpenSSL installation ],
@@ -1365,6 +1377,7 @@
echo " KerberosIV support: $KRB4_MSG"
echo " AFS support: $AFS_MSG"
echo " S/KEY support: $SKEY_MSG"
+echo " TIS via PAM support: $PAM_TIS_MSG"
echo " TCP Wrappers support: $TCPW_MSG"
echo " MD5 password support: $MD5_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
diff -urN -x *~ openssh-2.1.1p4/debian/rules openssh-2.1.1p4-hein/debian/rules
--- openssh-2.1.1p4/debian/rules Sun Aug 27 15:42:21 2000
+++ openssh-2.1.1p4-hein/debian/rules Sun Aug 27 17:39:02 2000
@@ -14,8 +14,8 @@
build: build-stamp
build-stamp:
dh_testdir
- ./configure --prefix='' --exec_prefix='$${prefix}/usr' --sysconfdir='$${prefix}/etc/ssh' --libexecdir='$${exec_prefix}/lib' --mandir='$${prefix}/usr/share/man' --with-tcp-wrappers --with-xauth=/usr/bin/X11/xauth --with-rsh=/usr/bin/netkit-rsh
- $(MAKE) OPT_FLAGS='-DLOGIN_PROGRAM=\"/bin/login\" -DSSHD_PAM_SERVICE=\"ssh\" -DFORWARD_AGENT_DEFAULT=0 -DFALLBACKTORSH_DEFAULT=0' ASKPASS_PROGRAM='/usr/bin/ssh-askpass'
+ ./configure --prefix='' --exec_prefix='$${prefix}/usr' --sysconfdir='$${prefix}/etc/ssh' --libexecdir='$${exec_prefix}/lib' --mandir='$${prefix}/usr/share/man' --with-tcp-wrappers --with-xauth=/usr/bin/X11/xauth --with-rsh=/usr/bin/netkit-rsh --with-pam-tis
+ $(MAKE) OPT_FLAGS='-DLOGIN_PROGRAM=\"/bin/login\" -DSSHD_PAM_SERVICE=\"ssh\" -DSSHD_PAM_TIS_SERVICE=\"ssh-tis\" -DFORWARD_AGENT_DEFAULT=0 -DFALLBACKTORSH_DEFAULT=0' ASKPASS_PROGRAM='/usr/bin/ssh-askpass'
gcc -O2 `gnome-config --cflags gnome gnomeui` \
contrib/gnome-ssh-askpass.c -o contrib/gnome-ssh-askpass \
`gnome-config --libs gnome gnomeui`
diff -urN -x *~ openssh-2.1.1p4/servconf.c openssh-2.1.1p4-hein/servconf.c
--- openssh-2.1.1p4/servconf.c Sun Aug 27 15:42:20 2000
+++ openssh-2.1.1p4-hein/servconf.c Sun Aug 27 12:36:00 2000
@@ -67,6 +67,9 @@
#ifdef SKEY
options->skey_authentication = -1;
#endif
+#ifdef PAM_TIS
+ options->tis_authentication = -1;
+#endif
options->permit_empty_passwd = -1;
options->use_login = -1;
options->num_allow_users = 0;
@@ -155,6 +158,10 @@
if (options->skey_authentication == -1)
options->skey_authentication = 1;
#endif
+#ifdef PAM_TIS
+ if (options->tis_authentication == -1)
+ options->tis_authentication = 1;
+#endif
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 0;
if (options->use_login == -1)
@@ -182,6 +189,9 @@
#ifdef SKEY
sSkeyAuthentication,
#endif
+#ifdef PAM_TIS
+ sTISAuthentication,
+#endif
sPasswordAuthentication, sListenAddress,
sPrintMotd, sPrintLastLog, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
@@ -222,6 +232,9 @@
#ifdef SKEY
{ "skeyauthentication", sSkeyAuthentication },
#endif
+#ifdef PAM_TIS
+ { "tisauthentication", sTISAuthentication },
+#endif
{ "checkmail", sCheckMail },
{ "listenaddress", sListenAddress },
{ "printmotd", sPrintMotd },
@@ -504,6 +517,12 @@
#ifdef SKEY
case sSkeyAuthentication:
intptr = &options->skey_authentication;
+ goto parse_flag;
+#endif
+
+#ifdef PAM_TIS
+ case sTISAuthentication:
+ intptr = &options->tis_authentication;
goto parse_flag;
#endif
diff -urN -x *~ openssh-2.1.1p4/servconf.h openssh-2.1.1p4-hein/servconf.h
--- openssh-2.1.1p4/servconf.h Sun Aug 27 15:42:20 2000
+++ openssh-2.1.1p4-hein/servconf.h Sun Aug 27 12:34:52 2000
@@ -85,6 +85,10 @@
int skey_authentication; /* If true, permit s/key
* authentication. */
#endif
+#ifdef PAM_TIS
+ int tis_authentication; /* If true, permit TIS via PAM
+ * authentication. */
+#endif
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int use_login; /* If true, login(1) is used */
diff -urN -x *~ openssh-2.1.1p4/ssh.h openssh-2.1.1p4-hein/ssh.h
--- openssh-2.1.1p4/ssh.h Sun Aug 27 15:42:20 2000
+++ openssh-2.1.1p4-hein/ssh.h Sun Aug 27 17:36:02 2000
@@ -80,6 +80,10 @@
#define SSHD_PAM_SERVICE "sshd"
#endif
+#if defined(PAM_TIS) && ! defined(SSHD_PAM_TIS_SERVICE)
+#define SSHD_PAM_TIS_SERVICE "sshd-tis"
+#endif
+
#ifndef ETCDIR
#define ETCDIR "/etc"
#endif /* ETCDIR */
diff -urN -x *~ openssh-2.1.1p4/sshd.c openssh-2.1.1p4-hein/sshd.c
--- openssh-2.1.1p4/sshd.c Wed Jul 12 01:45:27 2000
+++ openssh-2.1.1p4-hein/sshd.c Sun Aug 27 15:39:50 2000
@@ -1097,6 +1097,10 @@
if (options.skey_authentication == 1)
auth_mask |= 1 << SSH_AUTH_TIS;
#endif
+#ifdef PAM_TIS
+ if (options.tis_authentication == 1)
+ auth_mask |= 1 << SSH_AUTH_TIS;
+#endif
if (options.password_authentication)
auth_mask |= 1 << SSH_AUTH_PASSWORD;
packet_put_int(auth_mask);
More information about the openssh-unix-dev
mailing list