diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 132 |
1 files changed, 55 insertions, 77 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index 646bb18f3..19d079bd3 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: sshconnect2.c,v 1.52 2001/03/10 12:48:27 markus Exp $"); | 26 | RCSID("$OpenBSD: sshconnect2.c,v 1.53 2001/03/10 17:51:04 markus Exp $"); |
27 | 27 | ||
28 | #include <openssl/bn.h> | 28 | #include <openssl/bn.h> |
29 | #include <openssl/md5.h> | 29 | #include <openssl/md5.h> |
@@ -51,6 +51,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.52 2001/03/10 12:48:27 markus Exp $"); | |||
51 | #include "log.h" | 51 | #include "log.h" |
52 | #include "readconf.h" | 52 | #include "readconf.h" |
53 | #include "readpass.h" | 53 | #include "readpass.h" |
54 | #include "match.h" | ||
54 | 55 | ||
55 | void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); | 56 | void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); |
56 | void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); | 57 | void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *); |
@@ -498,9 +499,9 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, | |||
498 | sign_cb_fn *sign_callback); | 499 | sign_cb_fn *sign_callback); |
499 | void clear_auth_state(Authctxt *authctxt); | 500 | void clear_auth_state(Authctxt *authctxt); |
500 | 501 | ||
501 | void authmethod_clear(void); | ||
502 | Authmethod *authmethod_get(char *authlist); | 502 | Authmethod *authmethod_get(char *authlist); |
503 | Authmethod *authmethod_lookup(const char *name); | 503 | Authmethod *authmethod_lookup(const char *name); |
504 | char *authmethods_get(void); | ||
504 | 505 | ||
505 | Authmethod authmethods[] = { | 506 | Authmethod authmethods[] = { |
506 | {"publickey", | 507 | {"publickey", |
@@ -551,6 +552,9 @@ ssh_userauth2(const char *server_user, char *host) | |||
551 | packet_done(); | 552 | packet_done(); |
552 | debug("got SSH2_MSG_SERVICE_ACCEPT"); | 553 | debug("got SSH2_MSG_SERVICE_ACCEPT"); |
553 | 554 | ||
555 | if (options.preferred_authentications == NULL) | ||
556 | options.preferred_authentications = authmethods_get(); | ||
557 | |||
554 | /* setup authentication context */ | 558 | /* setup authentication context */ |
555 | authctxt.agent = ssh_get_authentication_connection(); | 559 | authctxt.agent = ssh_get_authentication_connection(); |
556 | authctxt.server_user = server_user; | 560 | authctxt.server_user = server_user; |
@@ -561,7 +565,6 @@ ssh_userauth2(const char *server_user, char *host) | |||
561 | authctxt.authlist = NULL; | 565 | authctxt.authlist = NULL; |
562 | if (authctxt.method == NULL) | 566 | if (authctxt.method == NULL) |
563 | fatal("ssh_userauth2: internal error: cannot send userauth none request"); | 567 | fatal("ssh_userauth2: internal error: cannot send userauth none request"); |
564 | authmethod_clear(); | ||
565 | 568 | ||
566 | /* initial userauth request */ | 569 | /* initial userauth request */ |
567 | userauth_none(&authctxt); | 570 | userauth_none(&authctxt); |
@@ -1106,39 +1109,6 @@ input_userauth_info_req(int type, int plen, void *ctxt) | |||
1106 | 1109 | ||
1107 | /* find auth method */ | 1110 | /* find auth method */ |
1108 | 1111 | ||
1109 | #define DELIM "," | ||
1110 | |||
1111 | static char *def_authlist = "publickey,password"; | ||
1112 | static char *authlist_current = NULL; /* clean copy used for comparison */ | ||
1113 | static char *authname_current = NULL; /* last used auth method */ | ||
1114 | static char *authlist_working = NULL; /* copy that gets modified by strtok_r() */ | ||
1115 | static char *authlist_state = NULL; /* state variable for strtok_r() */ | ||
1116 | |||
1117 | /* | ||
1118 | * Before starting to use a new authentication method list sent by the | ||
1119 | * server, reset internal variables. This should also be called when | ||
1120 | * finished processing server list to free resources. | ||
1121 | */ | ||
1122 | void | ||
1123 | authmethod_clear(void) | ||
1124 | { | ||
1125 | if (authlist_current != NULL) { | ||
1126 | xfree(authlist_current); | ||
1127 | authlist_current = NULL; | ||
1128 | } | ||
1129 | if (authlist_working != NULL) { | ||
1130 | xfree(authlist_working); | ||
1131 | authlist_working = NULL; | ||
1132 | } | ||
1133 | if (authname_current != NULL) { | ||
1134 | xfree(authname_current); | ||
1135 | authname_current = NULL; | ||
1136 | } | ||
1137 | if (authlist_state != NULL) | ||
1138 | authlist_state = NULL; | ||
1139 | return; | ||
1140 | } | ||
1141 | |||
1142 | /* | 1112 | /* |
1143 | * given auth method name, if configurable options permit this method fill | 1113 | * given auth method name, if configurable options permit this method fill |
1144 | * in auth_ident field and return true, otherwise return false. | 1114 | * in auth_ident field and return true, otherwise return false. |
@@ -1169,62 +1139,70 @@ authmethod_lookup(const char *name) | |||
1169 | return NULL; | 1139 | return NULL; |
1170 | } | 1140 | } |
1171 | 1141 | ||
1142 | /* XXX internal state */ | ||
1143 | static Authmethod *current = NULL; | ||
1144 | static char *supported = NULL; | ||
1145 | static char *preferred = NULL; | ||
1172 | /* | 1146 | /* |
1173 | * Given the authentication method list sent by the server, return the | 1147 | * Given the authentication method list sent by the server, return the |
1174 | * next method we should try. If the server initially sends a nil list, | 1148 | * next method we should try. If the server initially sends a nil list, |
1175 | * use a built-in default list. If the server sends a nil list after | 1149 | * use a built-in default list. |
1176 | * previously sending a valid list, continue using the list originally | ||
1177 | * sent. | ||
1178 | */ | 1150 | */ |
1179 | |||
1180 | Authmethod * | 1151 | Authmethod * |
1181 | authmethod_get(char *authlist) | 1152 | authmethod_get(char *authlist) |
1182 | { | 1153 | { |
1183 | char *name = NULL, *authname_old; | 1154 | |
1184 | Authmethod *method = NULL; | 1155 | char *name = NULL; |
1156 | int next; | ||
1185 | 1157 | ||
1186 | /* Use a suitable default if we're passed a nil list. */ | 1158 | /* Use a suitable default if we're passed a nil list. */ |
1187 | if (authlist == NULL || strlen(authlist) == 0) | 1159 | if (authlist == NULL || strlen(authlist) == 0) |
1188 | authlist = def_authlist; | 1160 | authlist = options.preferred_authentications; |
1189 | 1161 | ||
1190 | if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) { | 1162 | if (supported == NULL || strcmp(authlist, supported) != 0) { |
1191 | /* start over if passed a different list */ | 1163 | debug3("start over, passed a different list %s", authlist); |
1192 | debug3("start over, passed a different list"); | 1164 | if (supported != NULL) |
1193 | authmethod_clear(); | 1165 | xfree(supported); |
1194 | authlist_current = xstrdup(authlist); | 1166 | supported = xstrdup(authlist); |
1195 | authlist_working = xstrdup(authlist); | 1167 | preferred = options.preferred_authentications; |
1196 | name = strtok_r(authlist_working, DELIM, &authlist_state); | 1168 | debug3("preferred %s", preferred); |
1197 | } else { | 1169 | current = NULL; |
1198 | /* | 1170 | } else if (current != NULL && authmethod_is_enabled(current)) |
1199 | * try to use previously used authentication method | 1171 | return current; |
1200 | * or continue to use previously passed list | ||
1201 | */ | ||
1202 | name = (authname_current != NULL) ? | ||
1203 | authname_current : strtok_r(NULL, DELIM, &authlist_state); | ||
1204 | } | ||
1205 | 1172 | ||
1206 | while (name != NULL) { | 1173 | for (;;) { |
1174 | if ((name = match_list(preferred, supported, &next)) == NULL) { | ||
1175 | debug("no more auth methods to try"); | ||
1176 | current = NULL; | ||
1177 | return NULL; | ||
1178 | } | ||
1179 | preferred += next; | ||
1207 | debug3("authmethod_lookup %s", name); | 1180 | debug3("authmethod_lookup %s", name); |
1208 | method = authmethod_lookup(name); | 1181 | debug3("remaining preferred: %s", preferred); |
1209 | if (method != NULL && authmethod_is_enabled(method)) { | 1182 | if ((current = authmethod_lookup(name)) != NULL && |
1183 | authmethod_is_enabled(current)) { | ||
1210 | debug3("authmethod_is_enabled %s", name); | 1184 | debug3("authmethod_is_enabled %s", name); |
1211 | break; | 1185 | debug("next auth method to try is %s", name); |
1186 | return current; | ||
1212 | } | 1187 | } |
1213 | name = strtok_r(NULL, DELIM, &authlist_state); | ||
1214 | method = NULL; | ||
1215 | } | ||
1216 | |||
1217 | authname_old = authname_current; | ||
1218 | if (method != NULL) { | ||
1219 | debug("next auth method to try is %s", name); | ||
1220 | authname_current = xstrdup(name); | ||
1221 | } else { | ||
1222 | debug("no more auth methods to try"); | ||
1223 | authname_current = NULL; | ||
1224 | } | 1188 | } |
1189 | } | ||
1225 | 1190 | ||
1226 | if (authname_old != NULL) | ||
1227 | xfree(authname_old); | ||
1228 | 1191 | ||
1229 | return (method); | 1192 | #define DELIM "," |
1193 | char * | ||
1194 | authmethods_get(void) | ||
1195 | { | ||
1196 | Authmethod *method = NULL; | ||
1197 | char buf[1024]; | ||
1198 | |||
1199 | buf[0] = '\0'; | ||
1200 | for (method = authmethods; method->name != NULL; method++) { | ||
1201 | if (authmethod_is_enabled(method)) { | ||
1202 | if (buf[0] != '\0') | ||
1203 | strlcat(buf, DELIM, sizeof buf); | ||
1204 | strlcat(buf, method->name, sizeof buf); | ||
1205 | } | ||
1206 | } | ||
1207 | return xstrdup(buf); | ||
1230 | } | 1208 | } |