Resolve conflicts. Known issues:

- sshd fails to set TERM correctly.
 - privilege separation may break PAM and is currently turned off.
 - man pages have not yet been updated

I will have these issues resolved, and privilege separation turned on by
default, in time for DP2.

Sponsored by:	DARPA, NAI Labs
This commit is contained in:
Dag-Erling Smørgrav 2002-06-23 16:09:08 +00:00
parent f191b6f96c
commit 80628bacb0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=98684
45 changed files with 2060 additions and 1425 deletions

View File

@ -190,6 +190,8 @@ OpenSSH contains no GPL code.
Aaron Campbell
Damien Miller
Kevin Steves
Daniel Kouril
Per Allansson
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -253,3 +255,4 @@ OpenSSH contains no GPL code.
* SUCH DAMAGE.
$FreeBSD$

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-krb4.c,v 1.25 2001/12/19 07:18:56 deraadt Exp $");
RCSID("$OpenBSD: auth-krb4.c,v 1.27 2002/06/11 05:46:20 mpech Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
@ -58,8 +58,8 @@ krb4_init(void *context)
if (lstat("/ticket", &st) != -1)
tkt_root = "/ticket/";
#endif /* AFS */
snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%d",
tkt_root, authctxt->pw->pw_uid, getpid());
snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%ld",
tkt_root, authctxt->pw->pw_uid, (long)getpid());
krb_set_tkt_string(authctxt->krb4_ticket_file);
}
/* Register ticket cleanup in case of fatal error. */
@ -254,6 +254,7 @@ auth_krb4(Authctxt *authctxt, KTEXT auth, char **client)
log("Kerberos v4 .klogin authorization failed for %s to "
"account %s", *client, authctxt->user);
xfree(*client);
*client = NULL;
return (0);
}
/* Increment the checksum, and return it encrypted with the

View File

@ -1,9 +1,34 @@
/*
* Kerberos v5 authentication and ticket-passing routines.
*
* $FreeBSD$
*/
/*
* Copyright (c) 2002 Daniel Kouril. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth-krb5.c,v 1.6 2002/03/04 17:27:39 stevesk Exp $");
RCSID("$OpenBSD: auth-krb5.c,v 1.8 2002/03/19 10:49:35 markus Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"

View File

@ -36,7 +36,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-passwd.c,v 1.24 2002/03/04 12:43:06 markus Exp $");
RCSID("$OpenBSD: auth-passwd.c,v 1.27 2002/05/24 16:45:16 stevesk Exp $");
RCSID("$FreeBSD$");
#include "packet.h"
@ -55,7 +55,6 @@ int
auth_password(Authctxt *authctxt, const char *password)
{
struct passwd * pw = authctxt->pw;
char *encrypted_password;
/* deny if no user. */
if (pw == NULL)
@ -86,14 +85,20 @@ auth_password(Authctxt *authctxt, const char *password)
return 0;
else
return 1;
#endif
#else
/* Check for users with no password. */
if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
return 1;
/* Encrypt the candidate password using the proper salt. */
encrypted_password = crypt(password,
(pw->pw_passwd[0] && pw->pw_passwd[1]) ? pw->pw_passwd : "xx");
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
else {
/* Encrypt the candidate password using the proper salt. */
char *encrypted_password = crypt(password,
(pw->pw_passwd[0] && pw->pw_passwd[1]) ?
pw->pw_passwd : "xx");
/*
* Authentication is accepted if the encrypted passwords
* are identical.
*/
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
}
#endif
}

View File

@ -13,7 +13,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.29 2002/03/04 12:43:06 markus Exp $");
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.34 2002/03/25 09:25:06 markus Exp $");
RCSID("$FreeBSD$");
#include "packet.h"
@ -26,37 +26,48 @@ RCSID("$FreeBSD$");
#include "auth.h"
#include "canohost.h"
#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
int
auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
Key *client_host_key)
{
HostStatus host_status;
/* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, cuser))
return 0;
host_status = check_key_in_hostfiles(pw, client_host_key,
chost, _PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
return (host_status == HOST_OK);
}
/*
* Tries to authenticate the user using the .rhosts file and the host using
* its host key. Returns true if authentication succeeds.
*/
int
auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key)
auth_rhosts_rsa(struct passwd *pw, char *cuser, Key *client_host_key)
{
extern ServerOptions options;
const char *canonical_hostname;
HostStatus host_status;
char *chost;
debug("Trying rhosts with RSA host authentication for client user %.100s", client_user);
debug("Trying rhosts with RSA host authentication for client user %.100s",
cuser);
if (pw == NULL || client_host_key == NULL || client_host_key->rsa == NULL)
if (pw == NULL || client_host_key == NULL ||
client_host_key->rsa == NULL)
return 0;
/* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, client_user))
return 0;
chost = (char *)get_canonical_hostname(options.verify_reverse_mapping);
debug("Rhosts RSA authentication: canonical host %.900s", chost);
canonical_hostname = get_canonical_hostname(
options.verify_reverse_mapping);
debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
host_status = check_key_in_hostfiles(pw, client_host_key,
canonical_hostname, _PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
if (host_status != HOST_OK) {
if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {
debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
return 0;
@ -64,9 +75,9 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key
/* A matching host key was found and is known. */
/* Perform the challenge-response dialog with the client for the host key. */
if (!auth_rsa_challenge_dialog(client_host_key->rsa)) {
if (!auth_rsa_challenge_dialog(client_host_key)) {
log("Client on %.800s failed to respond correctly to host authentication.",
canonical_hostname);
chost);
return 0;
}
/*
@ -75,7 +86,7 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, Key *client_host_key
*/
verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
pw->pw_name, client_user, canonical_hostname);
pw->pw_name, cuser, chost);
packet_send_debug("Rhosts with RSA host authentication accepted.");
return 1;
}

View File

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-rsa.c,v 1.50 2001/12/28 14:50:54 markus Exp $");
RCSID("$OpenBSD: auth-rsa.c,v 1.56 2002/06/10 16:53:06 stevesk Exp $");
RCSID("$FreeBSD$");
#include <openssl/rsa.h>
@ -33,6 +33,8 @@ RCSID("$FreeBSD$");
#include "servconf.h"
#include "auth.h"
#include "hostfile.h"
#include "monitor_wrap.h"
#include "ssh.h"
/* import */
extern ServerOptions options;
@ -53,6 +55,58 @@ extern u_char session_id[16];
* description of the options.
*/
BIGNUM *
auth_rsa_generate_challenge(Key *key)
{
BIGNUM *challenge;
BN_CTX *ctx;
if ((challenge = BN_new()) == NULL)
fatal("auth_rsa_generate_challenge: BN_new() failed");
/* Generate a random challenge. */
BN_rand(challenge, 256, 0, 0);
if ((ctx = BN_CTX_new()) == NULL)
fatal("auth_rsa_generate_challenge: BN_CTX_new() failed");
BN_mod(challenge, challenge, key->rsa->n, ctx);
BN_CTX_free(ctx);
return challenge;
}
int
auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
{
u_char buf[32], mdbuf[16];
MD5_CTX md;
int len;
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
return (0);
}
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_verify_response: bad challenge length %d", len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
/* Verify that the response is the original challenge. */
if (memcmp(response, mdbuf, 16) != 0) {
/* Wrong answer. */
return (0);
}
/* Correct answer. */
return (1);
}
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to
@ -60,29 +114,19 @@ extern u_char session_id[16];
*/
int
auth_rsa_challenge_dialog(RSA *pk)
auth_rsa_challenge_dialog(Key *key)
{
BIGNUM *challenge, *encrypted_challenge;
BN_CTX *ctx;
u_char buf[32], mdbuf[16], response[16];
MD5_CTX md;
u_int i;
int len;
u_char response[16];
int i, success;
if ((encrypted_challenge = BN_new()) == NULL)
fatal("auth_rsa_challenge_dialog: BN_new() failed");
if ((challenge = BN_new()) == NULL)
fatal("auth_rsa_challenge_dialog: BN_new() failed");
/* Generate a random challenge. */
BN_rand(challenge, 256, 0, 0);
if ((ctx = BN_CTX_new()) == NULL)
fatal("auth_rsa_challenge_dialog: BN_CTX_new() failed");
BN_mod(challenge, challenge, pk->n, ctx);
BN_CTX_free(ctx);
challenge = PRIVSEP(auth_rsa_generate_challenge(key));
/* Encrypt the challenge with the public key. */
rsa_public_encrypt(encrypted_challenge, challenge, pk);
rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
/* Send the encrypted challenge to the client. */
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
@ -97,48 +141,26 @@ auth_rsa_challenge_dialog(RSA *pk)
response[i] = packet_get_char();
packet_check_eom();
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
BN_clear_free(challenge);
/* Verify that the response is the original challenge. */
if (memcmp(response, mdbuf, 16) != 0) {
/* Wrong answer. */
return 0;
}
/* Correct answer. */
return 1;
return (success);
}
/*
* Performs the RSA authentication dialog with the client. This returns
* 0 if the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
* check if there's user key matching client_n,
* return key if login is allowed, NULL otherwise
*/
int
auth_rsa(struct passwd *pw, BIGNUM *client_n)
auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
char line[8192], *file;
int authenticated;
int allowed = 0;
u_int bits;
FILE *f;
u_long linenum = 0;
struct stat st;
Key *key;
char *fp;
/* no user given */
if (pw == NULL)
return 0;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
@ -152,29 +174,27 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
/* Restore the privileged uid. */
restore_uid();
xfree(file);
return 0;
return (0);
}
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
packet_send_debug("Could not open %.900s for reading.", file);
packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
xfree(file);
return 0;
return (0);
}
if (options.strict_modes &&
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
xfree(file);
fclose(f);
log("Authentication refused: %s", line);
packet_send_debug("Authentication refused: %s", line);
restore_uid();
return 0;
return (0);
}
/* Flag indicating whether authentication has succeeded. */
authenticated = 0;
/* Flag indicating whether the key is allowed. */
allowed = 0;
key = key_new(KEY_RSA1);
@ -239,32 +259,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
if (!auth_parse_options(pw, options, file, linenum))
continue;
/* Perform the challenge-response dialog for this key. */
if (!auth_rsa_challenge_dialog(key->rsa)) {
/* Wrong response. */
verbose("Wrong response to RSA authentication challenge.");
packet_send_debug("Wrong response to RSA authentication challenge.");
/*
* Break out of the loop. Otherwise we might send
* another challenge and break the protocol.
*/
break;
}
/*
* Correct response. The client has been successfully
* authenticated. Note that we have not yet processed the
* options; this will be reset if the options cause the
* authentication to be rejected.
* Break out of the loop if authentication was successful;
* otherwise continue searching.
*/
authenticated = 1;
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(key), fp);
xfree(fp);
/* break out, this key is allowed */
allowed = 1;
break;
}
@ -275,13 +271,58 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
xfree(file);
fclose(f);
/* return key if allowed */
if (allowed && rkey != NULL)
*rkey = key;
else
key_free(key);
return (allowed);
}
/*
* Performs the RSA authentication dialog with the client. This returns
* 0 if the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
*/
int
auth_rsa(struct passwd *pw, BIGNUM *client_n)
{
Key *key;
char *fp;
/* no user given */
if (pw == NULL)
return 0;
if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) {
auth_clear_options();
return (0);
}
/* Perform the challenge-response dialog for this key. */
if (!auth_rsa_challenge_dialog(key)) {
/* Wrong response. */
verbose("Wrong response to RSA authentication challenge.");
packet_send_debug("Wrong response to RSA authentication challenge.");
/*
* Break out of the loop. Otherwise we might send
* another challenge and break the protocol.
*/
key_free(key);
return (0);
}
/*
* Correct response. The client has been successfully
* authenticated. Note that we have not yet processed the
* options; this will be reset if the options cause the
* authentication to be rejected.
*/
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(key), fp);
xfree(fp);
key_free(key);
if (authenticated)
packet_send_debug("RSA authentication accepted.");
else
auth_clear_options();
/* Return authentication result. */
return authenticated;
packet_send_debug("RSA authentication accepted.");
return (1);
}

View File

