1) Add kerberos5 functionality.
by Daniel Kouril <kouril@informatics.muni.cz> 2) Add full LOGIN_CAP capability by Andrey Chernov
This commit is contained in:
parent
898821d318
commit
e54fe4cc8e
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Dug Song <dugsong@UMICH.EDU>
|
||||
* Kerberos v4 authentication and ticket-passing routines.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -114,7 +116,7 @@ auth_krb4_password(struct passwd * pw, const char *password)
|
||||
kerberos_auth_failure:
|
||||
krb4_cleanup_proc(NULL);
|
||||
|
||||
if (!options.kerberos_or_local_passwd)
|
||||
if (!options.krb4_or_local_passwd)
|
||||
return 0;
|
||||
} else {
|
||||
/* Logging in as root or no local Kerberos realm. */
|
||||
@ -242,7 +244,7 @@ auth_krb4(const char *server_user, KTEXT auth, char **client)
|
||||
/* Clear session key. */
|
||||
memset(&adat.session, 0, sizeof(&adat.session));
|
||||
|
||||
packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
|
||||
packet_start(SSH_SMSG_AUTH_KRB4_RESPONSE);
|
||||
packet_put_string((char *) reply.dat, reply.length);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
@ -252,7 +254,7 @@ auth_krb4(const char *server_user, KTEXT auth, char **client)
|
||||
|
||||
#ifdef AFS
|
||||
int
|
||||
auth_kerberos_tgt(struct passwd *pw, const char *string)
|
||||
auth_krb4_tgt(struct passwd *pw, const char *string)
|
||||
{
|
||||
CREDENTIALS creds;
|
||||
|
||||
|
249
crypto/openssh/auth-krb5.c
Normal file
249
crypto/openssh/auth-krb5.c
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Kerberos v5 authentication and ticket-passing routines.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#ifdef KRB5
|
||||
|
||||
extern krb5_context ssh_context;
|
||||
krb5_auth_context auth_context;
|
||||
krb5_ccache mem_ccache = NULL; /* Credential cache for acquired ticket */
|
||||
|
||||
/* Try krb5 authentication. server_user is passed for logging purposes only,
|
||||
in auth is received ticket, in client is returned principal from the
|
||||
ticket */
|
||||
int
|
||||
auth_krb5(const char* server_user, krb5_data *auth, krb5_principal *client)
|
||||
{
|
||||
krb5_error_code problem;
|
||||
krb5_principal server = NULL;
|
||||
krb5_principal tkt_client = NULL;
|
||||
krb5_data reply;
|
||||
krb5_ticket *ticket = NULL;
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
reply.length = 0;
|
||||
|
||||
problem = krb5_init();
|
||||
if (problem)
|
||||
return 0;
|
||||
|
||||
problem = krb5_auth_con_init(ssh_context, &auth_context);
|
||||
if (problem) {
|
||||
log("Kerberos v5 authentication failed: %.100s",
|
||||
krb5_get_err_text(ssh_context, problem));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = packet_get_connection_in();
|
||||
problem = krb5_auth_con_setaddrs_from_fd(ssh_context, auth_context, &fd);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
problem = krb5_sname_to_principal(ssh_context, NULL, NULL ,
|
||||
KRB5_NT_SRV_HST, &server);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
problem = krb5_rd_req(ssh_context, &auth_context, auth, server, NULL,
|
||||
NULL, &ticket);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
problem = krb5_copy_principal(ssh_context, ticket->client, &tkt_client);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* if client wants mutual auth */
|
||||
problem = krb5_mk_rep(ssh_context, &auth_context, &reply);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
*client = tkt_client;
|
||||
|
||||
packet_start(SSH_SMSG_AUTH_KRB5_RESPONSE);
|
||||
packet_put_string((char *) reply.data, reply.length);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (server)
|
||||
krb5_free_principal(ssh_context, server);
|
||||
if (ticket)
|
||||
krb5_free_ticket(ssh_context, ticket);
|
||||
if (reply.length)
|
||||
xfree(reply.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
auth_krb5_tgt(char *server_user, krb5_data *tgt, krb5_principal tkt_client)
|
||||
{
|
||||
krb5_error_code problem;
|
||||
krb5_ccache ccache = NULL;
|
||||
|
||||
if (ssh_context == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
problem = krb5_cc_gen_new(ssh_context, &krb5_mcc_ops, &ccache);
|
||||
if (problem) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
problem = krb5_cc_initialize(ssh_context, ccache, tkt_client);
|
||||
if (problem) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
problem = krb5_rd_cred(ssh_context, auth_context, ccache, tgt);
|
||||
if (problem) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mem_ccache = ccache;
|
||||
ccache = NULL;
|
||||
|
||||
/*
|
||||
problem = krb5_cc_copy_cache(ssh_context, ccache, mem_ccache);
|
||||
if (problem) {
|
||||
mem_ccache = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
problem = krb5_cc_destroy(ssh_context, ccache);
|
||||
if (problem)
|
||||
goto fail;
|
||||
*/
|
||||
|
||||
#if 0
|
||||
packet_start(SSH_SMSG_SUCCESS);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
if (ccache)
|
||||
krb5_cc_destroy(ssh_context, ccache);
|
||||
#if 0
|
||||
packet_start(SSH_SMSG_FAILURE);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
auth_krb5_password(struct passwd *pw, const char *password)
|
||||
{
|
||||
krb5_error_code problem;
|
||||
krb5_ccache ccache = NULL;
|
||||
krb5_principal client = NULL;
|
||||
int ret;
|
||||
|
||||
problem = krb5_init();
|
||||
if (problem)
|
||||
return 0;
|
||||
|
||||
problem = krb5_parse_name(ssh_context, pw->pw_name, &client);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
problem = krb5_cc_gen_new(ssh_context, &krb5_mcc_ops, &ccache);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
problem = krb5_cc_initialize(ssh_context, ccache, client);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
problem = krb5_verify_user(ssh_context, client, ccache, password, 1, NULL);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
problem = krb5_cc_copy_cache(ssh_context, ccache, mem_ccache);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
mem_ccache = NULL;
|
||||
goto out;
|
||||
}
|
||||
*/
|
||||
mem_ccache = ccache;
|
||||
ccache = NULL;
|
||||
|
||||
ret = 1;
|
||||
out:
|
||||
if (client != NULL)
|
||||
krb5_free_principal(ssh_context, client);
|
||||
if (ccache != NULL)
|
||||
krb5_cc_destroy(ssh_context, ccache);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
krb5_cleanup_proc(void *ignore)
|
||||
{
|
||||
extern krb5_principal tkt_client;
|
||||
|
||||
debug("krb5_cleanup_proc() called");
|
||||
if (mem_ccache)
|
||||
krb5_cc_destroy(ssh_context, mem_ccache);
|
||||
if (tkt_client)
|
||||
krb5_free_principal(ssh_context, tkt_client);
|
||||
if (auth_context)
|
||||
krb5_auth_con_free(ssh_context, auth_context);
|
||||
if (ssh_context)
|
||||
krb5_free_context(ssh_context);
|
||||
}
|
||||
|
||||
int
|
||||
krb5_init(void)
|
||||
{
|
||||
krb5_error_code problem;
|
||||
static cleanup_registered = 0;
|
||||
|
||||
if (ssh_context == NULL) {
|
||||
problem = krb5_init_context(&ssh_context);
|
||||
if (problem)
|
||||
return problem;
|
||||
krb5_init_ets(ssh_context);
|
||||
}
|
||||
|
||||
if (!cleanup_registered) {
|
||||
fatal_add_cleanup(krb4_cleanup_proc, NULL);
|
||||
cleanup_registered = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* KRB5 */
|
@ -5,6 +5,8 @@
|
||||
* Created: Sat Mar 18 05:11:38 1995 ylo
|
||||
* Password authentication. This file contains the functions to check whether
|
||||
* the password is valid for the user.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -41,8 +43,16 @@ auth_password(struct passwd * pw, const char *password)
|
||||
/* Fall back to ordinary passwd authentication. */
|
||||
}
|
||||
#endif
|
||||
#ifdef KRB5
|
||||
if (options.krb5_authentication == 1) {
|
||||
if (auth_krb5_password(pw, password))
|
||||
return 1;
|
||||
/* Fall back to ordinary passwd authentication. */
|
||||
}
|
||||
|
||||
#endif /* KRB5 */
|
||||
#ifdef KRB4
|
||||
if (options.kerberos_authentication == 1) {
|
||||
if (options.krb4_authentication == 1) {
|
||||
int ret = auth_krb4_password(pw, password);
|
||||
if (ret == 1 || ret == 0)
|
||||
return ret;
|
||||
|
@ -93,10 +93,13 @@ typedef enum {
|
||||
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
|
||||
oSkeyAuthentication,
|
||||
#ifdef KRB4
|
||||
oKerberosAuthentication,
|
||||
oKrb4Authentication,
|
||||
#endif /* KRB4 */
|
||||
#ifdef KRB5
|
||||
oKrb5Authentication, oKrb5TgtPassing,
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
oKerberosTgtPassing, oAFSTokenPassing,
|
||||
oKrb4TgtPassing, oAFSTokenPassing,
|
||||
#endif
|
||||
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
|
||||
oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
|
||||
@ -121,10 +124,14 @@ static struct {
|
||||
{ "rsaauthentication", oRSAAuthentication },
|
||||
{ "skeyauthentication", oSkeyAuthentication },
|
||||
#ifdef KRB4
|
||||
{ "kerberosauthentication", oKerberosAuthentication },
|
||||
{ "kerberos4authentication", oKrb4Authentication },
|
||||
#endif /* KRB4 */
|
||||
#ifdef KRB5
|
||||
{ "kerberos5authentication", oKrb5Authentication },
|
||||
{ "kerberos5tgtpassing", oKrb5TgtPassing },
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
{ "kerberostgtpassing", oKerberosTgtPassing },
|
||||
{ "kerberos4tgtpassing", oKrb4TgtPassing },
|
||||
{ "afstokenpassing", oAFSTokenPassing },
|
||||
#endif
|
||||
{ "fallbacktorsh", oFallBackToRsh },
|
||||
@ -298,14 +305,24 @@ process_config_line(Options *options, const char *host,
|
||||
goto parse_flag;
|
||||
|
||||
#ifdef KRB4
|
||||
case oKerberosAuthentication:
|
||||
intptr = &options->kerberos_authentication;
|
||||
case oKrb4Authentication:
|
||||
intptr = &options->krb4_authentication;
|
||||
goto parse_flag;
|
||||
#endif /* KRB4 */
|
||||
|
||||
#ifdef KRB5
|
||||
case oKrb5Authentication:
|
||||
intptr = &options->krb5_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case oKrb5TgtPassing:
|
||||
intptr = &options->krb5_tgt_passing;
|
||||
goto parse_flag;
|
||||
#endif /* KRB5 */
|
||||
|
||||
#ifdef AFS
|
||||
case oKerberosTgtPassing:
|
||||
intptr = &options->kerberos_tgt_passing;
|
||||
case oKrb4TgtPassing:
|
||||
intptr = &options->krb4_tgt_passing;
|
||||
goto parse_flag;
|
||||
|
||||
case oAFSTokenPassing:
|
||||
@ -596,10 +613,14 @@ initialize_options(Options * options)
|
||||
options->rsa_authentication = -1;
|
||||
options->skey_authentication = -1;
|
||||
#ifdef KRB4
|
||||
options->kerberos_authentication = -1;
|
||||
options->krb4_authentication = -1;
|
||||
#endif
|
||||
#ifdef KRB5
|
||||
options->krb5_authentication = -1;
|
||||
options->krb5_tgt_passing = -1;
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
options->kerberos_tgt_passing = -1;
|
||||
options->krb4_tgt_passing = -1;
|
||||
options->afs_token_passing = -1;
|
||||
#endif
|
||||
options->password_authentication = -1;
|
||||
@ -651,12 +672,18 @@ fill_default_options(Options * options)
|
||||
if (options->skey_authentication == -1)
|
||||
options->skey_authentication = 0;
|
||||
#ifdef KRB4
|
||||
if (options->kerberos_authentication == -1)
|
||||
options->kerberos_authentication = 1;
|
||||
if (options->krb4_authentication == -1)
|
||||
options->krb4_authentication = 1;
|
||||
#endif /* KRB4 */
|
||||
#ifdef KRB5
|
||||
if (options->krb5_authentication == -1)
|
||||
options->krb5_authentication = 1;
|
||||
if (options->krb5_tgt_passing == -1)
|
||||
options->krb5_tgt_passing = 1;
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
if (options->kerberos_tgt_passing == -1)
|
||||
options->kerberos_tgt_passing = 1;
|
||||
if (options->krb4_tgt_passing == -1)
|
||||
options->krb4_tgt_passing = 1;
|
||||
if (options->afs_token_passing == -1)
|
||||
options->afs_token_passing = 1;
|
||||
#endif /* AFS */
|
||||
|
@ -11,6 +11,7 @@
|
||||
*
|
||||
* Functions for reading the configuration file.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* RCSID("$Id: readconf.h,v 1.13 1999/12/01 13:59:15 markus Exp $"); */
|
||||
@ -38,11 +39,17 @@ typedef struct {
|
||||
int rsa_authentication; /* Try RSA authentication. */
|
||||
int skey_authentication; /* Try S/Key or TIS authentication. */
|
||||
#ifdef KRB4
|
||||
int kerberos_authentication; /* Try Kerberos
|
||||
int krb4_authentication; /* Try Kerberos v4
|
||||
* authentication. */
|
||||
#endif
|
||||
|
||||
#ifdef KRB5
|
||||
int krb5_authentication;
|
||||
int krb5_tgt_passing;
|
||||
#endif /* KRB5 */
|
||||
|
||||
#ifdef AFS
|
||||
int kerberos_tgt_passing; /* Try Kerberos tgt passing. */
|
||||
int krb4_tgt_passing; /* Try Kerberos v4 tgt passing. */
|
||||
int afs_token_passing; /* Try AFS token passing. */
|
||||
#endif
|
||||
int password_authentication; /* Try password
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$Id: servconf.c,v 1.29 2000/01/04 00:07:59 markus Exp $");
|
||||
RCSID("$Id: servconf.c,v 1.30 2000/02/24 18:22:16 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "servconf.h"
|
||||
@ -50,12 +50,16 @@ initialize_server_options(ServerOptions *options)
|
||||
options->rhosts_rsa_authentication = -1;
|
||||
options->rsa_authentication = -1;
|
||||
#ifdef KRB4
|
||||
options->kerberos_authentication = -1;
|
||||
options->kerberos_or_local_passwd = -1;
|
||||
options->kerberos_ticket_cleanup = -1;
|
||||
options->krb4_authentication = -1;
|
||||
options->krb4_or_local_passwd = -1;
|
||||
options->krb4_ticket_cleanup = -1;
|
||||
#endif
|
||||
#ifdef KRB5
|
||||
options->krb5_authentication = -1;
|
||||
options->krb5_tgt_passing = -1;
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
options->kerberos_tgt_passing = -1;
|
||||
options->krb4_tgt_passing = -1;
|
||||
options->afs_token_passing = -1;
|
||||
#endif
|
||||
options->password_authentication = -1;
|
||||
@ -90,7 +94,7 @@ fill_default_server_options(ServerOptions *options)
|
||||
if (options->permit_root_login == -1)
|
||||
options->permit_root_login = 1; /* yes */
|
||||
if (options->ignore_rhosts == -1)
|
||||
options->ignore_rhosts = 0;
|
||||
options->ignore_rhosts = 1;
|
||||
if (options->ignore_user_known_hosts == -1)
|
||||
options->ignore_user_known_hosts = 0;
|
||||
if (options->check_mail == -1)
|
||||
@ -100,7 +104,7 @@ fill_default_server_options(ServerOptions *options)
|
||||
if (options->x11_forwarding == -1)
|
||||
options->x11_forwarding = 1;
|
||||
if (options->x11_display_offset == -1)
|
||||
options->x11_display_offset = 1;
|
||||
options->x11_display_offset = 10;
|
||||
if (options->strict_modes == -1)
|
||||
options->strict_modes = 1;
|
||||
if (options->keepalives == -1)
|
||||
@ -112,20 +116,26 @@ fill_default_server_options(ServerOptions *options)
|
||||
if (options->rhosts_authentication == -1)
|
||||
options->rhosts_authentication = 0;
|
||||
if (options->rhosts_rsa_authentication == -1)
|
||||
options->rhosts_rsa_authentication = 1;
|
||||
options->rhosts_rsa_authentication = 0;
|
||||
if (options->rsa_authentication == -1)
|
||||
options->rsa_authentication = 1;
|
||||
#ifdef KRB4
|
||||
if (options->kerberos_authentication == -1)
|
||||
options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
|
||||
if (options->kerberos_or_local_passwd == -1)
|
||||
options->kerberos_or_local_passwd = 1;
|
||||
if (options->kerberos_ticket_cleanup == -1)
|
||||
options->kerberos_ticket_cleanup = 1;
|
||||
if (options->krb4_authentication == -1)
|
||||
options->krb4_authentication = (access(KEYFILE, R_OK) == 0);
|
||||
if (options->krb4_or_local_passwd == -1)
|
||||
options->krb4_or_local_passwd = 1;
|
||||
if (options->krb4_ticket_cleanup == -1)
|
||||
options->krb4_ticket_cleanup = 1;
|
||||
#endif /* KRB4 */
|
||||
#ifdef KRB5
|
||||
if (options->krb5_authentication == -1)
|
||||
options->krb5_authentication = 1;
|
||||
if (options->krb5_tgt_passing == -1)
|
||||
options->krb5_tgt_passing = 1;
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
if (options->kerberos_tgt_passing == -1)
|
||||
options->kerberos_tgt_passing = 0;
|
||||
if (options->krb4_tgt_passing == -1)
|
||||
options->krb4_tgt_passing = 0;
|
||||
if (options->afs_token_passing == -1)
|
||||
options->afs_token_passing = k_hasafs();
|
||||
#endif /* AFS */
|
||||
@ -136,7 +146,7 @@ fill_default_server_options(ServerOptions *options)
|
||||
options->skey_authentication = 1;
|
||||
#endif
|
||||
if (options->permit_empty_passwd == -1)
|
||||
options->permit_empty_passwd = 1;
|
||||
options->permit_empty_passwd = 0;
|
||||
if (options->use_login == -1)
|
||||
options->use_login = 0;
|
||||
}
|
||||
@ -150,10 +160,13 @@ typedef enum {
|
||||
sPermitRootLogin, sLogFacility, sLogLevel,
|
||||
sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
|
||||
#ifdef KRB4
|
||||
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
|
||||
sKrb4Authentication, sKrb4OrLocalPasswd, sKrb4TicketCleanup,
|
||||
#endif
|
||||
#ifdef KRB5
|
||||
sKrb5Authentication, sKrb5TgtPassing,
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
sKerberosTgtPassing, sAFSTokenPassing,
|
||||
sKrb4TgtPassing, sAFSTokenPassing,
|
||||
#endif
|
||||
#ifdef SKEY
|
||||
sSkeyAuthentication,
|
||||
@ -182,12 +195,16 @@ static struct {
|
||||
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
|
||||
{ "rsaauthentication", sRSAAuthentication },
|
||||
#ifdef KRB4
|
||||
{ "kerberosauthentication", sKerberosAuthentication },
|
||||
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
|
||||
{ "kerberosticketcleanup", sKerberosTicketCleanup },
|
||||
{ "kerberos4authentication", sKrb4Authentication },
|
||||
{ "kerberos4orlocalpasswd", sKrb4OrLocalPasswd },
|
||||
{ "kerberos4ticketcleanup", sKrb4TicketCleanup },
|
||||
#endif
|
||||
#ifdef KRB5
|
||||
{ "kerberos5authentication", sKrb5Authentication },
|
||||
{ "kerberos5tgtpassing", sKrb5TgtPassing },
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
{ "kerberostgtpassing", sKerberosTgtPassing },
|
||||
{ "kerberos4tgtpassing", sKrb4TgtPassing },
|
||||
{ "afstokenpassing", sAFSTokenPassing },
|
||||
#endif
|
||||
{ "passwordauthentication", sPasswordAuthentication },
|
||||
@ -425,22 +442,32 @@ read_server_config(ServerOptions *options, const char *filename)
|
||||
goto parse_flag;
|
||||
|
||||
#ifdef KRB4
|
||||
case sKerberosAuthentication:
|
||||
intptr = &options->kerberos_authentication;
|
||||
case sKrb4Authentication:
|
||||
intptr = &options->krb4_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case sKerberosOrLocalPasswd:
|
||||
intptr = &options->kerberos_or_local_passwd;
|
||||
case sKrb4OrLocalPasswd:
|
||||
intptr = &options->krb4_or_local_passwd;
|
||||
goto parse_flag;
|
||||
|
||||
case sKerberosTicketCleanup:
|
||||
intptr = &options->kerberos_ticket_cleanup;
|
||||
case sKrb4TicketCleanup:
|
||||
intptr = &options->krb4_ticket_cleanup;
|
||||
goto parse_flag;
|
||||
#endif
|
||||
|
||||
#ifdef KRB5
|
||||
case sKrb5Authentication:
|
||||
intptr = &options->krb5_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case sKrb5TgtPassing:
|
||||
intptr = &options->krb5_tgt_passing;
|
||||
goto parse_flag;
|
||||
#endif /* KRB5 */
|
||||
|
||||
#ifdef AFS
|
||||
case sKerberosTgtPassing:
|
||||
intptr = &options->kerberos_tgt_passing;
|
||||
case sKrb4TgtPassing:
|
||||
intptr = &options->krb4_tgt_passing;
|
||||
goto parse_flag;
|
||||
|
||||
case sAFSTokenPassing:
|
||||
|
@ -56,18 +56,23 @@ typedef struct {
|
||||
* authentication. */
|
||||
int rsa_authentication; /* If true, permit RSA authentication. */
|
||||
#ifdef KRB4
|
||||
int kerberos_authentication; /* If true, permit Kerberos
|
||||
int krb4_authentication; /* If true, permit Kerberos v4
|
||||
* authentication. */
|
||||
int kerberos_or_local_passwd; /* If true, permit kerberos
|
||||
int krb4_or_local_passwd; /* If true, permit kerberos v4
|
||||
* and any other password
|
||||
* authentication mechanism,
|
||||
* such as SecurID or
|
||||
* /etc/passwd */
|
||||
int kerberos_ticket_cleanup; /* If true, destroy ticket
|
||||
int krb4_ticket_cleanup; /* If true, destroy ticket
|
||||
* file on logout. */
|
||||
#endif
|
||||
#ifdef KRB5
|
||||
int krb5_authentication;
|
||||
int krb5_tgt_passing;
|
||||
|
||||
#endif /* KRB5 */
|
||||
#ifdef AFS
|
||||
int kerberos_tgt_passing; /* If true, permit Kerberos tgt
|
||||
int krb4_tgt_passing; /* If true, permit Kerberos v4 tgt
|
||||
* passing. */
|
||||
int afs_token_passing; /* If true, permit AFS token passing. */
|
||||
#endif
|
||||
|
@ -295,7 +295,8 @@ main(int ac, char **av)
|
||||
break;
|
||||
#ifdef AFS
|
||||
case 'k':
|
||||
options.kerberos_tgt_passing = 0;
|
||||
options.krb4_tgt_passing = 0;
|
||||
options.krb5_tgt_passing = 0;
|
||||
options.afs_token_passing = 0;
|
||||
break;
|
||||
#endif
|
||||
|
@ -182,11 +182,14 @@
|
||||
#define SSH_AUTH_PASSWORD 3
|
||||
#define SSH_AUTH_RHOSTS_RSA 4
|
||||
#define SSH_AUTH_TIS 5
|
||||
#define SSH_AUTH_KERBEROS 6
|
||||
#define SSH_PASS_KERBEROS_TGT 7
|
||||
#define SSH_AUTH_KRB4 6
|
||||
#define SSH_PASS_KRB4_TGT 7
|
||||
/* 8 to 15 are reserved */
|
||||
#define SSH_PASS_AFS_TOKEN 21
|
||||
|
||||
#define SSH_AUTH_KRB5 29
|
||||
#define SSH_PASS_KRB5_TGT 30
|
||||
|
||||
/* Protocol flags. These are bit masks. */
|
||||
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
|
||||
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
|
||||
@ -240,11 +243,15 @@
|
||||
#define SSH_CMSG_AUTH_TIS 39 /* we use this for s/key */
|
||||
#define SSH_SMSG_AUTH_TIS_CHALLENGE 40 /* challenge (string) */
|
||||
#define SSH_CMSG_AUTH_TIS_RESPONSE 41 /* response (string) */
|
||||
#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
|
||||
#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
|
||||
#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */
|
||||
#define SSH_CMSG_AUTH_KRB4 42 /* (KTEXT) */
|
||||
#define SSH_SMSG_AUTH_KRB4_RESPONSE 43 /* (KTEXT) */
|
||||
#define SSH_CMSG_HAVE_KRB4_TGT 44 /* credentials (s) */
|
||||
#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */
|
||||
|
||||
#define SSH_CMSG_AUTH_KRB5 110
|
||||
#define SSH_SMSG_AUTH_KRB5_RESPONSE 111
|
||||
#define SSH_CMSG_HAVE_KRB5_TGT 112
|
||||
|
||||
/*------------ definitions for login.c -------------*/
|
||||
|
||||
/*
|
||||
@ -690,6 +697,15 @@ struct envstring {
|
||||
*/
|
||||
ssize_t atomicio(ssize_t (*f)(), int fd, void *s, size_t n);
|
||||
|
||||
#ifdef KRB5
|
||||
#include <krb5.h>
|
||||
int auth_krb5(); /* XXX Doplnit prototypy */
|
||||
int auth_krb5_tgt();
|
||||
int krb5_init();
|
||||
void krb5_cleanup_proc(void *ignore);
|
||||
int auth_krb5_password(struct passwd *pw, const char *password);
|
||||
#endif /* KRB5 */
|
||||
|
||||
#ifdef KRB4
|
||||
#include <krb.h>
|
||||
/*
|
||||
@ -706,7 +722,7 @@ int auth_krb4_password(struct passwd * pw, const char *password);
|
||||
#include <kafs.h>
|
||||
|
||||
/* Accept passed Kerberos v4 ticket-granting ticket and AFS tokens. */
|
||||
int auth_kerberos_tgt(struct passwd * pw, const char *string);
|
||||
int auth_krb4_tgt(struct passwd * pw, const char *string);
|
||||
int auth_afs_token(struct passwd * pw, const char *token_string);
|
||||
|
||||
int creds_to_radix(CREDENTIALS * creds, unsigned char *buf);
|
||||
|
@ -626,7 +626,7 @@ try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
|
||||
|
||||
#ifdef KRB4
|
||||
int
|
||||
try_kerberos_authentication()
|
||||
try_krb4_authentication()
|
||||
{
|
||||
KTEXT_ST auth; /* Kerberos data */
|
||||
char *reply;
|
||||
@ -668,7 +668,7 @@ try_kerberos_authentication()
|
||||
des_key_sched((des_cblock *) cred.session, schedule);
|
||||
|
||||
/* Send authentication info to server. */
|
||||
packet_start(SSH_CMSG_AUTH_KERBEROS);
|
||||
packet_start(SSH_CMSG_AUTH_KRB4);
|
||||
packet_put_string((char *) auth.dat, auth.length);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
@ -693,13 +693,13 @@ try_kerberos_authentication()
|
||||
type = packet_read(&plen);
|
||||
switch (type) {
|
||||
case SSH_SMSG_FAILURE:
|
||||
/* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
|
||||
/* Should really be SSH_SMSG_AUTH_KRB4_FAILURE */
|
||||
debug("Kerberos V4 authentication failed.");
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
|
||||
/* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
|
||||
case SSH_SMSG_AUTH_KRB4_RESPONSE:
|
||||
/* SSH_SMSG_AUTH_KRB4_SUCCESS */
|
||||
debug("Kerberos V4 authentication accepted.");
|
||||
|
||||
/* Get server's response. */
|
||||
@ -742,7 +742,7 @@ try_kerberos_authentication()
|
||||
|
||||
#ifdef AFS
|
||||
int
|
||||
send_kerberos_tgt()
|
||||
send_krb4_tgt()
|
||||
{
|
||||
CREDENTIALS *creds;
|
||||
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
|
||||
@ -771,7 +771,7 @@ send_kerberos_tgt()
|
||||
creds_to_radix(creds, buffer);
|
||||
xfree(creds);
|
||||
|
||||
packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
|
||||
packet_start(SSH_CMSG_HAVE_KRB4_TGT);
|
||||
packet_put_string((char *) buffer, strlen(buffer));
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
@ -856,6 +856,247 @@ send_afs_tokens(void)
|
||||
|
||||
#endif /* AFS */
|
||||
|
||||
#ifdef KRB5
|
||||
int
|
||||
try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context)
|
||||
{
|
||||
krb5_error_code problem;
|
||||
const char *tkfile;
|
||||
struct stat buf;
|
||||
krb5_ccache ccache = NULL;
|
||||
krb5_creds req_creds;
|
||||
krb5_creds *new_creds = NULL;
|
||||
const char *remotehost;
|
||||
krb5_data ap;
|
||||
int type, payload_len;
|
||||
krb5_ap_rep_enc_part *reply = NULL;
|
||||
int ret;
|
||||
|
||||
memset(&ap, 0, sizeof(ap));
|
||||
|
||||
problem = krb5_init_context(context);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tkfile = krb5_cc_default_name(*context);
|
||||
if (strncmp(tkfile, "FILE:", 5) == 0)
|
||||
tkfile += 5;
|
||||
|
||||
if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) {
|
||||
debug("Kerberos V5: could not get default ccache (permission denied).");
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
problem = krb5_cc_default(*context, &ccache);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(&req_creds, 0, sizeof(req_creds));
|
||||
|
||||
remotehost = get_canonical_hostname();
|
||||
|
||||
problem = krb5_sname_to_principal(*context, remotehost,
|
||||
"host", KRB5_NT_SRV_HST,
|
||||
&req_creds.server);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
|
||||
}
|
||||
|
||||
problem = krb5_cc_get_principal(*context, ccache, &req_creds.client);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* creds.session.keytype=ETYPE_DES_CBC_CRC; */
|
||||
|
||||
problem = krb5_get_credentials(*context, 0, ccache, &req_creds, &new_creds);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
problem = krb5_auth_con_init(*context, auth_context);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* krb5_auth_con_setflags(ssh_context, auth_context,
|
||||
KRB5_AUTH_CONTEXT_RET_TIME);
|
||||
*/
|
||||
problem = krb5_mk_req_extended(*context, auth_context,
|
||||
AP_OPTS_MUTUAL_REQUIRED /*| AP_OPTS_USE_SUBKEY*/ ,
|
||||
NULL, new_creds, &ap);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
packet_start(SSH_CMSG_AUTH_KRB5);
|
||||
packet_put_string((char *) ap.data, ap.length);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
xfree(ap.data);
|
||||
ap.length = 0;
|
||||
|
||||
type = packet_read(&payload_len);
|
||||
switch (type) {
|
||||
case SSH_SMSG_FAILURE:
|
||||
/* Should really be SSH_SMSG_AUTH_KRB5_FAILURE */
|
||||
debug("Kerberos V5 authentication failed.");
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case SSH_SMSG_AUTH_KRB5_RESPONSE:
|
||||
/* SSH_SMSG_AUTH_KRB5_SUCCESS */
|
||||
debug("Kerberos V5 authentication accepted.");
|
||||
|
||||
/* Get server's response. */
|
||||
ap.data = packet_get_string((unsigned int *) &ap.length);
|
||||
|
||||
packet_integrity_check(payload_len, 4 + ap.length, type);
|
||||
/* XXX je to dobre? */
|
||||
|
||||
problem = krb5_rd_rep(*context, *auth_context, &ap, &reply);
|
||||
if (problem) {
|
||||
ret = 0;
|
||||
}
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
packet_disconnect("Protocol error on Kerberos V5 response: %d", type);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
if (req_creds.server != NULL)
|
||||
krb5_free_principal(*context, req_creds.server);
|
||||
if (req_creds.client != NULL)
|
||||
krb5_free_principal(*context, req_creds.client);
|
||||
if (new_creds != NULL)
|
||||
krb5_free_creds(*context, new_creds);
|
||||
if (ccache != NULL)
|
||||
krb5_cc_close(*context, ccache);
|
||||
if (reply != NULL)
|
||||
krb5_free_ap_rep_enc_part(*context, reply);
|
||||
if (ap.length > 0)
|
||||
krb5_data_free(&ap);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
send_krb5_tgt(krb5_context context, krb5_auth_context auth_context)
|
||||
{
|
||||
int fd;
|
||||
int type, payload_len;
|
||||
krb5_error_code problem;
|
||||
krb5_data outbuf;
|
||||
krb5_ccache ccache = NULL;
|
||||
krb5_creds creds;
|
||||
krb5_kdc_flags flags;
|
||||
const char* remotehost = get_canonical_hostname();
|
||||
|
||||
memset(&creds, 0, sizeof(creds));
|
||||
memset(&outbuf, 0, sizeof(outbuf));
|
||||
|
||||
fd = packet_get_connection_in();
|
||||
problem = krb5_auth_con_setaddrs_from_fd(context, auth_context, &fd);
|
||||
if (problem) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if 0
|
||||
tkfile = krb5_cc_default_name(context);
|
||||
if (strncmp(tkfile, "FILE:", 5) == 0)
|
||||
tkfile += 5;
|
||||
|
||||
if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) {
|
||||
debug("Kerberos V5: could not get default ccache (permission denied).");
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
problem = krb5_cc_default(context, &ccache);
|
||||
if (problem) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
problem = krb5_cc_get_principal(context, ccache, &creds.client);
|
||||
if (problem) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
problem = krb5_build_principal(context, &creds.server,
|
||||
strlen(creds.client->realm),
|
||||
creds.client->realm,
|
||||
"krbtgt",
|
||||
creds.client->realm,
|
||||
NULL);
|
||||
if (problem) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
creds.times.endtime = 0;
|
||||
|
||||
flags.i = 0;
|
||||
flags.b.forwarded = 1;
|
||||
flags.b.forwardable = krb5_config_get_bool(context, NULL,
|
||||
"libdefaults", "forwardable", NULL);
|
||||
|
||||
problem = krb5_get_forwarded_creds (context,
|
||||
auth_context,
|
||||
ccache,
|
||||
flags.i,
|
||||
remotehost,
|
||||
&creds,
|
||||
&outbuf);
|
||||
if (problem) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
packet_start(SSH_CMSG_HAVE_KRB5_TGT);
|
||||
packet_put_string((char *)outbuf.data, outbuf.length);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
type = packet_read(&payload_len);
|
||||
switch (type) {
|
||||
case SSH_SMSG_SUCCESS:
|
||||
break;
|
||||
case SSH_SMSG_FAILURE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if (creds.client)
|
||||
krb5_free_principal(context, creds.client);
|
||||
if (creds.server)
|
||||
krb5_free_principal(context, creds.server);
|
||||
if (ccache)
|
||||
krb5_cc_close(context, ccache);
|
||||
if (outbuf.data)
|
||||
xfree(outbuf.data);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* KRB5 */
|
||||
|
||||
/*
|
||||
* Tries to authenticate with any string-based challenge/response system.
|
||||
* Note that the client code is not tied to s/key or TIS.
|
||||
@ -1087,11 +1328,9 @@ check_host_key(char *host, struct sockaddr *hostaddr, RSA *host_key)
|
||||
case AF_INET:
|
||||
local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
local = 0;
|
||||
break;
|
||||
@ -1512,11 +1751,11 @@ ssh_userauth(int host_key_valid, RSA *own_host_key,
|
||||
|
||||
#ifdef AFS
|
||||
/* Try Kerberos tgt passing if the server supports it. */
|
||||
if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
|
||||
options.kerberos_tgt_passing) {
|
||||
if ((supported_authentications & (1 << SSH_PASS_KRB4_TGT)) &&
|
||||
options.krb4_tgt_passing) {
|
||||
if (options.cipher == SSH_CIPHER_NONE)
|
||||
log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
|
||||
(void) send_kerberos_tgt();
|
||||
(void) send_krb4_tgt();
|
||||
}
|
||||
/* Try AFS token passing if the server supports it. */
|
||||
if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
|
||||
@ -1528,10 +1767,10 @@ ssh_userauth(int host_key_valid, RSA *own_host_key,
|
||||
#endif /* AFS */
|
||||
|
||||
#ifdef KRB4
|
||||
if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
|
||||
options.kerberos_authentication) {
|
||||
if ((supported_authentications & (1 << SSH_AUTH_KRB4)) &&
|
||||
options.krb4_authentication) {
|
||||
debug("Trying Kerberos authentication.");
|
||||
if (try_kerberos_authentication()) {
|
||||
if (try_krb4_authentication()) {
|
||||
/* The server should respond with success or failure. */
|
||||
type = packet_read(&payload_len);
|
||||
if (type == SSH_SMSG_SUCCESS)
|
||||
@ -1542,6 +1781,35 @@ ssh_userauth(int host_key_valid, RSA *own_host_key,
|
||||
}
|
||||
#endif /* KRB4 */
|
||||
|
||||
#ifdef KRB5
|
||||
if ((supported_authentications & (1 << SSH_AUTH_KRB5)) &&
|
||||
options.krb5_authentication){
|
||||
krb5_context ssh_context = NULL;
|
||||
krb5_auth_context auth_context = NULL;
|
||||
|
||||
debug("Trying Kerberos V5 authentication.");
|
||||
|
||||
if (try_krb5_authentication(&ssh_context, &auth_context)) {
|
||||
type = packet_read(&payload_len);
|
||||
if (type == SSH_SMSG_SUCCESS) {
|
||||
if ((supported_authentications & (1 << SSH_PASS_KRB5_TGT)) &&
|
||||
options.krb5_tgt_passing) {
|
||||
if (options.cipher == SSH_CIPHER_NONE)
|
||||
log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
|
||||
send_krb5_tgt(ssh_context, auth_context);
|
||||
|
||||
}
|
||||
krb5_auth_con_free(ssh_context, auth_context);
|
||||
krb5_free_context(ssh_context);
|
||||
return;
|
||||
}
|
||||
if (type != SSH_SMSG_FAILURE)
|
||||
packet_disconnect("Protocol error: got %d in response to Kerberos5 auth", type);
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* KRB5 */
|
||||
|
||||
/*
|
||||
* Use rhosts authentication if running in privileged socket and we
|
||||
* do not wish to remain anonymous.
|
||||
|
@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.\" Created: Sat Apr 22 21:55:14 1995 ylo
|
||||
.\"
|
||||
.\" $Id: sshd.8,v 1.33 2000/02/21 14:19:09 deraadt Exp $
|
||||
.\" $Id: sshd.8,v 1.34 2000/02/24 18:22:16 markus Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 25, 1999
|
||||
@ -284,13 +284,16 @@ Note that
|
||||
.Nm
|
||||
does not start if this file is group/world-accessible.
|
||||
.It Cm IgnoreRhosts
|
||||
Specifies that rhosts and shosts files will not be used in
|
||||
authentication.
|
||||
Specifies that
|
||||
.Pa .rhosts
|
||||
and
|
||||
.Pa .shosts
|
||||
files will not be used in authentication.
|
||||
.Pa /etc/hosts.equiv
|
||||
and
|
||||
.Pa /etc/shosts.equiv
|
||||
are still used. The default is
|
||||
.Dq no .
|
||||
.Dq yes .
|
||||
.It Cm IgnoreUserKnownHosts
|
||||
Specifies whether
|
||||
.Nm
|
||||
@ -378,7 +381,7 @@ The default is
|
||||
When password authentication is allowed, it specifies whether the
|
||||
server allows login to accounts with empty password strings. The default
|
||||
is
|
||||
.Dq yes .
|
||||
.Dq no .
|
||||
.It Cm PermitRootLogin
|
||||
Specifies whether the root can log in using
|
||||
.Xr ssh 1 .
|
||||
@ -429,7 +432,7 @@ The default is
|
||||
.It Cm RhostsRSAAuthentication
|
||||
Specifies whether rhosts or /etc/hosts.equiv authentication together
|
||||
with successful RSA host authentication is allowed. The default is
|
||||
.Dq yes .
|
||||
.Dq no .
|
||||
.It Cm RSAAuthentication
|
||||
Specifies whether pure RSA authentication is allowed. The default is
|
||||
.Dq yes .
|
||||
@ -468,6 +471,7 @@ Specifies the first display number available for
|
||||
X11 forwarding. This prevents
|
||||
.Nm
|
||||
from interfering with real X11 servers.
|
||||
The default is 10.
|
||||
.It Cm X11Forwarding
|
||||
Specifies whether X11 forwarding is permitted. The default is
|
||||
.Dq yes .
|
||||
|
@ -37,9 +37,8 @@ int deny_severity = LOG_WARNING;
|
||||
#endif /* LIBWRAP */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <libutil.h>
|
||||
#include <syslog.h>
|
||||
#define LOGIN_CAP
|
||||
#define _PATH_CHPASS "/usr/bin/passwd"
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#ifdef LOGIN_CAP
|
||||
@ -50,6 +49,14 @@ int deny_severity = LOG_WARNING;
|
||||
#define O_NOCTTY 0
|
||||
#endif
|
||||
|
||||
#ifdef KRB5
|
||||
#include <krb5.h>
|
||||
krb5_context ssh_context = NULL;
|
||||
krb5_principal tkt_client = NULL; /* Principal from the received ticket.
|
||||
Also is used as an indication of succesful krb5 authentization. */
|
||||
#endif /* KRB5 */
|
||||
|
||||
|
||||
/* Local Xauthority file. */
|
||||
static char *xauthfile = NULL;
|
||||
|
||||
@ -149,7 +156,7 @@ struct magic_connection {
|
||||
const size_t MAGIC_CONNECTIONS_SIZE = 1;
|
||||
|
||||
static __inline int
|
||||
magic_hash(struct sockaddr_storage *sa) {
|
||||
magic_hash(struct sockaddr *sa) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -302,9 +309,13 @@ get_authname(int type)
|
||||
case SSH_CMSG_AUTH_RHOSTS:
|
||||
return "rhosts";
|
||||
#ifdef KRB4
|
||||
case SSH_CMSG_AUTH_KERBEROS:
|
||||
return "kerberos";
|
||||
case SSH_CMSG_AUTH_KRB4:
|
||||
return "kerberosV4";
|
||||
#endif
|
||||
#ifdef KRB5
|
||||
case SSH_CMSG_AUTH_KRB5:
|
||||
return "kerberosV5";
|
||||
#endif /* KRB5 */
|
||||
#ifdef SKEY
|
||||
case SSH_CMSG_AUTH_TIS_RESPONSE:
|
||||
return "s/key";
|
||||
@ -723,7 +734,7 @@ main(int ac, char **av)
|
||||
struct magic_connection *mc;
|
||||
|
||||
(void)gettimeofday(&connections_end, NULL);
|
||||
mc = &magic_connections[magic_hash(&from)];
|
||||
mc = &magic_connections[magic_hash((struct sockaddr *)0)];
|
||||
diff = timevaldiff(&mc->connections_begin, &connections_end);
|
||||
if (diff.tv_sec >= options.connections_period) {
|
||||
/*
|
||||
@ -948,9 +959,9 @@ main(int ac, char **av)
|
||||
}
|
||||
#ifdef KRB4
|
||||
if (!packet_connection_is_ipv4() &&
|
||||
options.kerberos_authentication) {
|
||||
options.krb4_authentication) {
|
||||
debug("Kerberos Authentication disabled, only available for IPv4.");
|
||||
options.kerberos_authentication = 0;
|
||||
options.krb4_authentication = 0;
|
||||
}
|
||||
#endif /* KRB4 */
|
||||
|
||||
@ -964,7 +975,7 @@ main(int ac, char **av)
|
||||
|
||||
#ifdef KRB4
|
||||
/* Cleanup user's ticket cache file. */
|
||||
if (options.kerberos_ticket_cleanup)
|
||||
if (options.krb4_ticket_cleanup)
|
||||
(void) dest_tkt();
|
||||
#endif /* KRB4 */
|
||||
|
||||
@ -1042,12 +1053,22 @@ do_ssh_kex()
|
||||
if (options.rsa_authentication)
|
||||
auth_mask |= 1 << SSH_AUTH_RSA;
|
||||
#ifdef KRB4
|
||||
if (options.kerberos_authentication)
|
||||
auth_mask |= 1 << SSH_AUTH_KERBEROS;
|
||||
if (options.krb4_authentication)
|
||||
auth_mask |= 1 << SSH_AUTH_KRB4;
|
||||
#endif
|
||||
#ifdef KRB5
|
||||
if (options.krb5_authentication) {
|
||||
auth_mask |= 1 << SSH_AUTH_KRB5;
|
||||
/* compatibility with MetaCentre ssh */
|
||||
auth_mask |= 1 << SSH_AUTH_KRB4;
|
||||
}
|
||||
if (options.krb5_tgt_passing)
|
||||
auth_mask |= 1 << SSH_PASS_KRB5_TGT;
|
||||
#endif /* KRB5 */
|
||||
|
||||
#ifdef AFS
|
||||
if (options.kerberos_tgt_passing)
|
||||
auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;
|
||||
if (options.krb4_tgt_passing)
|
||||
auth_mask |= 1 << SSH_PASS_KRB4_TGT;
|
||||
if (options.afs_token_passing)
|
||||
auth_mask |= 1 << SSH_PASS_AFS_TOKEN;
|
||||
#endif
|
||||
@ -1246,6 +1267,7 @@ allowed_user(struct passwd * pw)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifndef __FreeBSD__ /* FreeBSD handle it later */
|
||||
/* Fail if the account's expiration time has passed. */
|
||||
if (pw->pw_expire != 0) {
|
||||
struct timeval tv;
|
||||
@ -1254,6 +1276,7 @@ allowed_user(struct passwd * pw)
|
||||
if (tv.tv_sec >= pw->pw_expire)
|
||||
return 0;
|
||||
}
|
||||
#endif /* !__FreeBSD__ */
|
||||
/* We found no reason not to let this user try to log on... */
|
||||
return 1;
|
||||
}
|
||||
@ -1268,6 +1291,12 @@ do_authentication()
|
||||
struct passwd *pw, pwcopy;
|
||||
int plen, ulen;
|
||||
char *user;
|
||||
#ifdef LOGIN_CAP
|
||||
login_cap_t *lc;
|
||||
char *hosts;
|
||||
const char *from_host, *from_ip;
|
||||
int denied;
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
/* Get the name of the user that we wish to log in as. */
|
||||
packet_read_expect(&plen, SSH_CMSG_USER);
|
||||
@ -1316,8 +1345,11 @@ do_authentication()
|
||||
|
||||
/* If the user has no password, accept authentication immediately. */
|
||||
if (options.password_authentication &&
|
||||
#ifdef KRB5
|
||||
!options.krb5_authentication &&
|
||||
#endif /* KRB5 */
|
||||
#ifdef KRB4
|
||||
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
|
||||
(!options.krb4_authentication || options.krb4_or_local_passwd) &&
|
||||
#endif /* KRB4 */
|
||||
auth_password(pw, "")) {
|
||||
/* Authentication with empty password succeeded. */
|
||||
@ -1338,6 +1370,38 @@ do_authentication()
|
||||
packet_disconnect("ROOT LOGIN REFUSED FROM %.200s",
|
||||
get_canonical_hostname());
|
||||
}
|
||||
|
||||
#ifdef LOGIN_CAP
|
||||
lc = login_getpwclass(pw);
|
||||
if (lc == NULL)
|
||||
lc = login_getclassbyname(NULL, pw);
|
||||
from_host = get_canonical_hostname();
|
||||
from_ip = get_remote_ipaddr();
|
||||
|
||||
denied = 0;
|
||||
if ((hosts = login_getcapstr(lc, "host.deny", NULL, NULL)) != NULL) {
|
||||
denied = match_hostname(from_host, hosts, strlen(hosts));
|
||||
if (!denied)
|
||||
denied = match_hostname(from_ip, hosts, strlen(hosts));
|
||||
}
|
||||
if (!denied &&
|
||||
(hosts = login_getcapstr(lc, "host.allow", NULL, NULL)) != NULL) {
|
||||
denied = !match_hostname(from_host, hosts, strlen(hosts));
|
||||
if (denied)
|
||||
denied = !match_hostname(from_ip, hosts, strlen(hosts));
|
||||
}
|
||||
login_close(lc);
|
||||
if (denied) {
|
||||
log("Denied connection for %.200s from %.200s [%.200s].",
|
||||
pw->pw_name, from_host, from_ip);
|
||||
packet_disconnect("Sorry, you are not allowed to connect.");
|
||||
}
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
if (pw->pw_uid == 0)
|
||||
log("ROOT LOGIN as '%.100s' from %.100s",
|
||||
pw->pw_name, get_canonical_hostname());
|
||||
|
||||
/* The user has been authenticated and accepted. */
|
||||
packet_start(SSH_SMSG_SUCCESS);
|
||||
packet_send();
|
||||
@ -1367,6 +1431,22 @@ do_authloop(struct passwd * pw)
|
||||
int plen, dlen, nlen, ulen, elen;
|
||||
int type = 0;
|
||||
void (*authlog) (const char *fmt,...) = verbose;
|
||||
#ifdef HAVE_LIBPAM
|
||||
int pam_retval;
|
||||
#endif /* HAVE_LIBPAM */
|
||||
#if 0
|
||||
#ifdef KRB5
|
||||
{
|
||||
krb5_error_code ret;
|
||||
|
||||
ret = krb5_init_context(&ssh_context);
|
||||
if (ret)
|
||||
verbose("Error while initializing Kerberos V5.");
|
||||
krb5_init_ets(ssh_context);
|
||||
|
||||
}
|
||||
#endif /* KRB5 */
|
||||
#endif
|
||||
|
||||
/* Indicate that authentication is needed. */
|
||||
packet_start(SSH_SMSG_FAILURE);
|
||||
@ -1383,17 +1463,17 @@ do_authloop(struct passwd * pw)
|
||||
/* Process the packet. */
|
||||
switch (type) {
|
||||
#ifdef AFS
|
||||
case SSH_CMSG_HAVE_KERBEROS_TGT:
|
||||
if (!options.kerberos_tgt_passing) {
|
||||
case SSH_CMSG_HAVE_KRB4_TGT:
|
||||
if (!options.krb4_tgt_passing) {
|
||||
/* packet_get_all(); */
|
||||
verbose("Kerberos tgt passing disabled.");
|
||||
verbose("Kerberos v4 tgt passing disabled.");
|
||||
break;
|
||||
} else {
|
||||
/* Accept Kerberos tgt. */
|
||||
/* Accept Kerberos v4 tgt. */
|
||||
char *tgt = packet_get_string(&dlen);
|
||||
packet_integrity_check(plen, 4 + dlen, type);
|
||||
if (!auth_kerberos_tgt(pw, tgt))
|
||||
verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
|
||||
if (!auth_krb4_tgt(pw, tgt))
|
||||
verbose("Kerberos v4 tgt REFUSED for %s", pw->pw_name);
|
||||
xfree(tgt);
|
||||
}
|
||||
continue;
|
||||
@ -1414,10 +1494,10 @@ do_authloop(struct passwd * pw)
|
||||
continue;
|
||||
#endif /* AFS */
|
||||
#ifdef KRB4
|
||||
case SSH_CMSG_AUTH_KERBEROS:
|
||||
if (!options.kerberos_authentication) {
|
||||
case SSH_CMSG_AUTH_KRB4:
|
||||
if (!options.krb4_authentication) {
|
||||
/* packet_get_all(); */
|
||||
verbose("Kerberos authentication disabled.");
|
||||
verbose("Kerberos v4 authentication disabled.");
|
||||
break;
|
||||
} else {
|
||||
/* Try Kerberos v4 authentication. */
|
||||
@ -1439,6 +1519,36 @@ do_authloop(struct passwd * pw)
|
||||
}
|
||||
break;
|
||||
#endif /* KRB4 */
|
||||
#ifdef KRB5
|
||||
case SSH_CMSG_AUTH_KRB5:
|
||||
if (!options.krb5_authentication) {
|
||||
verbose("Kerberos v5 authentication disabled.");
|
||||
break;
|
||||
} else {
|
||||
krb5_data k5data;
|
||||
#if 0
|
||||
if (krb5_init_context(&ssh_context)) {
|
||||
verbose("Error while initializing Kerberos V5.");
|
||||
break;
|
||||
}
|
||||
krb5_init_ets(ssh_context);
|
||||
#endif
|
||||
|
||||
k5data.data = packet_get_string(&k5data.length);
|
||||
packet_integrity_check(plen, 4 + k5data.length, type);
|
||||
if (auth_krb5(pw->pw_name, &k5data, &tkt_client)) {
|
||||
/* pw->name is passed just for logging purposes
|
||||
* */
|
||||
/* authorize client against .k5login */
|
||||
if (krb5_kuserok(ssh_context,
|
||||
tkt_client,
|
||||
pw->pw_name))
|
||||
authenticated = 1;
|
||||
}
|
||||
xfree(k5data.data);
|
||||
}
|
||||
break;
|
||||
#endif /* KRB5 */
|
||||
|
||||
case SSH_CMSG_AUTH_RHOSTS:
|
||||
if (!options.rhosts_authentication) {
|
||||
@ -1908,6 +2018,32 @@ do_authenticated(struct passwd * pw)
|
||||
do_exec_no_pty(command, pw, display, proto, data);
|
||||
xfree(command);
|
||||
return;
|
||||
#ifdef KRB5
|
||||
case SSH_CMSG_HAVE_KRB5_TGT:
|
||||
/* Passing krb5 ticket */
|
||||
if (!options.krb5_tgt_passing
|
||||
/*|| !options.krb5_authentication */) {
|
||||
|
||||
}
|
||||
|
||||
if (tkt_client == NULL) {
|
||||
/* passing tgt without krb5 authentication */
|
||||
}
|
||||
|
||||
{
|
||||
krb5_data tgt;
|
||||
tgt.data = packet_get_string(&tgt.length);
|
||||
|
||||
if (!auth_krb5_tgt(pw->pw_name, &tgt, tkt_client)) {
|
||||
verbose ("Kerberos V5 TGT refused for %.100s", pw->pw_name);
|
||||
xfree(tgt.data);
|
||||
goto fail;
|
||||
}
|
||||
xfree(tgt.data);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* KRB5 */
|
||||
|
||||
default:
|
||||
/*
|
||||
@ -2086,6 +2222,11 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
||||
login_cap_t *lc;
|
||||
char *fname;
|
||||
#endif /* LOGIN_CAP */
|
||||
#ifdef __FreeBSD__
|
||||
#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
|
||||
struct timeval tv;
|
||||
time_t warntime = DEFAULT_WARN;
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/* Get remote host name. */
|
||||
hostname = get_canonical_hostname();
|
||||
@ -2157,6 +2298,50 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
||||
quiet_login = login_getcapbool(lc, "hushlogin", quiet_login);
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (pw->pw_change || pw->pw_expire)
|
||||
(void)gettimeofday(&tv, NULL);
|
||||
#ifdef LOGIN_CAP
|
||||
warntime = login_getcaptime(lc, "warnpassword",
|
||||
DEFAULT_WARN, DEFAULT_WARN);
|
||||
#endif /* LOGIN_CAP */
|
||||
/*
|
||||
* If the password change time is set and has passed, give the
|
||||
* user a password expiry notice and chance to change it.
|
||||
*/
|
||||
if (pw->pw_change != 0) {
|
||||
if (tv.tv_sec >= pw->pw_change) {
|
||||
(void)printf(
|
||||
"Sorry -- your password has expired.\n");
|
||||
log("%s Password expired - forcing change",
|
||||
pw->pw_name);
|
||||
command = _PATH_CHPASS;
|
||||
} else if (pw->pw_change - tv.tv_sec < warntime &&
|
||||
!quiet_login)
|
||||
(void)printf(
|
||||
"Warning: your password expires on %s",
|
||||
ctime(&pw->pw_change));
|
||||
}
|
||||
#ifdef LOGIN_CAP
|
||||
warntime = login_getcaptime(lc, "warnexpire",
|
||||
DEFAULT_WARN, DEFAULT_WARN);
|
||||
#endif /* LOGIN_CAP */
|
||||
if (pw->pw_expire) {
|
||||
if (tv.tv_sec >= pw->pw_expire) {
|
||||
(void)printf(
|
||||
"Sorry -- your account has expired.\n");
|
||||
log(
|
||||
"LOGIN %.200s REFUSED (EXPIRED) FROM %.200s ON TTY %.200s",
|
||||
pw->pw_name, hostname, ttyname);
|
||||
exit(254);
|
||||
} else if (pw->pw_expire - tv.tv_sec < warntime &&
|
||||
!quiet_login)
|
||||
(void)printf(
|
||||
"Warning: your account expires on %s",
|
||||
ctime(&pw->pw_expire));
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/*
|
||||
* If the user has logged in before, display the time of last
|
||||
* login. However, don't display anything extra if a command
|
||||
@ -2203,10 +2388,9 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
||||
!options.use_login) {
|
||||
#ifdef LOGIN_CAP
|
||||
fname = login_getcapstr(lc, "welcome", NULL, NULL);
|
||||
login_close(lc);
|
||||
if (fname == NULL || (f = fopen(fname, "r")) == NULL)
|
||||
f = fopen("/etc/motd", "r");
|
||||
#else /* LOGIN_CAP */
|
||||
#else /* !LOGIN_CAP */
|
||||
f = fopen("/etc/motd", "r");
|
||||
#endif /* LOGIN_CAP */
|
||||
/* Print /etc/motd if it exists. */
|
||||
@ -2216,6 +2400,9 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
#ifdef LOGIN_CAP
|
||||
login_close(lc);
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
/* Do common processing for the child, such as execing the command. */
|
||||
do_child(command, pw, term, display, auth_proto, auth_data, ttyname);
|
||||
@ -2363,7 +2550,7 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
char buf[256];
|
||||
FILE *f;
|
||||
unsigned int envsize, i;
|
||||
char **env;
|
||||
char **env = NULL;
|
||||
extern char **environ;
|
||||
struct stat st;
|
||||
char *argv[10];
|
||||
@ -2373,29 +2560,24 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
lc = login_getpwclass(pw);
|
||||
if (lc == NULL)
|
||||
lc = login_getclassbyname(NULL, pw);
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
if (pw->pw_uid != 0)
|
||||
auth_checknologin(lc);
|
||||
#else /* !LOGIN_CAP */
|
||||
f = fopen("/etc/nologin", "r");
|
||||
#ifdef __FreeBSD__
|
||||
if (f == NULL)
|
||||
f = fopen("/var/run/nologin", "r");
|
||||
#endif /* __FreeBSD__ */
|
||||
if (f) {
|
||||
/* /etc/nologin exists. Print its contents and exit. */
|
||||
#ifdef LOGIN_CAP
|
||||
/* On FreeBSD, etc., allow overriding nologin via login.conf. */
|
||||
if (!login_getcapbool(lc, "ignorenologin", 0)) {
|
||||
#else /* LOGIN_CAP */
|
||||
if (1) {
|
||||
#endif /* LOGIN_CAP */
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
fputs(buf, stderr);
|
||||
fclose(f);
|
||||
if (pw->pw_uid != 0)
|
||||
exit(254);
|
||||
}
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
fputs(buf, stderr);
|
||||
fclose(f);
|
||||
if (pw->pw_uid != 0)
|
||||
exit(254);
|
||||
|
||||
}
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
#ifdef LOGIN_CAP
|
||||
if (options.use_login)
|
||||
#endif /* LOGIN_CAP */
|
||||
/* Set login name in the kernel. */
|
||||
if (setlogin(pw->pw_name) < 0)
|
||||
error("setlogin failed: %s", strerror(errno));
|
||||
@ -2405,12 +2587,42 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
switch, so we let login(1) to this for us. */
|
||||
if (!options.use_login) {
|
||||
#ifdef LOGIN_CAP
|
||||
if (setclasscontext(pw->pw_class, LOGIN_SETPRIORITY |
|
||||
LOGIN_SETRESOURCES | LOGIN_SETUMASK) == -1) {
|
||||
perror("setclasscontext");
|
||||
exit(1);
|
||||
}
|
||||
#endif /* LOGIN_CAP */
|
||||
char **tmpenv;
|
||||
|
||||
/* Initialize temp environment */
|
||||
envsize = 64;
|
||||
env = xmalloc(envsize * sizeof(char *));
|
||||
env[0] = NULL;
|
||||
|
||||
child_set_env(&env, &envsize, "PATH",
|
||||
(pw->pw_uid == 0) ?
|
||||
_PATH_STDPATH : _PATH_DEFPATH);
|
||||
|
||||
snprintf(buf, sizeof buf, "%.200s/%.50s",
|
||||
_PATH_MAILDIR, pw->pw_name);
|
||||
child_set_env(&env, &envsize, "MAIL", buf);
|
||||
|
||||
if (getenv("TZ"))
|
||||
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
|
||||
|
||||
/* Save parent environment */
|
||||
tmpenv = environ;
|
||||
environ = env;
|
||||
|
||||
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETALL) < 0)
|
||||
fatal("setusercontext failed: %s", strerror(errno));
|
||||
|
||||
/* Restore parent environment */
|
||||
env = environ;
|
||||
environ = tmpenv;
|
||||
|
||||
for (envsize = 0; env[envsize] != NULL; ++envsize)
|
||||
;
|
||||
envsize = (envsize < 100) ? 100 : envsize + 16;
|
||||
env = xrealloc(env, envsize * sizeof(char *));
|
||||
|
||||
#else /* !LOGIN_CAP */
|
||||
|
||||
if (getuid() == 0 || geteuid() == 0) {
|
||||
if (setgid(pw->pw_gid) < 0) {
|
||||
perror("setgid");
|
||||
@ -2428,18 +2640,15 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
}
|
||||
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
|
||||
fatal("Failed to set uids to %d.", (int) pw->pw_uid);
|
||||
#endif /* LOGIN_CAP */
|
||||
}
|
||||
/*
|
||||
* Get the shell from the password data. An empty shell field is
|
||||
* legal, and means /bin/sh.
|
||||
*/
|
||||
#ifdef LOGIN_CAP
|
||||
shell = pw->pw_shell;
|
||||
shell = login_getcapstr(lc, "shell", shell, shell);
|
||||
if (shell[0] == '\0')
|
||||
shell = _PATH_BSHELL;
|
||||
#else /* LOGIN_CAP */
|
||||
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
|
||||
#ifdef LOGIN_CAP
|
||||
shell = login_getcapstr(lc, "shell", shell, shell);
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
#ifdef AFS
|
||||
@ -2455,29 +2664,31 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
#endif /* AFS */
|
||||
|
||||
/* Initialize the environment. */
|
||||
envsize = 100;
|
||||
env = xmalloc(envsize * sizeof(char *));
|
||||
env[0] = NULL;
|
||||
if (env == NULL) {
|
||||
envsize = 100;
|
||||
env = xmalloc(envsize * sizeof(char *));
|
||||
env[0] = NULL;
|
||||
}
|
||||
|
||||
if (!options.use_login) {
|
||||
/* Set basic environment. */
|
||||
child_set_env(&env, &envsize, "USER", pw->pw_name);
|
||||
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
|
||||
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
|
||||
#ifdef LOGIN_CAP
|
||||
child_set_env(&env, &envsize, "PATH",
|
||||
login_getpath(lc, "path", _PATH_STDPATH));
|
||||
#else /* LOGIN_CAP */
|
||||
#ifndef LOGIN_CAP
|
||||
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
snprintf(buf, sizeof buf, "%.200s/%.50s",
|
||||
_PATH_MAILDIR, pw->pw_name);
|
||||
child_set_env(&env, &envsize, "MAIL", buf);
|
||||
#endif /* !LOGIN_CAP */
|
||||
|
||||
/* Normal systems set SHELL by default. */
|
||||
child_set_env(&env, &envsize, "SHELL", shell);
|
||||
}
|
||||
#ifdef LOGIN_CAP
|
||||
if (options.use_login)
|
||||
#endif /* LOGIN_CAP */
|
||||
if (getenv("TZ"))
|
||||
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
|
||||
|
||||
@ -2516,6 +2727,32 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
}
|
||||
#endif /* KRB4 */
|
||||
|
||||
#ifdef KRB5
|
||||
{
|
||||
extern krb5_ccache mem_ccache;
|
||||
|
||||
if (mem_ccache) {
|
||||
krb5_error_code problem;
|
||||
krb5_ccache ccache;
|
||||
#ifdef AFS
|
||||
if (k_hasafs())
|
||||
krb5_afslog(ssh_context, mem_ccache, NULL, NULL);
|
||||
#endif /* AFS */
|
||||
|
||||
problem = krb5_cc_default(ssh_context, &ccache);
|
||||
if (problem) {}
|
||||
else {
|
||||
problem = krb5_cc_copy_cache(ssh_context, mem_ccache, ccache);
|
||||
if (problem) {}
|
||||
}
|
||||
|
||||
krb5_cc_close(ssh_context, ccache);
|
||||
}
|
||||
|
||||
krb5_cleanup_proc(NULL);
|
||||
}
|
||||
#endif /* KRB5 */
|
||||
|
||||
if (xauthfile)
|
||||
child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
|
||||
if (auth_get_socket_name() != NULL)
|
||||
@ -2559,10 +2796,6 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
*/
|
||||
endpwent();
|
||||
|
||||
#ifdef LOGIN_CAP
|
||||
login_close(lc);
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
/*
|
||||
* Close any extra open file descriptors so that we don\'t have them
|
||||
* hanging around in clients. Note that we want to do this after
|
||||
@ -2573,9 +2806,46 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
close(i);
|
||||
|
||||
/* Change current directory to the user\'s home directory. */
|
||||
if (chdir(pw->pw_dir) < 0)
|
||||
if (
|
||||
#ifdef __FreeBSD__
|
||||
!*pw->pw_dir ||
|
||||
#endif /* __FreeBSD__ */
|
||||
chdir(pw->pw_dir) < 0
|
||||
) {
|
||||
#ifdef __FreeBSD__
|
||||
int quiet_login = 0;
|
||||
#endif /* __FreeBSD__ */
|
||||
#ifdef LOGIN_CAP
|
||||
if (login_getcapbool(lc, "requirehome", 0)) {
|
||||
(void)printf("Home directory not available\n");
|
||||
log("LOGIN %.200s REFUSED (HOMEDIR) ON TTY %.200s",
|
||||
pw->pw_name, ttyname);
|
||||
exit(254);
|
||||
}
|
||||
#endif /* LOGIN_CAP */
|
||||
#ifdef __FreeBSD__
|
||||
if (chdir("/") < 0) {
|
||||
(void)printf("Cannot find root directory\n");
|
||||
log("LOGIN %.200s REFUSED (ROOTDIR) ON TTY %.200s",
|
||||
pw->pw_name, ttyname);
|
||||
exit(254);
|
||||
}
|
||||
#ifdef LOGIN_CAP
|
||||
quiet_login = login_getcapbool(lc, "hushlogin", 0);
|
||||
#endif /* LOGIN_CAP */
|
||||
if (!quiet_login || *pw->pw_dir)
|
||||
(void)printf(
|
||||
"No home directory.\nLogging in with home = \"/\".\n");
|
||||
|
||||
#else /* !__FreeBSD__ */
|
||||
|
||||
fprintf(stderr, "Could not chdir to home directory %s: %s\n",
|
||||
pw->pw_dir, strerror(errno));
|
||||
#endif /* __FreeBSD__ */
|
||||
}
|
||||
#ifdef LOGIN_CAP
|
||||
login_close(lc);
|
||||
#endif /* LOGIN_CAP */
|
||||
|
||||
/*
|
||||
* Must take new environment into use so that .ssh/rc, /etc/sshrc and
|
||||
@ -2588,26 +2858,6 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
* in this order).
|
||||
*/
|
||||
if (!options.use_login) {
|
||||
#ifdef __FreeBSD__
|
||||
/*
|
||||
* If the password change time is set and has passed, give the
|
||||
* user a password expiry notice and chance to change it.
|
||||
*/
|
||||
if (pw->pw_change != 0) {
|
||||
struct timeval tv;
|
||||
|
||||
(void)gettimeofday(&tv, NULL);
|
||||
if (tv.tv_sec >= pw->pw_change) {
|
||||
(void)printf(
|
||||
"Sorry -- your password has expired.\n");
|
||||
syslog(LOG_INFO,
|
||||
"%s Password expired - forcing change",
|
||||
pw->pw_name);
|
||||
if (system("/usr/bin/passwd") != 0)
|
||||
perror("/usr/bin/passwd");
|
||||
}
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
if (stat(SSH_USER_RC, &st) >= 0) {
|
||||
if (debug_flag)
|
||||
fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
|
||||
@ -2675,7 +2925,11 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
||||
mailbox = getenv("MAIL");
|
||||
if (mailbox != NULL) {
|
||||
if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0)
|
||||
#ifdef __FreeBSD__
|
||||
;
|
||||
#else /* !__FreeBSD__ */
|
||||
printf("No mail.\n");
|
||||
#endif /* __FreeBSD__ */
|
||||
else if (mailstat.st_mtime < mailstat.st_atime)
|
||||
printf("You have mail.\n");
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user