implement kerberos over ssh2 ("kerberos-2@ssh.com"); tested with jakob@
server interops with commercial client; ok jakob@ djm@
- (djm) Make portable build with MIT krb5 (some issues remain)
+ - (djm) Add new UsePAM configuration directive to allow runtime control
+ over usage of PAM. This allows non-root use of sshd when built with
+ --with-pam
20030512
- (djm) Redhat spec: Don't install profile.d scripts when not
#include "ssh2.h"
#include "xmalloc.h"
+extern ServerOptions options;
+
#define __unused
#ifdef USE_POSIX_THREADS
static int
sshpam_init(const char *user)
{
- extern ServerOptions options;
extern u_int utmp_len;
const char *pam_rhost, *pam_user;
struct pam_ctxt *ctxt;
int socks[2];
+ /* Refuse to start if we don't have PAM enabled */
+ if (!options.use_pam)
+ return NULL;
+
/* Initialize PAM */
if (sshpam_init(authctxt->user) == -1) {
error("PAM: initialization failed");
#ifdef WITH_AIXAUTHENTICATE
char *loginmsg;
#endif /* WITH_AIXAUTHENTICATE */
-#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
- !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
+#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) && \
+ defined(HAS_SHADOW_EXPIRE)
struct spwd *spw;
time_t today;
#endif
if (!pw || !pw->pw_name)
return 0;
-#if !defined(USE_PAM) && defined(HAVE_SHADOW_H) && \
- !defined(DISABLE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
+#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) && \
+ defined(HAS_SHADOW_EXPIRE)
#define DAY (24L * 60 * 60) /* 1 day in seconds */
- if ((spw = getspnam(pw->pw_name)) != NULL) {
+ if (!options.use_pam && (spw = getspnam(pw->pw_name)) != NULL) {
today = time(NULL) / DAY;
debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
" sp_max %d", (int)today, (int)spw->sp_expire,
!auth_root_allowed(get_authname(type)))
authenticated = 0;
#endif
-#ifdef USE_PAM
- if (!use_privsep && authenticated &&
- !do_pam_account(pw->pw_name, client_user))
- authenticated = 0;
-#endif
/* Log before sending the reply */
auth_log(authctxt, authenticated, get_authname(type), info);
use_privsep ? " [net]" : "");
#ifdef USE_PAM
- PRIVSEP(start_pam(user));
+ if (options.use_pam)
+ PRIVSEP(start_pam(user));
#endif
/*
/* challenge-response is implemented via keyboard interactive */
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
- if (options.pam_authentication_via_kbd_int)
- options.kbd_interactive_authentication = 1;
- if (use_privsep)
- options.pam_authentication_via_kbd_int = 0;
dispatch_init(&dispatch_protocol_error);
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
#ifdef USE_PAM
- PRIVSEP(start_pam(authctxt->pw->pw_name));
+ if (options.use_pam)
+ PRIVSEP(start_pam(authctxt->pw->pw_name));
#endif
} else {
logit("input_userauth_request: illegal user %s", user);
#ifdef USE_PAM
- PRIVSEP(start_pam(user));
+ if (options.use_pam)
+ PRIVSEP(start_pam(user));
#endif
}
setproctitle("%s%s", authctxt->pw ? user : "unknown",
!auth_root_allowed(method))
authenticated = 0;
-#ifdef USE_PAM
- if (!use_privsep && authenticated && authctxt->user &&
- !do_pam_account(authctxt->user, NULL))
- authenticated = 0;
-#endif /* USE_PAM */
-
#ifdef _UNICOS
if (authenticated && cray_access_denied(authctxt->user)) {
authenticated = 0;
}
#ifdef USE_PAM
- monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
+ if (options.use_pam)
+ monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
#endif
return (0);
{
char *user;
+ if (!options.use_pam)
+ fatal("UsePAM not set, but ended up in %s anyway", __func__);
+
user = buffer_get_string(m, NULL);
start_pam(user);
#include "atomicio.h"
#include "monitor_fdpass.h"
#include "getput.h"
+#include "servconf.h"
#include "auth.h"
#include "channels.h"
extern z_stream outgoing_stream;
extern struct monitor *pmonitor;
extern Buffer input, output;
+extern ServerOptions options;
void
mm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
Buffer m;
debug3("%s entering", __func__);
+ if (!options.use_pam)
+ fatal("UsePAM=no, but ended up in %s anyway", __func__);
buffer_init(&m);
buffer_put_cstring(&m, user);
{
memset(options, 0, sizeof(*options));
+#ifdef USE_PAM
/* Portable-specific options */
- options->pam_authentication_via_kbd_int = -1;
+ options->use_pam = -1;
+#endif
/* Standard Options */
options->num_ports = 0;
fill_default_server_options(ServerOptions *options)
{
/* Portable-specific options */
- if (options->pam_authentication_via_kbd_int == -1)
- options->pam_authentication_via_kbd_int = 0;
+#ifdef USE_PAM
+ if (options->use_pam == -1)
+ options->use_pam = 1;
+#endif
/* Standard Options */
if (options->protocol == SSH_PROTO_UNKNOWN)
typedef enum {
sBadOption, /* == unknown option */
/* Portable-specific options */
- sPAMAuthenticationViaKbdInt,
+ sUsePAM,
/* Standard Options */
sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
sPermitRootLogin, sLogFacility, sLogLevel,
ServerOpCodes opcode;
} keywords[] = {
/* Portable-specific options */
- { "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt },
+ { "UsePAM", sUsePAM },
/* Standard Options */
{ "port", sPort },
{ "hostkey", sHostKeyFile },
opcode = parse_token(arg, filename, linenum);
switch (opcode) {
/* Portable-specific options */
- case sPAMAuthenticationViaKbdInt:
- intptr = &options->pam_authentication_via_kbd_int;
+ case sUsePAM:
+ intptr = &options->use_pam;
goto parse_flag;
/* Standard Options */
char *authorized_keys_file; /* File containing public keys */
char *authorized_keys_file2;
- int pam_authentication_via_kbd_int;
+ int use_pam; /* Enable auth via PAM */
} ServerOptions;
void initialize_server_options(ServerOptions *);
session_proctitle(s);
#if defined(USE_PAM)
- do_pam_session(s->pw->pw_name, NULL);
- do_pam_setcred(1);
- if (is_pam_password_change_required())
- packet_disconnect("Password change required but no "
- "TTY available");
+ if (options.use_pam) {
+ do_pam_session(s->pw->pw_name, NULL);
+ do_pam_setcred(1);
+ if (is_pam_password_change_required())
+ packet_disconnect("Password change required but no "
+ "TTY available");
+ }
#endif /* USE_PAM */
/* Fork the child. */
ttyfd = s->ttyfd;
#if defined(USE_PAM)
- do_pam_session(s->pw->pw_name, s->tty);
- do_pam_setcred(1);
+ if (options.use_pam) {
+ do_pam_session(s->pw->pw_name, s->tty);
+ do_pam_setcred(1);
+ }
#endif
/* Fork the child. */
* If password change is needed, do it now.
* This needs to occur before the ~/.hushlogin check.
*/
- if (is_pam_password_change_required()) {
+ if (options.use_pam && is_pam_password_change_required()) {
print_pam_messages();
do_pam_chauthtok();
}
return;
#ifdef USE_PAM
- if (!is_pam_password_change_required())
+ if (options.use_pam && !is_pam_password_change_required())
print_pam_messages();
#endif /* USE_PAM */
#ifdef WITH_AIXAUTHENTICATE
* Pull in any environment variables that may have
* been set by PAM.
*/
- {
- char **p;
+ if (options.use_pam) {
+ char **p = fetch_pam_environment();
- p = fetch_pam_environment();
copy_environment(p, &env, &envsize);
free_pam_environment(p);
}
* These will have been wiped by the above initgroups() call.
* Reestablish them here.
*/
- do_pam_setcred(0);
+ if (options.use_pam)
+ do_pam_setcred(0);
# endif /* USE_PAM */
# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
irix_setusercontext(pw);
verbose("Closing connection to %.100s", remote_ip);
#ifdef USE_PAM
- finish_pam();
+ if (options.use_pam)
+ finish_pam();
#endif /* USE_PAM */
packet_close();
are refused if the number of unauthenticated connections reaches
.Dq full
(60).
-.It Cm PAMAuthenticationViaKbdInt
-Specifies whether PAM challenge response authentication is allowed. This
-allows the use of most PAM challenge response authentication modules, but
-it will allow password authentication regardless of whether
-.Cm PasswordAuthentication
-is enabled.
+
+.It Cm UsePAM
+Enables PAM authentication (via challenge-response) and session set up.
+If you enable this, you should probably disable
+.Cm PasswordAuthentication .
+If you enable
+.CM UsePAM
+then you will not be able to run sshd as a non-root user.
+
.It Cm PasswordAuthentication
Specifies whether password authentication is allowed.
The default is