mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-02-08 01:52:52 +00:00
- markus@cvs.openbsd.org 2001/03/10 17:51:04
[kex.c match.c match.h readconf.c readconf.h sshconnect2.c] add PreferredAuthentications
This commit is contained in:
parent
7f283fcc94
commit
b9be60a722
@ -15,6 +15,10 @@
|
||||
handle password padding (newer OSU is fixed)
|
||||
- tim@mindrot.org 2001/03/10 16:33:42 [configure.in Makefile.in sshd_config]
|
||||
make sure $bindir is in USER_PATH so scp will work
|
||||
- OpenBSD CVS Sync
|
||||
- markus@cvs.openbsd.org 2001/03/10 17:51:04
|
||||
[kex.c match.c match.h readconf.c readconf.h sshconnect2.c]
|
||||
add PreferredAuthentications
|
||||
|
||||
20010310
|
||||
- OpenBSD CVS Sync
|
||||
@ -4486,4 +4490,4 @@
|
||||
- Wrote replacements for strlcpy and mkdtemp
|
||||
- Released 1.0pre1
|
||||
|
||||
$Id: ChangeLog,v 1.938 2001/03/11 00:52:25 tim Exp $
|
||||
$Id: ChangeLog,v 1.939 2001/03/11 01:49:19 mouring Exp $
|
||||
|
53
kex.c
53
kex.c
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: kex.c,v 1.22 2001/03/05 17:17:20 markus Exp $");
|
||||
RCSID("$OpenBSD: kex.c,v 1.23 2001/03/10 17:51:04 markus Exp $");
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/bio.h>
|
||||
@ -42,6 +42,7 @@ RCSID("$OpenBSD: kex.c,v 1.22 2001/03/05 17:17:20 markus Exp $");
|
||||
#include "key.h"
|
||||
#include "log.h"
|
||||
#include "mac.h"
|
||||
#include "match.h"
|
||||
|
||||
#define KEX_COOKIE_LEN 16
|
||||
|
||||
@ -372,49 +373,10 @@ derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret)
|
||||
return digest;
|
||||
}
|
||||
|
||||
#define NKEYS 6
|
||||
|
||||
#define MAX_PROP 20
|
||||
#define SEP ","
|
||||
|
||||
char *
|
||||
get_match(char *client, char *server)
|
||||
{
|
||||
char *sproposals[MAX_PROP];
|
||||
char *c, *s, *p, *ret, *cp, *sp;
|
||||
int i, j, nproposals;
|
||||
|
||||
c = cp = xstrdup(client);
|
||||
s = sp = xstrdup(server);
|
||||
|
||||
for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0';
|
||||
(p = strsep(&sp, SEP)), i++) {
|
||||
if (i < MAX_PROP)
|
||||
sproposals[i] = p;
|
||||
else
|
||||
break;
|
||||
}
|
||||
nproposals = i;
|
||||
|
||||
for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0';
|
||||
(p = strsep(&cp, SEP)), i++) {
|
||||
for (j = 0; j < nproposals; j++) {
|
||||
if (strcmp(p, sproposals[j]) == 0) {
|
||||
ret = xstrdup(p);
|
||||
xfree(c);
|
||||
xfree(s);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
xfree(c);
|
||||
xfree(s);
|
||||
return NULL;
|
||||
}
|
||||
void
|
||||
choose_enc(Enc *enc, char *client, char *server)
|
||||
{
|
||||
char *name = get_match(client, server);
|
||||
char *name = match_list(client, server, NULL);
|
||||
if (name == NULL)
|
||||
fatal("no matching cipher found: client %s server %s", client, server);
|
||||
enc->cipher = cipher_by_name(name);
|
||||
@ -428,7 +390,7 @@ choose_enc(Enc *enc, char *client, char *server)
|
||||
void
|
||||
choose_mac(Mac *mac, char *client, char *server)
|
||||
{
|
||||
char *name = get_match(client, server);
|
||||
char *name = match_list(client, server, NULL);
|
||||
if (name == NULL)
|
||||
fatal("no matching mac found: client %s server %s", client, server);
|
||||
if (mac_init(mac, name) < 0)
|
||||
@ -443,7 +405,7 @@ choose_mac(Mac *mac, char *client, char *server)
|
||||
void
|
||||
choose_comp(Comp *comp, char *client, char *server)
|
||||
{
|
||||
char *name = get_match(client, server);
|
||||
char *name = match_list(client, server, NULL);
|
||||
if (name == NULL)
|
||||
fatal("no matching comp found: client %s server %s", client, server);
|
||||
if (strcmp(name, "zlib") == 0) {
|
||||
@ -458,7 +420,7 @@ choose_comp(Comp *comp, char *client, char *server)
|
||||
void
|
||||
choose_kex(Kex *k, char *client, char *server)
|
||||
{
|
||||
k->name = get_match(client, server);
|
||||
k->name = match_list(client, server, NULL);
|
||||
if (k->name == NULL)
|
||||
fatal("no kex alg");
|
||||
if (strcmp(k->name, KEX_DH1) == 0) {
|
||||
@ -471,7 +433,7 @@ choose_kex(Kex *k, char *client, char *server)
|
||||
void
|
||||
choose_hostkeyalg(Kex *k, char *client, char *server)
|
||||
{
|
||||
char *hostkeyalg = get_match(client, server);
|
||||
char *hostkeyalg = match_list(client, server, NULL);
|
||||
if (hostkeyalg == NULL)
|
||||
fatal("no hostkey alg");
|
||||
k->hostkey_type = key_type_from_name(hostkeyalg);
|
||||
@ -524,6 +486,7 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server
|
||||
return k;
|
||||
}
|
||||
|
||||
#define NKEYS 6
|
||||
int
|
||||
kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret)
|
||||
{
|
||||
|
69
match.c
69
match.c
@ -10,11 +10,35 @@
|
||||
* incompatible with the protocol description in the RFC file, it must be
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. 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: match.c,v 1.11 2001/01/21 19:05:52 markus Exp $");
|
||||
RCSID("$OpenBSD: match.c,v 1.12 2001/03/10 17:51:04 markus Exp $");
|
||||
|
||||
#include "match.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/*
|
||||
* Returns true if the given string matches the pattern (which may contain ?
|
||||
@ -137,3 +161,46 @@ match_hostname(const char *host, const char *pattern, u_int len)
|
||||
*/
|
||||
return got_positive;
|
||||
}
|
||||
|
||||
|
||||
#define MAX_PROP 20
|
||||
#define SEP ","
|
||||
char *
|
||||
match_list(const char *client, const char *server, u_int *next)
|
||||
{
|
||||
char *sproposals[MAX_PROP];
|
||||
char *c, *s, *p, *ret, *cp, *sp;
|
||||
int i, j, nproposals;
|
||||
|
||||
c = cp = xstrdup(client);
|
||||
s = sp = xstrdup(server);
|
||||
|
||||
for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0';
|
||||
(p = strsep(&sp, SEP)), i++) {
|
||||
if (i < MAX_PROP)
|
||||
sproposals[i] = p;
|
||||
else
|
||||
break;
|
||||
}
|
||||
nproposals = i;
|
||||
|
||||
for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0';
|
||||
(p = strsep(&cp, SEP)), i++) {
|
||||
for (j = 0; j < nproposals; j++) {
|
||||
if (strcmp(p, sproposals[j]) == 0) {
|
||||
ret = xstrdup(p);
|
||||
if (next != NULL)
|
||||
*next = (cp == NULL) ?
|
||||
strlen(c) : cp - c;
|
||||
xfree(c);
|
||||
xfree(s);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next != NULL)
|
||||
*next = strlen(c);
|
||||
xfree(c);
|
||||
xfree(s);
|
||||
return NULL;
|
||||
}
|
||||
|
8
match.h
8
match.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: match.h,v 1.6 2001/01/29 01:58:17 niklas Exp $ */
|
||||
/* $OpenBSD: match.h,v 1.7 2001/03/10 17:51:04 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -30,4 +30,10 @@ int match_pattern(const char *s, const char *pattern);
|
||||
*/
|
||||
int match_hostname(const char *host, const char *pattern, u_int len);
|
||||
|
||||
/*
|
||||
* Returns first item from client-list that is also supported by server-list,
|
||||
* caller must xfree() returned string.
|
||||
*/
|
||||
char *match_list(const char *client, const char *server, u_int *next);
|
||||
|
||||
#endif
|
||||
|
12
readconf.c
12
readconf.c
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: readconf.c,v 1.66 2001/03/10 12:53:52 deraadt Exp $");
|
||||
RCSID("$OpenBSD: readconf.c,v 1.67 2001/03/10 17:51:04 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
@ -109,7 +109,8 @@ typedef enum {
|
||||
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
|
||||
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
|
||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
|
||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias
|
||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
||||
oPreferredAuthentications
|
||||
} OpCodes;
|
||||
|
||||
/* Textual representations of the tokens. */
|
||||
@ -171,6 +172,7 @@ static struct {
|
||||
{ "keepalive", oKeepAlives },
|
||||
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
|
||||
{ "loglevel", oLogLevel },
|
||||
{ "preferredauthentications", oPreferredAuthentications },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@ -446,6 +448,10 @@ parse_string:
|
||||
charptr = &options->host_key_alias;
|
||||
goto parse_string;
|
||||
|
||||
case oPreferredAuthentications:
|
||||
charptr = &options->preferred_authentications;
|
||||
goto parse_string;
|
||||
|
||||
case oProxyCommand:
|
||||
charptr = &options->proxy_command;
|
||||
string = xstrdup("");
|
||||
@ -722,6 +728,7 @@ initialize_options(Options * options)
|
||||
options->num_local_forwards = 0;
|
||||
options->num_remote_forwards = 0;
|
||||
options->log_level = (LogLevel) - 1;
|
||||
options->preferred_authentications = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -837,4 +844,5 @@ fill_default_options(Options * options)
|
||||
/* options->user will be set in the main program if appropriate */
|
||||
/* options->hostname will be set in the main program if appropriate */
|
||||
/* options->host_key_alias should not be set by default */
|
||||
/* options->preferred_authentications will be set in ssh */
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: readconf.h,v 1.27 2001/03/08 21:42:32 markus Exp $"); */
|
||||
/* RCSID("$OpenBSD: readconf.h,v 1.28 2001/03/10 17:51:04 markus Exp $"); */
|
||||
|
||||
#ifndef READCONF_H
|
||||
#define READCONF_H
|
||||
@ -82,6 +82,7 @@ typedef struct {
|
||||
char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
|
||||
char *system_hostfile2;
|
||||
char *user_hostfile2;
|
||||
char *preferred_authentications;
|
||||
|
||||
int num_identity_files; /* Number of files for RSA/DSA identities. */
|
||||
char *identity_files[SSH_MAX_IDENTITY_FILES];
|
||||
|
138
sshconnect2.c
138
sshconnect2.c
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshconnect2.c,v 1.52 2001/03/10 12:48:27 markus Exp $");
|
||||
RCSID("$OpenBSD: sshconnect2.c,v 1.53 2001/03/10 17:51:04 markus Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/md5.h>
|
||||
@ -51,6 +51,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.52 2001/03/10 12:48:27 markus Exp $");
|
||||
#include "log.h"
|
||||
#include "readconf.h"
|
||||
#include "readpass.h"
|
||||
#include "match.h"
|
||||
|
||||
void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
|
||||
void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
|
||||
@ -498,9 +499,9 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k,
|
||||
sign_cb_fn *sign_callback);
|
||||
void clear_auth_state(Authctxt *authctxt);
|
||||
|
||||
void authmethod_clear(void);
|
||||
Authmethod *authmethod_get(char *authlist);
|
||||
Authmethod *authmethod_lookup(const char *name);
|
||||
char *authmethods_get(void);
|
||||
|
||||
Authmethod authmethods[] = {
|
||||
{"publickey",
|
||||
@ -551,6 +552,9 @@ ssh_userauth2(const char *server_user, char *host)
|
||||
packet_done();
|
||||
debug("got SSH2_MSG_SERVICE_ACCEPT");
|
||||
|
||||
if (options.preferred_authentications == NULL)
|
||||
options.preferred_authentications = authmethods_get();
|
||||
|
||||
/* setup authentication context */
|
||||
authctxt.agent = ssh_get_authentication_connection();
|
||||
authctxt.server_user = server_user;
|
||||
@ -561,7 +565,6 @@ ssh_userauth2(const char *server_user, char *host)
|
||||
authctxt.authlist = NULL;
|
||||
if (authctxt.method == NULL)
|
||||
fatal("ssh_userauth2: internal error: cannot send userauth none request");
|
||||
authmethod_clear();
|
||||
|
||||
/* initial userauth request */
|
||||
userauth_none(&authctxt);
|
||||
@ -1106,39 +1109,6 @@ input_userauth_info_req(int type, int plen, void *ctxt)
|
||||
|
||||
/* find auth method */
|
||||
|
||||
#define DELIM ","
|
||||
|
||||
static char *def_authlist = "publickey,password";
|
||||
static char *authlist_current = NULL; /* clean copy used for comparison */
|
||||
static char *authname_current = NULL; /* last used auth method */
|
||||
static char *authlist_working = NULL; /* copy that gets modified by strtok_r() */
|
||||
static char *authlist_state = NULL; /* state variable for strtok_r() */
|
||||
|
||||
/*
|
||||
* Before starting to use a new authentication method list sent by the
|
||||
* server, reset internal variables. This should also be called when
|
||||
* finished processing server list to free resources.
|
||||
*/
|
||||
void
|
||||
authmethod_clear(void)
|
||||
{
|
||||
if (authlist_current != NULL) {
|
||||
xfree(authlist_current);
|
||||
authlist_current = NULL;
|
||||
}
|
||||
if (authlist_working != NULL) {
|
||||
xfree(authlist_working);
|
||||
authlist_working = NULL;
|
||||
}
|
||||
if (authname_current != NULL) {
|
||||
xfree(authname_current);
|
||||
authname_current = NULL;
|
||||
}
|
||||
if (authlist_state != NULL)
|
||||
authlist_state = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* given auth method name, if configurable options permit this method fill
|
||||
* in auth_ident field and return true, otherwise return false.
|
||||
@ -1169,62 +1139,70 @@ authmethod_lookup(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX internal state */
|
||||
static Authmethod *current = NULL;
|
||||
static char *supported = NULL;
|
||||
static char *preferred = NULL;
|
||||
/*
|
||||
* Given the authentication method list sent by the server, return the
|
||||
* next method we should try. If the server initially sends a nil list,
|
||||
* use a built-in default list. If the server sends a nil list after
|
||||
* previously sending a valid list, continue using the list originally
|
||||
* sent.
|
||||
* use a built-in default list.
|
||||
*/
|
||||
|
||||
Authmethod *
|
||||
authmethod_get(char *authlist)
|
||||
{
|
||||
char *name = NULL, *authname_old;
|
||||
Authmethod *method = NULL;
|
||||
|
||||
char *name = NULL;
|
||||
int next;
|
||||
|
||||
/* Use a suitable default if we're passed a nil list. */
|
||||
if (authlist == NULL || strlen(authlist) == 0)
|
||||
authlist = def_authlist;
|
||||
authlist = options.preferred_authentications;
|
||||
|
||||
if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) {
|
||||
/* start over if passed a different list */
|
||||
debug3("start over, passed a different list");
|
||||
authmethod_clear();
|
||||
authlist_current = xstrdup(authlist);
|
||||
authlist_working = xstrdup(authlist);
|
||||
name = strtok_r(authlist_working, DELIM, &authlist_state);
|
||||
} else {
|
||||
/*
|
||||
* try to use previously used authentication method
|
||||
* or continue to use previously passed list
|
||||
*/
|
||||
name = (authname_current != NULL) ?
|
||||
authname_current : strtok_r(NULL, DELIM, &authlist_state);
|
||||
}
|
||||
if (supported == NULL || strcmp(authlist, supported) != 0) {
|
||||
debug3("start over, passed a different list %s", authlist);
|
||||
if (supported != NULL)
|
||||
xfree(supported);
|
||||
supported = xstrdup(authlist);
|
||||
preferred = options.preferred_authentications;
|
||||
debug3("preferred %s", preferred);
|
||||
current = NULL;
|
||||
} else if (current != NULL && authmethod_is_enabled(current))
|
||||
return current;
|
||||
|
||||
while (name != NULL) {
|
||||
debug3("authmethod_lookup %s", name);
|
||||
method = authmethod_lookup(name);
|
||||
if (method != NULL && authmethod_is_enabled(method)) {
|
||||
debug3("authmethod_is_enabled %s", name);
|
||||
break;
|
||||
for (;;) {
|
||||
if ((name = match_list(preferred, supported, &next)) == NULL) {
|
||||
debug("no more auth methods to try");
|
||||
current = NULL;
|
||||
return NULL;
|
||||
}
|
||||
preferred += next;
|
||||
debug3("authmethod_lookup %s", name);
|
||||
debug3("remaining preferred: %s", preferred);
|
||||
if ((current = authmethod_lookup(name)) != NULL &&
|
||||
authmethod_is_enabled(current)) {
|
||||
debug3("authmethod_is_enabled %s", name);
|
||||
debug("next auth method to try is %s", name);
|
||||
return current;
|
||||
}
|
||||
name = strtok_r(NULL, DELIM, &authlist_state);
|
||||
method = NULL;
|
||||
}
|
||||
|
||||
authname_old = authname_current;
|
||||
if (method != NULL) {
|
||||
debug("next auth method to try is %s", name);
|
||||
authname_current = xstrdup(name);
|
||||
} else {
|
||||
debug("no more auth methods to try");
|
||||
authname_current = NULL;
|
||||
}
|
||||
|
||||
if (authname_old != NULL)
|
||||
xfree(authname_old);
|
||||
|
||||
return (method);
|
||||
}
|
||||
|
||||
|
||||
#define DELIM ","
|
||||
char *
|
||||
authmethods_get(void)
|
||||
{
|
||||
Authmethod *method = NULL;
|
||||
char buf[1024];
|
||||
|
||||
buf[0] = '\0';
|
||||
for (method = authmethods; method->name != NULL; method++) {
|
||||
if (authmethod_is_enabled(method)) {
|
||||
if (buf[0] != '\0')
|
||||
strlcat(buf, DELIM, sizeof buf);
|
||||
strlcat(buf, method->name, sizeof buf);
|
||||
}
|
||||
}
|
||||
return xstrdup(buf);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user