version 1.52, 2001/03/10 12:48:27 |
version 1.53, 2001/03/10 17:51:04 |
|
|
#include "log.h" |
#include "log.h" |
#include "readconf.h" |
#include "readconf.h" |
#include "readpass.h" |
#include "readpass.h" |
|
#include "match.h" |
|
|
void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); |
void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); |
void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); |
void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); |
|
|
sign_cb_fn *sign_callback); |
sign_cb_fn *sign_callback); |
void clear_auth_state(Authctxt *authctxt); |
void clear_auth_state(Authctxt *authctxt); |
|
|
void authmethod_clear(void); |
|
Authmethod *authmethod_get(char *authlist); |
Authmethod *authmethod_get(char *authlist); |
Authmethod *authmethod_lookup(const char *name); |
Authmethod *authmethod_lookup(const char *name); |
|
char *authmethods_get(void); |
|
|
Authmethod authmethods[] = { |
Authmethod authmethods[] = { |
{"publickey", |
{"publickey", |
|
|
packet_done(); |
packet_done(); |
debug("got SSH2_MSG_SERVICE_ACCEPT"); |
debug("got SSH2_MSG_SERVICE_ACCEPT"); |
|
|
|
if (options.preferred_authentications == NULL) |
|
options.preferred_authentications = authmethods_get(); |
|
|
/* setup authentication context */ |
/* setup authentication context */ |
authctxt.agent = ssh_get_authentication_connection(); |
authctxt.agent = ssh_get_authentication_connection(); |
authctxt.server_user = server_user; |
authctxt.server_user = server_user; |
|
|
authctxt.authlist = NULL; |
authctxt.authlist = NULL; |
if (authctxt.method == NULL) |
if (authctxt.method == NULL) |
fatal("ssh_userauth2: internal error: cannot send userauth none request"); |
fatal("ssh_userauth2: internal error: cannot send userauth none request"); |
authmethod_clear(); |
|
|
|
/* initial userauth request */ |
/* initial userauth request */ |
userauth_none(&authctxt); |
userauth_none(&authctxt); |
|
|
|
|
/* find auth method */ |
/* 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 |
* given auth method name, if configurable options permit this method fill |
* in auth_ident field and return true, otherwise return false. |
* in auth_ident field and return true, otherwise return false. |
*/ |
*/ |
|
|
return NULL; |
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 |
* Given the authentication method list sent by the server, return the |
* next method we should try. If the server initially sends a nil list, |
* 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 |
* use a built-in default list. |
* previously sending a valid list, continue using the list originally |
|
* sent. |
|
*/ |
*/ |
|
|
Authmethod * |
Authmethod * |
authmethod_get(char *authlist) |
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. */ |
/* Use a suitable default if we're passed a nil list. */ |
if (authlist == NULL || strlen(authlist) == 0) |
if (authlist == NULL || strlen(authlist) == 0) |
authlist = def_authlist; |
authlist = options.preferred_authentications; |
|
|
if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) { |
if (supported == NULL || strcmp(authlist, supported) != 0) { |
/* start over if passed a different list */ |
debug3("start over, passed a different list %s", authlist); |
debug3("start over, passed a different list"); |
if (supported != NULL) |
authmethod_clear(); |
xfree(supported); |
authlist_current = xstrdup(authlist); |
supported = xstrdup(authlist); |
authlist_working = xstrdup(authlist); |
preferred = options.preferred_authentications; |
name = strtok_r(authlist_working, DELIM, &authlist_state); |
debug3("preferred %s", preferred); |
} else { |
current = NULL; |
/* |
} else if (current != NULL && authmethod_is_enabled(current)) |
* try to use previously used authentication method |
return current; |
* or continue to use previously passed list |
|
*/ |
|
name = (authname_current != NULL) ? |
|
authname_current : strtok_r(NULL, DELIM, &authlist_state); |
|
} |
|
|
|
while (name != NULL) { |
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("authmethod_lookup %s", name); |
method = authmethod_lookup(name); |
debug3("remaining preferred: %s", preferred); |
if (method != NULL && authmethod_is_enabled(method)) { |
if ((current = authmethod_lookup(name)) != NULL && |
|
authmethod_is_enabled(current)) { |
debug3("authmethod_is_enabled %s", name); |
debug3("authmethod_is_enabled %s", name); |
break; |
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) |
#define DELIM "," |
xfree(authname_old); |
char * |
|
authmethods_get(void) |
|
{ |
|
Authmethod *method = NULL; |
|
char buf[1024]; |
|
|
return (method); |
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); |
} |
} |