@ -22,7 +22,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth-skey.c,v 1.16 2002/01/12 13:10:29 markus Exp $");
RCSID("$OpenBSD: auth-skey.c,v 1.19 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#ifdef SKEY
@ -31,6 +31,7 @@ RCSID("$FreeBSD$");
#include "xmalloc.h"
#include "auth.h"
#include "monitor_wrap.h"
static void *
skey_init_ctx(Authctxt *authctxt)
@ -38,9 +39,7 @@ skey_init_ctx(Authctxt *authctxt)
return authctxt;
}
#define PROMPT "\nOPIE Password: "
static int
int
skey_query(void *ctx, char **name, char **infotxt,
u_int* numprompts, char ***prompts, u_int **echo_on)
{
@ -54,23 +53,23 @@ skey_query(void *ctx, char **name, char **infotxt,
if (opiechallenge(&opie, authctxt->user, challenge) == -1)
return -1;
*name = xstrdup("");
*infotxt = xstrdup("");
*name = xstrdup("");
*infotxt = xstrdup("");
*numprompts = 1;
*prompts = xmalloc(*numprompts * sizeof(char*));
*echo_on = xmalloc(*numprompts * sizeof(u_int));
(*echo_on)[0] = 0;
len = strlen(challenge) + strlen(PROMPT) + 1;
len = strlen(challenge) + strlen(SKEY_PROMPT) + 1;
p = xmalloc(len);
strlcpy(p, challenge, len);
strlcat(p, PROMPT, len);
strlcat(p, SKEY_PROMPT, len);
(*prompts)[0] = p;
return 0;
}
static int
int
skey_respond(void *ctx, u_int numresponses, char **responses)
{
Authctxt *authctxt = ctx;
@ -96,4 +95,12 @@ KbdintDevice skey_device = {
skey_respond,
skey_free_ctx
};
KbdintDevice mm_skey_device = {
"skey",
skey_init_ctx,
mm_skey_query,
mm_skey_respond,
skey_free_ctx
};
#endif /* SKEY */

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth.c,v 1.35 2002/03/01 13:12:10 markus Exp $");
RCSID("$OpenBSD: auth.c,v 1.43 2002/05/17 14:27:55 millert Exp $");
RCSID("$FreeBSD$");
#include <libgen.h>
@ -40,10 +40,17 @@ RCSID("$FreeBSD$");
#include "bufaux.h"
#include "uidswap.h"
#include "tildexpand.h"
#include "misc.h"
#include "bufaux.h"
#include "packet.h"
/* import */
extern ServerOptions options;
/* Debugging messages */
Buffer auth_debug;
int auth_debug_init;
/*
* Check if the user is allowed to log in via ssh. If user is listed
* in DenyUsers or one of user's groups is listed in DenyGroups, false
@ -77,7 +84,8 @@ allowed_user(struct passwd * pw)
pw->pw_name, shell);
return 0;
}
if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) {
if (S_ISREG(st.st_mode) == 0 ||
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
log("User %.100s not allowed because shell %.100s is not executable",
pw->pw_name, shell);
return 0;
@ -91,17 +99,17 @@ allowed_user(struct passwd * pw)
/* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) {
for (i = 0; i < options.num_deny_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
if (match_user(pw->pw_name, hostname, ipaddr,
options.deny_users[i])) {
log("User %.100s not allowed because listed in DenyUsers",
pw->pw_name);
log("User %.100s not allowed because listed in DenyUsers",
pw->pw_name);
return 0;
}
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
for (i = 0; i < options.num_allow_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
if (match_user(pw->pw_name, hostname, ipaddr,
options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
@ -387,3 +395,77 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
}
return 0;
}
struct passwd *
getpwnamallow(const char *user)
{
#ifdef HAVE_LOGIN_CAP
extern login_cap_t *lc;
#ifdef BSD_AUTH
auth_session_t *as;
#endif
#endif
struct passwd *pw;
pw = getpwnam(user);
if (pw == NULL || !allowed_user(pw))
return (NULL);
#ifdef HAVE_LOGIN_CAP
if ((lc = login_getclass(pw->pw_class)) == NULL) {
debug("unable to get login class: %s", user);
return (NULL);
}
#ifdef BSD_AUTH
if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
debug("Approval failure for %s", user);
pw = NULL;
}
if (as != NULL)
auth_close(as);
#endif
#endif
if (pw != NULL)
return (pwcopy(pw));
return (NULL);
}
void
auth_debug_add(const char *fmt,...)
{
char buf[1024];
va_list args;
if (!auth_debug_init)
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
buffer_put_cstring(&auth_debug, buf);
}
void
auth_debug_send(void)
{
char *msg;
if (!auth_debug_init)
return;
while (buffer_len(&auth_debug)) {
msg = buffer_get_string(&auth_debug, NULL);
packet_send_debug("%s", msg);
xfree(msg);
}
}
void
auth_debug_reset(void)
{
if (auth_debug_init)
buffer_clear(&auth_debug);
else {
buffer_init(&auth_debug);
auth_debug_init = 1;
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.h,v 1.29 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: auth.h,v 1.39 2002/05/31 11:35:15 markus Exp $ */
/* $FreeBSD$ */
/*
@ -44,6 +44,7 @@
#endif
typedef struct Authctxt Authctxt;
typedef struct Authmethod Authmethod;
typedef struct KbdintDevice KbdintDevice;
struct Authctxt {
@ -72,6 +73,12 @@ struct Authctxt {
#endif
};
struct Authmethod {
char *name;
int (*userauth)(Authctxt *authctxt);
int *enabled;
};
/*
* Keyboard interactive device:
* init_ctx returns: non NULL upon success
@ -89,14 +96,21 @@ struct KbdintDevice
void (*free_ctx)(void *ctx);
};
int auth_rhosts(struct passwd *, const char *);
int auth_rhosts(struct passwd *, const char *);
int
auth_rhosts2(struct passwd *, const char *, const char *, const char *);
int auth_rhosts_rsa(struct passwd *, const char *, Key *);
int auth_rhosts_rsa(struct passwd *, char *, Key *);
int auth_password(Authctxt *, const char *);
int auth_rsa(struct passwd *, BIGNUM *);
int auth_rsa_challenge_dialog(RSA *);
int auth_rsa_challenge_dialog(Key *);
BIGNUM *auth_rsa_generate_challenge(Key *);
int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
int user_key_allowed(struct passwd *, Key *);
#ifdef KRB4
#include <krb.h>
@ -119,18 +133,27 @@ int auth_krb5_password(Authctxt *authctxt, const char *password);
void krb5_cleanup_proc(void *authctxt);
#endif /* KRB5 */
void do_authentication(void);
void do_authentication2(void);
Authctxt *do_authentication(void);
Authctxt *do_authentication2(void);
Authctxt *authctxt_new(void);
void auth_log(Authctxt *, int, char *, char *);
void userauth_finish(Authctxt *, int, char *);
int auth_root_allowed(char *);
char *auth2_read_banner(void);
void privsep_challenge_enable(void);
int auth2_challenge(Authctxt *, char *);
void auth2_challenge_stop(Authctxt *);
int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int bsdauth_respond(void *, u_int, char **);
int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
int skey_respond(void *, u_int, char **);
int allowed_user(struct passwd *);
struct passwd * getpwnamallow(const char *user);
char *get_challenge(Authctxt *);
int verify_response(Authctxt *, const char *);
@ -148,8 +171,20 @@ HostStatus
check_key_in_hostfiles(struct passwd *, Key *, const char *,
const char *, const char *);
/* hostkey handling */
Key *get_hostkey_by_index(int);
Key *get_hostkey_by_type(int);
int get_hostkey_index(Key *);
int ssh1_session_key(BIGNUM *);
/* debug messages during authentication */
void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void auth_debug_send(void);
void auth_debug_reset(void);
#define AUTH_FAIL_MAX 6
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
#define SKEY_PROMPT "\nOPIE Password: "
#endif

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth1.c,v 1.35 2002/02/03 17:53:25 markus Exp $");
RCSID("$OpenBSD: auth1.c,v 1.41 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
@ -26,8 +26,8 @@ RCSID("$FreeBSD$");
#include "channels.h"
#include "session.h"
#include "canohost.h"
#include "misc.h"
#include "uidswap.h"
#include "monitor_wrap.h"
#include <login_cap.h>
#include "auth-pam.h"
@ -104,9 +104,9 @@ do_authloop(Authctxt *authctxt)
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
#ifdef USE_PAM
auth_pam_password(authctxt, "")) {
/* XXX PRIVSEP */ auth_pam_password(authctxt, "")) {
#else
auth_password(authctxt, "")) {
PRIVSEP(auth_password(authctxt, ""))) {
#endif
auth_log(authctxt, 1, "without authentication", "");
return;
@ -228,7 +228,7 @@ do_authloop(Authctxt *authctxt)
if (bits != BN_num_bits(client_host_key->rsa->n))
verbose("Warning: keysize mismatch for client_host_key: "
"actual %d, announced %d",
BN_num_bits(client_host_key->rsa->n), bits);
BN_num_bits(client_host_key->rsa->n), bits);
packet_check_eom();
authenticated = auth_rhosts_rsa(pw, client_user,
@ -267,10 +267,10 @@ do_authloop(Authctxt *authctxt)
#ifdef USE_PAM
/* Do PAM auth with password */
authenticated = auth_pam_password(authctxt, password);
authenticated = /* XXX PRIVSEP */ auth_pam_password(authctxt, password);
#else /* !USE_PAM */
/* Try authentication with the password. */
authenticated = auth_password(authctxt, password);
authenticated = PRIVSEP(auth_password(authctxt, password));
#endif /* USE_PAM */
memset(password, 0, strlen(password));
@ -418,13 +418,12 @@ do_authloop(Authctxt *authctxt)
* Performs authentication of an incoming connection. Session key has already
* been exchanged and encryption is enabled.
*/
void
Authctxt *
do_authentication(void)
{
Authctxt *authctxt;
struct passwd *pw;
u_int ulen;
char *p, *user, *style = NULL;
char *user, *style = NULL;
/* Get the name of the user that we wish to log in as. */
packet_read_expect(SSH_CMSG_USER);
@ -436,36 +435,39 @@ do_authentication(void)
if ((style = strchr(user, ':')) != NULL)
*style++ = '\0';
#ifdef KRB5
/* XXX - SSH.com Kerberos v5 braindeath. */
if ((p = strchr(user, '@')) != NULL)
*p = '\0';
if ((datafellows & SSH_BUG_K5USER) &&
options.kerberos_authentication) {
char *p;
if ((p = strchr(user, '@')) != NULL)
*p = '\0';
}
#endif
authctxt = authctxt_new();
authctxt->user = user;
authctxt->style = style;
/* Verify that the user is a valid user. */
pw = getpwnam(user);
if (pw && allowed_user(pw)) {
if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
authctxt->valid = 1;
pw = pwcopy(pw);
} else {
else
debug("do_authentication: illegal user %s", user);
pw = NULL;
}
authctxt->pw = pw;
#ifdef USE_PAM
if (pw != NULL)
start_pam(pw);
if (authctxt->pw != NULL)
start_pam(authctxt->pw);
#endif
setproctitle("%s", pw ? user : "unknown");
setproctitle("%s%s", authctxt->pw ? user : "unknown",
use_privsep ? " [net]" : "");
/*
* If we are not running as root, the user must have the same uid as
* the server.
*/
if (getuid() != 0 && pw && pw->pw_uid != getuid())
if (!use_privsep && getuid() != 0 && authctxt->pw &&
authctxt->pw->pw_uid != getuid())
packet_disconnect("Cannot change user when server not running as root.");
/*
@ -479,6 +481,5 @@ do_authentication(void)
packet_send();
packet_write_wait();
/* Perform session preparation. */
do_authenticated(authctxt);
return (authctxt);
}

View File

@ -23,7 +23,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth2-chall.c,v 1.16 2002/01/13 17:57:37 markus Exp $");
RCSID("$OpenBSD: auth2-chall.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include "ssh2.h"
@ -220,7 +220,7 @@ send_userauth_info_request(Authctxt *authctxt)
packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST);
packet_put_cstring(name);
packet_put_cstring(instr);
packet_put_cstring(""); /* language not used */
packet_put_cstring(""); /* language not used */
packet_put_int(numprompts);
for (i = 0; i < numprompts; i++) {
packet_put_cstring(prompts[i]);
@ -311,3 +311,22 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
userauth_finish(authctxt, authenticated, method);
xfree(method);
}
void
privsep_challenge_enable(void)
{
#ifdef BSD_AUTH
extern KbdintDevice mm_bsdauth_device;
#endif
#ifdef SKEY
extern KbdintDevice mm_skey_device;
#endif
/* As long as SSHv1 has devices[0] hard coded this is fine */
#ifdef BSD_AUTH
devices[0] = &mm_bsdauth_device;
#else
#ifdef SKEY
devices[0] = &mm_skey_device;
#endif
#endif
}

View File

@ -23,35 +23,20 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $");
RCSID("$OpenBSD: auth2.c,v 1.93 2002/05/31 11:35:15 markus Exp $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
#include "ssh2.h"
#include "xmalloc.h"
#include "rsa.h"
#include "sshpty.h"
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "servconf.h"
#include "compat.h"
#include "channels.h"
#include "bufaux.h"
#include "auth.h"
#include "session.h"
#include "dispatch.h"
#include "key.h"
#include "cipher.h"
#include "kex.h"
#include "pathnames.h"
#include "uidswap.h"
#include "auth-options.h"
#include "misc.h"
#include "hostfile.h"
#include "canohost.h"
#include "match.h"
#include "monitor_wrap.h"
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
@ -62,14 +47,23 @@ extern ServerOptions options;
extern u_char *session_id2;
extern int session_id2_len;
static Authctxt *x_authctxt = NULL;
static int one = 1;
Authctxt *x_authctxt = NULL;
typedef struct Authmethod Authmethod;
struct Authmethod {
char *name;
int (*userauth)(Authctxt *authctxt);
int *enabled;
/* methods */
extern Authmethod method_none;
extern Authmethod method_pubkey;
extern Authmethod method_passwd;
extern Authmethod method_kbdint;
extern Authmethod method_hostbased;
Authmethod *authmethods[] = {
&method_none,
&method_pubkey,
&method_passwd,
&method_kbdint,
&method_hostbased,
NULL
};
/* protocol */
@ -80,41 +74,14 @@ static void input_userauth_request(int, u_int32_t, void *);
/* helper */
static Authmethod *authmethod_lookup(const char *);
static char *authmethods_get(void);
static int user_key_allowed(struct passwd *, Key *);
static int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
/* auth */
static void userauth_banner(void);
static int userauth_none(Authctxt *);
static int userauth_passwd(Authctxt *);
static int userauth_pubkey(Authctxt *);
static int userauth_hostbased(Authctxt *);
static int userauth_kbdint(Authctxt *);
Authmethod authmethods[] = {
{"none",
userauth_none,
&one},
{"publickey",
userauth_pubkey,
&options.pubkey_authentication},
{"password",
userauth_passwd,
&options.password_authentication},
{"keyboard-interactive",
userauth_kbdint,
&options.kbd_interactive_authentication},
{"hostbased",
userauth_hostbased,
&options.hostbased_authentication},
{NULL, NULL, NULL}
};
int user_key_allowed(struct passwd *, Key *);
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
/*
* loop until authctxt->success == TRUE
*/
void
Authctxt *
do_authentication2(void)
{
Authctxt *authctxt = authctxt_new();
@ -128,7 +95,8 @@ do_authentication2(void)
dispatch_init(&dispatch_protocol_error);
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
do_authenticated(authctxt);
return (authctxt);
}
static void
@ -195,23 +163,24 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (authctxt->attempt++ == 0) {
/* setup auth context */
struct passwd *pw = NULL;
pw = getpwnam(user);
if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
authctxt->pw = pwcopy(pw);
authctxt->pw = PRIVSEP(getpwnamallow(user));
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
#ifdef USE_PAM
start_pam(pw);
start_pam(authctxt->pw);
#endif
} else {
log("input_userauth_request: illegal user %s", user);
authctxt->pw = NULL;
}
setproctitle("%s", pw ? user : "unknown");
setproctitle("%s%s", authctxt->pw ? user : "unknown",
use_privsep ? " [net]" : "");
authctxt->user = xstrdup(user);
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
if (use_privsep)
mm_inform_authserv(service, style);
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
@ -301,289 +270,6 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
}
}
static void
userauth_banner(void)
{
struct stat st;
char *banner = NULL;
off_t len, n;
int fd;
if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
return;
if ((fd = open(options.banner, O_RDONLY)) < 0)
return;
if (fstat(fd, &st) < 0)
goto done;
len = st.st_size;
banner = xmalloc(len + 1);
if ((n = read(fd, banner, len)) < 0)
goto done;
banner[n] = '\0';
packet_start(SSH2_MSG_USERAUTH_BANNER);
packet_put_cstring(banner);
packet_put_cstring(""); /* language, unused */
packet_send();
debug("userauth_banner: sent");
done:
if (banner)
xfree(banner);
close(fd);
return;
}
static int
userauth_none(Authctxt *authctxt)
{
/* disable method "none", only allowed one time */
Authmethod *m = authmethod_lookup("none");
if (m != NULL)
m->enabled = NULL;
packet_check_eom();
userauth_banner();
#ifdef USE_PAM
return authctxt->valid ? auth_pam_password(authctxt, "") : 0;
#else /* !USE_PAM */
return authctxt->valid ? auth_password(authctxt, "") : 0;
#endif /* USE_PAM */
}
static int
userauth_passwd(Authctxt *authctxt)
{
char *password;
int authenticated = 0;
int change;
u_int len;
change = packet_get_char();
if (change)
log("password change not supported");
password = packet_get_string(&len);
packet_check_eom();
if (authctxt->valid &&
#ifdef USE_PAM
auth_password(authctxt, password) == 1)
#else
auth_password(authctxt, password) == 1)
#endif
authenticated = 1;
memset(password, 0, len);
xfree(password);
return authenticated;
}
static int
userauth_kbdint(Authctxt *authctxt)
{
int authenticated = 0;
char *lang, *devs;
lang = packet_get_string(NULL);
devs = packet_get_string(NULL);
packet_check_eom();
debug("keyboard-interactive devs %s", devs);
if (options.challenge_response_authentication)
authenticated = auth2_challenge(authctxt, devs);
xfree(devs);
xfree(lang);
return authenticated;
}
static int
userauth_pubkey(Authctxt *authctxt)
{
Buffer b;
Key *key = NULL;
char *pkalg;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int have_sig, pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("userauth_pubkey: disabled because of invalid user");
return 0;
}
have_sig = packet_get_char();
if (datafellows & SSH_BUG_PKAUTH) {
debug2("userauth_pubkey: SSH_BUG_PKAUTH");
/* no explicit pkalg given */
pkblob = packet_get_string(&blen);
buffer_init(&b);
buffer_append(&b, pkblob, blen);
/* so we have to extract the pkalg from the pkblob */
pkalg = buffer_get_string(&b, &alen);
buffer_free(&b);
} else {
pkalg = packet_get_string(&alen);
pkblob = packet_get_string(&blen);
}
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
log("userauth_pubkey: unsupported public key algorithm: %s",
pkalg);
goto done;
}
key = key_from_blob(pkblob, blen);
if (key == NULL) {
error("userauth_pubkey: cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
error("userauth_pubkey: type mismatch for decoded key "
"(received %d, expected %d)", key->type, pktype);
goto done;
}
if (have_sig) {
sig = packet_get_string(&slen);
packet_check_eom();
buffer_init(&b);
if (datafellows & SSH_OLD_SESSIONID) {
buffer_append(&b, session_id2, session_id2_len);
} else {
buffer_put_string(&b, session_id2, session_id2_len);
}
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b,
datafellows & SSH_BUG_PKSERVICE ?
"ssh-userauth" :
authctxt->service);
if (datafellows & SSH_BUG_PKAUTH) {
buffer_put_char(&b, have_sig);
} else {
buffer_put_cstring(&b, "publickey");
buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, pkalg);
}
buffer_put_string(&b, pkblob, blen);
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
/* test for correct signature */
if (user_key_allowed(authctxt->pw, key) &&
key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
authenticated = 1;
buffer_clear(&b);
xfree(sig);
} else {
debug("test whether pkalg/pkblob are acceptable");
packet_check_eom();
/* XXX fake reply and always send PK_OK ? */
/*
* XXX this allows testing whether a user is allowed
* to login: if you happen to have a valid pubkey this
* message is sent. the message is NEVER sent at all
* if a user is not allowed to login. is this an
* issue? -markus
*/
if (user_key_allowed(authctxt->pw, key)) {
packet_start(SSH2_MSG_USERAUTH_PK_OK);
packet_put_string(pkalg, alen);
packet_put_string(pkblob, blen);
packet_send();
packet_write_wait();
authctxt->postponed = 1;
}
}
if (authenticated != 1)
auth_clear_options();
done:
debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
if (key != NULL)
key_free(key);
xfree(pkalg);
xfree(pkblob);
return authenticated;
}
static int
userauth_hostbased(Authctxt *authctxt)
{
Buffer b;
Key *key = NULL;
char *pkalg, *cuser, *chost, *service;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int pktype;
int authenticated = 0;
if (!authctxt->valid) {
debug2("userauth_hostbased: disabled because of invalid user");
return 0;
}
pkalg = packet_get_string(&alen);
pkblob = packet_get_string(&blen);
chost = packet_get_string(NULL);
cuser = packet_get_string(NULL);
sig = packet_get_string(&slen);
debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
cuser, chost, pkalg, slen);
#ifdef DEBUG_PK
debug("signature:");
buffer_init(&b);
buffer_append(&b, sig, slen);
buffer_dump(&b);
buffer_free(&b);
#endif
pktype = key_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
log("userauth_hostbased: unsupported "
"public key algorithm: %s", pkalg);
goto done;
}
key = key_from_blob(pkblob, blen);
if (key == NULL) {
error("userauth_hostbased: cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
error("userauth_hostbased: type mismatch for decoded key "
"(received %d, expected %d)", key->type, pktype);
goto done;
}
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
authctxt->service;
buffer_init(&b);
buffer_put_string(&b, session_id2, session_id2_len);
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b, service);
buffer_put_cstring(&b, "hostbased");
buffer_put_string(&b, pkalg, alen);
buffer_put_string(&b, pkblob, blen);
buffer_put_cstring(&b, chost);
buffer_put_cstring(&b, cuser);
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
/* test for allowed key and correct signature */
if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
authenticated = 1;
buffer_clear(&b);
done:
debug2("userauth_hostbased: authenticated %d", authenticated);
if (key != NULL)
key_free(key);
xfree(pkalg);
xfree(pkblob);
xfree(cuser);
xfree(chost);
xfree(sig);
return authenticated;
}
/* get current user */
struct passwd*
@ -597,18 +283,20 @@ auth_get_user(void)
static char *
authmethods_get(void)
{
Authmethod *method = NULL;
Buffer b;
char *list;
int i;
buffer_init(&b);
for (method = authmethods; method->name != NULL; method++) {
if (strcmp(method->name, "none") == 0)
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
if (method->enabled != NULL && *(method->enabled) != 0) {
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, method->name, strlen(method->name));
buffer_append(&b, authmethods[i]->name,
strlen(authmethods[i]->name));
}
}
buffer_append(&b, "\0", 1);
@ -620,174 +308,15 @@ authmethods_get(void)
static Authmethod *
authmethod_lookup(const char *name)
{
Authmethod *method = NULL;
int i;
if (name != NULL)
for (method = authmethods; method->name != NULL; method++)
if (method->enabled != NULL &&
*(method->enabled) != 0 &&
strcmp(name, method->name) == 0)
return method;
debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
for (i = 0; authmethods[i] != NULL; i++)
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0 &&
strcmp(name, authmethods[i]->name) == 0)
return authmethods[i];
debug2("Unrecognized authentication method name: %s",
name ? name : "NULL");
return NULL;
}
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
char line[8192];
int found_key = 0;
FILE *f;
u_long linenum = 0;
struct stat st;
Key *found;
char *fp;
if (pw == NULL)
return 0;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
debug("trying public key file %s", file);
/* Fail quietly if file does not exist */
if (stat(file, &st) < 0) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
if (options.strict_modes &&
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
fclose(f);
log("Authentication refused: %s", line);
restore_uid();
return 0;
}
found_key = 0;
found = key_new(key->type);
while (fgets(line, sizeof(line), f)) {
char *cp, *options = NULL;
linenum++;
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
if (key_read(found, &cp) != 1) {
/* no key? check if there are options for this key */
int quoted = 0;
debug2("user_key_allowed: check options: '%s'", cp);
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
if (key_read(found, &cp) != 1) {
debug2("user_key_allowed: advance: '%s'", cp);
/* still no key? advance to next line*/
continue;
}
}
if (key_equal(found, key) &&
auth_parse_options(pw, options, file, linenum) == 1) {
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(found), fp);
xfree(fp);
break;
}
}
restore_uid();
fclose(f);
key_free(found);
if (!found_key)
debug2("key not found");
return found_key;
}
/* check whether given key is in .ssh/authorized_keys* */
static int
user_key_allowed(struct passwd *pw, Key *key)
{
int success;
char *file;
file = authorized_keys_file(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
if (success)
return success;
/* try suffix "2" for backward compat, too */
file = authorized_keys_file2(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
return success;
}
/* return 1 if given hostkey is allowed */
static int
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
Key *key)
{
const char *resolvedname, *ipaddr, *lookup;
HostStatus host_status;
int len;
resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
ipaddr = get_remote_ipaddr();
debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
chost, resolvedname, ipaddr);
if (options.hostbased_uses_name_from_packet_only) {
if (auth_rhosts2(pw, cuser, chost, chost) == 0)
return 0;
lookup = chost;
} else {
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
debug2("stripping trailing dot from chost %s", chost);
chost[len - 1] = '\0';
}
if (strcasecmp(resolvedname, chost) != 0)
log("userauth_hostbased mismatch: "
"client sends %s, but we resolve %s to %s",
chost, ipaddr, resolvedname);
if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
return 0;
lookup = resolvedname;
}
debug2("userauth_hostbased: access allowed by auth_rhosts2");
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
/* backward compat if no key has been found. */
if (host_status == HOST_NEW)
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE2,
options.ignore_user_known_hosts ? NULL :
_PATH_SSH_USER_HOSTFILE2);
return (host_status == HOST_OK);
}

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: authfd.c,v 1.48 2002/02/24 19:14:59 markus Exp $");
RCSID("$OpenBSD: authfd.c,v 1.55 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@ -60,7 +60,7 @@ int decode_reply(int type);
/* macro to check for "agent failure" message */
#define agent_failed(x) \
((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \
(x == SSH2_AGENT_FAILURE))
(x == SSH2_AGENT_FAILURE))
/* Returns the number of the authentication fd, or -1 if there is none. */
@ -208,6 +208,26 @@ ssh_close_authentication_connection(AuthenticationConnection *auth)
xfree(auth);
}
/* Lock/unlock agent */
int
ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password)
{
int type;
Buffer msg;
buffer_init(&msg);
buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK);
buffer_put_cstring(&msg, password);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
}
type = buffer_get_char(&msg);
buffer_free(&msg);
return decode_reply(type);
}
/*
* Returns the first authentication identity held by the agent.
*/
@ -420,8 +440,6 @@ ssh_agent_sign(AuthenticationConnection *auth,
static void
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
buffer_put_int(b, BN_num_bits(key->n));
buffer_put_bignum(b, key->n);
buffer_put_bignum(b, key->e);
@ -436,8 +454,6 @@ ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
static void
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
buffer_put_cstring(b, key_ssh_name(key));
switch (key->type) {
case KEY_RSA:
@ -465,19 +481,28 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
*/
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
const char *comment, u_int life)
{
Buffer msg;
int type;
int type, constrained = (life != 0);
buffer_init(&msg);
switch (key->type) {
case KEY_RSA1:
type = constrained ?
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
SSH_AGENTC_ADD_RSA_IDENTITY;
buffer_put_char(&msg, type);
ssh_encode_identity_rsa1(&msg, key->rsa, comment);
break;
case KEY_RSA:
case KEY_DSA:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;
buffer_put_char(&msg, type);
ssh_encode_identity_ssh2(&msg, key, comment);
break;
default:
@ -485,6 +510,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
return 0;
break;
}
if (constrained) {
if (life != 0) {
buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
buffer_put_int(&msg, life);
}
}
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
@ -494,6 +525,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
return decode_reply(type);
}
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{
return ssh_add_identity_constrained(auth, key, comment, 0);
}
/*
* Removes an identity from the authentication server. This call is not
* meant to be used by normal applications.
@ -533,7 +570,7 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
}
int
ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id)
ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id, const char *pin)
{
Buffer msg;
int type;
@ -542,6 +579,7 @@ ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id)
buffer_put_char(&msg, add ? SSH_AGENTC_ADD_SMARTCARD_KEY :
SSH_AGENTC_REMOVE_SMARTCARD_KEY);
buffer_put_cstring(&msg, reader_id);
buffer_put_cstring(&msg, pin);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;

View File

@ -36,7 +36,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: authfile.c,v 1.48 2002/02/28 15:46:33 markus Exp $");
RCSID("$OpenBSD: authfile.c,v 1.49 2002/05/23 19:24:30 markus Exp $");
RCSID("$FreeBSD$");
#include <openssl/err.h>
@ -422,7 +422,7 @@ key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
return NULL;
}
static Key *
Key *
key_load_private_pem(int fd, int type, const char *passphrase,
char **commentp)
{

View File

@ -37,7 +37,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: bufaux.c,v 1.22 2002/01/18 18:14:17 stevesk Exp $");
RCSID("$OpenBSD: bufaux.c,v 1.25 2002/04/20 09:14:58 markus Exp $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
@ -138,10 +138,18 @@ buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
BN_bin2bn(bin, len, value);
xfree(bin);
}
/*
* Returns an integer from the buffer (4 bytes, msb first).
* Returns integers from the buffer (msb first).
*/
u_short
buffer_get_short(Buffer *buffer)
{
u_char buf[2];
buffer_get(buffer, (char *) buf, 2);
return GET_16BIT(buf);
}
u_int
buffer_get_int(Buffer *buffer)
{
@ -159,8 +167,16 @@ buffer_get_int64(Buffer *buffer)
}
/*
* Stores an integer in the buffer in 4 bytes, msb first.
* Stores integers in the buffer, msb first.
*/
void
buffer_put_short(Buffer *buffer, u_short value)
{
char buf[2];
PUT_16BIT(buf, value);
buffer_append(buffer, buf, 2);
}
void
buffer_put_int(Buffer *buffer, u_int value)
{
@ -193,7 +209,7 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
/* Get the length. */
len = buffer_get_int(buffer);
if (len > 256 * 1024)
fatal("Received packet with bad string length %d", len);
fatal("buffer_get_string: bad string length %d", len);
/* Allocate space for the string. Add one byte for a null character. */
value = xmalloc(len + 1);
/* Get the string. */
@ -218,6 +234,8 @@ buffer_put_string(Buffer *buffer, const void *buf, u_int len)
void
buffer_put_cstring(Buffer *buffer, const char *s)
{
if (s == NULL)
fatal("buffer_put_cstring: s == NULL");
buffer_put_string(buffer, s, strlen(s));
}

View File

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: canohost.c,v 1.31 2002/02/27 21:23:13 stevesk Exp $");
RCSID("$OpenBSD: canohost.c,v 1.32 2002/06/11 08:11:45 itojun Exp $");
RCSID("$FreeBSD$");
#include "packet.h"
@ -43,13 +43,14 @@ get_remote_hostname(int socket, int verify_reverse_mapping)
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
if (from.ss_family == AF_INET)
check_ip_options(socket, ntop);
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
if (from.ss_family == AF_INET)
check_ip_options(socket, ntop);
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),

View File

@ -39,7 +39,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: channels.c,v 1.171 2002/03/04 19:37:58 markus Exp $");
RCSID("$OpenBSD: channels.c,v 1.175 2002/06/10 22:28:41 markus Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
@ -47,7 +47,6 @@ RCSID("$FreeBSD$");
#include "ssh2.h"
#include "packet.h"
#include "xmalloc.h"
#include "uidswap.h"
#include "log.h"
#include "misc.h"
#include "channels.h"
@ -130,10 +129,6 @@ static u_int x11_fake_data_len;
#define NUM_SOCKS 10
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
static char *auth_sock_dir = NULL;
/* AF_UNSPEC or AF_INET or AF_INET6 */
int IPv4or6 = AF_UNSPEC;
@ -707,7 +702,11 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
if (buffer_len(&c->output) > 0) {
FD_SET(c->wfd, writeset);
} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
chan_obuf_empty(c);
if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
debug2("channel %d: obuf_empty delayed efd %d/(%d)",
c->self, c->efd, buffer_len(&c->extended));
else
chan_obuf_empty(c);
}
}
/** XXX check close conditions, too */
@ -715,7 +714,8 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
if (c->extended_usage == CHAN_EXTENDED_WRITE &&
buffer_len(&c->extended) > 0)
FD_SET(c->efd, writeset);
else if (c->extended_usage == CHAN_EXTENDED_READ &&
else if (!(c->flags & CHAN_EOF_SENT) &&
c->extended_usage == CHAN_EXTENDED_READ &&
buffer_len(&c->extended) < c->remote_window)
FD_SET(c->efd, readset);
}
@ -1633,12 +1633,18 @@ channel_output_poll(void)
fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
/*
* input-buffer is empty and read-socket shutdown:
* tell peer, that we will not send more data: send IEOF
* tell peer, that we will not send more data: send IEOF.
* hack for extended data: delay EOF if EFD still in use.
*/
chan_ibuf_empty(c);
if (CHANNEL_EFD_INPUT_ACTIVE(c))
debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
c->self, c->efd, buffer_len(&c->extended));
else
chan_ibuf_empty(c);
}
/* Send extended data, i.e. stderr */
if (compat20 &&
!(c->flags & CHAN_EOF_SENT) &&
c->remote_window > 0 &&
(len = buffer_len(&c->extended)) > 0 &&
c->extended_usage == CHAN_EXTENDED_READ) {
@ -1727,6 +1733,13 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
log("channel %d: ext data for non open", id);
return;
}
if (c->flags & CHAN_EOF_RCVD) {
if (datafellows & SSH_BUG_EXTEOF)
debug("channel %d: accepting ext data after eof", id);
else
packet_disconnect("Received extended_data after EOF "
"on channel %d.", id);
}
tcode = packet_get_int();
if (c->efd == -1 ||
c->extended_usage != CHAN_EXTENDED_WRITE ||
@ -2109,7 +2122,7 @@ channel_request_remote_forwarding(u_short listen_port,
const char *address_to_bind = "0.0.0.0";
packet_start(SSH2_MSG_GLOBAL_REQUEST);
packet_put_cstring("tcpip-forward");
packet_put_char(0); /* boolean: want reply */
packet_put_char(1); /* boolean: want reply */
packet_put_cstring(address_to_bind);
packet_put_int(listen_port);
packet_send();
@ -2655,105 +2668,6 @@ auth_request_forwarding(void)
packet_write_wait();
}
/*
* Returns the name of the forwarded authentication socket. Returns NULL if
* there is no forwarded authentication socket. The returned value points to
* a static buffer.
*/
char *
auth_get_socket_name(void)
{
return auth_sock_name;
}
/* removes the agent forwarding socket */
void
auth_sock_cleanup_proc(void *_pw)
{
struct passwd *pw = _pw;
if (auth_sock_name) {
temporarily_use_uid(pw);
unlink(auth_sock_name);
rmdir(auth_sock_dir);
auth_sock_name = NULL;
restore_uid();
}
}
/*
* This is called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
* This starts forwarding authentication requests.
*/
int
auth_input_request_forwarding(struct passwd * pw)
{
Channel *nc;
int sock;
struct sockaddr_un sunaddr;
if (auth_get_socket_name() != NULL) {
error("authentication forwarding requested twice.");
return 0;
}
/* Temporarily drop privileged uid for mkdir/bind. */
temporarily_use_uid(pw);
/* Allocate a buffer for the socket name, and format the name. */
auth_sock_name = xmalloc(MAXPATHLEN);
auth_sock_dir = xmalloc(MAXPATHLEN);
strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
/* Create private directory for socket */
if (mkdtemp(auth_sock_dir) == NULL) {
packet_send_debug("Agent forwarding disabled: "
"mkdtemp() failed: %.100s", strerror(errno));
restore_uid();
xfree(auth_sock_name);
xfree(auth_sock_dir);
auth_sock_name = NULL;
auth_sock_dir = NULL;
return 0;
}
snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%d",
auth_sock_dir, (int) getpid());
/* delete agent socket on fatal() */
fatal_add_cleanup(auth_sock_cleanup_proc, pw);
/* Create the socket. */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
packet_disconnect("socket: %.100s", strerror(errno));
/* Bind it to the name. */
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
packet_disconnect("bind: %.100s", strerror(errno));
/* Restore the privileged uid. */
restore_uid();
/* Start listening on the socket. */
if (listen(sock, 5) < 0)
packet_disconnect("listen: %.100s", strerror(errno));
/* Allocate a channel for the authentication agent socket. */
nc = channel_new("auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, xstrdup("auth socket"), 1);
strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
return 1;
}
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.65 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: channels.h,v 1.68 2002/06/10 22:28:41 markus Exp $ */
/* $FreeBSD$ */
/*
@ -136,6 +136,18 @@ struct Channel {
#define CHAN_CLOSE_SENT 0x01
#define CHAN_CLOSE_RCVD 0x02
#define CHAN_EOF_SENT 0x04
#define CHAN_EOF_RCVD 0x08
/* check whether 'efd' is still in use */
#define CHANNEL_EFD_INPUT_ACTIVE(c) \
(compat20 && c->extended_usage == CHAN_EXTENDED_READ && \
(c->efd != -1 || \
buffer_len(&c->extended) > 0))
#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \
(compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \
((c->efd != -1 && !(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD))) || \
buffer_len(&c->extended) > 0))
/* channel management */
@ -202,8 +214,6 @@ void deny_input_open(int, u_int32_t, void *);
/* agent forwarding */
void auth_request_forwarding(void);
char *auth_get_socket_name(void);
int auth_input_request_forwarding(struct passwd *);
void auth_input_open_request(int, u_int32_t, void *);
/* channel close */

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: cipher.c,v 1.52 2002/02/18 13:05:32 markus Exp $");
RCSID("$OpenBSD: cipher.c,v 1.59 2002/06/19 18:01:00 markus Exp $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
@ -43,18 +43,20 @@ RCSID("$FreeBSD$");
#include "cipher.h"
#include <openssl/md5.h>
#include "rijndael.h"
static EVP_CIPHER *evp_ssh1_3des(void);
static EVP_CIPHER *evp_ssh1_bf(void);
static EVP_CIPHER *evp_rijndael(void);
#if OPENSSL_VERSION_NUMBER < 0x00907000L
#include "rijndael.h"
static const EVP_CIPHER *evp_rijndael(void);
#endif
static const EVP_CIPHER *evp_ssh1_3des(void);
static const EVP_CIPHER *evp_ssh1_bf(void);
struct Cipher {
char *name;
int number; /* for ssh1 only */
u_int block_size;
u_int key_len;
EVP_CIPHER *(*evptype)(void);
const EVP_CIPHER *(*evptype)(void);
} ciphers[] = {
{ "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
@ -65,25 +67,40 @@ struct Cipher {
{ "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
{ "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
#if OPENSSL_VERSION_NUMBER < 0x00907000L
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
#else
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, EVP_aes_128_cbc },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, EVP_aes_192_cbc },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
#endif
{ NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL }
};
/*--*/
u_int
u_int
cipher_blocksize(Cipher *c)
{
return (c->block_size);
}
u_int
u_int
cipher_keylen(Cipher *c)
{
return (c->key_len);
}
u_int
cipher_get_number(Cipher *c)
{
return (c->number);
}
u_int
cipher_mask_ssh1(int client)
@ -334,7 +351,7 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
}
return (1);
}
static EVP_CIPHER *
static const EVP_CIPHER *
evp_ssh1_3des(void)
{
static EVP_CIPHER ssh1_3des;
@ -384,7 +401,7 @@ bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
swap_bytes(out, out, len);
return (ret);
}
static EVP_CIPHER *
static const EVP_CIPHER *
evp_ssh1_bf(void)
{
static EVP_CIPHER ssh1_bf;
@ -397,6 +414,7 @@ evp_ssh1_bf(void)
return (&ssh1_bf);
}
#if OPENSSL_VERSION_NUMBER < 0x00907000L
/* RIJNDAEL */
#define RIJNDAEL_BLOCKSIZE 16
struct ssh_rijndael_ctx
@ -482,7 +500,7 @@ ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
}
return (1);
}
static EVP_CIPHER *
static const EVP_CIPHER *
evp_rijndael(void)
{
static EVP_CIPHER rijndal_cbc;
@ -499,3 +517,155 @@ evp_rijndael(void)
EVP_CIPH_ALWAYS_CALL_INIT;
return (&rijndal_cbc);
}
#endif
/*
* Exports an IV from the CipherContext required to export the key
* state back from the unprivileged child to the privileged parent
* process.
*/
int
cipher_get_keyiv_len(CipherContext *cc)
{
Cipher *c = cc->cipher;
int ivlen;
if (c->number == SSH_CIPHER_3DES)
ivlen = 24;
else
ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
return (ivlen);
}
void
cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
{
Cipher *c = cc->cipher;
u_char *civ = NULL;
int evplen;
switch (c->number) {
case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen == 0)
return;
if (evplen != len)
fatal("%s: wrong iv length %d != %d", __func__,
evplen, len);
#if OPENSSL_VERSION_NUMBER < 0x00907000L
if (c->evptype == evp_rijndael) {
struct ssh_rijndael_ctx *aesc;
aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
if (aesc == NULL)
fatal("%s: no rijndael context", __func__);
civ = aesc->r_iv;
} else
#endif
{
civ = cc->evp.iv;
}
break;
case SSH_CIPHER_3DES: {
struct ssh1_3des_ctx *desc;
if (len != 24)
fatal("%s: bad 3des iv length: %d", __func__, len);
desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
if (desc == NULL)
fatal("%s: no 3des context", __func__);
debug3("%s: Copying 3DES IV", __func__);
memcpy(iv, desc->k1.iv, 8);
memcpy(iv + 8, desc->k2.iv, 8);
memcpy(iv + 16, desc->k3.iv, 8);
return;
}
default:
fatal("%s: bad cipher %d", __func__, c->number);
}
memcpy(iv, civ, len);
}
void
cipher_set_keyiv(CipherContext *cc, u_char *iv)
{
Cipher *c = cc->cipher;
u_char *div = NULL;
int evplen = 0;
switch (c->number) {
case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen == 0)
return;
#if OPENSSL_VERSION_NUMBER < 0x00907000L
if (c->evptype == evp_rijndael) {
struct ssh_rijndael_ctx *aesc;
aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
if (aesc == NULL)
fatal("%s: no rijndael context", __func__);
div = aesc->r_iv;
} else
#endif
{
div = cc->evp.iv;
}
break;
case SSH_CIPHER_3DES: {
struct ssh1_3des_ctx *desc;
desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
if (desc == NULL)
fatal("%s: no 3des context", __func__);
debug3("%s: Installed 3DES IV", __func__);
memcpy(desc->k1.iv, iv, 8);
memcpy(desc->k2.iv, iv + 8, 8);
memcpy(desc->k3.iv, iv + 16, 8);
return;
}
default:
fatal("%s: bad cipher %d", __func__, c->number);
}
memcpy(div, iv, evplen);
}
#if OPENSSL_VERSION_NUMBER < 0x00907000L
#define EVP_X_STATE(evp) &(evp).c
#define EVP_X_STATE_LEN(evp) sizeof((evp).c)
#else
#define EVP_X_STATE(evp) (evp).cipher_data
#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
#endif
int
cipher_get_keycontext(CipherContext *cc, u_char *dat)
{
Cipher *c = cc->cipher;
int plen = 0;
if (c->evptype == EVP_rc4) {
plen = EVP_X_STATE_LEN(cc->evp);
if (dat == NULL)
return (plen);
memcpy(dat, EVP_X_STATE(cc->evp), plen);
}
return (plen);
}
void
cipher_set_keycontext(CipherContext *cc, u_char *dat)
{
Cipher *c = cc->cipher;
int plen;
if (c->evptype == EVP_rc4) {
plen = EVP_X_STATE_LEN(cc->evp);
memcpy(EVP_X_STATE(cc->evp), dat, plen);
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.h,v 1.32 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: cipher.h,v 1.33 2002/03/18 17:13:15 markus Exp $ */
/* $FreeBSD$ */
/*
@ -82,4 +82,11 @@ void cipher_cleanup(CipherContext *);
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(Cipher *);
u_int cipher_keylen(Cipher *);
u_int cipher_get_number(Cipher *);
void cipher_get_keyiv(CipherContext *, u_char *, u_int);
void cipher_set_keyiv(CipherContext *, u_char *);
int cipher_get_keyiv_len(CipherContext *);
int cipher_get_keycontext(CipherContext *, u_char *);
void cipher_set_keycontext(CipherContext *, u_char *);
#endif /* CIPHER_H */

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: compat.c,v 1.61 2002/03/06 00:24:39 markus Exp $");
RCSID("$OpenBSD: compat.c,v 1.63 2002/04/10 08:21:47 markus Exp $");
RCSID("$FreeBSD$");
#include "buffer.h"
@ -62,20 +62,26 @@ compat_datafellows(const char *version)
"OpenSSH-2.1*,"
"OpenSSH_2.1*,"
"OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER|
SSH_OLD_DHGEX|SSH_BUG_NOREKEY },
SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
SSH_BUG_EXTEOF},
{ "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES|
SSH_OLD_DHGEX|SSH_BUG_NOREKEY},
SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
SSH_BUG_EXTEOF},
{ "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
SSH_BUG_NOREKEY},
SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_2.5.0p1*,"
"OpenSSH_2.5.1p1*",
SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
SSH_BUG_NOREKEY },
SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_2.5.0*,"
"OpenSSH_2.5.1*,"
"OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY },
{ "OpenSSH_2.5.3*", SSH_BUG_NOREKEY },
{ "Sun_SSH_1.0*", SSH_BUG_NOREKEY },
"OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
SSH_BUG_EXTEOF},
{ "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_2.*,"
"OpenSSH_3.0*,"
"OpenSSH_3.1*", SSH_BUG_EXTEOF},
{ "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH*", 0 },
{ "*MindTerm*", 0 },
{ "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
@ -122,8 +128,12 @@ compat_datafellows(const char *version)
"1.2.19*,"
"1.2.20*,"
"1.2.21*,"
"1.2.22*", SSH_BUG_IGNOREMSG },
{ "1.3.2*", SSH_BUG_IGNOREMSG }, /* f-secure */
"1.2.22*", SSH_BUG_IGNOREMSG|SSH_BUG_K5USER },
{ "1.3.2*", /* F-Secure */
SSH_BUG_IGNOREMSG|SSH_BUG_K5USER },
{ "1.2.1*,"
"1.2.2*,"
"1.2.3*", SSH_BUG_K5USER },
{ "*SSH Compatible Server*", /* Netscreen */
SSH_BUG_PASSWORDPAD },
{ "*OSU_0*,"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.h,v 1.30 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: compat.h,v 1.32 2002/04/10 08:21:47 markus Exp $ */
/* $FreeBSD$ */
/*
@ -53,6 +53,8 @@
#define SSH_BUG_OPENFAILURE 0x00020000
#define SSH_BUG_DERIVEKEY 0x00040000
#define SSH_BUG_DUMMYCHAN 0x00100000
#define SSH_BUG_EXTEOF 0x00200000
#define SSH_BUG_K5USER 0x00400000
void enable_compat13(void);
void enable_compat20(void);

View File

@ -32,7 +32,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: key.c,v 1.41 2002/02/28 15:46:33 markus Exp $");
RCSID("$OpenBSD: key.c,v 1.44 2002/05/31 13:16:48 markus Exp $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@ -780,6 +780,10 @@ key_sign(
}
}
/*
* key_verify returns 1 for a correct signature, 0 for an incorrect signature
* and -1 on error.
*/
int
key_verify(
Key *key,
@ -802,3 +806,46 @@ key_verify(
break;
}
}
/* Converts a private to a public key */
Key *
key_demote(Key *k)
{
Key *pk;
pk = xmalloc(sizeof(*pk));
pk->type = k->type;
pk->flags = k->flags;
pk->dsa = NULL;
pk->rsa = NULL;
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
if ((pk->rsa = RSA_new()) == NULL)
fatal("key_demote: RSA_new failed");
if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
fatal("key_demote: BN_dup failed");
if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
fatal("key_demote: BN_dup failed");
break;
case KEY_DSA:
if ((pk->dsa = DSA_new()) == NULL)
fatal("key_demote: DSA_new failed");
if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
fatal("key_demote: BN_dup failed");
if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
fatal("key_demote: BN_dup failed");
if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
fatal("key_demote: BN_dup failed");
if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
fatal("key_demote: BN_dup failed");
break;
default:
fatal("key_free: bad key type %d", k->type);
break;
}
return (pk);
}

