Attempt to clean up PAM code
Use PWDB getpw* functions if HAVE_PWDB defined
Minor other tidyups
diff --git a/Makefile.GNU b/Makefile.GNU
index f36bdb3..0971995 100644
--- a/Makefile.GNU
+++ b/Makefile.GNU
@@ -1,8 +1,8 @@
OPT_FLAGS=-g
-CFLAGS=$(OPT_FLAGS) -Wall -DETCDIR=\"/etc/ssh\" -DHAVE_PAM
+CFLAGS=$(OPT_FLAGS) -Wall -DETCDIR=\"/etc/ssh\" -DHAVE_PAM -DHAVE_PWDB
TARGETS=bin/libssh.a bin/ssh bin/sshd bin/ssh-add bin/ssh-keygen bin/ssh-agent bin/scp
LFLAGS=-L./bin
-LIBS=-lssh -lcrypto -lz -lutil -lpam -ldl
+LIBS=-lssh -lcrypto -lz -lutil -lpwdb -lpam -ldl
AR=ar
RANLIB=ranlib
diff --git a/auth-passwd.c b/auth-passwd.c
index 7d68467..61f66fe 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -15,7 +15,7 @@
*/
#include "includes.h"
-RCSID("$Id: auth-passwd.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
+RCSID("$Id: auth-passwd.c,v 1.2 1999/10/27 13:42:05 damien Exp $");
#include "packet.h"
#include "ssh.h"
@@ -26,14 +26,6 @@
extern char *ticket;
#endif /* KRB4 */
-#ifdef HAVE_PAM
-#include <security/pam_appl.h>
-extern pam_handle_t *pamh;
-extern int retval;
-extern char* pampasswd;
-extern int origretval;
-#endif /* HAVE_PAM */
-
/* Tries to authenticate the user using password. Returns true if
authentication succeeds. */
@@ -58,26 +50,6 @@
if (pw == NULL)
return 0;
-#ifdef HAVE_PAM
- retval = origretval;
-
- pampasswd = xstrdup(password);
-
- if (retval == PAM_SUCCESS)
- retval = pam_authenticate ((pam_handle_t *)pamh, 0);
-
- if (retval == PAM_SUCCESS)
- retval = pam_acct_mgmt ((pam_handle_t *)pamh, 0);
-
- xfree(pampasswd);
-
- if (retval == PAM_SUCCESS)
- retval = pam_open_session ((pam_handle_t *)pamh, 0);
-
- return (retval == PAM_SUCCESS);
-
-#else /* HAVE_PAM */
-
#ifdef SKEY
if (options.skey_authentication == 1) {
if (strncasecmp(password, "s/key", 5) == 0) {
@@ -205,5 +177,4 @@
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
-#endif /* HAVE_PAM */
}
diff --git a/includes.h b/includes.h
index 8fa174b..b2e8c1e 100644
--- a/includes.h
+++ b/includes.h
@@ -61,6 +61,14 @@
#include "mktemp.h"
#include "strlcpy.h"
+#ifdef HAVE_PAM
+#include <security/pam_appl.h>
+#endif /* HAVE_PAM */
+
+#ifdef HAVE_PWDB
+#include <pwdb/pwdb_map.h>
+#endif /* HAVE_PWDB */
+
/* Define this to be the path of the xauth program. */
#ifndef XAUTH_PATH
#define XAUTH_PATH "/usr/X11R6/bin/xauth"
diff --git a/sshd.c b/sshd.c
index 059f311..08fb30e 100644
--- a/sshd.c
+++ b/sshd.c
@@ -18,7 +18,7 @@
*/
#include "includes.h"
-RCSID("$Id: sshd.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
+RCSID("$Id: sshd.c,v 1.2 1999/10/27 13:42:05 damien Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -47,14 +47,6 @@
char *ticket = NULL;
#endif /* KRB4 */
-#ifdef HAVE_PAM
-#include <security/pam_appl.h>
-struct pam_handle_t *pamh=NULL;
-char *pampasswd=NULL;
-int retval;
-int origretval;
-#endif /* HAVE_PAM */
-
/* Local Xauthority file. */
char *xauthfile = NULL;
@@ -139,69 +131,127 @@
#ifdef HAVE_PAM
static int pamconv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr);
+void do_pam_authentication(const char *username, const char *password,
+ const char *remote_user, const char *remote_host);
+void pam_cleanup_proc(void *context);
static struct pam_conv conv = {
pamconv,
NULL
};
+struct pam_handle_t *pamh = NULL;
+const char *pampasswd = NULL;
static int pamconv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int count = 0;
- int replies = 0;
struct pam_response *reply = NULL;
- int size = sizeof(struct pam_response);
+ /* PAM will free this later */
+ reply = malloc(num_msg * sizeof(*reply));
+ if (reply == NULL)
+ return PAM_CONV_ERR;
+
for(count = 0; count < num_msg; count++)
{
switch (msg[count]->msg_style)
{
- case PAM_PROMPT_ECHO_ON:
case PAM_PROMPT_ECHO_OFF:
- if (reply == NULL)
- reply = xmalloc(size);
- else
- reply = realloc(reply, size);
-
- if (reply == NULL)
- return PAM_CONV_ERR;
-
- size += sizeof(struct pam_response);
-
- reply[replies].resp_retcode = PAM_SUCCESS;
-
- reply[replies++].resp = xstrdup(pampasswd);
- /* PAM frees resp */
- break;
-
- case PAM_TEXT_INFO:
- /* ignore it... */
- break;
-
- case PAM_ERROR_MSG:
- default:
- /* Must be an error of some sort... */
- if (reply != NULL)
+ if (pampasswd == NULL)
+ {
free(reply);
+ return PAM_CONV_ERR;
+ }
+ reply[count].resp_retcode = PAM_SUCCESS;
+ reply[count].resp = xstrdup(pampasswd);
+ break;
- return PAM_CONV_ERR;
- }
+ case PAM_TEXT_INFO:
+ reply[count].resp_retcode = PAM_SUCCESS;
+ reply[count].resp = xstrdup("");
+ break;
+
+ case PAM_PROMPT_ECHO_ON:
+ case PAM_ERROR_MSG:
+ default:
+ free(reply);
+ return PAM_CONV_ERR;
+ }
}
- if (reply != NULL)
- *resp = reply;
+ *resp = reply;
return PAM_SUCCESS;
}
void pam_cleanup_proc(void *context)
{
- if (retval == PAM_SUCCESS)
+ int retval;
+
+ if (pamh != NULL)
+ {
retval = pam_close_session((pam_handle_t *)pamh, 0);
- if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
- log("Cannot release PAM authentication.");
+ if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
+ log("Cannot release PAM authentication.");
+ }
+}
+
+void do_pam_authentication(const char *username, const char *password, const char *remote_user, const char *remote_host)
+{
+ int pam_auth_ok = 1;
+
+ pampasswd = password;
+
+ do
+ {
+ if (PAM_SUCCESS != pam_start("ssh", username, &conv, (pam_handle_t**)&pamh))
+ {
+ pam_auth_ok = 0;
+ break;
+ }
+
+ fatal_add_cleanup(&pam_cleanup_proc, NULL);
+
+ if (remote_host && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RHOST, remote_host)))
+ {
+ pam_auth_ok = 0;
+ break;
+ }
+
+ if (remote_user && (PAM_SUCCESS != pam_set_item((pam_handle_t *)pamh, PAM_RUSER, remote_user)))
+ {
+ pam_auth_ok = 0;
+ break;
+ }
+
+ if (PAM_SUCCESS != pam_authenticate((pam_handle_t *)pamh, 0))
+ {
+ pam_auth_ok = 0;
+ break;
+ }
+
+ if (PAM_SUCCESS != pam_acct_mgmt((pam_handle_t *)pamh, 0))
+ {
+ pam_auth_ok = 0;
+ break;
+ }
+
+ if (PAM_SUCCESS != pam_open_session((pam_handle_t *)pamh, 0))
+ {
+ pam_auth_ok = 0;
+ break;
+ }
+ } while (0);
+
+ if (!pam_auth_ok)
+ {
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ packet_disconnect("PAM authentication failed.");
+ }
}
#endif /* HAVE_PAM */
@@ -788,13 +838,19 @@
log("Closing connection to %.100s", inet_ntoa(sin.sin_addr));
#ifdef HAVE_PAM
- if (retval == PAM_SUCCESS)
- retval = pam_close_session((pam_handle_t *)pamh, 0);
+ {
+ int retval;
+
+ if (pamh != NULL)
+ {
+ retval = pam_close_session((pam_handle_t *)pamh, 0);
- if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
- log("Cannot release PAM authentication.");
+ if (pam_end((pam_handle_t *)pamh, retval) != PAM_SUCCESS)
+ log("Cannot release PAM authentication.");
- fatal_remove_cleanup(&pam_cleanup_proc, NULL);
+ fatal_remove_cleanup(&pam_cleanup_proc, NULL);
+ }
+ }
#endif /* HAVE_PAM */
packet_close();
@@ -1078,14 +1134,11 @@
int type;
int authenticated = 0;
int authentication_failures = 0;
- char *password;
+ char *password = NULL;
struct passwd *pw, pwcopy;
- char *client_user;
+ char *client_user = NULL;
unsigned int client_host_key_bits;
BIGNUM *client_host_key_e, *client_host_key_n;
-#ifdef HAVE_PAM
- int pam_auth_ok;
-#endif /* HAVE_PAM */
#ifdef AFS
/* If machine has AFS, set process authentication group. */
@@ -1097,21 +1150,7 @@
/* Verify that the user is a valid user. */
pw = getpwnam(user);
-#ifdef HAVE_PAM
- if ((pw != NULL) && allowed_user(pw))
- {
- /* Initialise PAM */
- retval = pam_start("ssh", pw->pw_name, &conv, (pam_handle_t **)&pamh);
- fatal_add_cleanup(&pam_cleanup_proc, NULL);
- origretval = retval;
- if (retval == PAM_SUCCESS)
- pam_auth_ok = 1;
- }
-
- if (pam_auth_ok == 0)
-#else /* HAVE_PAM */
if (!pw || !allowed_user(pw))
-#endif /* HAVE_PAM */
{
/* The user does not exist or access is denied,
but fake indication that authentication is needed. */
@@ -1306,12 +1345,16 @@
log("Rhosts authentication accepted for %.100s, remote %.100s on %.700s.",
user, client_user, get_canonical_hostname());
authenticated = 1;
+#ifndef HAVE_PAM
xfree(client_user);
+#endif /* HAVE_PAM */
break;
}
log("Rhosts authentication failed for %.100s, remote %.100s.",
user, client_user);
+#ifndef HAVE_PAM
xfree(client_user);
+#endif /* HAVE_PAM */
break;
case SSH_CMSG_AUTH_RHOSTS_RSA:
@@ -1354,14 +1397,18 @@
{
/* Authentication accepted. */
authenticated = 1;
+#ifndef HAVE_PAM
xfree(client_user);
+#endif /* HAVE_PAM */
BN_clear_free(client_host_key_e);
BN_clear_free(client_host_key_n);
break;
}
log("Rhosts authentication failed for %.100s, remote %.100s.",
user, client_user);
- xfree(client_user);
+#ifndef HAVE_PAM
+ xfree(client_user);
+#endif /* HAVE_PAM */
BN_clear_free(client_host_key_e);
BN_clear_free(client_host_key_n);
break;
@@ -1412,6 +1459,12 @@
packet_integrity_check(plen, 4 + passw_len, type);
}
+#ifdef HAVE_PAM
+ /* Authentication will be handled later */
+ /* keep password around until then */
+ authenticated = 1;
+ break;
+#else /* HAVE_PAM */
/* Try authentication with the password. */
if (auth_password(pw, password))
{
@@ -1427,6 +1480,7 @@
memset(password, 0, strlen(password));
xfree(password);
break;
+#endif /* HAVE_PAM */
case SSH_CMSG_AUTH_TIS:
/* TIS Authentication is unsupported */
@@ -1464,6 +1518,20 @@
get_canonical_hostname());
}
+#ifdef HAVE_PAM
+ do_pam_authentication(pw->pw_name, password, client_user, get_canonical_hostname());
+
+ /* Clean up */
+ if (client_user != NULL)
+ xfree(client_user);
+
+ if (password != NULL)
+ {
+ memset(password, 0, strlen(password));
+ xfree(password);
+ }
+#endif /* HAVE_PAM */
+
/* The user has been authenticated and accepted. */
packet_start(SSH_SMSG_SUCCESS);
packet_send();
@@ -2151,10 +2219,6 @@
exit(254);
}
- /* Set login name in the kernel. */
- if (setlogin(pw->pw_name) < 0)
- error("setlogin failed: %s", strerror(errno));
-
/* Set uid, gid, and groups. */
/* Login(1) does this as well, and it needs uid 0 for the "-h" switch,
so we let login(1) to this for us. */