summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c171
1 files changed, 102 insertions, 69 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 6a7b69938..343ca7459 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.213 2015/01/08 10:14:08 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.214 2015/01/14 20:05:27 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -70,6 +70,7 @@
70#include "pathnames.h" 70#include "pathnames.h"
71#include "uidswap.h" 71#include "uidswap.h"
72#include "hostfile.h" 72#include "hostfile.h"
73#include "ssherr.h"
73 74
74#ifdef GSSAPI 75#ifdef GSSAPI
75#include "ssh-gss.h" 76#include "ssh-gss.h"
@@ -131,10 +132,10 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
131 } while (0) 132 } while (0)
132 133
133 while ((alg = strsep(&avail, ",")) && *alg != '\0') { 134 while ((alg = strsep(&avail, ",")) && *alg != '\0') {
134 if ((ktype = key_type_from_name(alg)) == KEY_UNSPEC) 135 if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC)
135 fatal("%s: unknown alg %s", __func__, alg); 136 fatal("%s: unknown alg %s", __func__, alg);
136 if (lookup_key_in_hostkeys_by_type(hostkeys, 137 if (lookup_key_in_hostkeys_by_type(hostkeys,
137 key_type_plain(ktype), NULL)) 138 sshkey_type_plain(ktype), NULL))
138 ALG_APPEND(first, alg); 139 ALG_APPEND(first, alg);
139 else 140 else
140 ALG_APPEND(last, alg); 141 ALG_APPEND(last, alg);
@@ -242,15 +243,15 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
242 * Authenticate user 243 * Authenticate user
243 */ 244 */
244 245
245typedef struct Authctxt Authctxt; 246typedef struct cauthctxt Authctxt;
246typedef struct Authmethod Authmethod; 247typedef struct cauthmethod Authmethod;
247typedef struct identity Identity; 248typedef struct identity Identity;
248typedef struct idlist Idlist; 249typedef struct idlist Idlist;
249 250
250struct identity { 251struct identity {
251 TAILQ_ENTRY(identity) next; 252 TAILQ_ENTRY(identity) next;
252 AuthenticationConnection *ac; /* set if agent supports key */ 253 int agent_fd; /* >=0 if agent supports key */
253 Key *key; /* public/private key */ 254 struct sshkey *key; /* public/private key */
254 char *filename; /* comment for agent-only keys */ 255 char *filename; /* comment for agent-only keys */
255 int tried; 256 int tried;
256 int isprivate; /* key points to the private key */ 257 int isprivate; /* key points to the private key */
@@ -258,17 +259,18 @@ struct identity {
258}; 259};
259TAILQ_HEAD(idlist, identity); 260TAILQ_HEAD(idlist, identity);
260 261
261struct Authctxt { 262struct cauthctxt {
262 const char *server_user; 263 const char *server_user;
263 const char *local_user; 264 const char *local_user;
264 const char *host; 265 const char *host;
265 const char *service; 266 const char *service;
266 Authmethod *method; 267 struct cauthmethod *method;
267 sig_atomic_t success; 268 sig_atomic_t success;
268 char *authlist; 269 char *authlist;
270 int attempt;
269 /* pubkey */ 271 /* pubkey */
270 Idlist keys; 272 struct idlist keys;
271 AuthenticationConnection *agent; 273 int agent_fd;
272 /* hostbased */ 274 /* hostbased */
273 Sensitive *sensitive; 275 Sensitive *sensitive;
274 /* kbd-interactive */ 276 /* kbd-interactive */
@@ -276,7 +278,8 @@ struct Authctxt {
276 /* generic */ 278 /* generic */
277 void *methoddata; 279 void *methoddata;
278}; 280};
279struct Authmethod { 281
282struct cauthmethod {
280 char *name; /* string to compare against server's list */ 283 char *name; /* string to compare against server's list */
281 int (*userauth)(Authctxt *authctxt); 284 int (*userauth)(Authctxt *authctxt);
282 void (*cleanup)(Authctxt *authctxt); 285 void (*cleanup)(Authctxt *authctxt);
@@ -582,7 +585,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
582 key->type, pktype); 585 key->type, pktype);
583 goto done; 586 goto done;
584 } 587 }
585 fp = key_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); 588 fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
586 debug2("input_userauth_pk_ok: fp %s", fp); 589 debug2("input_userauth_pk_ok: fp %s", fp);
587 free(fp); 590 free(fp);
588 591
@@ -956,27 +959,29 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
956} 959}
957 960
958static int 961static int
959identity_sign(Identity *id, u_char **sigp, u_int *lenp, 962identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
960 u_char *data, u_int datalen) 963 const u_char *data, size_t datalen, u_int compat)
961{ 964{
962 Key *prv; 965 Key *prv;
963 int ret; 966 int ret;
964 967
965 /* the agent supports this key */ 968 /* the agent supports this key */
966 if (id->ac) 969 if (id->agent_fd)
967 return (ssh_agent_sign(id->ac, id->key, sigp, lenp, 970 return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
968 data, datalen)); 971 data, datalen, compat);
972
969 /* 973 /*
970 * we have already loaded the private key or 974 * we have already loaded the private key or
971 * the private key is stored in external hardware 975 * the private key is stored in external hardware
972 */ 976 */
973 if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)) 977 if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
974 return (key_sign(id->key, sigp, lenp, data, datalen)); 978 return (sshkey_sign(id->key, sigp, lenp, data, datalen,
979 compat));
975 /* load the private key from the file */ 980 /* load the private key from the file */
976 if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL) 981 if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL)
977 return (-1); 982 return (-1); /* XXX return decent error code */
978 ret = key_sign(prv, sigp, lenp, data, datalen); 983 ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat);
979 key_free(prv); 984 sshkey_free(prv);
980 return (ret); 985 return (ret);
981} 986}
982 987
@@ -985,7 +990,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
985{ 990{
986 Buffer b; 991 Buffer b;
987 u_char *blob, *signature; 992 u_char *blob, *signature;
988 u_int bloblen, slen; 993 u_int bloblen;
994 size_t slen;
989 u_int skip = 0; 995 u_int skip = 0;
990 int ret = -1; 996 int ret = -1;
991 int have_sig = 1; 997 int have_sig = 1;
@@ -1026,8 +1032,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
1026 1032
1027 /* generate signature */ 1033 /* generate signature */
1028 ret = identity_sign(id, &signature, &slen, 1034 ret = identity_sign(id, &signature, &slen,
1029 buffer_ptr(&b), buffer_len(&b)); 1035 buffer_ptr(&b), buffer_len(&b), datafellows);
1030 if (ret == -1) { 1036 if (ret != 0) {
1031 free(blob); 1037 free(blob);
1032 buffer_free(&b); 1038 buffer_free(&b);
1033 return 0; 1039 return 0;
@@ -1102,7 +1108,7 @@ load_identity_file(char *filename, int userprovided)
1102{ 1108{
1103 Key *private; 1109 Key *private;
1104 char prompt[300], *passphrase; 1110 char prompt[300], *passphrase;
1105 int perm_ok = 0, quit, i; 1111 int r, perm_ok = 0, quit, i;
1106 struct stat st; 1112 struct stat st;
1107 1113
1108 if (stat(filename, &st) < 0) { 1114 if (stat(filename, &st) < 0) {
@@ -1110,33 +1116,49 @@ load_identity_file(char *filename, int userprovided)
1110 filename, strerror(errno)); 1116 filename, strerror(errno));
1111 return NULL; 1117 return NULL;
1112 } 1118 }
1113 private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok); 1119 snprintf(prompt, sizeof prompt,
1114 if (!perm_ok) { 1120 "Enter passphrase for key '%.100s': ", filename);
1115 if (private != NULL) 1121 for (i = 0; i <= options.number_of_password_prompts; i++) {
1116 key_free(private); 1122 if (i == 0)
1117 return NULL; 1123 passphrase = "";
1118 } 1124 else {
1119 if (private == NULL) {
1120 if (options.batch_mode)
1121 return NULL;
1122 snprintf(prompt, sizeof prompt,
1123 "Enter passphrase for key '%.100s': ", filename);
1124 for (i = 0; i < options.number_of_password_prompts; i++) {
1125 passphrase = read_passphrase(prompt, 0); 1125 passphrase = read_passphrase(prompt, 0);
1126 if (strcmp(passphrase, "") != 0) { 1126 if (*passphrase == '\0') {
1127 private = key_load_private_type(KEY_UNSPEC,
1128 filename, passphrase, NULL, NULL);
1129 quit = 0;
1130 } else {
1131 debug2("no passphrase given, try next key"); 1127 debug2("no passphrase given, try next key");
1128 free(passphrase);
1129 break;
1130 }
1131 }
1132 switch ((r = sshkey_load_private_type(KEY_UNSPEC, filename,
1133 passphrase, &private, NULL, &perm_ok))) {
1134 case 0:
1135 break;
1136 case SSH_ERR_KEY_WRONG_PASSPHRASE:
1137 if (options.batch_mode) {
1138 quit = 1;
1139 break;
1140 }
1141 debug2("bad passphrase given, try again...");
1142 break;
1143 case SSH_ERR_SYSTEM_ERROR:
1144 if (errno == ENOENT) {
1145 debug2("Load key \"%s\": %s",
1146 filename, ssh_err(r));
1132 quit = 1; 1147 quit = 1;
1148 break;
1133 } 1149 }
1150 /* FALLTHROUGH */
1151 default:
1152 error("Load key \"%s\": %s", filename, ssh_err(r));
1153 quit = 1;
1154 break;
1155 }
1156 if (i > 0) {
1134 explicit_bzero(passphrase, strlen(passphrase)); 1157 explicit_bzero(passphrase, strlen(passphrase));
1135 free(passphrase); 1158 free(passphrase);
1136 if (private != NULL || quit)
1137 break;
1138 debug2("bad passphrase given, try again...");
1139 } 1159 }
1160 if (private != NULL || quit)
1161 break;
1140 } 1162 }
1141 return private; 1163 return private;
1142} 1164}
@@ -1150,12 +1172,12 @@ load_identity_file(char *filename, int userprovided)
1150static void 1172static void
1151pubkey_prepare(Authctxt *authctxt) 1173pubkey_prepare(Authctxt *authctxt)
1152{ 1174{
1153 Identity *id, *id2, *tmp; 1175 struct identity *id, *id2, *tmp;
1154 Idlist agent, files, *preferred; 1176 struct idlist agent, files, *preferred;
1155 Key *key; 1177 struct sshkey *key;
1156 AuthenticationConnection *ac; 1178 int agent_fd, i, r, found;
1157 char *comment; 1179 size_t j;
1158 int i, found; 1180 struct ssh_identitylist *idlist;
1159 1181
1160 TAILQ_INIT(&agent); /* keys from the agent */ 1182 TAILQ_INIT(&agent); /* keys from the agent */
1161 TAILQ_INIT(&files); /* keys from the config file */ 1183 TAILQ_INIT(&files); /* keys from the config file */
@@ -1185,7 +1207,7 @@ pubkey_prepare(Authctxt *authctxt)
1185 if (id2->key == NULL || 1207 if (id2->key == NULL ||
1186 (id2->key->flags & SSHKEY_FLAG_EXT) == 0) 1208 (id2->key->flags & SSHKEY_FLAG_EXT) == 0)
1187 continue; 1209 continue;
1188 if (key_equal(id->key, id2->key)) { 1210 if (sshkey_equal(id->key, id2->key)) {
1189 TAILQ_REMOVE(&files, id, next); 1211 TAILQ_REMOVE(&files, id, next);
1190 TAILQ_INSERT_TAIL(preferred, id, next); 1212 TAILQ_INSERT_TAIL(preferred, id, next);
1191 found = 1; 1213 found = 1;
@@ -1200,37 +1222,48 @@ pubkey_prepare(Authctxt *authctxt)
1200 } 1222 }
1201 } 1223 }
1202 /* list of keys supported by the agent */ 1224 /* list of keys supported by the agent */
1203 if ((ac = ssh_get_authentication_connection())) { 1225 if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
1204 for (key = ssh_get_first_identity(ac, &comment, 2); 1226 if (r != SSH_ERR_AGENT_NOT_PRESENT)
1205 key != NULL; 1227 debug("%s: ssh_get_authentication_socket: %s",
1206 key = ssh_get_next_identity(ac, &comment, 2)) { 1228 __func__, ssh_err(r));
1229 } else if ((r = ssh_fetch_identitylist(agent_fd, 2, &idlist)) != 0) {
1230 if (r != SSH_ERR_AGENT_NO_IDENTITIES)
1231 debug("%s: ssh_fetch_identitylist: %s",
1232 __func__, ssh_err(r));
1233 } else {
1234 for (j = 0; j < idlist->nkeys; j++) {
1207 found = 0; 1235 found = 0;
1208 TAILQ_FOREACH(id, &files, next) { 1236 TAILQ_FOREACH(id, &files, next) {
1209 /* agent keys from the config file are preferred */ 1237 /*
1210 if (key_equal(key, id->key)) { 1238 * agent keys from the config file are
1211 key_free(key); 1239 * preferred
1212 free(comment); 1240 */
1241 if (sshkey_equal(idlist->keys[j], id->key)) {
1213 TAILQ_REMOVE(&files, id, next); 1242 TAILQ_REMOVE(&files, id, next);
1214 TAILQ_INSERT_TAIL(preferred, id, next); 1243 TAILQ_INSERT_TAIL(preferred, id, next);
1215 id->ac = ac; 1244 id->agent_fd = agent_fd;
1216 found = 1; 1245 found = 1;
1217 break; 1246 break;
1218 } 1247 }
1219 } 1248 }
1220 if (!found && !options.identities_only) { 1249 if (!found && !options.identities_only) {
1221 id = xcalloc(1, sizeof(*id)); 1250 id = xcalloc(1, sizeof(*id));
1222 id->key = key; 1251 /* XXX "steals" key/comment from idlist */
1223 id->filename = comment; 1252 id->key = idlist->keys[j];
1224 id->ac = ac; 1253 id->filename = idlist->comments[j];
1254 idlist->keys[j] = NULL;
1255 idlist->comments[j] = NULL;
1256 id->agent_fd = agent_fd;
1225 TAILQ_INSERT_TAIL(&agent, id, next); 1257 TAILQ_INSERT_TAIL(&agent, id, next);
1226 } 1258 }
1227 } 1259 }
1260 ssh_free_identitylist(idlist);
1228 /* append remaining agent keys */ 1261 /* append remaining agent keys */
1229 for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) { 1262 for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
1230 TAILQ_REMOVE(&agent, id, next); 1263 TAILQ_REMOVE(&agent, id, next);
1231 TAILQ_INSERT_TAIL(preferred, id, next); 1264 TAILQ_INSERT_TAIL(preferred, id, next);
1232 } 1265 }
1233 authctxt->agent = ac; 1266 authctxt->agent_fd = agent_fd;
1234 } 1267 }
1235 /* append remaining keys from the config file */ 1268 /* append remaining keys from the config file */
1236 for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) { 1269 for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
@@ -1248,13 +1281,13 @@ pubkey_cleanup(Authctxt *authctxt)
1248{ 1281{
1249 Identity *id; 1282 Identity *id;
1250 1283
1251 if (authctxt->agent != NULL) 1284 if (authctxt->agent_fd != -1)
1252 ssh_close_authentication_connection(authctxt->agent); 1285 ssh_close_authentication_socket(authctxt->agent_fd);
1253 for (id = TAILQ_FIRST(&authctxt->keys); id; 1286 for (id = TAILQ_FIRST(&authctxt->keys); id;
1254 id = TAILQ_FIRST(&authctxt->keys)) { 1287 id = TAILQ_FIRST(&authctxt->keys)) {
1255 TAILQ_REMOVE(&authctxt->keys, id, next); 1288 TAILQ_REMOVE(&authctxt->keys, id, next);
1256 if (id->key) 1289 if (id->key)
1257 key_free(id->key); 1290 sshkey_free(id->key);
1258 free(id->filename); 1291 free(id->filename);
1259 free(id); 1292 free(id);
1260 } 1293 }