View File

@ -26,11 +26,12 @@
#include "includes.h"
RCSID("$OpenBSD: monitor.c,v 1.16 2002/06/21 05:50:51 djm Exp $");
RCSID("$FreeBSD$");
#include <openssl/dh.h>
#ifdef SKEY
#include <skey.h>
#include <opie.h>
#endif
#include "ssh.h"
@ -656,11 +657,11 @@ mm_answer_bsdauthrespond(int socket, Buffer *m)
int
mm_answer_skeyquery(int socket, Buffer *m)
{
struct skey skey;
struct opie opie;
char challenge[1024];
int res;
res = skeychallenge(&skey, authctxt->user, challenge);
res = opiechallenge(&opie, authctxt->user, challenge);
buffer_clear(m);
buffer_put_int(m, res);
@ -683,8 +684,8 @@ mm_answer_skeyrespond(int socket, Buffer *m)
authok = (options.challenge_response_authentication &&
authctxt->valid &&
skey_haskey(authctxt->pw->pw_name) == 0 &&
skey_passcheck(authctxt->pw->pw_name, response) != -1);
opie_haskey(authctxt->pw->pw_name) == 0 &&
opie_passverify(authctxt->pw->pw_name, response) != -1);
xfree(response);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: myproposal.h,v 1.13 2002/01/21 22:30:12 markus Exp $ */
/* $OpenBSD: myproposal.h,v 1.14 2002/04/03 09:26:11 markus Exp $ */
/* $FreeBSD$ */
/*
@ -28,7 +28,7 @@
#define KEX_DEFAULT_PK_ALG "ssh-dss,ssh-rsa"
#define KEX_DEFAULT_ENCRYPT \
"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \
"aes192-cbc,aes256-cbc"
"aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se"
#define KEX_DEFAULT_MAC \
"hmac-md5,hmac-sha1,hmac-ripemd160," \
"hmac-ripemd160@openssh.com," \

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.h,v 1.33 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: packet.h,v 1.35 2002/06/19 18:01:00 markus Exp $ */
/* $FreeBSD$ */
/*
@ -25,6 +25,7 @@ int packet_get_connection_in(void);
int packet_get_connection_out(void);
void packet_close(void);
void packet_set_encryption_key(const u_char *, u_int, int);
u_int packet_get_encryption_key(u_char *);
void packet_set_protocol_flags(u_int);
u_int packet_get_protocol_flags(void);
void packet_start_compression(int);
@ -57,6 +58,16 @@ void *packet_get_string(u_int *length_ptr);
void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void set_newkeys(int mode);
int packet_get_keyiv_len(int);
void packet_get_keyiv(int, u_char *, u_int);
int packet_get_keycontext(int, u_char *);
void packet_set_keycontext(int, u_char *);
u_int32_t packet_get_seqnr(int);
void packet_set_seqnr(int, u_int32_t);
int packet_get_ssh1_cipher(void);
void packet_set_iv(int, u_char *);
void packet_write_poll(void);
void packet_write_wait(void);
int packet_have_data_to_write(void);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pathnames.h,v 1.11 2002/02/09 17:37:34 deraadt Exp $ */
/* $OpenBSD: pathnames.h,v 1.13 2002/05/23 19:24:30 markus Exp $ */
/* $FreeBSD$ */
/*
@ -111,6 +111,9 @@
*/
#define _PATH_SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass"
/* Location of ssh-keysign for hostbased authentication */
#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign"
/* xauth for X11 forwarding */
#define _PATH_XAUTH "/usr/X11R6/bin/xauth"
@ -120,3 +123,6 @@
/* for sftp */
#define _PATH_SFTP_SERVER "/usr/libexec/sftp-server"
#define _PATH_LS "ls"
/* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */
#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty"

View File

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $");
RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
@ -42,7 +42,7 @@ RCSID("$FreeBSD$");
# that they are given in.
Host *.ngs.fi ngs.fi
FallBackToRsh no
User foo
Host fake.com
HostName another.host.name.real.org
@ -66,7 +66,7 @@ RCSID("$FreeBSD$");
ProxyCommand ssh-proxy %h %p
Host *.fr
UseRsh yes
PublicKeyAuthentication no
Host *.su
Cipher none
@ -80,8 +80,6 @@ RCSID("$FreeBSD$");
PasswordAuthentication yes
RSAAuthentication yes
RhostsRSAAuthentication yes
FallBackToRsh no
UseRsh no
StrictHostKeyChecking yes
KeepAlives no
IdentityFile ~/.ssh/identity
@ -95,7 +93,7 @@ RCSID("$FreeBSD$");
typedef enum {
oBadOption,
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
oPasswordAuthentication, oRSAAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
#if defined(KRB4) || defined(KRB5)
oKerberosAuthentication,
@ -117,7 +115,8 @@ typedef enum {
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oVersionAddendum
oVersionAddendum,
oDeprecated
} OpCodes;
/* Textual representations of the tokens. */
@ -152,8 +151,8 @@ static struct {
#ifdef AFS
{ "afstokenpassing", oAFSTokenPassing },
#endif
{ "fallbacktorsh", oFallBackToRsh },
{ "usersh", oUseRsh },
{ "fallbacktorsh", oDeprecated },
{ "usersh", oDeprecated },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* alias */
{ "hostname", oHostName },
@ -374,14 +373,6 @@ process_config_line(Options *options, const char *host,
intptr = &options->afs_token_passing;
goto parse_flag;
#endif
case oFallBackToRsh:
intptr = &options->fallback_to_rsh;
goto parse_flag;
case oUseRsh:
intptr = &options->use_rsh;
goto parse_flag;
case oBatchMode:
intptr = &options->batch_mode;
goto parse_flag;
@ -686,6 +677,11 @@ process_config_line(Options *options, const char *host,
} while (arg != NULL && *arg != '\0');
break;
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
return 0;
default:
fatal("process_config_line: Unimplemented opcode %d", opcode);
}
@ -773,8 +769,6 @@ initialize_options(Options * options)
options->kbd_interactive_devices = NULL;
options->rhosts_rsa_authentication = -1;
options->hostbased_authentication = -1;
options->fallback_to_rsh = -1;
options->use_rsh = -1;
options->batch_mode = -1;
options->check_host_ip = -1;
options->strict_host_key_checking = -1;
@ -830,7 +824,7 @@ fill_default_options(Options * options)
if (options->use_privileged_port == -1)
options->use_privileged_port = 0;
if (options->rhosts_authentication == -1)
options->rhosts_authentication = 1;
options->rhosts_authentication = 0;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->pubkey_authentication == -1)
@ -854,13 +848,9 @@ fill_default_options(Options * options)
if (options->kbd_interactive_authentication == -1)
options->kbd_interactive_authentication = 1;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 1;
options->rhosts_rsa_authentication = 0;
if (options->hostbased_authentication == -1)
options->hostbased_authentication = 0;
if (options->fallback_to_rsh == -1)
options->fallback_to_rsh = 0;
if (options->use_rsh == -1)
options->use_rsh = 0;
if (options->batch_mode == -1)
options->batch_mode = 0;
if (options->check_host_ip == -1)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.42 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: readconf.h,v 1.43 2002/06/08 05:17:01 markus Exp $ */
/* $FreeBSD$ */
/*
@ -55,8 +55,6 @@ typedef struct {
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */
int use_rsh; /* Always use rsh (don\'t try ssh). */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: servconf.c,v 1.101 2002/02/04 12:15:25 markus Exp $");
RCSID("$OpenBSD: servconf.c,v 1.111 2002/06/20 23:05:55 markus Exp $");
RCSID("$FreeBSD$");
#if defined(KRB4)
@ -40,6 +40,8 @@ static void add_one_listen_addr(ServerOptions *, char *, u_short);
/* AF_UNSPEC or AF_INET or AF_INET6 */
extern int IPv4or6;
/* Use of privilege separation or not */
extern int use_privsep;
/* Initializes the server options to their default values. */
@ -90,6 +92,7 @@ initialize_server_options(ServerOptions *options)
options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
options->use_login = -1;
options->compression = -1;
options->allow_tcp_forwarding = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
@ -111,6 +114,9 @@ initialize_server_options(ServerOptions *options)
options->authorized_keys_file = NULL;
options->authorized_keys_file2 = NULL;
options->check_mail = -1;
/* Needs to be accessable in many places */
use_privsep = -1;
}
void
@ -205,7 +211,7 @@ fill_default_server_options(ServerOptions *options)
#endif
#ifdef AFS
if (options->afs_token_passing == -1)
options->afs_token_passing = k_hasafs();
options->afs_token_passing = 0;
#endif
if (options->password_authentication == -1)
options->password_authentication = 1;
@ -217,6 +223,8 @@ fill_default_server_options(ServerOptions *options)
options->permit_empty_passwd = 0;
if (options->use_login == -1)
options->use_login = 0;
if (options->compression == -1)
options->compression = 1;
if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = 1;
if (options->gateway_ports == -1)
@ -242,6 +250,10 @@ fill_default_server_options(ServerOptions *options)
}
if (options->authorized_keys_file == NULL)
options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
/* Turn privilege separation off by default */
if (use_privsep == -1)
use_privsep = 0;
}
/* Keyword tokens. */
@ -264,13 +276,14 @@ typedef enum {
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sStrictModes, sEmptyPasswd, sKeepAlives,
sUseLogin, sAllowTcpForwarding,
sUseLogin, sAllowTcpForwarding, sCompression,
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
sUsePrivilegeSeparation,
sCheckMail, sVersionAddendum,
sDeprecated
} ServerOpCodes;
@ -324,6 +337,7 @@ static struct {
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
{ "compression", sCompression },
{ "keepalive", sKeepAlives },
{ "allowtcpforwarding", sAllowTcpForwarding },
{ "allowusers", sAllowUsers },
@ -343,6 +357,7 @@ static struct {
{ "clientalivecountmax", sClientAliveCountMax },
{ "authorizedkeysfile", sAuthorizedKeysFile },
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
{ "useprivilegeseparation", sUsePrivilegeSeparation},
{ "checkmail", sCheckMail },
{ "versionaddendum", sVersionAddendum },
{ NULL, sBadOption }
@ -681,6 +696,10 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->use_login;
goto parse_flag;
case sCompression:
intptr = &options->compression;
goto parse_flag;
case sGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
@ -715,6 +734,10 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->allow_tcp_forwarding;
goto parse_flag;
case sUsePrivilegeSeparation:
intptr = &use_privsep;
goto parse_flag;
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.54 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: servconf.h,v 1.58 2002/06/20 23:05:55 markus Exp $ */
/* $FreeBSD$ */
/*
@ -100,6 +100,7 @@ typedef struct {
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int use_login; /* If true, login(1) is used */
int compression; /* If true, compression is allowed */
int allow_tcp_forwarding;
u_int num_allow_users;
char *allow_users[MAX_ALLOW_USERS];
@ -132,7 +133,6 @@ typedef struct {
char *authorized_keys_file; /* File containing public keys */
char *authorized_keys_file2;
} ServerOptions;
void initialize_server_options(ServerOptions *);

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: serverloop.c,v 1.98 2002/02/06 14:55:16 markus Exp $");
RCSID("$OpenBSD: serverloop.c,v 1.102 2002/06/11 05:46:20 mpech Exp $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
@ -319,9 +319,6 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
tvp = &tv;
}
if (tvp!=NULL)
debug3("tvp!=NULL kid %d mili %d", (int) child_terminated,
max_time_milliseconds);
/* Wait for something to happen, or the timeout to expire. */
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
@ -674,12 +671,12 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
/* We no longer want our SIGCHLD handler to be called. */
signal(SIGCHLD, SIG_DFL);
wait_pid = waitpid(-1, &wait_status, 0);
if (wait_pid == -1)
packet_disconnect("wait: %.100s", strerror(errno));
else if (wait_pid != pid)
error("Strange, wait returned pid %d, expected %d",
wait_pid, pid);
while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
if (errno != EINTR)
packet_disconnect("wait: %.100s", strerror(errno));
if (wait_pid != pid)
error("Strange, wait returned pid %ld, expected %ld",
(long)wait_pid, (long)pid);
/* Check if it exited normally. */
if (WIFEXITED(wait_status)) {
@ -727,8 +724,10 @@ collect_children(void)
sigaddset(&nset, SIGCHLD);
sigprocmask(SIG_BLOCK, &nset, &oset);
if (child_terminated) {
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
session_close_by_pid(pid, status);
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
if (pid > 0)
session_close_by_pid(pid, status);
child_terminated = 0;
}
sigprocmask(SIG_SETMASK, &oset, NULL);
@ -785,7 +784,7 @@ server_loop2(Authctxt *authctxt)
channel_free_all();
/* free remaining sessions, e.g. remove wtmp entries */
session_destroy_all();
session_destroy_all(NULL);
}
static void

View File

@ -33,7 +33,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $");
RCSID("$OpenBSD: session.c,v 1.138 2002/06/20 23:05:55 markus Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
@ -57,6 +57,7 @@ RCSID("$FreeBSD$");
#include "serverloop.h"
#include "canohost.h"
#include "session.h"
#include "monitor_wrap.h"
#ifdef __FreeBSD__
#define _PATH_CHPASS "/usr/bin/passwd"
@ -69,39 +70,11 @@ RCSID("$FreeBSD$");
#include <login_cap.h>
#endif
/* types */
#define TTYSZ 64
typedef struct Session Session;
struct Session {
int used;
int self;
struct passwd *pw;
Authctxt *authctxt;
pid_t pid;
/* tty */
char *term;
int ptyfd, ttyfd, ptymaster;
int row, col, xpixel, ypixel;
char tty[TTYSZ];
/* X11 */
int display_number;
char *display;
int screen;
char *auth_display;
char *auth_proto;
char *auth_data;
int single_connection;
/* proto 2 */
int chanid;
int is_subsystem;
};
/* func */
Session *session_new(void);
void session_set_fds(Session *, int, int, int);
static void session_pty_cleanup(void *);
void session_pty_cleanup(void *);
void session_proctitle(Session *);
int session_setup_x11fwd(Session *);
void do_exec_pty(Session *, const char *);
@ -115,7 +88,6 @@ int check_quietlogin(Session *, const char *);
static void do_authenticated1(Authctxt *);
static void do_authenticated2(Authctxt *);
static void session_close(Session *);
static int session_pty_req(Session *);
/* import */
@ -135,9 +107,96 @@ const char *original_command = NULL;
Session sessions[MAX_SESSIONS];
#ifdef HAVE_LOGIN_CAP
static login_cap_t *lc;
login_cap_t *lc;
#endif
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
static char *auth_sock_dir = NULL;
/* removes the agent forwarding socket */
static void
auth_sock_cleanup_proc(void *_pw)
{
struct passwd *pw = _pw;
if (auth_sock_name != NULL) {
temporarily_use_uid(pw);
unlink(auth_sock_name);
rmdir(auth_sock_dir);
auth_sock_name = NULL;
restore_uid();
}
}
static int
auth_input_request_forwarding(struct passwd * pw)
{
Channel *nc;
int sock;
struct sockaddr_un sunaddr;
if (auth_sock_name != NULL) {
error("authentication forwarding requested twice.");
return 0;
}
/* Temporarily drop privileged uid for mkdir/bind. */
temporarily_use_uid(pw);
/* Allocate a buffer for the socket name, and format the name. */
auth_sock_name = xmalloc(MAXPATHLEN);
auth_sock_dir = xmalloc(MAXPATHLEN);
strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
/* Create private directory for socket */
if (mkdtemp(auth_sock_dir) == NULL) {
packet_send_debug("Agent forwarding disabled: "
"mkdtemp() failed: %.100s", strerror(errno));
restore_uid();
xfree(auth_sock_name);
xfree(auth_sock_dir);
auth_sock_name = NULL;
auth_sock_dir = NULL;
return 0;
}
snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
auth_sock_dir, (long) getpid());
/* delete agent socket on fatal() */
fatal_add_cleanup(auth_sock_cleanup_proc, pw);
/* Create the socket. */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
packet_disconnect("socket: %.100s", strerror(errno));
/* Bind it to the name. */
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
packet_disconnect("bind: %.100s", strerror(errno));
/* Restore the privileged uid. */
restore_uid();
/* Start listening on the socket. */
if (listen(sock, 5) < 0)
packet_disconnect("listen: %.100s", strerror(errno));
/* Allocate a channel for the authentication agent socket. */
nc = channel_new("auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, xstrdup("auth socket"), 1);
strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
return 1;
}
void
do_authenticated(Authctxt *authctxt)
{
@ -150,18 +209,6 @@ do_authenticated(Authctxt *authctxt)
close(startup_pipe);
startup_pipe = -1;
}
#ifdef HAVE_LOGIN_CAP
if ((lc = login_getpwclass(authctxt->pw)) == NULL) {
error("unable to get login class");
return;
}
#ifdef BSD_AUTH
if (auth_approval(NULL, lc, authctxt->pw->pw_name, "ssh") <= 0) {
packet_disconnect("Approval failure for %s",
authctxt->pw->pw_name);
}
#endif
#endif
/* setup the channel layer */
if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
channel_permit_all_opens();
@ -172,7 +219,7 @@ do_authenticated(Authctxt *authctxt)
do_authenticated1(authctxt);
/* remove agent socket */
if (auth_get_socket_name())
if (auth_sock_name != NULL)
auth_sock_cleanup_proc(authctxt->pw);
#ifdef KRB4
if (options.kerberos_ticket_cleanup)
@ -223,6 +270,10 @@ do_authenticated1(Authctxt *authctxt)
compression_level);
break;
}
if (!options.compression) {
debug2("compression disabled");
break;
}
/* Enable compression after we have responded with SUCCESS. */
enable_compression_after_reply = 1;
success = 1;
@ -379,7 +430,7 @@ do_authenticated1(Authctxt *authctxt)
void
do_exec_no_pty(Session *s, const char *command)
{
int pid;
pid_t pid;
#ifdef USE_PIPES
int pin[2], pout[2], perr[2];
@ -603,22 +654,13 @@ do_exec(Session *s, const char *command)
void
do_login(Session *s, const char *command)
{
FILE *f;
#ifndef USE_PAM
char *time_string;
char *newcommand = NULL;
#endif
char buf[256];
#ifndef USE_PAM
char hostname[MAXHOSTNAMELEN];
socklen_t fromlen;
struct sockaddr_storage from;
time_t last_login_time;
#endif
struct passwd * pw = s->pw;
#ifndef USE_PAM
pid_t pid = getpid();
#endif
#ifdef __FreeBSD__
#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
struct timeval tv;
@ -644,20 +686,6 @@ do_login(Session *s, const char *command)
}
#endif
#ifndef USE_PAM
/* Get the time and hostname when the user last logged in. */
if (options.print_lastlog) {
hostname[0] = '\0';
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
hostname, sizeof(hostname));
}
/* Record that there was a login on that tty from the remote host. */
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
(struct sockaddr *)&from);
#endif
#ifdef USE_PAM
/*
* If password change is needed, do it now.
@ -729,6 +757,13 @@ do_login(Session *s, const char *command)
}
#endif /* HAVE_LOGIN_CAP */
/* Record that there was a login on that tty from the remote host. */
if (!use_privsep)
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
get_remote_name_or_ip(utmp_len,
options.verify_reverse_mapping),
(struct sockaddr *)&from);
#ifdef USE_PAM
if (command == NULL && options.print_lastlog &&
!check_quietlogin(s, command) &&
@ -745,22 +780,27 @@ do_login(Session *s, const char *command)
*/
if (command == NULL && options.print_lastlog &&
last_login_time != 0 && !check_quietlogin(s, command) &&
s->last_login_time != 0 && !check_quietlogin(s, command) &&
!options.use_login) {
time_string = ctime(&last_login_time);
time_string = ctime(&s->last_login_time);
if (strchr(time_string, '\n'))
*strchr(time_string, '\n') = 0;
if (strcmp(hostname, "") == 0)
if (strcmp(s->hostname, "") == 0)
printf("Last login: %s\r\n", time_string);
else
printf("Last login: %s from %s\r\n", time_string, hostname);
printf("Last login: %s from %s\r\n", time_string,
s->hostname);
}
#endif /* !USE_PAM */
if (command == NULL && !check_quietlogin(s, command) &&
!options.use_login) {
#ifdef HAVE_LOGIN_CAP
const char *fname = login_getcapstr(lc, "copyright", NULL, NULL);
const char *fname;
char buf[256];
FILE *f;
fname = login_getcapstr(lc, "copyright", NULL, NULL);
if (fname != NULL && (f = fopen(fname, "r")) != NULL) {
while (fgets(buf, sizeof(buf), f) != NULL)
fputs(buf, stdout);
@ -1033,9 +1073,9 @@ do_setup_env(char **env, Session *s, const char *shell)
do_pam_environment(&env, &envsize);
#endif /* USE_PAM */
if (auth_get_socket_name() != NULL)
if (auth_sock_name != NULL)
child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
auth_get_socket_name());
auth_sock_name);
/* read $HOME/.ssh/environment. */
if (!options.use_login) {
@ -1099,7 +1139,7 @@ do_rc_files(Session *s, const char *shell)
/* Add authority data to .Xauthority if appropriate. */
if (debug_flag) {
fprintf(stderr,
"Running %.100s add "
"Running %.500s add "
"%.100s %.100s %.100s\n",
options.xauth_location, s->auth_display,
s->auth_proto, s->auth_data);
@ -1143,11 +1183,10 @@ do_nologin(struct passwd *pw)
}
/* Set login name, uid, gid, and groups. */
static char **
do_setusercontext(Session *s)
void
do_setusercontext(struct passwd *pw)
{
char **env = NULL;
struct passwd *pw = s->pw;
#ifdef HAVE_LOGIN_CAP
char buf[256];
char **tmpenv;
@ -1170,9 +1209,6 @@ do_setusercontext(Session *s)
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
if (s->term)
child_set_env(&env, &envsize, "TERM", s->term);
/* Save parent environment */
tmpenv = environ;
/* Switch to env */
@ -1207,7 +1243,21 @@ do_setusercontext(Session *s)
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
#endif /* HAVE_LOGIN_CAP */
return env;
return;
}
static void
launch_login(struct passwd *pw, const char *hostname)
{
/* Launch login(1). */
execl("/usr/bin/login", "login", "-h", hostname,
"-p", "-f", "--", pw->pw_name, (char *)NULL);
/* Login couldn't be executed, die. */
perror("login");
exit(1);
}
/*
@ -1242,7 +1292,7 @@ do_child(Session *s, const char *command)
*/
if (!options.use_login) {
do_nologin(pw);
env = do_setusercontext(s);
do_setusercontext(pw);
}
/*
@ -1336,15 +1386,8 @@ do_child(Session *s, const char *command)
signal(SIGPIPE, SIG_DFL);
if (options.use_login) {
/* Launch login(1). */
execl("/usr/bin/login", "login", "-h", hostname,
"-p", "-f", "--", pw->pw_name, (char *)NULL);
/* Login couldn't be executed, die. */
perror("login");
exit(1);
launch_login(pw, hostname);
/* NEVERREACHED */
}
/* Get the last component of the shell name. */
@ -1450,12 +1493,12 @@ session_dump(void)
int i;
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
debug("dump: used %d session %d %p channel %d pid %d",
debug("dump: used %d session %d %p channel %d pid %ld",
s->used,
s->self,
s,
s->chanid,
s->pid);
(long)s->pid);
}
}
@ -1477,6 +1520,22 @@ session_open(Authctxt *authctxt, int chanid)
return 1;
}
Session *
session_by_tty(char *tty)
{
int i;
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
debug("session_by_tty: session %d tty %s", i, tty);
return s;
}
}
debug("session_by_tty: unknown tty %.100s", tty);
session_dump();
return NULL;
}
static Session *
session_by_channel(int id)
{
@ -1497,13 +1556,13 @@ static Session *
session_by_pid(pid_t pid)
{
int i;
debug("session_by_pid: pid %d", pid);
debug("session_by_pid: pid %ld", (long)pid);
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used && s->pid == pid)
return s;
}
error("session_by_pid: unknown pid %d", pid);
error("session_by_pid: unknown pid %ld", (long)pid);
session_dump();
return NULL;
}
@ -1534,6 +1593,12 @@ session_pty_req(Session *s)
packet_disconnect("Protocol error: you already have a pty.");
return 0;
}
/* Get the time and hostname when the user last logged in. */
if (options.print_lastlog) {
s->hostname[0] = '\0';
s->last_login_time = get_last_login_time(s->pw->pw_uid,
s->pw->pw_name, s->hostname, sizeof(s->hostname));
}
s->term = packet_get_string(&len);
@ -1554,7 +1619,7 @@ session_pty_req(Session *s)
/* Allocate a pty and open it. */
debug("Allocating pty.");
if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) {
if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
if (s->term)
xfree(s->term);
s->term = NULL;
@ -1575,7 +1640,8 @@ session_pty_req(Session *s)
* time in case we call fatal() (e.g., the connection gets closed).
*/
fatal_add_cleanup(session_pty_cleanup, (void *)s);
pty_setowner(s->pw, s->tty);
if (!use_privsep)
pty_setowner(s->pw, s->tty);
/* Set window size from the packet. */
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
@ -1738,8 +1804,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr)
* Function to perform pty cleanup. Also called if we get aborted abnormally
* (e.g., due to a dropped connection).
*/
static void
session_pty_cleanup(void *session)
void
session_pty_cleanup2(void *session)
{
Session *s = session;
@ -1757,7 +1823,8 @@ session_pty_cleanup(void *session)
record_logout(s->pid, s->tty);
/* Release the pseudo-tty. */
pty_release(s->tty);
if (getuid() == 0)
pty_release(s->tty);
/*
* Close the server side of the socket pairs. We must do this after
@ -1765,12 +1832,18 @@ session_pty_cleanup(void *session)
* while we're still cleaning up.
*/
if (close(s->ptymaster) < 0)
error("close(s->ptymaster): %s", strerror(errno));
error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));
/* unlink pty from session */
s->ttyfd = -1;
}
void
session_pty_cleanup(void *session)
{
PRIVSEP(session_pty_cleanup2(session));
}
static void
session_exit_message(Session *s, int status)
{
@ -1779,8 +1852,8 @@ session_exit_message(Session *s, int status)
if ((c = channel_lookup(s->chanid)) == NULL)
fatal("session_exit_message: session %d: no channel %d",
s->self, s->chanid);
debug("session_exit_message: session %d channel %d pid %d",
s->self, s->chanid, s->pid);
debug("session_exit_message: session %d channel %d pid %ld",
s->self, s->chanid, (long)s->pid);
if (WIFEXITED(status)) {
channel_request_start(s->chanid, "exit-status", 0);
@ -1812,10 +1885,10 @@ session_exit_message(Session *s, int status)
s->chanid = -1;
}
static void
void
session_close(Session *s)
{
debug("session_close: session %d pid %d", s->self, s->pid);
debug("session_close: session %d pid %ld", s->self, (long)s->pid);
if (s->ttyfd != -1) {
fatal_remove_cleanup(session_pty_cleanup, (void *)s);
session_pty_cleanup(s);
@ -1839,7 +1912,8 @@ session_close_by_pid(pid_t pid, int status)
{
Session *s = session_by_pid(pid);
if (s == NULL) {
debug("session_close_by_pid: no session for pid %d", pid);
debug("session_close_by_pid: no session for pid %ld",
(long)pid);
return;
}
if (s->chanid != -1)
@ -1859,7 +1933,8 @@ session_close_by_channel(int id, void *arg)
debug("session_close_by_channel: no session for id %d", id);
return;
}
debug("session_close_by_channel: channel %d child %d", id, s->pid);
debug("session_close_by_channel: channel %d child %ld",
id, (long)s->pid);
if (s->pid != 0) {
debug("session_close_by_channel: channel %d: has child", id);
/*
@ -1879,13 +1954,17 @@ session_close_by_channel(int id, void *arg)
}
void
session_destroy_all(void)
session_destroy_all(void (*closefunc)(Session *))
{
int i;
for (i = 0; i < MAX_SESSIONS; i++) {
Session *s = &sessions[i];
if (s->used)
session_close(s);
if (s->used) {
if (closefunc != NULL)
closefunc(s);
else
session_close(s);
}
}
}

View File

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-add.c,v 1.50 2002/01/29 14:27:57 markus Exp $");
RCSID("$OpenBSD: ssh-add.c,v 1.61 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@ -49,6 +49,7 @@ RCSID("$FreeBSD$");
#include "authfile.h"
#include "pathnames.h"
#include "readpass.h"
#include "misc.h"
/* argv0 */
extern char *__progname;
@ -57,10 +58,12 @@ extern char *__progname;
static char *default_files[] = {
_PATH_SSH_CLIENT_ID_RSA,
_PATH_SSH_CLIENT_ID_DSA,
_PATH_SSH_CLIENT_IDENTITY,
_PATH_SSH_CLIENT_IDENTITY,
NULL
};
/* Default lifetime (0 == forever) */
static int lifetime = 0;
/* we keep a cache of one passphrases */
static char *pass = NULL;
@ -156,11 +159,19 @@ add_file(AuthenticationConnection *ac, const char *filename)
strlcpy(msg, "Bad passphrase, try again: ", sizeof msg);
}
}
if (ssh_add_identity(ac, private, comment)) {
if (ssh_add_identity_constrained(ac, private, comment, lifetime)) {
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
ret = 0;
} else
if (lifetime != 0)
fprintf(stderr,
"Lifetime set to %d seconds\n", lifetime);
} else if (ssh_add_identity(ac, private, comment)) {
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
ret = 0;
} else {
fprintf(stderr, "Could not add identity: %s\n", filename);
}
xfree(comment);
key_free(private);
@ -171,7 +182,13 @@ add_file(AuthenticationConnection *ac, const char *filename)
static int
update_card(AuthenticationConnection *ac, int add, const char *id)
{
if (ssh_update_card(ac, add, id)) {
char *pin;
pin = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
if (pin == NULL)
return -1;
if (ssh_update_card(ac, add, id, pin)) {
fprintf(stderr, "Card %s: %s\n",
add ? "added" : "removed", id);
return 0;
@ -217,6 +234,34 @@ list_identities(AuthenticationConnection *ac, int do_fp)
return 0;
}
static int
lock_agent(AuthenticationConnection *ac, int lock)
{
char prompt[100], *p1, *p2;
int passok = 1, ret = -1;
strlcpy(prompt, "Enter lock password: ", sizeof(prompt));
p1 = read_passphrase(prompt, RP_ALLOW_STDIN);
if (lock) {
strlcpy(prompt, "Again: ", sizeof prompt);
p2 = read_passphrase(prompt, RP_ALLOW_STDIN);
if (strcmp(p1, p2) != 0) {
fprintf(stderr, "Passwords do not match.\n");
passok = 0;
}
memset(p2, 0, strlen(p2));
xfree(p2);
}
if (passok && ssh_lock_agent(ac, lock, p1)) {
fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
ret = 0;
} else
fprintf(stderr, "Failed to %slock agent.\n", lock ? "" : "un");
memset(p1, 0, strlen(p1));
xfree(p1);
return -1;
}
static int
do_file(AuthenticationConnection *ac, int deleting, char *file)
{
@ -239,6 +284,9 @@ usage(void)
fprintf(stderr, " -L List public key parameters of all identities.\n");
fprintf(stderr, " -d Delete identity.\n");
fprintf(stderr, " -D Delete all identities.\n");
fprintf(stderr, " -x Lock agent.\n");
fprintf(stderr, " -x Unlock agent.\n");
fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
#ifdef SMARTCARD
fprintf(stderr, " -s reader Add key in smartcard reader.\n");
fprintf(stderr, " -e reader Remove key in smartcard reader.\n");
@ -262,7 +310,7 @@ main(int argc, char **argv)
fprintf(stderr, "Could not open a connection to your authentication agent.\n");
exit(2);
}
while ((ch = getopt(argc, argv, "lLdDe:s:")) != -1) {
while ((ch = getopt(argc, argv, "lLdDxXe:s:t:")) != -1) {
switch (ch) {
case 'l':
case 'L':
@ -270,6 +318,12 @@ main(int argc, char **argv)
ret = 1;
goto done;
break;
case 'x':
case 'X':
if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1)
ret = 1;
goto done;
break;
case 'd':
deleting = 1;
break;
@ -285,6 +339,13 @@ main(int argc, char **argv)
deleting = 1;
sc_reader_id = optarg;
break;
case 't':
if ((lifetime = convtime(optarg)) == -1) {
fprintf(stderr, "Invalid lifetime\n");
ret = 1;
goto done;
}
break;
default:
usage();
ret = 1;
@ -301,6 +362,8 @@ main(int argc, char **argv)
if (argc == 0) {
char buf[MAXPATHLEN];
struct passwd *pw;
struct stat st;
int count = 0;
if ((pw = getpwuid(getuid())) == NULL) {
fprintf(stderr, "No user found with uid %u\n",
@ -310,11 +373,17 @@ main(int argc, char **argv)
}
for(i = 0; default_files[i]; i++) {
snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
default_files[i]);
if (stat(buf, &st) < 0)
continue;
if (do_file(ac, deleting, buf) == -1)
ret = 1;
else
count++;
}
if (count == 0)
ret = 1;
} else {
for(i = 0; i < argc; i++) {
if (do_file(ac, deleting, argv[i]) == -1)

View File

@ -35,7 +35,7 @@
#include "includes.h"
#include <sys/queue.h>
RCSID("$OpenBSD: ssh-agent.c,v 1.82 2002/03/04 17:27:39 stevesk Exp $");
RCSID("$OpenBSD: ssh-agent.c,v 1.95 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@ -53,7 +53,6 @@ RCSID("$FreeBSD$");
#include "log.h"
#ifdef SMARTCARD
#include <openssl/engine.h>
#include "scard.h"
#endif
@ -68,6 +67,7 @@ typedef struct {
sock_type type;
Buffer input;
Buffer output;
Buffer request;
} SocketEntry;
u_int sockets_alloc = 0;
@ -77,6 +77,7 @@ typedef struct identity {
TAILQ_ENTRY(identity) next;
Key *key;
char *comment;
u_int death;
} Identity;
typedef struct {
@ -96,6 +97,10 @@ pid_t parent_pid = -1;
char socket_name[1024];
char socket_dir[1024];
/* locking */
int locked = 0;
char *lock_passwd = NULL;
extern char *__progname;
static void
@ -117,6 +122,14 @@ idtab_lookup(int version)
return &idtable[version];
}
static void
free_identity(Identity *id)
{
key_free(id->key);
xfree(id->comment);
xfree(id);
}
/* return matching private key for given public key */
static Identity *
lookup_identity(Key *key, int version)
@ -131,14 +144,6 @@ lookup_identity(Key *key, int version)
return (NULL);
}
static void
free_identity(Identity *id)
{
key_free(id->key);
xfree(id->comment);
xfree(id);
}
/* send list of supported public keys to 'client' */
static void
process_request_identities(SocketEntry *e, int version)
@ -188,16 +193,16 @@ process_authentication_challenge1(SocketEntry *e)
if ((challenge = BN_new()) == NULL)
fatal("process_authentication_challenge1: BN_new failed");
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
buffer_get_bignum(&e->input, challenge);
buffer_get_int(&e->request); /* ignored */
buffer_get_bignum(&e->request, key->rsa->e);
buffer_get_bignum(&e->request, key->rsa->n);
buffer_get_bignum(&e->request, challenge);
/* Only protocol 1.1 is supported */
if (buffer_len(&e->input) == 0)
if (buffer_len(&e->request) == 0)
goto failure;
buffer_get(&e->input, session_id, 16);
response_type = buffer_get_int(&e->input);
buffer_get(&e->request, session_id, 16);
response_type = buffer_get_int(&e->request);
if (response_type != 1)
goto failure;
@ -253,10 +258,10 @@ process_sign_request2(SocketEntry *e)
datafellows = 0;
blob = buffer_get_string(&e->input, &blen);
data = buffer_get_string(&e->input, &dlen);
blob = buffer_get_string(&e->request, &blen);
data = buffer_get_string(&e->request, &dlen);
flags = buffer_get_int(&e->input);
flags = buffer_get_int(&e->request);
if (flags & SSH_AGENT_OLD_SIGNATURE)
datafellows = SSH_BUG_SIGBLOB;
@ -297,16 +302,16 @@ process_remove_identity(SocketEntry *e, int version)
switch (version) {
case 1:
key = key_new(KEY_RSA1);
bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
bits = buffer_get_int(&e->request);
buffer_get_bignum(&e->request, key->rsa->e);
buffer_get_bignum(&e->request, key->rsa->n);
if (bits != key_size(key))
log("Warning: identity keysize mismatch: actual %d, announced %d",
key_size(key), bits);
break;
case 2:
blob = buffer_get_string(&e->input, &blen);
blob = buffer_get_string(&e->request, &blen);
key = key_from_blob(blob, blen);
xfree(blob);
break;
@ -357,7 +362,27 @@ process_remove_all_identities(SocketEntry *e, int version)
/* Send success. */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
return;
}
static void
reaper(void)
{
Idtab *tab;
Identity *id, *nxt;
int version;
u_int now = time(NULL);
for (version = 1; version < 3; version++) {
tab = idtab_lookup(version);
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
nxt = TAILQ_NEXT(id, next);
if (id->death != 0 && now >= id->death) {
TAILQ_REMOVE(&tab->idlist, id, next);
free_identity(id);
tab->nentries--;
}
}
}
}
static void
@ -366,66 +391,76 @@ process_add_identity(SocketEntry *e, int version)
Key *k = NULL;
char *type_name;
char *comment;
int type, success = 0;
int type, success = 0, death = 0;
Idtab *tab = idtab_lookup(version);
switch (version) {
case 1:
k = key_new_private(KEY_RSA1);
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, k->rsa->n);
buffer_get_bignum(&e->input, k->rsa->e);
buffer_get_bignum(&e->input, k->rsa->d);
buffer_get_bignum(&e->input, k->rsa->iqmp);
buffer_get_int(&e->request); /* ignored */
buffer_get_bignum(&e->request, k->rsa->n);
buffer_get_bignum(&e->request, k->rsa->e);
buffer_get_bignum(&e->request, k->rsa->d);
buffer_get_bignum(&e->request, k->rsa->iqmp);
/* SSH and SSL have p and q swapped */
buffer_get_bignum(&e->input, k->rsa->q); /* p */
buffer_get_bignum(&e->input, k->rsa->p); /* q */
buffer_get_bignum(&e->request, k->rsa->q); /* p */
buffer_get_bignum(&e->request, k->rsa->p); /* q */
/* Generate additional parameters */
rsa_generate_additional_parameters(k->rsa);
break;
case 2:
type_name = buffer_get_string(&e->input, NULL);
type_name = buffer_get_string(&e->request, NULL);
type = key_type_from_name(type_name);
xfree(type_name);
switch (type) {
case KEY_DSA:
k = key_new_private(type);
buffer_get_bignum2(&e->input, k->dsa->p);
buffer_get_bignum2(&e->input, k->dsa->q);
buffer_get_bignum2(&e->input, k->dsa->g);
buffer_get_bignum2(&e->input, k->dsa->pub_key);
buffer_get_bignum2(&e->input, k->dsa->priv_key);
buffer_get_bignum2(&e->request, k->dsa->p);
buffer_get_bignum2(&e->request, k->dsa->q);
buffer_get_bignum2(&e->request, k->dsa->g);
buffer_get_bignum2(&e->request, k->dsa->pub_key);
buffer_get_bignum2(&e->request, k->dsa->priv_key);
break;
case KEY_RSA:
k = key_new_private(type);
buffer_get_bignum2(&e->input, k->rsa->n);
buffer_get_bignum2(&e->input, k->rsa->e);
buffer_get_bignum2(&e->input, k->rsa->d);
buffer_get_bignum2(&e->input, k->rsa->iqmp);
buffer_get_bignum2(&e->input, k->rsa->p);
buffer_get_bignum2(&e->input, k->rsa->q);
buffer_get_bignum2(&e->request, k->rsa->n);
buffer_get_bignum2(&e->request, k->rsa->e);
buffer_get_bignum2(&e->request, k->rsa->d);
buffer_get_bignum2(&e->request, k->rsa->iqmp);
buffer_get_bignum2(&e->request, k->rsa->p);
buffer_get_bignum2(&e->request, k->rsa->q);
/* Generate additional parameters */
rsa_generate_additional_parameters(k->rsa);
break;
default:
buffer_clear(&e->input);
buffer_clear(&e->request);
goto send;
}
break;
}
comment = buffer_get_string(&e->input, NULL);
comment = buffer_get_string(&e->request, NULL);
if (k == NULL) {
xfree(comment);
goto send;
}
success = 1;
while (buffer_len(&e->request)) {
switch (buffer_get_char(&e->request)) {
case SSH_AGENT_CONSTRAIN_LIFETIME:
death = time(NULL) + buffer_get_int(&e->request);
break;
default:
break;
}
}
if (lookup_identity(k, version) == NULL) {
Identity *id = xmalloc(sizeof(Identity));
id->key = k;
id->comment = comment;
id->death = death;
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
/* Increment the number of identities. */
tab->nentries++;
@ -439,53 +474,86 @@ process_add_identity(SocketEntry *e, int version)
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
/* XXX todo: encrypt sensitive data with passphrase */
static void
process_lock_agent(SocketEntry *e, int lock)
{
char *passwd;
int success = 0;
passwd = buffer_get_string(&e->request, NULL);
if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
locked = 0;
memset(lock_passwd, 0, strlen(lock_passwd));
xfree(lock_passwd);
lock_passwd = NULL;
success = 1;
} else if (!locked && lock) {
locked = 1;
lock_passwd = xstrdup(passwd);
success = 1;
}
memset(passwd, 0, strlen(passwd));
xfree(passwd);
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
static void
no_identities(SocketEntry *e, u_int type)
{
Buffer msg;
buffer_init(&msg);
buffer_put_char(&msg,
(type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ?
SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
buffer_put_int(&msg, 0);
buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
buffer_free(&msg);
}
#ifdef SMARTCARD
static void
process_add_smartcard_key (SocketEntry *e)
{
Identity *id;
Idtab *tab;
Key *n = NULL, *k = NULL;
char *sc_reader_id = NULL;
int success = 0;
Key **keys, *k;
char *sc_reader_id = NULL, *pin;
int i, version, success = 0;
sc_reader_id = buffer_get_string(&e->input, NULL);
k = sc_get_key(sc_reader_id);
sc_reader_id = buffer_get_string(&e->request, NULL);
pin = buffer_get_string(&e->request, NULL);
keys = sc_get_keys(sc_reader_id, pin);
xfree(sc_reader_id);
xfree(pin);
if (k == NULL) {
error("sc_get_pubkey failed");
if (keys == NULL || keys[0] == NULL) {
error("sc_get_keys failed");
goto send;
}
success = 1;
tab = idtab_lookup(1);
k->type = KEY_RSA1;
if (lookup_identity(k, 1) == NULL) {
Identity *id = xmalloc(sizeof(Identity));
n = key_new(KEY_RSA1);
BN_copy(n->rsa->n, k->rsa->n);
BN_copy(n->rsa->e, k->rsa->e);
RSA_set_method(n->rsa, sc_get_engine());
id->key = n;
id->comment = xstrdup("rsa1 smartcard");
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
tab->nentries++;
for (i = 0; keys[i] != NULL; i++) {
k = keys[i];
version = k->type == KEY_RSA1 ? 1 : 2;
tab = idtab_lookup(version);
if (lookup_identity(k, version) == NULL) {
id = xmalloc(sizeof(Identity));
id->key = k;
id->comment = xstrdup("smartcard key");
id->death = 0;
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
tab->nentries++;
success = 1;
} else {
key_free(k);
}
keys[i] = NULL;
}
k->type = KEY_RSA;
tab = idtab_lookup(2);
if (lookup_identity(k, 2) == NULL) {
Identity *id = xmalloc(sizeof(Identity));
n = key_new(KEY_RSA);
BN_copy(n->rsa->n, k->rsa->n);
BN_copy(n->rsa->e, k->rsa->e);
RSA_set_method(n->rsa, sc_get_engine());
id->key = n;
id->comment = xstrdup("rsa smartcard");
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
tab->nentries++;
}
key_free(k);
xfree(keys);
send:
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
@ -495,39 +563,37 @@ process_add_smartcard_key (SocketEntry *e)
static void
process_remove_smartcard_key(SocketEntry *e)
{
Key *k = NULL;
int success = 0;
char *sc_reader_id = NULL;
Identity *id;
Idtab *tab;
Key **keys, *k = NULL;
char *sc_reader_id = NULL, *pin;
int i, version, success = 0;
sc_reader_id = buffer_get_string(&e->input, NULL);
k = sc_get_key(sc_reader_id);
sc_reader_id = buffer_get_string(&e->request, NULL);
pin = buffer_get_string(&e->request, NULL);
keys = sc_get_keys(sc_reader_id, pin);
xfree(sc_reader_id);
xfree(pin);
if (k == NULL) {
error("sc_get_pubkey failed");
} else {
Identity *id;
k->type = KEY_RSA1;
id = lookup_identity(k, 1);
if (id != NULL) {
Idtab *tab = idtab_lookup(1);
if (keys == NULL || keys[0] == NULL) {
error("sc_get_keys failed");
goto send;
}
for (i = 0; keys[i] != NULL; i++) {
k = keys[i];
version = k->type == KEY_RSA1 ? 1 : 2;
if ((id = lookup_identity(k, version)) != NULL) {
tab = idtab_lookup(version);
TAILQ_REMOVE(&tab->idlist, id, next);
free_identity(id);
tab->nentries--;
success = 1;
}
k->type = KEY_RSA;
id = lookup_identity(k, 2);
if (id != NULL) {
Idtab *tab = idtab_lookup(2);
TAILQ_REMOVE(&tab->idlist, id, next);
free_identity(id);
tab->nentries--;
success = 1;
}
key_free(k);
keys[i] = NULL;
}
xfree(keys);
send:
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
@ -542,6 +608,10 @@ process_message(SocketEntry *e)
u_int msg_len;
u_int type;
u_char *cp;
/* kill dead keys */
reaper();
if (buffer_len(&e->input) < 5)
return; /* Incomplete message. */
cp = buffer_ptr(&e->input);
@ -550,15 +620,44 @@ process_message(SocketEntry *e)
shutdown(e->fd, SHUT_RDWR);
close(e->fd);
e->type = AUTH_UNUSED;
buffer_free(&e->input);
buffer_free(&e->output);
buffer_free(&e->request);
return;
}
if (buffer_len(&e->input) < msg_len + 4)
return;
/* move the current input to e->request */
buffer_consume(&e->input, 4);
type = buffer_get_char(&e->input);
buffer_clear(&e->request);
buffer_append(&e->request, buffer_ptr(&e->input), msg_len);
buffer_consume(&e->input, msg_len);
type = buffer_get_char(&e->request);
/* check wheter agent is locked */
if (locked && type != SSH_AGENTC_UNLOCK) {
buffer_clear(&e->request);
switch (type) {
case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
case SSH2_AGENTC_REQUEST_IDENTITIES:
/* send empty lists */
no_identities(e, type);
break;
default:
/* send a fail message for all other request types */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_FAILURE);
}
return;
}
debug("type %d", type);
switch (type) {
case SSH_AGENTC_LOCK:
case SSH_AGENTC_UNLOCK:
process_lock_agent(e, type == SSH_AGENTC_LOCK);
break;
/* ssh1 */
case SSH_AGENTC_RSA_CHALLENGE:
process_authentication_challenge1(e);
@ -567,6 +666,7 @@ process_message(SocketEntry *e)
process_request_identities(e, 1);
break;
case SSH_AGENTC_ADD_RSA_IDENTITY:
case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
process_add_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
@ -583,6 +683,7 @@ process_message(SocketEntry *e)
process_request_identities(e, 2);
break;
case SSH2_AGENTC_ADD_IDENTITY:
case SSH2_AGENTC_ADD_ID_CONSTRAINED:
process_add_identity(e, 2);
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
@ -602,7 +703,7 @@ process_message(SocketEntry *e)
default:
/* Unknown message. Respond with failure. */
error("Unknown message %d", type);
buffer_clear(&e->input);
buffer_clear(&e->request);
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_FAILURE);
break;
@ -625,6 +726,7 @@ new_socket(sock_type type, int fd)
sockets[i].type = type;
buffer_init(&sockets[i].input);
buffer_init(&sockets[i].output);
buffer_init(&sockets[i].request);
return;
}
old_alloc = sockets_alloc;
@ -639,6 +741,7 @@ new_socket(sock_type type, int fd)
sockets[old_alloc].fd = fd;
buffer_init(&sockets[old_alloc].input);
buffer_init(&sockets[old_alloc].output);
buffer_init(&sockets[old_alloc].request);
}
static int
@ -736,6 +839,7 @@ after_select(fd_set *readset, fd_set *writeset)
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
buffer_free(&sockets[i].request);
break;
}
buffer_consume(&sockets[i].output, len);
@ -754,6 +858,7 @@ after_select(fd_set *readset, fd_set *writeset)
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
buffer_free(&sockets[i].request);
break;
}
buffer_append(&sockets[i].input, buf, len);
@ -812,6 +917,7 @@ usage(void)
fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n");
fprintf(stderr, " -k Kill the current agent.\n");
fprintf(stderr, " -d Debug mode.\n");
fprintf(stderr, " -a socket Bind agent socket to given name.\n");
exit(1);
}
@ -823,12 +929,13 @@ main(int ac, char **av)
struct rlimit rlim;
pid_t pid;
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
char *agentsocket = NULL;
extern int optind;
fd_set *readsetp = NULL, *writesetp = NULL;
SSLeay_add_all_algorithms();
while ((ch = getopt(ac, av, "cdks")) != -1) {
while ((ch = getopt(ac, av, "cdksa:")) != -1) {
switch (ch) {
case 'c':
if (s_flag)
@ -848,6 +955,9 @@ main(int ac, char **av)
usage();
d_flag++;
break;
case 'a':
agentsocket = optarg;
break;
default:
usage();
}
@ -858,7 +968,7 @@ main(int ac, char **av)
if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
usage();
if (ac == 0 && !c_flag && !k_flag && !s_flag && !d_flag) {
if (ac == 0 && !c_flag && !s_flag) {
shell = getenv("SHELL");
if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
c_flag = 1;
@ -883,19 +993,25 @@ main(int ac, char **av)
format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %d killed;\n", pid);
printf("echo Agent pid %ld killed;\n", (long)pid);
exit(0);
}
parent_pid = getpid();
/* Create private directory for agent socket */
strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
if (mkdtemp(socket_dir) == NULL) {
perror("mkdtemp: private socket dir");
exit(1);
if (agentsocket == NULL) {
/* Create private directory for agent socket */
strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
if (mkdtemp(socket_dir) == NULL) {
perror("mkdtemp: private socket dir");
exit(1);
}
snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
(long)parent_pid);
} else {
/* Try to use specified agent socket */
socket_dir[0] = '\0';
strlcpy(socket_name, agentsocket, sizeof socket_name);
}
snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
parent_pid);
/*
* Create socket early so it will exist before command gets run from
@ -928,7 +1044,7 @@ main(int ac, char **av)
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf("echo Agent pid %d;\n", parent_pid);
printf("echo Agent pid %ld;\n", (long)parent_pid);
goto skip;
}
pid = fork();
@ -938,14 +1054,14 @@ main(int ac, char **av)
}
if (pid != 0) { /* Parent - execute the given command. */
close(sock);
snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
if (ac == 0) {
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %d;\n", pid);
printf("echo Agent pid %ld;\n", (long)pid);
exit(0);
}
if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||

View File

@ -13,6 +13,7 @@
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 1999 Niels Provos. All rights reserved.
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
* Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
* in Canada (German citizen).
@ -39,7 +40,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh.c,v 1.164 2002/02/14 23:28:00 markus Exp $");
RCSID("$OpenBSD: ssh.c,v 1.179 2002/06/12 01:09:52 markus Exp $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
@ -53,7 +54,6 @@ RCSID("$FreeBSD$");
#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
#include "uidswap.h"
#include "channels.h"
#include "key.h"
#include "authfd.h"
@ -71,7 +71,6 @@ RCSID("$FreeBSD$");
#include "sshtty.h"
#ifdef SMARTCARD
#include <openssl/engine.h>
#include "scard.h"
#endif
@ -100,7 +99,7 @@ int stdin_null_flag = 0;
/*
* Flag indicating that ssh should fork after authentication. This is useful
* so that the pasphrase can be entered manually, and then ssh goes to the
* so that the passphrase can be entered manually, and then ssh goes to the
* background.
*/
int fork_after_authentication_flag = 0;
@ -125,13 +124,11 @@ char *host;
struct sockaddr_storage hostaddr;
/* Private host keys. */
struct {
Key **keys;
int nkeys;
} sensitive_data;
Sensitive sensitive_data;
/* Original real UID. */
uid_t original_real_uid;
uid_t original_effective_uid;
/* command to be executed */
Buffer command;
@ -139,6 +136,9 @@ Buffer command;
/* Should we execute a command or invoke a subsystem? */
int subsystem_flag = 0;
/* # of replies received for global requests */
static int client_global_request_id = 0;
/* Prints a help message to the user. This function never returns. */
static void
@ -193,47 +193,6 @@ usage(void)
exit(1);
}
/*
* Connects to the given host using rsh (or prints an error message and exits
* if rsh is not available). This function never returns.
*/
static void
rsh_connect(char *host, char *user, Buffer * command)
{
char *args[10];
int i;
log("Using rsh. WARNING: Connection will not be encrypted.");
/* Build argument list for rsh. */
i = 0;
#ifndef _PATH_RSH
#define _PATH_RSH "/usr/bin/rsh"
#endif
args[i++] = _PATH_RSH;
/* host may have to come after user on some systems */
args[i++] = host;
if (user) {
args[i++] = "-l";
args[i++] = user;
}
if (buffer_len(command) > 0) {
buffer_append(command, "\0", 1);
args[i++] = buffer_ptr(command);
}
args[i++] = NULL;
if (debug_flag) {
for (i = 0; args[i]; i++) {
if (i != 0)
fprintf(stderr, " ");
fprintf(stderr, "%s", args[i]);
}
fprintf(stderr, "\n");
}
execv(_PATH_RSH, args);
perror(_PATH_RSH);
exit(1);
}
static int ssh_session(void);
static int ssh_session2(void);
static void load_public_identity_files(void);
@ -244,14 +203,13 @@ static void load_public_identity_files(void);
int
main(int ac, char **av)
{
int i, opt, exit_status, cerr;
int i, opt, exit_status;
u_short fwd_port, fwd_host_port;
char sfwd_port[6], sfwd_host_port[6];
char *p, *cp, buf[256];
struct stat st;
struct passwd *pw;
int dummy;
uid_t original_effective_uid;
extern int optind, optreset;
extern char *optarg;
@ -285,7 +243,7 @@ main(int ac, char **av)
* them when the port has been created (actually, when the connection
* has been made, as we may need to create the port several times).
*/
temporarily_use_uid(pw);
PRIV_END;
/*
* Set our umask to something reasonable, as some files are created
@ -466,7 +424,7 @@ main(int ac, char **av)
/* NOTREACHED */
}
if ((fwd_port = a2port(sfwd_port)) == 0 ||
(fwd_host_port = a2port(sfwd_host_port)) == 0) {
(fwd_host_port = a2port(sfwd_host_port)) == 0) {
fprintf(stderr,
"Bad forwarding port(s) '%s'\n", optarg);
exit(1);
@ -650,52 +608,48 @@ main(int ac, char **av)
"originating port will not be trusted.");
options.rhosts_authentication = 0;
}
/*
* If using rsh has been selected, exec it now (without trying
* anything else). Note that we must release privileges first.
*/
if (options.use_rsh) {
/*
* Restore our superuser privileges. This must be done
* before permanently setting the uid.
*/
restore_uid();
/* Switch to the original uid permanently. */
permanently_set_uid(pw);
/* Execute rsh. */
rsh_connect(host, options.user, &command);
fatal("rsh_connect returned");
}
/* Restore our superuser privileges. */
restore_uid();
/* Open a connection to the remote host. */
cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6,
if (ssh_connect(host, &hostaddr, options.port, IPv4or6,
options.connection_attempts,
original_effective_uid != 0 || !options.use_privileged_port,
pw, options.proxy_command);
original_effective_uid == 0 && options.use_privileged_port,
options.proxy_command) != 0)
exit(1);
/*
* If we successfully made the connection, load the host private key
* in case we will need it later for combined rsa-rhosts
* authentication. This must be done before releasing extra
* privileges, because the file is only readable by root.
* If we cannot access the private keys, load the public keys
* instead and try to execute the ssh-keysign helper instead.
*/
sensitive_data.nkeys = 0;
sensitive_data.keys = NULL;
if (!cerr && (options.rhosts_rsa_authentication ||
options.hostbased_authentication)) {
sensitive_data.external_keysign = 0;
if (options.rhosts_rsa_authentication ||
options.hostbased_authentication) {
sensitive_data.nkeys = 3;
sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
PRIV_START;
sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
_PATH_HOST_KEY_FILE, "", NULL);
sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
_PATH_HOST_DSA_KEY_FILE, "", NULL);
sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
_PATH_HOST_RSA_KEY_FILE, "", NULL);
PRIV_END;
if (sensitive_data.keys[0] == NULL &&
sensitive_data.keys[1] == NULL &&
sensitive_data.keys[2] == NULL) {
sensitive_data.keys[1] = key_load_public(
_PATH_HOST_DSA_KEY_FILE, NULL);
sensitive_data.keys[2] = key_load_public(
_PATH_HOST_RSA_KEY_FILE, NULL);
sensitive_data.external_keysign = 1;
}
}
/*
* Get rid of any extra privileges that we may have. We will no
@ -704,15 +658,8 @@ main(int ac, char **av)
* user's home directory if it happens to be on a NFS volume where
* root is mapped to nobody.
*/
/*
* Note that some legacy systems need to postpone the following call
* to permanently_set_uid() until the private hostkey is destroyed
* with RSA_free(). Otherwise the calling user could ptrace() the
* process, read the private hostkey and impersonate the host.
* OpenBSD does not allow ptracing of setuid processes.
*/
permanently_set_uid(pw);
seteuid(original_real_uid);
setuid(original_real_uid);
/*
* Now that we are back to our own permissions, create ~/.ssh
@ -723,21 +670,6 @@ main(int ac, char **av)
if (mkdir(buf, 0700) < 0)
error("Could not create directory '%.200s'.", buf);
/* Check if the connection failed, and try "rsh" if appropriate. */
if (cerr) {
if (!options.fallback_to_rsh)
exit(1);
if (options.port != 0)
log("Secure connection to %.100s on port %hu refused; "
"reverting to insecure method",
host, options.port);
else
log("Secure connection to %.100s refused; "
"reverting to insecure method.", host);
rsh_connect(host, options.user, &command);
fatal("rsh_connect returned");
}
/* load options.identity_files */
load_public_identity_files();
@ -755,8 +687,7 @@ main(int ac, char **av)
signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
/* Log into the remote system. This never returns if the login fails. */
ssh_login(sensitive_data.keys, sensitive_data.nkeys,
host, (struct sockaddr *)&hostaddr, pw);
ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw);
/* We no longer need the private host keys. Clear them now. */
if (sensitive_data.nkeys != 0) {
@ -808,10 +739,10 @@ x11_get_proto(char **_proto, char **_data)
* XXX: "localhost" match to determine FamilyLocal
* is not perfect.
*/
snprintf(line, sizeof line, "%.100s list unix:%s 2>"
snprintf(line, sizeof line, "%s list unix:%s 2>"
_PATH_DEVNULL, options.xauth_location, display+10);
else
snprintf(line, sizeof line, "%.100s list %.200s 2>"
snprintf(line, sizeof line, "%s list %.200s 2>"
_PATH_DEVNULL, options.xauth_location, display);
debug2("x11_get_proto %s", line);
f = popen(line, "r");
@ -1041,6 +972,27 @@ client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
len, (u_char *)buffer_ptr(&command), id);
}
void
client_global_request_reply(int type, u_int32_t seq, void *ctxt)
{
int i;
i = client_global_request_id++;
if (i >= options.num_remote_forwards) {
debug("client_global_request_reply: too many replies %d > %d",
i, options.num_remote_forwards);
return;
}
debug("remote forward %s for: listen %d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
options.remote_forwards[i].port,
options.remote_forwards[i].host,
options.remote_forwards[i].host_port);
if (type == SSH2_MSG_REQUEST_FAILURE)
log("Warning: remote port forwarding failed for listen port %d",
options.remote_forwards[i].port);
}
/* request pty/x11/agent/tcpfwd/shell for channel */
static void
ssh_session2_setup(int id, void *arg)
@ -1100,7 +1052,7 @@ ssh_session2_setup(int id, void *arg)
debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command));
channel_request_start(id, "subsystem", /*want reply*/ 1);
/* register callback for reply */
/* XXX we asume that client_loop has already been called */
/* XXX we assume that client_loop has already been called */
dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply);
dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply);
} else {
@ -1187,40 +1139,29 @@ static void
load_public_identity_files(void)
{
char *filename;
Key *public;
int i = 0;
Key *public;
#ifdef SMARTCARD
Key **keys;
if (options.smartcard_device != NULL &&
options.num_identity_files + 1 < SSH_MAX_IDENTITY_FILES &&
(public = sc_get_key(options.smartcard_device)) != NULL ) {
Key *new;
if (options.num_identity_files + 2 > SSH_MAX_IDENTITY_FILES)
options.num_identity_files = SSH_MAX_IDENTITY_FILES - 2;
memmove(&options.identity_files[2], &options.identity_files[0],
sizeof(char *) * options.num_identity_files);
options.num_identity_files += 2;
i = 2;
/* XXX ssh1 vs ssh2 */
new = key_new(KEY_RSA);
new->flags = KEY_FLAG_EXT;
BN_copy(new->rsa->n, public->rsa->n);
BN_copy(new->rsa->e, public->rsa->e);
RSA_set_method(new->rsa, sc_get_engine());
options.identity_keys[0] = new;
options.identity_files[0] = xstrdup("smartcard rsa key");;
new = key_new(KEY_RSA1);
new->flags = KEY_FLAG_EXT;
BN_copy(new->rsa->n, public->rsa->n);
BN_copy(new->rsa->e, public->rsa->e);
RSA_set_method(new->rsa, sc_get_engine());
options.identity_keys[1] = new;
options.identity_files[1] = xstrdup("smartcard rsa1 key");
key_free(public);
options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
(keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) {
int count = 0;
for (i = 0; keys[i] != NULL; i++) {
count++;
memmove(&options.identity_files[1], &options.identity_files[0],
sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
memmove(&options.identity_keys[1], &options.identity_keys[0],
sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
options.num_identity_files++;
options.identity_keys[0] = keys[i];
options.identity_files[0] = xstrdup("smartcard key");;
}
if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
options.num_identity_files = SSH_MAX_IDENTITY_FILES;
i = count;
xfree(keys);
}
#endif /* SMARTCARD */
for (; i < options.num_identity_files; i++) {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.h,v 1.64 2002/03/04 17:27:39 stevesk Exp $ */
/* $OpenBSD: ssh.h,v 1.70 2002/06/03 12:04:07 deraadt Exp $ */
/* $FreeBSD$ */
/*
@ -32,7 +32,7 @@
#define SSH_MAX_IDENTITY_FILES 100
/*
* Major protocol version. Different version indicates major incompatiblity
* Major protocol version. Different version indicates major incompatibility
* that prevents communication.
*
* Minor protocol version. Different version indicates minor incompatibility
@ -86,6 +86,16 @@
/* Used to identify ``EscapeChar none'' */
#define SSH_ESCAPECHAR_NONE -2
/*
* unprivileged user when UsePrivilegeSeparation=yes;
* sshd will change its privileges to this user and its
* primary group.
*/
#define SSH_PRIVSEP_USER "sshd"
/* Minimum modulus size (n) for RSA keys. */
#define SSH_RSA_MINIMUM_MODULUS_SIZE 768
#ifdef USE_PAM
#include "auth-pam.h"
#endif /* USE_PAM */

View File

@ -1,10 +1,10 @@
# $OpenBSD: ssh_config,v 1.12 2002/01/16 17:55:33 stevesk Exp $
# $FreeBSD$
# $OpenBSD: ssh_config,v 1.15 2002/06/20 20:03:34 stevesk Exp $
# $FreeBSD$
# This is the ssh client system-wide configuration file. See ssh(1)
# for more information. This file provides defaults for users, and
# the values can be changed in per-user configuration files or on the
# command line.
# This is the ssh client system-wide configuration file. See
# ssh_config(5) for more information. This file provides defaults for
# users, and the values can be changed in per-user configuration files
# or on the command line.
# Configuration data is parsed as follows:
# 1. command line options
@ -19,12 +19,10 @@
# Host *
# ForwardAgent no
# ForwardX11 no
# RhostsAuthentication yes
# RhostsRSAAuthentication yes
# RhostsAuthentication no
# RhostsRSAAuthentication no
# RSAAuthentication yes
# PasswordAuthentication yes
# FallBackToRsh no
# UseRsh no
# BatchMode no
# CheckHostIP yes
# StrictHostKeyChecking ask

View File

@ -13,7 +13,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect.c,v 1.119 2002/01/21 15:13:51 markus Exp $");
RCSID("$OpenBSD: sshconnect.c,v 1.125 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
@ -37,27 +37,20 @@ RCSID("$FreeBSD$");
char *client_version_string = NULL;
char *server_version_string = NULL;
/* import */
extern Options options;
extern char *__progname;
extern uid_t original_real_uid;
extern uid_t original_effective_uid;
static const char *
sockaddr_ntop(struct sockaddr *sa)
sockaddr_ntop(struct sockaddr *sa, socklen_t salen)
{
void *addr;
static char addrbuf[INET6_ADDRSTRLEN];
static char addrbuf[NI_MAXHOST];
switch (sa->sa_family) {
case AF_INET:
addr = &((struct sockaddr_in *)sa)->sin_addr;
break;
case AF_INET6:
addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
break;
default:
/* This case should be protected against elsewhere */
abort(); /* XXX abort is bad -- do something else */
}
inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf));
if (getnameinfo(sa, salen, addrbuf, sizeof(addrbuf), NULL, 0,
NI_NUMERICHOST) != 0)
fatal("sockaddr_ntop: getnameinfo NI_NUMERICHOST failed");
return addrbuf;
}
@ -65,8 +58,7 @@ sockaddr_ntop(struct sockaddr *sa)
* Connect to the given ssh server using a proxy command.
*/
static int
ssh_proxy_connect(const char *host, u_short port, struct passwd *pw,
const char *proxy_command)
ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
{
Buffer command;
const char *cp;
@ -116,7 +108,8 @@ ssh_proxy_connect(const char *host, u_short port, struct passwd *pw,
char *argv[10];
/* Child. Permanently give up superuser privileges. */
permanently_set_uid(pw);
seteuid(original_real_uid);
setuid(original_real_uid);
/* Redirect stdin and stdout. */
close(pin[1]);
@ -166,7 +159,7 @@ ssh_proxy_connect(const char *host, u_short port, struct passwd *pw,
* Creates a (possibly privileged) socket for use as the ssh connection.
*/
static int
ssh_create_socket(struct passwd *pw, int privileged, int family)
ssh_create_socket(int privileged, int family)
{
int sock, gaierr;
struct addrinfo hints, *res;
@ -177,22 +170,18 @@ ssh_create_socket(struct passwd *pw, int privileged, int family)
*/
if (privileged) {
int p = IPPORT_RESERVED - 1;
PRIV_START;
sock = rresvport_af(&p, family);
PRIV_END;
if (sock < 0)
error("rresvport: af=%d %.100s", family, strerror(errno));
else
debug("Allocated local port %d.", p);
return sock;
}
/*
* Just create an ordinary socket on arbitrary port. We use
* the user's uid to create the socket.
*/
temporarily_use_uid(pw);
sock = socket(family, SOCK_STREAM, 0);
if (sock < 0)
error("socket: %.100s", strerror(errno));
restore_uid();
/* Bind the socket to an alternative local IP address */
if (options.bind_address == NULL)
@ -222,9 +211,9 @@ ssh_create_socket(struct passwd *pw, int privileged, int family)
/*
* Opens a TCP/IP connection to the remote server on the given host.
* The address of the remote host will be returned in hostaddr.
* If port is 0, the default port will be used. If anonymous is zero,
* If port is 0, the default port will be used. If needpriv is true,
* a privileged port will be allocated to make the connection.
* This requires super-user privileges if anonymous is false.
* This requires super-user privileges if needpriv is true.
* Connection_attempts specifies the maximum number of tries (one per
* second). If proxy_command is non-NULL, it specifies the command (with %h
* and %p substituted for host and port, respectively) to use to contact
@ -239,7 +228,7 @@ ssh_create_socket(struct passwd *pw, int privileged, int family)
int
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
u_short port, int family, int connection_attempts,
int anonymous, struct passwd *pw, const char *proxy_command)
int needpriv, const char *proxy_command)
{
int gaierr;
int on = 1;
@ -255,8 +244,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
*/
int full_failure = 1;
debug("ssh_connect: getuid %u geteuid %u anon %d",
(u_int) getuid(), (u_int) geteuid(), anonymous);
debug("ssh_connect: needpriv %d", needpriv);
/* Get default port if port has not been set. */
if (port == 0) {
@ -268,7 +256,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
}
/* If a proxy command is given, connect using it. */
if (proxy_command != NULL)
return ssh_proxy_connect(host, port, pw, proxy_command);
return ssh_proxy_connect(host, port, proxy_command);
/* No proxy command. */
@ -304,30 +292,21 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
host, ntop, strport);
/* Create a socket for connecting. */
sock = ssh_create_socket(pw,
!anonymous && geteuid() == 0,
ai->ai_family);
sock = ssh_create_socket(needpriv, ai->ai_family);
if (sock < 0)
/* Any error is already output */
continue;
/* Connect to the host. We use the user's uid in the
* hope that it will help with tcp_wrappers showing
* the remote uid as root.
*/
temporarily_use_uid(pw);
if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
/* Successful connection. */
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
restore_uid();
break;
} else {
if (errno == ECONNREFUSED)
full_failure = 0;
log("ssh: connect to address %s port %s: %s",
sockaddr_ntop(ai->ai_addr), strport,
strerror(errno));
restore_uid();
sockaddr_ntop(ai->ai_addr, ai->ai_addrlen),
strport, strerror(errno));
/*
* Close the failed socket; there appear to
* be some problems when reusing a socket for
@ -785,7 +764,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
len = strlen(msg);
snprintf(msg + len, sizeof(msg) - len,
"\nMatching host key in %s:%d",
host_file, host_line);
host_file, host_line);
}
if (options.strict_host_key_checking == 1) {
log(msg);
@ -833,7 +812,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
* This function does not require super-user privileges.
*/
void
ssh_login(Key **keys, int nkeys, const char *orighost,
ssh_login(Sensitive *sensitive, const char *orighost,
struct sockaddr *hostaddr, struct passwd *pw)
{
char *host, *cp;
@ -858,10 +837,10 @@ ssh_login(Key **keys, int nkeys, const char *orighost,
/* authenticate user */
if (compat20) {
ssh_kex2(host, hostaddr);
ssh_userauth2(local_user, server_user, host, keys, nkeys);
ssh_userauth2(local_user, server_user, host, sensitive);
} else {
ssh_kex(host, hostaddr);
ssh_userauth1(local_user, server_user, host, keys, nkeys);
ssh_userauth1(local_user, server_user, host, sensitive);
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.h,v 1.13 2001/10/08 19:05:05 markus Exp $ */
/* $OpenBSD: sshconnect.h,v 1.17 2002/06/19 00:27:55 deraadt Exp $ */
/* $FreeBSD$ */
/*
@ -27,21 +27,44 @@
#ifndef SSHCONNECT_H
#define SSHCONNECT_H
typedef struct Sensitive Sensitive;
struct Sensitive {
Key **keys;
int nkeys;
int external_keysign;
};
int
ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int,
int, struct passwd *, const char *);
int, const char *);
void
ssh_login(Key **, int, const char *, struct sockaddr *, struct passwd *);
ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *);
int verify_host_key(char *, struct sockaddr *, Key *);
void ssh_kex(char *, struct sockaddr *);
void ssh_kex2(char *, struct sockaddr *);
void ssh_userauth1(const char *, const char *, char *, Key **, int);
void ssh_userauth2(const char *, const char *, char *, Key **, int);
void ssh_userauth1(const char *, const char *, char *, Sensitive *);
void ssh_userauth2(const char *, const char *, char *, Sensitive *);
void ssh_put_password(char *);
/*
* Macros to raise/lower permissions.
*/
#define PRIV_START do { \
int save_errno = errno; \
(void)seteuid(original_effective_uid); \
errno = save_errno; \
} while (0)
#define PRIV_END do { \
int save_errno = errno; \
(void)seteuid(original_real_uid); \
errno = save_errno; \
} while (0)
#endif

View File

@ -13,7 +13,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect1.c,v 1.48 2002/02/11 16:15:46 markus Exp $");
RCSID("$OpenBSD: sshconnect1.c,v 1.51 2002/05/23 19:24:30 markus Exp $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
@ -460,6 +460,8 @@ try_krb4_authentication(void)
/* Get server's response. */
reply = packet_get_string((u_int *) &auth.length);
if (auth.length >= MAX_KTXT_LEN)
fatal("Kerberos v4: Malformed response from server");
memcpy(auth.dat, reply, auth.length);
xfree(reply);
@ -844,7 +846,7 @@ try_challenge_response_authentication(void)
error("Permission denied, please try again.");
if (options.cipher == SSH_CIPHER_NONE)
log("WARNING: Encryption is disabled! "
"Reponse will be transmitted in clear text.");
"Response will be transmitted in clear text.");
response = read_passphrase(prompt, 0);
if (strcmp(response, "") == 0) {
xfree(response);
@ -1091,7 +1093,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
*/
void
ssh_userauth1(const char *local_user, const char *server_user, char *host,
Key **keys, int nkeys)
Sensitive *sensitive)
{
#ifdef KRB5
krb5_context context = NULL;
@ -1177,9 +1179,11 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host,
*/
if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
options.rhosts_rsa_authentication) {
for (i = 0; i < nkeys; i++) {
if (keys[i] != NULL && keys[i]->type == KEY_RSA1 &&
try_rhosts_rsa_authentication(local_user, keys[i]))
for (i = 0; i < sensitive->nkeys; i++) {
if (sensitive->keys[i] != NULL &&
sensitive->keys[i]->type == KEY_RSA1 &&
try_rhosts_rsa_authentication(local_user,
sensitive->keys[i]))
goto success;
}
}

View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect2.c,v 1.97 2002/02/25 16:33:27 markus Exp $");
RCSID("$OpenBSD: sshconnect2.c,v 1.104 2002/06/19 00:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
@ -46,6 +46,8 @@ RCSID("$FreeBSD$");
#include "match.h"
#include "dispatch.h"
#include "canohost.h"
#include "msg.h"
#include "pathnames.h"
/* import */
extern char *client_version_string;
@ -155,8 +157,7 @@ struct Authctxt {
int last_key_hint;
AuthenticationConnection *agent;
/* hostbased */
Key **keys;
int nkeys;
Sensitive *sensitive;
/* kbd-interactive */
int info_req_seen;
};
@ -173,6 +174,7 @@ void input_userauth_banner(int, u_int32_t, void *);
void input_userauth_error(int, u_int32_t, void *);
void input_userauth_info_req(int, u_int32_t, void *);
void input_userauth_pk_ok(int, u_int32_t, void *);
void input_userauth_passwd_changereq(int, u_int32_t, void *);
int userauth_none(Authctxt *);
int userauth_pubkey(Authctxt *);
@ -215,7 +217,7 @@ Authmethod authmethods[] = {
void
ssh_userauth2(const char *local_user, const char *server_user, char *host,
Key **keys, int nkeys)
Sensitive *sensitive)
{
Authctxt authctxt;
int type;
@ -255,8 +257,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
authctxt.success = 0;
authctxt.method = authmethod_lookup("none");
authctxt.authlist = NULL;
authctxt.keys = keys;
authctxt.nkeys = nkeys;
authctxt.sensitive = sensitive;
authctxt.info_req_seen = 0;
if (authctxt.method == NULL)
fatal("ssh_userauth2: internal error: cannot send userauth none request");
@ -392,10 +393,10 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
debug("no key from blob. pkalg %s", pkalg);
break;
}
if (key->type != pktype) {
if (key->type != pktype) {
error("input_userauth_pk_ok: type mismatch "
"for decoded key (received %d, expected %d)",
key->type, pktype);
key->type, pktype);
break;
}
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
@ -440,7 +441,7 @@ int
userauth_passwd(Authctxt *authctxt)
{
static int attempt = 0;
char prompt[80];
char prompt[150];
char *password;
if (attempt++ >= options.number_of_password_prompts)
@ -462,13 +463,85 @@ userauth_passwd(Authctxt *authctxt)
xfree(password);
packet_add_padding(64);
packet_send();
dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
&input_userauth_passwd_changereq);
return 1;
}
/*
* parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
*/
void
input_userauth_passwd_changereq(int type, uint32_t seqnr, void *ctxt)
{
Authctxt *authctxt = ctxt;
char *info, *lang, *password = NULL, *retype = NULL;
char prompt[150];
debug2("input_userauth_passwd_changereq");
if (authctxt == NULL)
fatal("input_userauth_passwd_changereq: "
"no authentication context");
info = packet_get_string(NULL);
lang = packet_get_string(NULL);
if (strlen(info) > 0)
log("%s", info);
xfree(info);
xfree(lang);
packet_start(SSH2_MSG_USERAUTH_REQUEST);
packet_put_cstring(authctxt->server_user);
packet_put_cstring(authctxt->service);
packet_put_cstring(authctxt->method->name);
packet_put_char(1); /* additional info */
snprintf(prompt, sizeof(prompt),
"Enter %.30s@%.128s's old password: ",
authctxt->server_user, authctxt->host);
password = read_passphrase(prompt, 0);
packet_put_cstring(password);
memset(password, 0, strlen(password));
xfree(password);
password = NULL;
while (password == NULL) {
snprintf(prompt, sizeof(prompt),
"Enter %.30s@%.128s's new password: ",
authctxt->server_user, authctxt->host);
password = read_passphrase(prompt, RP_ALLOW_EOF);
if (password == NULL) {
/* bail out */
return;
}
snprintf(prompt, sizeof(prompt),
"Retype %.30s@%.128s's new password: ",
authctxt->server_user, authctxt->host);
retype = read_passphrase(prompt, 0);
if (strcmp(password, retype) != 0) {
memset(password, 0, strlen(password));
xfree(password);
log("Mismatch; try again, EOF to quit.");
password = NULL;
}
memset(retype, 0, strlen(retype));
xfree(retype);
}
packet_put_cstring(password);
memset(password, 0, strlen(password));
xfree(password);
packet_add_padding(64);
packet_send();
dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
&input_userauth_passwd_changereq);
}
static void
clear_auth_state(Authctxt *authctxt)
{
/* XXX clear authentication state */
dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL);
if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
debug3("clear_auth_state: key_free %p", authctxt->last_key);
key_free(authctxt->last_key);
@ -821,14 +894,88 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
packet_send();
}
/*
* this will be move to an external program (ssh-keysign) ASAP. ssh-keysign
* will be setuid-root and the sbit can be removed from /usr/bin/ssh.
*/
static int
ssh_keysign(
Key *key,
u_char **sigp, u_int *lenp,
u_char *data, u_int datalen)
{
Buffer b;
struct stat st;
pid_t pid;
int to[2], from[2], status, version = 2;
debug("ssh_keysign called");
if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
error("ssh_keysign: no installed: %s", strerror(errno));
return -1;
}
if (fflush(stdout) != 0)
error("ssh_keysign: fflush: %s", strerror(errno));
if (pipe(to) < 0) {
error("ssh_keysign: pipe: %s", strerror(errno));
return -1;
}
if (pipe(from) < 0) {
error("ssh_keysign: pipe: %s", strerror(errno));
return -1;
}
if ((pid = fork()) < 0) {
error("ssh_keysign: fork: %s", strerror(errno));
return -1;
}
if (pid == 0) {
seteuid(getuid());
setuid(getuid());
close(from[0]);
if (dup2(from[1], STDOUT_FILENO) < 0)
fatal("ssh_keysign: dup2: %s", strerror(errno));
close(to[1]);
if (dup2(to[0], STDIN_FILENO) < 0)
fatal("ssh_keysign: dup2: %s", strerror(errno));
close(from[1]);
close(to[0]);
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN,
strerror(errno));
}
close(from[1]);
close(to[0]);
buffer_init(&b);
buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
buffer_put_string(&b, data, datalen);
msg_send(to[1], version, &b);
if (msg_recv(from[0], &b) < 0) {
error("ssh_keysign: no reply");
buffer_clear(&b);
return -1;
}
close(from[0]);
close(to[1]);
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR)
break;
if (buffer_get_char(&b) != version) {
error("ssh_keysign: bad version");
buffer_clear(&b);
return -1;
}
*sigp = buffer_get_string(&b, lenp);
buffer_clear(&b);
return 0;
}
int
userauth_hostbased(Authctxt *authctxt)
{
Key *private = NULL;
Sensitive *sensitive = authctxt->sensitive;
Buffer b;
u_char *signature, *blob;
char *chost, *pkalg, *p;
@ -837,12 +984,12 @@ userauth_hostbased(Authctxt *authctxt)
int ok, i, len, found = 0;
/* check for a useful key */
for (i = 0; i < authctxt->nkeys; i++) {
private = authctxt->keys[i];
for (i = 0; i < sensitive->nkeys; i++) {
private = sensitive->keys[i];
if (private && private->type != KEY_RSA1) {
found = 1;
/* we take and free the key */
authctxt->keys[i] = NULL;
sensitive->keys[i] = NULL;
break;
}
}
@ -884,7 +1031,12 @@ userauth_hostbased(Authctxt *authctxt)
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
ok = key_sign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
if (sensitive->external_keysign)
ok = ssh_keysign(private, &signature, &slen,
buffer_ptr(&b), buffer_len(&b));
else
ok = key_sign(private, &signature, &slen,
buffer_ptr(&b), buffer_len(&b));
key_free(private);
buffer_free(&b);
if (ok != 0) {

View File

@ -15,8 +15,10 @@
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation:
* Privilege Separation:
*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
* Copyright (c) 2002 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -40,12 +42,13 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshd.c,v 1.228 2002/02/27 21:23:13 stevesk Exp $");
RCSID("$OpenBSD: sshd.c,v 1.246 2002/06/20 23:05:56 markus Exp $");
RCSID("$FreeBSD$");
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
#include "ssh.h"
#include "ssh1.h"
@ -76,6 +79,11 @@ RCSID("$FreeBSD$");
#include "misc.h"
#include "dispatch.h"
#include "channels.h"
#include "session.h"
#include "monitor_mm.h"
#include "monitor.h"
#include "monitor_wrap.h"
#include "monitor_fdpass.h"
#ifdef LIBWRAP
#include <tcpd.h>
@ -184,8 +192,13 @@ u_int utmp_len = MAXHOSTNAMELEN;
int *startup_pipes = NULL;
int startup_pipe; /* in child */
/* variables used for privilege separation */
extern struct monitor *pmonitor;
extern int use_privsep;
/* Prototypes for various functions defined later in this file. */
void destroy_sensitive_data(void);
void demote_sensitive_data(void);
static void do_ssh1_kex(void);
static void do_ssh2_kex(void);
@ -258,10 +271,12 @@ sigterm_handler(int sig)
static void
main_sigchld_handler(int sig)
{
pid_t pid;
int save_errno = errno;
int status;
while (waitpid(-1, &status, WNOHANG) > 0)
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
;
signal(SIGCHLD, main_sigchld_handler);
@ -354,7 +369,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
fatal_cleanup();
}
/* Read other side's version identification. */
/* Read other sides version identification. */
memset(buf, 0, sizeof(buf));
for (i = 0; i < sizeof(buf) - 1; i++) {
if (atomicio(read, sock_in, &buf[i], 1) != 1) {
@ -472,6 +487,160 @@ destroy_sensitive_data(void)
memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
}
/* Demote private to public keys for network child */
void
demote_sensitive_data(void)
{
Key *tmp;
int i;
if (sensitive_data.server_key) {
tmp = key_demote(sensitive_data.server_key);
key_free(sensitive_data.server_key);
sensitive_data.server_key = tmp;
}
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
tmp = key_demote(sensitive_data.host_keys[i]);
key_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = tmp;
if (tmp->type == KEY_RSA1)
sensitive_data.ssh1_host_key = tmp;
}
}
/* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */
}
static void
privsep_preauth_child(void)
{
u_int32_t rand[256];
int i;
struct passwd *pw;
/* Enable challenge-response authentication for privilege separation */
privsep_challenge_enable();
for (i = 0; i < 256; i++)
rand[i] = arc4random();
RAND_seed(rand, sizeof(rand));
/* Demote the private keys to public keys. */
demote_sensitive_data();
if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
fatal("Privilege separation user %s does not exist",
SSH_PRIVSEP_USER);
memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
endpwent();
/* Change our root directory*/
if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
strerror(errno));
if (chdir("/") == -1)
fatal("chdir(\"/\"): %s", strerror(errno));
/* Drop our privileges */
debug3("privsep user:group %u:%u", (u_int)pw->pw_uid,
(u_int)pw->pw_gid);
do_setusercontext(pw);
}
static Authctxt*
privsep_preauth(void)
{
Authctxt *authctxt = NULL;
int status;
pid_t pid;
/* Set up unprivileged child process to deal with network data */
pmonitor = monitor_init();
/* Store a pointer to the kex for later rekeying */
pmonitor->m_pkex = &xxx_kex;
pid = fork();
if (pid == -1) {
fatal("fork of unprivileged child failed");
} else if (pid != 0) {
debug2("Network child is on pid %ld", (long)pid);
close(pmonitor->m_recvfd);
authctxt = monitor_child_preauth(pmonitor);
close(pmonitor->m_sendfd);
/* Sync memory */
monitor_sync(pmonitor);
/* Wait for the child's exit status */
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR)
break;
return (authctxt);
} else {
/* child */
close(pmonitor->m_sendfd);
/* Demote the child */
if (getuid() == 0 || geteuid() == 0)
privsep_preauth_child();
setproctitle("%s", "[net]");
}
return (NULL);
}
static void
privsep_postauth(Authctxt *authctxt)
{
extern Authctxt *x_authctxt;
/* XXX - Remote port forwarding */
x_authctxt = authctxt;
if (authctxt->pw->pw_uid == 0 || options.use_login) {
/* File descriptor passing is broken or root login */
monitor_apply_keystate(pmonitor);
use_privsep = 0;
return;
}
/* Authentication complete */
alarm(0);
if (startup_pipe != -1) {
close(startup_pipe);
startup_pipe = -1;
}
/* New socket pair */
monitor_reinit(pmonitor);
pmonitor->m_pid = fork();
if (pmonitor->m_pid == -1)
fatal("fork of unprivileged child failed");
else if (pmonitor->m_pid != 0) {
debug2("User child is on pid %ld", (long)pmonitor->m_pid);
close(pmonitor->m_recvfd);
monitor_child_postauth(pmonitor);
/* NEVERREACHED */
exit(0);
}
close(pmonitor->m_sendfd);
/* Demote the private keys to public keys. */
demote_sensitive_data();
/* Drop privileges */
do_setusercontext(authctxt->pw);
/* It is safe now to apply the key state */
monitor_apply_keystate(pmonitor);
}
static char *
list_hostkey_types(void)
{
@ -501,7 +670,7 @@ list_hostkey_types(void)
return p;
}
static Key *
Key *
get_hostkey_by_type(int type)
{
int i;
@ -513,6 +682,25 @@ get_hostkey_by_type(int type)
return NULL;
}
Key *
get_hostkey_by_index(int ind)
{
if (ind < 0 || ind >= options.num_host_key_files)
return (NULL);
return (sensitive_data.host_keys[ind]);
}
int
get_hostkey_index(Key *key)
{
int i;
for (i = 0; i < options.num_host_key_files; i++) {
if (key == sensitive_data.host_keys[i])
return (i);
}
return (-1);
}
/*
* returns 1 if connection should be dropped, 0 otherwise.
* dropping starts at connection #max_startups_begin with a probability
@ -589,6 +777,7 @@ main(int ac, char **av)
int listen_sock, maxfd;
int startup_p[2];
int startups = 0;
Authctxt *authctxt;
Key *key;
int ret, key_used = 0;
@ -787,6 +976,19 @@ main(int ac, char **av)
}
}
if (use_privsep) {
struct passwd *pw;
struct stat st;
if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
fatal("Privilege separation user %s does not exist",
SSH_PRIVSEP_USER);
if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
(S_ISDIR(st.st_mode) == 0))
fatal("Missing privilege separation directory: %s",
_PATH_PRIVSEP_CHROOT_DIR);
}
/* Configuration looks good, so exit if in test mode. */
if (test_flag)
exit(0);
@ -933,7 +1135,7 @@ main(int ac, char **av)
*/
f = fopen(options.pid_file, "w");
if (f) {
fprintf(f, "%u\n", (u_int) getpid());
fprintf(f, "%ld\n", (long) getpid());
fclose(f);
}
}
@ -1080,7 +1282,7 @@ main(int ac, char **av)
if (pid < 0)
error("fork: %.100s", strerror(errno));
else
debug("Forked child %d.", pid);
debug("Forked child %ld.", (long)pid);
close(startup_p[1]);
@ -1106,6 +1308,14 @@ main(int ac, char **av)
/* This is the child processing a new connection. */
/*
* Create a new session and process group since the 4.4BSD
* setlogin() affects the entire process group. We don't
* want the child to be able to affect the parent.
*/
if (setsid() < 0)
error("setsid: %.100s", strerror(errno));
/*
* Disable the key regeneration alarm. We will not regenerate the
* key since we are no longer in a position to give it to anyone. We
@ -1179,7 +1389,7 @@ main(int ac, char **av)
sshd_exchange_identification(sock_in, sock_out);
/*
* Check that the connection comes from a privileged port.
* Rhosts-Authentication only makes sense from priviledged
* Rhosts-Authentication only makes sense from privileged
* programs. Of course, if the intruder has root access on his local
* machine, he can connect from any port. So do not use these
* authentication methods from machines that you do not trust.
@ -1208,15 +1418,43 @@ main(int ac, char **av)
packet_set_nonblocking();
if (use_privsep)
if ((authctxt = privsep_preauth()) != NULL)
goto authenticated;
/* perform the key exchange */
/* authenticate user and start session */
if (compat20) {
do_ssh2_kex();
do_authentication2();
authctxt = do_authentication2();
} else {
do_ssh1_kex();
do_authentication();
authctxt = do_authentication();
}
/*
* If we use privilege separation, the unprivileged child transfers
* the current keystate and exits
*/
if (use_privsep) {
mm_send_keystate(pmonitor);
exit(0);
}
authenticated:
/*
* In privilege separation, we fork another child and prepare
* file descriptor passing.
*/
if (use_privsep) {
privsep_postauth(authctxt);
/* the monitor process [priv] will not return */
if (!compat20)
destroy_sensitive_data();
}
/* Perform session preparation. */
do_authenticated(authctxt);
/* The connection has been terminated. */
verbose("Closing connection to %.100s", remote_ip);
@ -1225,9 +1463,57 @@ main(int ac, char **av)
#endif /* USE_PAM */
packet_close();
if (use_privsep)
mm_terminate();
exit(0);
}
/*
* Decrypt session_key_int using our private server key and private host key
* (key with larger modulus first).
*/
int
ssh1_session_key(BIGNUM *session_key_int)
{
int rsafail = 0;
if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
/* Server key has bigger modulus. */
if (BN_num_bits(sensitive_data.server_key->rsa->n) <
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(),
BN_num_bits(sensitive_data.server_key->rsa->n),
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
SSH_KEY_BITS_RESERVED);
}
if (rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.server_key->rsa) <= 0)
rsafail++;
if (rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.ssh1_host_key->rsa) <= 0)
rsafail++;
} else {
/* Host key has bigger modulus (or they are equal). */
if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(),
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
BN_num_bits(sensitive_data.server_key->rsa->n),
SSH_KEY_BITS_RESERVED);
}
if (rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.ssh1_host_key->rsa) < 0)
rsafail++;
if (rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.server_key->rsa) < 0)
rsafail++;
}
return (rsafail);
}
/*
* SSH1 key exchange
*/
@ -1343,43 +1629,9 @@ do_ssh1_kex(void)
packet_set_protocol_flags(protocol_flags);
packet_check_eom();
/*
* Decrypt it using our private server key and private host key (key
* with larger modulus first).
*/
if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
/* Server key has bigger modulus. */
if (BN_num_bits(sensitive_data.server_key->rsa->n) <
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(),
BN_num_bits(sensitive_data.server_key->rsa->n),
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
SSH_KEY_BITS_RESERVED);
}
if (rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.server_key->rsa) <= 0)
rsafail++;
if (rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.ssh1_host_key->rsa) <= 0)
rsafail++;
} else {
/* Host key has bigger modulus (or they are equal). */
if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
get_remote_ipaddr(),
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
BN_num_bits(sensitive_data.server_key->rsa->n),
SSH_KEY_BITS_RESERVED);
}
if (rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.ssh1_host_key->rsa) < 0)
rsafail++;
if (rsa_private_decrypt(session_key_int, session_key_int,
sensitive_data.server_key->rsa) < 0)
rsafail++;
}
/* Decrypt session_key_int using host/server keys */
rsafail = PRIVSEP(ssh1_session_key(session_key_int));
/*
* Extract session key from the decrypted integer. The key is in the
* least significant 256 bits of the integer; the first byte of the
@ -1430,9 +1682,12 @@ do_ssh1_kex(void)
for (i = 0; i < 16; i++)
session_id[i] = session_key[i] ^ session_key[i + 16];
}
/* Destroy the private and public keys. They will no longer be needed. */
/* Destroy the private and public keys. No longer. */
destroy_sensitive_data();
if (use_privsep)
mm_ssh1_session_id(session_id);
/* Destroy the decrypted integer. It is no longer needed. */
BN_clear_free(session_key_int);
@ -1444,7 +1699,7 @@ do_ssh1_kex(void)
debug("Received session key; encryption turned on.");
/* Send an acknowledgement packet. Note that this packet is sent encrypted. */
/* Send an acknowledgment packet. Note that this packet is sent encrypted. */
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
@ -1471,6 +1726,10 @@ do_ssh2_kex(void)
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
}
if (!options.compression) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
}
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
/* start key exchange */
@ -1479,6 +1738,7 @@ do_ssh2_kex(void)
kex->client_version_string=client_version_string;
kex->server_version_string=server_version_string;
kex->load_host_key=&get_hostkey_by_type;
kex->host_key_index=&get_hostkey_index;
xxx_kex = kex;

View File

@ -1,8 +1,8 @@
# $OpenBSD: src/usr.bin/ssh/sshd_config,v 1.48 2002/02/19 02:50:59 deraadt Exp $
# $FreeBSD$
# $OpenBSD: sshd_config,v 1.56 2002/06/20 23:37:12 markus Exp $
# $FreeBSD$
# This is the sshd server system-wide configuration file. See sshd(8)
# for more information.
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
@ -64,13 +64,11 @@
#ChallengeResponseAuthentication yes
# Kerberos options
# KerberosAuthentication automatically enabled if keyfile exists
#KerberosAuthentication yes
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
# AFSTokenPassing automatically enabled if k_hasafs() is true
#AFSTokenPassing yes
#AFSTokenPassing no
# Kerberos TGT Passing only works with the AFS kaserver
#KerberosTgtPassing no
@ -83,6 +81,8 @@
#KeepAlive yes
#UseLogin no
#CheckMail yes
#UsePrivilegeSeparation no
#Compression yes
#MaxStartups 10
# no default banner path

View File

@ -1,11 +1,11 @@
/* $OpenBSD: version.h,v 1.28 2002/03/06 00:25:55 markus Exp $ */
/* $OpenBSD: version.h,v 1.33 2002/06/21 15:41:20 markus Exp $ */
/* $FreeBSD$ */
#ifndef SSH_VERSION
#define SSH_VERSION (ssh_version_get())
#define SSH_VERSION_BASE "OpenSSH_3.1"
#define SSH_VERSION_ADDENDUM "FreeBSD-20020402"
#define SSH_VERSION_BASE "OpenSSH_3.3"
#define SSH_VERSION_ADDENDUM "FreeBSD-20020623"
const char *ssh_version_get(void);
void ssh_version_set_addendum(const char *add);