summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog44
-rw-r--r--Makefile.in6
-rw-r--r--README.openssh215
-rw-r--r--auth-rsa.c3
-rw-r--r--auth.c686
-rw-r--r--auth.h7
-rw-r--r--auth1.c512
-rw-r--r--auth2.c459
-rw-r--r--authfile.c206
-rw-r--r--authfile.h36
-rw-r--r--compat.c3
-rw-r--r--dsa.c78
-rw-r--r--dsa.h12
-rw-r--r--hostfile.c23
-rw-r--r--key.c107
-rw-r--r--key.h3
-rw-r--r--radix.c96
-rw-r--r--readconf.c45
-rw-r--r--readconf.h6
-rw-r--r--servconf.c4
-rw-r--r--serverloop.c2
-rw-r--r--session.c3
-rw-r--r--ssh-add.c37
-rw-r--r--ssh-keygen.18
-rw-r--r--ssh-keygen.c350
-rw-r--r--ssh.c65
-rw-r--r--ssh.h37
-rw-r--r--sshconnect.c1356
-rw-r--r--sshconnect.h16
-rw-r--r--sshconnect1.c1020
-rw-r--r--sshconnect2.c449
-rw-r--r--sshd.c221
-rw-r--r--uuencode.c120
-rw-r--r--uuencode.h6
-rw-r--r--version.h2
35 files changed, 3544 insertions, 2499 deletions
diff --git a/ChangeLog b/ChangeLog
index 98a5a9b31..9efe31fef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,47 @@
120000429
2 - Merge big update to OpenSSH-2.0 from OpenBSD CVS
3 [README.openssh2]
4 - interop w/ F-secure windows client
5 - sync documentation
6 - ssh_host_dsa_key not ssh_dsa_key
7 [auth-rsa.c]
8 - missing fclose
9 [auth.c authfile.c compat.c dsa.c dsa.h hostfile.c key.c key.h radix.c]
10 [readconf.c readconf.h ssh-add.c ssh-keygen.c ssh.c ssh.h sshconnect.c]
11 [sshd.c uuencode.c uuencode.h authfile.h]
12 - add DSA pubkey auth and other SSH2 fixes. use ssh-keygen -[xX]
13 for trading keys with the real and the original SSH, directly from the
14 people who invented the SSH protocol.
15 [auth.c auth.h authfile.c sshconnect.c auth1.c auth2.c sshconnect.h]
16 [sshconnect1.c sshconnect2.c]
17 - split auth/sshconnect in one file per protocol version
18 [sshconnect2.c]
19 - remove debug
20 [uuencode.c]
21 - add trailing =
22 [version.h]
23 - OpenSSH-2.0
24 [ssh-keygen.1 ssh-keygen.c]
25 - add -R flag: exit code indicates if RSA is alive
26 [sshd.c]
27 - remove unused
28 silent if -Q is specified
29 [ssh.h]
30 - host key becomes /etc/ssh_host_dsa_key
31 [readconf.c servconf.c ]
32 - ssh/sshd default to proto 1 and 2
33 [uuencode.c]
34 - remove debug
35 [auth2.c ssh-keygen.c sshconnect2.c sshd.c]
36 - xfree DSA blobs
37 [auth2.c serverloop.c session.c]
38 - cleanup logging for sshd/2, respect PasswordAuth no
39 [sshconnect2.c]
40 - less debug, respect .ssh/config
41 [README.openssh2 channels.c channels.h]
42 - clientloop.c session.c ssh.c
43 - support for x11-fwding, client+server
44
120000421 4520000421
2 - Merge fix from OpenBSD CVS 46 - Merge fix from OpenBSD CVS
3 [ssh-agent.c] 47 [ssh-agent.c]
diff --git a/Makefile.in b/Makefile.in
index 196cc5786..d5e3fde6c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -31,11 +31,11 @@ LDFLAGS=-L. @LDFLAGS@
31 31
32TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) 32TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
33 33
34LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o 34LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o
35 35
36SSHOBJS= ssh.o sshconnect.o log-client.o readconf.o clientloop.o 36SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o
37 37
38SSHDOBJS= sshd.o auth-rhosts.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o serverloop.o bsd-login.o md5crypt.o session.o auth.o 38SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-rhosts.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o serverloop.o bsd-login.o md5crypt.o session.o
39 39
40TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 40TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8
41CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 41CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0
diff --git a/README.openssh2 b/README.openssh2
index bdf78bf58..fca3173ae 100644
--- a/README.openssh2
+++ b/README.openssh2
@@ -1,13 +1,16 @@
1$Id: README.openssh2,v 1.3 2000/04/12 07:45:43 markus Exp $ 1$Id: README.openssh2,v 1.6 2000/04/27 13:42:58 provos Exp $
2 2
3howto: 3howto:
4 1) generate server key: 4 1) generate server key:
5 $ umask 077 5 $ ssh-keygen -d -f /etc/ssh_host_dsa_key -N ''
6 $ openssl dsaparam 1024 -out dsa1024.pem
7 $ openssl gendsa -out /etc/ssh_dsa_key dsa1024.pem -rand /dev/arandom
8 2) enable ssh2: 6 2) enable ssh2:
9 server: add 'Protocol 2,1' to /etc/sshd_config 7 server: add 'Protocol 2,1' to /etc/sshd_config
10 client: ssh -o 'Protocol 2,1', or add to .ssh/config 8 client: ssh -o 'Protocol 2,1', or add to .ssh/config
9 3) interop w/ ssh.com dsa-keys:
10 ssh-keygen -f /key/from/ssh.com -X >> ~/.ssh/authorized_keys2
11 and vice versa
12 ssh-keygen -f /privatekey/from/openssh -x > ~/.ssh2/mykey.pub
13 echo Key mykey.pub >> ~/.ssh2/authorization
11 14
12works: 15works:
13 secsh-transport: works w/o rekey 16 secsh-transport: works w/o rekey
@@ -22,7 +25,7 @@ works:
22 key database in ~/.ssh/known_hosts with bits == 0 hack 25 key database in ~/.ssh/known_hosts with bits == 0 hack
23 dss: signature works, keygen w/ openssl 26 dss: signature works, keygen w/ openssl
24 client interops w/ sshd2, lshd 27 client interops w/ sshd2, lshd
25 server interops w/ ssh2, lsh, ssh.com's Windows client, SecureCRT 28 server interops w/ ssh2, lsh, ssh.com's Windows client, SecureCRT, F-Secure SSH Client 4.0
26 server supports multiple concurrent sessions (e.g. with SSH.com Windows client) 29 server supports multiple concurrent sessions (e.g. with SSH.com Windows client)
27todo: 30todo:
28 re-keying 31 re-keying
@@ -38,4 +41,4 @@ todo:
38 sftp 41 sftp
39 42
40-markus 43-markus
41$Date: 2000/04/12 07:45:43 $ 44$Date: 2000/04/27 13:42:58 $
diff --git a/auth-rsa.c b/auth-rsa.c
index aa8be2bb0..c61eab29a 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -16,7 +16,7 @@
16 */ 16 */
17 17
18#include "includes.h" 18#include "includes.h"
19RCSID("$Id: auth-rsa.c,v 1.17 2000/04/16 02:31:49 damien Exp $"); 19RCSID("$Id: auth-rsa.c,v 1.18 2000/04/29 13:57:09 damien Exp $");
20 20
21#include "rsa.h" 21#include "rsa.h"
22#include "packet.h" 22#include "packet.h"
@@ -185,6 +185,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
185 } 185 }
186 } 186 }
187 if (fail) { 187 if (fail) {
188 fclose(f);
188 log(buf); 189 log(buf);
189 packet_send_debug(buf); 190 packet_send_debug(buf);
190 restore_uid(); 191 restore_uid();
diff --git a/auth.c b/auth.c
index 4c6f32b0a..3bfcfd8e2 100644
--- a/auth.c
+++ b/auth.c
@@ -5,7 +5,7 @@
5 */ 5 */
6 6
7#include "includes.h" 7#include "includes.h"
8RCSID("$OpenBSD: auth.c,v 1.4 2000/04/14 10:30:29 markus Exp $"); 8RCSID("$OpenBSD: auth.c,v 1.6 2000/04/26 21:28:31 markus Exp $");
9 9
10#include "xmalloc.h" 10#include "xmalloc.h"
11#include "rsa.h" 11#include "rsa.h"
@@ -40,7 +40,7 @@ extern char *forced_command;
40 * If the user's shell is not executable, false will be returned. 40 * If the user's shell is not executable, false will be returned.
41 * Otherwise true is returned. 41 * Otherwise true is returned.
42 */ 42 */
43static int 43int
44allowed_user(struct passwd * pw) 44allowed_user(struct passwd * pw)
45{ 45{
46 struct stat st; 46 struct stat st;
@@ -118,685 +118,3 @@ allowed_user(struct passwd * pw)
118 /* We found no reason not to let this user try to log on... */ 118 /* We found no reason not to let this user try to log on... */
119 return 1; 119 return 1;
120} 120}
121
122/*
123 * convert ssh auth msg type into description
124 */
125char *
126get_authname(int type)
127{
128 static char buf[1024];
129 switch (type) {
130 case SSH_CMSG_AUTH_PASSWORD:
131 return "password";
132 case SSH_CMSG_AUTH_RSA:
133 return "rsa";
134 case SSH_CMSG_AUTH_RHOSTS_RSA:
135 return "rhosts-rsa";
136 case SSH_CMSG_AUTH_RHOSTS:
137 return "rhosts";
138#ifdef KRB4
139 case SSH_CMSG_AUTH_KERBEROS:
140 return "kerberos";
141#endif
142#ifdef SKEY
143 case SSH_CMSG_AUTH_TIS_RESPONSE:
144 return "s/key";
145#endif
146 }
147 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
148 return buf;
149}
150
151#define AUTH_FAIL_MAX 6
152#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
153#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
154
155/*
156 * The user does not exist or access is denied,
157 * but fake indication that authentication is needed.
158 */
159void
160do_fake_authloop1(char *user)
161{
162 int attempt = 0;
163
164 log("Faking authloop for illegal user %.200s from %.200s port %d",
165 user,
166 get_remote_ipaddr(),
167 get_remote_port());
168
169#ifdef WITH_AIXAUTHENTICATE
170 if (strncmp(get_authname(type),"password",
171 strlen(get_authname(type))) == 0)
172 loginfailed(pw->pw_name,get_canonical_hostname(),"ssh");
173#endif /* WITH_AIXAUTHENTICATE */
174
175 /* Indicate that authentication is needed. */
176 packet_start(SSH_SMSG_FAILURE);
177 packet_send();
178 packet_write_wait();
179
180 /*
181 * Keep reading packets, and always respond with a failure. This is
182 * to avoid disclosing whether such a user really exists.
183 */
184 for (attempt = 1;; attempt++) {
185 /* Read a packet. This will not return if the client disconnects. */
186 int plen;
187#ifndef SKEY
188 (void)packet_read(&plen);
189#else /* SKEY */
190 int type = packet_read(&plen);
191 unsigned int dlen;
192 char *password, *skeyinfo;
193 /* Try to send a fake s/key challenge. */
194 if (options.skey_authentication == 1 &&
195 (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
196 password = NULL;
197 if (type == SSH_CMSG_AUTH_TIS) {
198 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
199 packet_put_string(skeyinfo, strlen(skeyinfo));
200 packet_send();
201 packet_write_wait();
202 continue;
203 } else if (type == SSH_CMSG_AUTH_PASSWORD &&
204 options.password_authentication &&
205 (password = packet_get_string(&dlen)) != NULL &&
206 dlen == 5 &&
207 strncasecmp(password, "s/key", 5) == 0 ) {
208 packet_send_debug(skeyinfo);
209 }
210 if (password != NULL)
211 xfree(password);
212 }
213#endif
214 if (attempt > AUTH_FAIL_MAX)
215 packet_disconnect(AUTH_FAIL_MSG, user);
216
217 /*
218 * Send failure. This should be indistinguishable from a
219 * failed authentication.
220 */
221 packet_start(SSH_SMSG_FAILURE);
222 packet_send();
223 packet_write_wait();
224 }
225 /* NOTREACHED */
226 abort();
227}
228
229/*
230 * read packets and try to authenticate local user *pw.
231 * return if authentication is successfull
232 */
233void
234do_authloop(struct passwd * pw)
235{
236 int attempt = 0;
237 unsigned int bits;
238 RSA *client_host_key;
239 BIGNUM *n;
240 char *client_user = NULL, *password = NULL;
241 char user[1024];
242 unsigned int dlen;
243 int plen, nlen, elen;
244 unsigned int ulen;
245 int type = 0;
246 void (*authlog) (const char *fmt,...) = verbose;
247
248 /* Indicate that authentication is needed. */
249 packet_start(SSH_SMSG_FAILURE);
250 packet_send();
251 packet_write_wait();
252
253 for (attempt = 1;; attempt++) {
254 int authenticated = 0;
255 strlcpy(user, "", sizeof user);
256
257 /* Get a packet from the client. */
258 type = packet_read(&plen);
259
260 /* Process the packet. */
261 switch (type) {
262#ifdef AFS
263 case SSH_CMSG_HAVE_KERBEROS_TGT:
264 if (!options.kerberos_tgt_passing) {
265 /* packet_get_all(); */
266 verbose("Kerberos tgt passing disabled.");
267 break;
268 } else {
269 /* Accept Kerberos tgt. */
270 char *tgt = packet_get_string(&dlen);
271 packet_integrity_check(plen, 4 + dlen, type);
272 if (!auth_kerberos_tgt(pw, tgt))
273 verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
274 xfree(tgt);
275 }
276 continue;
277
278 case SSH_CMSG_HAVE_AFS_TOKEN:
279 if (!options.afs_token_passing || !k_hasafs()) {
280 /* packet_get_all(); */
281 verbose("AFS token passing disabled.");
282 break;
283 } else {
284 /* Accept AFS token. */
285 char *token_string = packet_get_string(&dlen);
286 packet_integrity_check(plen, 4 + dlen, type);
287 if (!auth_afs_token(pw, token_string))
288 verbose("AFS token REFUSED for %s", pw->pw_name);
289 xfree(token_string);
290 }
291 continue;
292#endif /* AFS */
293#ifdef KRB4
294 case SSH_CMSG_AUTH_KERBEROS:
295 if (!options.kerberos_authentication) {
296 /* packet_get_all(); */
297 verbose("Kerberos authentication disabled.");
298 break;
299 } else {
300 /* Try Kerberos v4 authentication. */
301 KTEXT_ST auth;
302 char *tkt_user = NULL;
303 char *kdata = packet_get_string((unsigned int *) &auth.length);
304 packet_integrity_check(plen, 4 + auth.length, type);
305
306 if (auth.length < MAX_KTXT_LEN)
307 memcpy(auth.dat, kdata, auth.length);
308 xfree(kdata);
309
310 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
311
312 if (authenticated) {
313 snprintf(user, sizeof user, " tktuser %s", tkt_user);
314 xfree(tkt_user);
315 }
316 }
317 break;
318#endif /* KRB4 */
319
320 case SSH_CMSG_AUTH_RHOSTS:
321 if (!options.rhosts_authentication) {
322 verbose("Rhosts authentication disabled.");
323 break;
324 }
325 /*
326 * Get client user name. Note that we just have to
327 * trust the client; this is one reason why rhosts
328 * authentication is insecure. (Another is
329 * IP-spoofing on a local network.)
330 */
331 client_user = packet_get_string(&ulen);
332 packet_integrity_check(plen, 4 + ulen, type);
333
334 /* Try to authenticate using /etc/hosts.equiv and
335 .rhosts. */
336 authenticated = auth_rhosts(pw, client_user);
337
338 snprintf(user, sizeof user, " ruser %s", client_user);
339 break;
340
341 case SSH_CMSG_AUTH_RHOSTS_RSA:
342 if (!options.rhosts_rsa_authentication) {
343 verbose("Rhosts with RSA authentication disabled.");
344 break;
345 }
346 /*
347 * Get client user name. Note that we just have to
348 * trust the client; root on the client machine can
349 * claim to be any user.
350 */
351 client_user = packet_get_string(&ulen);
352
353 /* Get the client host key. */
354 client_host_key = RSA_new();
355 if (client_host_key == NULL)
356 fatal("RSA_new failed");
357 client_host_key->e = BN_new();
358 client_host_key->n = BN_new();
359 if (client_host_key->e == NULL || client_host_key->n == NULL)
360 fatal("BN_new failed");
361 bits = packet_get_int();
362 packet_get_bignum(client_host_key->e, &elen);
363 packet_get_bignum(client_host_key->n, &nlen);
364
365 if (bits != BN_num_bits(client_host_key->n))
366 error("Warning: keysize mismatch for client_host_key: "
367 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
368 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
369
370 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
371 RSA_free(client_host_key);
372
373 snprintf(user, sizeof user, " ruser %s", client_user);
374 break;
375
376 case SSH_CMSG_AUTH_RSA:
377 if (!options.rsa_authentication) {
378 verbose("RSA authentication disabled.");
379 break;
380 }
381 /* RSA authentication requested. */
382 n = BN_new();
383 packet_get_bignum(n, &nlen);
384 packet_integrity_check(plen, nlen, type);
385 authenticated = auth_rsa(pw, n);
386 BN_clear_free(n);
387 break;
388
389 case SSH_CMSG_AUTH_PASSWORD:
390 if (!options.password_authentication) {
391 verbose("Password authentication disabled.");
392 break;
393 }
394 /*
395 * Read user password. It is in plain text, but was
396 * transmitted over the encrypted channel so it is
397 * not visible to an outside observer.
398 */
399 password = packet_get_string(&dlen);
400 packet_integrity_check(plen, 4 + dlen, type);
401
402#ifdef USE_PAM
403 /* Do PAM auth with password */
404 authenticated = auth_pam_password(pw, password);
405#else /* USE_PAM */
406 /* Try authentication with the password. */
407 authenticated = auth_password(pw, password);
408#endif /* USE_PAM */
409 memset(password, 0, strlen(password));
410 xfree(password);
411 break;
412
413#ifdef SKEY
414 case SSH_CMSG_AUTH_TIS:
415 debug("rcvd SSH_CMSG_AUTH_TIS");
416 if (options.skey_authentication == 1) {
417 char *skeyinfo = skey_keyinfo(pw->pw_name);
418 if (skeyinfo == NULL) {
419 debug("generating fake skeyinfo for %.100s.", pw->pw_name);
420 skeyinfo = skey_fake_keyinfo(pw->pw_name);
421 }
422 if (skeyinfo != NULL) {
423 /* we send our s/key- in tis-challenge messages */
424 debug("sending challenge '%s'", skeyinfo);
425 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
426 packet_put_string(skeyinfo, strlen(skeyinfo));
427 packet_send();
428 packet_write_wait();
429 continue;
430 }
431 }
432 break;
433 case SSH_CMSG_AUTH_TIS_RESPONSE:
434 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
435 if (options.skey_authentication == 1) {
436 char *response = packet_get_string(&dlen);
437 debug("skey response == '%s'", response);
438 packet_integrity_check(plen, 4 + dlen, type);
439 authenticated = (skey_haskey(pw->pw_name) == 0 &&
440 skey_passcheck(pw->pw_name, response) != -1);
441 xfree(response);
442 }
443 break;
444#else
445 case SSH_CMSG_AUTH_TIS:
446 /* TIS Authentication is unsupported */
447 log("TIS authentication unsupported.");
448 break;
449#endif
450
451 default:
452 /*
453 * Any unknown messages will be ignored (and failure
454 * returned) during authentication.
455 */
456 log("Unknown message during authentication: type %d", type);
457 break;
458 }
459
460 /*
461 * Check if the user is logging in as root and root logins
462 * are disallowed.
463 * Note that root login is allowed for forced commands.
464 */
465 if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
466 if (forced_command) {
467 log("Root login accepted for forced command.");
468 } else {
469 authenticated = 0;
470 log("ROOT LOGIN REFUSED FROM %.200s",
471 get_canonical_hostname());
472 }
473 }
474
475 /* Raise logging level */
476 if (authenticated ||
477 attempt == AUTH_FAIL_LOG ||
478 type == SSH_CMSG_AUTH_PASSWORD)
479 authlog = log;
480
481 authlog("%s %s for %.200s from %.200s port %d%s",
482 authenticated ? "Accepted" : "Failed",
483 get_authname(type),
484 pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
485 get_remote_ipaddr(),
486 get_remote_port(),
487 user);
488
489#ifdef USE_PAM
490 if (authenticated) {
491 if (!do_pam_account(pw->pw_name, client_user)) {
492 if (client_user != NULL) {
493 xfree(client_user);
494 client_user = NULL;
495 }
496 do_fake_authloop1(pw->pw_name);
497 }
498 return;
499 }
500#else /* USE_PAM */
501 if (authenticated) {
502 return;
503 }
504#endif /* USE_PAM */
505
506 if (client_user != NULL) {
507 xfree(client_user);
508 client_user = NULL;
509 }
510
511 if (attempt > AUTH_FAIL_MAX)
512 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
513
514 /* Send a message indicating that the authentication attempt failed. */
515 packet_start(SSH_SMSG_FAILURE);
516 packet_send();
517 packet_write_wait();
518 }
519}
520
521/*
522 * Performs authentication of an incoming connection. Session key has already
523 * been exchanged and encryption is enabled.
524 */
525void
526do_authentication()
527{
528 struct passwd *pw, pwcopy;
529 int plen;
530 unsigned int ulen;
531 char *user;
532#ifdef WITH_AIXAUTHENTICATE
533 char *loginmsg;
534#endif /* WITH_AIXAUTHENTICATE */
535
536 /* Get the name of the user that we wish to log in as. */
537 packet_read_expect(&plen, SSH_CMSG_USER);
538
539 /* Get the user name. */
540 user = packet_get_string(&ulen);
541 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
542
543 setproctitle("%s", user);
544
545#ifdef AFS
546 /* If machine has AFS, set process authentication group. */
547 if (k_hasafs()) {
548 k_setpag();
549 k_unlog();
550 }
551#endif /* AFS */
552
553 /* Verify that the user is a valid user. */
554 pw = getpwnam(user);
555 if (!pw || !allowed_user(pw))
556 do_fake_authloop1(user);
557 xfree(user);
558
559 /* Take a copy of the returned structure. */
560 memset(&pwcopy, 0, sizeof(pwcopy));
561 pwcopy.pw_name = xstrdup(pw->pw_name);
562 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
563 pwcopy.pw_uid = pw->pw_uid;
564 pwcopy.pw_gid = pw->pw_gid;
565 pwcopy.pw_dir = xstrdup(pw->pw_dir);
566 pwcopy.pw_shell = xstrdup(pw->pw_shell);
567 pw = &pwcopy;
568
569#ifdef USE_PAM
570 start_pam(pw);
571#endif
572
573 /*
574 * If we are not running as root, the user must have the same uid as
575 * the server.
576 */
577 if (getuid() != 0 && pw->pw_uid != getuid())
578 packet_disconnect("Cannot change user when server not running as root.");
579
580 debug("Attempting authentication for %.100s.", pw->pw_name);
581
582 /* If the user has no password, accept authentication immediately. */
583 if (options.password_authentication &&
584#ifdef KRB4
585 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
586#endif /* KRB4 */
587#ifdef USE_PAM
588 auth_pam_password(pw, "")) {
589#else /* USE_PAM */
590 auth_password(pw, "")) {
591#endif /* USE_PAM */
592 /* Authentication with empty password succeeded. */
593 log("Login for user %s from %.100s, accepted without authentication.",
594 pw->pw_name, get_remote_ipaddr());
595 } else {
596 /* Loop until the user has been authenticated or the
597 connection is closed, do_authloop() returns only if
598 authentication is successfull */
599 do_authloop(pw);
600 }
601
602 /* The user has been authenticated and accepted. */
603#ifdef WITH_AIXAUTHENTICATE
604 loginsuccess(user,get_canonical_hostname(),"ssh",&loginmsg);
605#endif /* WITH_AIXAUTHENTICATE */
606 packet_start(SSH_SMSG_SUCCESS);
607 packet_send();
608 packet_write_wait();
609
610 /* Perform session preparation. */
611 do_authenticated(pw);
612}
613
614
615void input_service_request(int type, int plen);
616void input_userauth_request(int type, int plen);
617void ssh2_pty_cleanup(void);
618
619typedef struct Authctxt Authctxt;
620struct Authctxt {
621 char *user;
622 char *service;
623 struct passwd pw;
624 int valid;
625};
626static Authctxt *authctxt = NULL;
627static int userauth_success = 0;
628
629struct passwd*
630auth_get_user(void)
631{
632 return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL;
633}
634struct passwd*
635auth_set_user(char *u, char *s)
636{
637 struct passwd *pw, *copy;
638
639 if (authctxt == NULL) {
640 authctxt = xmalloc(sizeof(*authctxt));
641 authctxt->valid = 0;
642 authctxt->user = xstrdup(u);
643 authctxt->service = xstrdup(s);
644 setproctitle("%s", u);
645 pw = getpwnam(u);
646 if (!pw || !allowed_user(pw)) {
647 log("auth_set_user: bad user %s", u);
648 return NULL;
649 }
650#ifdef USE_PAM
651 start_pam(pw);
652#endif
653 copy = &authctxt->pw;
654 memset(copy, 0, sizeof(*copy));
655 copy->pw_name = xstrdup(pw->pw_name);
656 copy->pw_passwd = xstrdup(pw->pw_passwd);
657 copy->pw_uid = pw->pw_uid;
658 copy->pw_gid = pw->pw_gid;
659 copy->pw_dir = xstrdup(pw->pw_dir);
660 copy->pw_shell = xstrdup(pw->pw_shell);
661 authctxt->valid = 1;
662 } else {
663 if (strcmp(u, authctxt->user) != 0 ||
664 strcmp(s, authctxt->service) != 0) {
665 log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
666 u, s, authctxt->user, authctxt->service);
667 return NULL;
668 }
669 }
670 return auth_get_user();
671}
672
673static void
674protocol_error(int type, int plen)
675{
676 log("auth: protocol error: type %d plen %d", type, plen);
677 packet_start(SSH2_MSG_UNIMPLEMENTED);
678 packet_put_int(0);
679 packet_send();
680 packet_write_wait();
681}
682void
683input_service_request(int type, int plen)
684{
685 unsigned int len;
686 int accept = 0;
687 char *service = packet_get_string(&len);
688 packet_done();
689
690 if (strcmp(service, "ssh-userauth") == 0) {
691 if (!userauth_success) {
692 accept = 1;
693 /* now we can handle user-auth requests */
694 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
695 }
696 }
697 /* XXX all other service requests are denied */
698
699 if (accept) {
700 packet_start(SSH2_MSG_SERVICE_ACCEPT);
701 packet_put_cstring(service);
702 packet_send();
703 packet_write_wait();
704 } else {
705 debug("bad service request %s", service);
706 packet_disconnect("bad service request %s", service);
707 }
708 xfree(service);
709}
710void
711input_userauth_request(int type, int plen)
712{
713 static int try = 0;
714 unsigned int len;
715 int c, authenticated = 0;
716 char *user, *service, *method;
717 struct passwd *pw;
718
719 if (++try == AUTH_FAIL_MAX)
720 packet_disconnect("too many failed userauth_requests");
721
722 user = packet_get_string(&len);
723 service = packet_get_string(&len);
724 method = packet_get_string(&len);
725 debug("userauth-request for user %s service %s method %s", user, service, method);
726
727 /* XXX we only allow the ssh-connection service */
728 pw = auth_set_user(user, service);
729 if (pw && strcmp(service, "ssh-connection")==0) {
730 if (strcmp(method, "none") == 0 && try == 1) {
731 packet_done();
732#ifdef USE_PAM
733 /* Do PAM auth with password */
734 authenticated = auth_pam_password(pw, "");
735#else /* USE_PAM */
736 /* Try authentication with the password. */
737 authenticated = auth_password(pw, "");
738#endif /* USE_PAM */
739 } else if (strcmp(method, "password") == 0) {
740 char *password;
741 c = packet_get_char();
742 if (c)
743 debug("password change not supported");
744 password = packet_get_string(&len);
745 packet_done();
746#ifdef USE_PAM
747 /* Do PAM auth with password */
748 authenticated = auth_pam_password(pw, password);
749#else /* USE_PAM */
750 /* Try authentication with the password. */
751 authenticated = auth_password(pw, password);
752#endif /* USE_PAM */
753 memset(password, 0, len);
754 xfree(password);
755 } else if (strcmp(method, "publickey") == 0) {
756 /* XXX TODO */
757 char *pkalg, *pkblob, *sig;
758 int have_sig = packet_get_char();
759 pkalg = packet_get_string(&len);
760 pkblob = packet_get_string(&len);
761 if (have_sig) {
762 sig = packet_get_string(&len);
763 /* test for correct signature */
764 packet_done();
765 xfree(sig);
766 } else {
767 packet_done();
768 /* test whether pkalg/pkblob are acceptable */
769 }
770 xfree(pkalg);
771 xfree(pkblob);
772 }
773 }
774 /* XXX check if other auth methods are needed */
775 if (authenticated) {
776 /* turn off userauth */
777 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error);
778 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
779 packet_send();
780 packet_write_wait();
781 log("userauth success for %s", user);
782 /* now we can break out */
783 userauth_success = 1;
784 } else {
785 packet_start(SSH2_MSG_USERAUTH_FAILURE);
786 packet_put_cstring("password");
787 packet_put_char(0); /* partial success */
788 packet_send();
789 packet_write_wait();
790 }
791 xfree(service);
792 xfree(user);
793 xfree(method);
794}
795void
796do_authentication2()
797{
798 dispatch_init(&protocol_error);
799 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
800 dispatch_run(DISPATCH_BLOCK, &userauth_success);
801 do_authenticated2();
802}
diff --git a/auth.h b/auth.h
index 3771e826f..72126e099 100644
--- a/auth.h
+++ b/auth.h
@@ -7,4 +7,11 @@ void do_authentication2(void);
7struct passwd * 7struct passwd *
8auth_get_user(void); 8auth_get_user(void);
9 9
10int allowed_user(struct passwd * pw);;
11
12#define AUTH_FAIL_MAX 6
13#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
14#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
15
10#endif 16#endif
17
diff --git a/auth1.c b/auth1.c
new file mode 100644
index 000000000..ae5f1cd84
--- /dev/null
+++ b/auth1.c
@@ -0,0 +1,512 @@
1/*
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 * All rights reserved
4 */
5
6#include "includes.h"
7RCSID("$OpenBSD: auth1.c,v 1.1 2000/04/26 21:28:32 markus Exp $");
8
9#include "xmalloc.h"
10#include "rsa.h"
11#include "ssh.h"
12#include "packet.h"
13#include "buffer.h"
14#include "cipher.h"
15#include "mpaux.h"
16#include "servconf.h"
17#include "compat.h"
18#include "auth.h"
19#include "session.h"
20
21/* import */
22extern ServerOptions options;
23extern char *forced_command;
24
25/*
26 * convert ssh auth msg type into description
27 */
28char *
29get_authname(int type)
30{
31 static char buf[1024];
32 switch (type) {
33 case SSH_CMSG_AUTH_PASSWORD:
34 return "password";
35 case SSH_CMSG_AUTH_RSA:
36 return "rsa";
37 case SSH_CMSG_AUTH_RHOSTS_RSA:
38 return "rhosts-rsa";
39 case SSH_CMSG_AUTH_RHOSTS:
40 return "rhosts";
41#ifdef KRB4
42 case SSH_CMSG_AUTH_KERBEROS:
43 return "kerberos";
44#endif
45#ifdef SKEY
46 case SSH_CMSG_AUTH_TIS_RESPONSE:
47 return "s/key";
48#endif
49 }
50 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
51 return buf;
52}
53
54/*
55 * The user does not exist or access is denied,
56 * but fake indication that authentication is needed.
57 */
58void
59do_fake_authloop1(char *user)
60{
61 int attempt = 0;
62
63 log("Faking authloop for illegal user %.200s from %.200s port %d",
64 user,
65 get_remote_ipaddr(),
66 get_remote_port());
67
68#ifdef WITH_AIXAUTHENTICATE
69 if (strncmp(get_authname(type),"password",
70 strlen(get_authname(type))) == 0)
71 loginfailed(pw->pw_name,get_canonical_hostname(),"ssh");
72#endif /* WITH_AIXAUTHENTICATE */
73
74 /* Indicate that authentication is needed. */
75 packet_start(SSH_SMSG_FAILURE);
76 packet_send();
77 packet_write_wait();
78
79 /*
80 * Keep reading packets, and always respond with a failure. This is
81 * to avoid disclosing whether such a user really exists.
82 */
83 for (attempt = 1;; attempt++) {
84 /* Read a packet. This will not return if the client disconnects. */
85 int plen;
86#ifndef SKEY
87 (void)packet_read(&plen);
88#else /* SKEY */
89 int type = packet_read(&plen);
90 unsigned int dlen;
91 char *password, *skeyinfo;
92 password = NULL;
93 /* Try to send a fake s/key challenge. */
94 if (options.skey_authentication == 1 &&
95 (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
96 if (type == SSH_CMSG_AUTH_TIS) {
97 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
98 packet_put_string(skeyinfo, strlen(skeyinfo));
99 packet_send();
100 packet_write_wait();
101 continue;
102 } else if (type == SSH_CMSG_AUTH_PASSWORD &&
103 options.password_authentication &&
104 (password = packet_get_string(&dlen)) != NULL &&
105 dlen == 5 &&
106 strncasecmp(password, "s/key", 5) == 0 ) {
107 packet_send_debug(skeyinfo);
108 }
109 }
110 if (password != NULL)
111 xfree(password);
112#endif
113 if (attempt > AUTH_FAIL_MAX)
114 packet_disconnect(AUTH_FAIL_MSG, user);
115
116 /*
117 * Send failure. This should be indistinguishable from a
118 * failed authentication.
119 */
120 packet_start(SSH_SMSG_FAILURE);
121 packet_send();
122 packet_write_wait();
123 }
124 /* NOTREACHED */
125 abort();
126}
127
128/*
129 * read packets and try to authenticate local user *pw.
130 * return if authentication is successfull
131 */
132void
133do_authloop(struct passwd * pw)
134{
135 int attempt = 0;
136 unsigned int bits;
137 RSA *client_host_key;
138 BIGNUM *n;
139 char *client_user = NULL, *password = NULL;
140 char user[1024];
141 unsigned int dlen;
142 int plen, nlen, elen;
143 unsigned int ulen;
144 int type = 0;
145 void (*authlog) (const char *fmt,...) = verbose;
146
147 /* Indicate that authentication is needed. */
148 packet_start(SSH_SMSG_FAILURE);
149 packet_send();
150 packet_write_wait();
151
152 for (attempt = 1;; attempt++) {
153 int authenticated = 0;
154 strlcpy(user, "", sizeof user);
155
156 /* Get a packet from the client. */
157 type = packet_read(&plen);
158
159 /* Process the packet. */
160 switch (type) {
161#ifdef AFS
162 case SSH_CMSG_HAVE_KERBEROS_TGT:
163 if (!options.kerberos_tgt_passing) {
164 /* packet_get_all(); */
165 verbose("Kerberos tgt passing disabled.");
166 break;
167 } else {
168 /* Accept Kerberos tgt. */
169 char *tgt = packet_get_string(&dlen);
170 packet_integrity_check(plen, 4 + dlen, type);
171 if (!auth_kerberos_tgt(pw, tgt))
172 verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
173 xfree(tgt);
174 }
175 continue;
176
177 case SSH_CMSG_HAVE_AFS_TOKEN:
178 if (!options.afs_token_passing || !k_hasafs()) {
179 /* packet_get_all(); */
180 verbose("AFS token passing disabled.");
181 break;
182 } else {
183 /* Accept AFS token. */
184 char *token_string = packet_get_string(&dlen);
185 packet_integrity_check(plen, 4 + dlen, type);
186 if (!auth_afs_token(pw, token_string))
187 verbose("AFS token REFUSED for %s", pw->pw_name);
188 xfree(token_string);
189 }
190 continue;
191#endif /* AFS */
192#ifdef KRB4
193 case SSH_CMSG_AUTH_KERBEROS:
194 if (!options.kerberos_authentication) {
195 /* packet_get_all(); */
196 verbose("Kerberos authentication disabled.");
197 break;
198 } else {
199 /* Try Kerberos v4 authentication. */
200 KTEXT_ST auth;
201 char *tkt_user = NULL;
202 char *kdata = packet_get_string((unsigned int *) &auth.length);
203 packet_integrity_check(plen, 4 + auth.length, type);
204
205 if (auth.length < MAX_KTXT_LEN)
206 memcpy(auth.dat, kdata, auth.length);
207 xfree(kdata);
208
209 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
210
211 if (authenticated) {
212 snprintf(user, sizeof user, " tktuser %s", tkt_user);
213 xfree(tkt_user);
214 }
215 }
216 break;
217#endif /* KRB4 */
218
219 case SSH_CMSG_AUTH_RHOSTS:
220 if (!options.rhosts_authentication) {
221 verbose("Rhosts authentication disabled.");
222 break;
223 }
224 /*
225 * Get client user name. Note that we just have to
226 * trust the client; this is one reason why rhosts
227 * authentication is insecure. (Another is
228 * IP-spoofing on a local network.)
229 */
230 client_user = packet_get_string(&ulen);
231 packet_integrity_check(plen, 4 + ulen, type);
232
233 /* Try to authenticate using /etc/hosts.equiv and
234 .rhosts. */
235 authenticated = auth_rhosts(pw, client_user);
236
237 snprintf(user, sizeof user, " ruser %s", client_user);
238 break;
239
240 case SSH_CMSG_AUTH_RHOSTS_RSA:
241 if (!options.rhosts_rsa_authentication) {
242 verbose("Rhosts with RSA authentication disabled.");
243 break;
244 }
245 /*
246 * Get client user name. Note that we just have to
247 * trust the client; root on the client machine can
248 * claim to be any user.
249 */
250 client_user = packet_get_string(&ulen);
251
252 /* Get the client host key. */
253 client_host_key = RSA_new();
254 if (client_host_key == NULL)
255 fatal("RSA_new failed");
256 client_host_key->e = BN_new();
257 client_host_key->n = BN_new();
258 if (client_host_key->e == NULL || client_host_key->n == NULL)
259 fatal("BN_new failed");
260 bits = packet_get_int();
261 packet_get_bignum(client_host_key->e, &elen);
262 packet_get_bignum(client_host_key->n, &nlen);
263
264 if (bits != BN_num_bits(client_host_key->n))
265 error("Warning: keysize mismatch for client_host_key: "
266 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
267 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
268
269 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
270 RSA_free(client_host_key);
271
272 snprintf(user, sizeof user, " ruser %s", client_user);
273 break;
274
275 case SSH_CMSG_AUTH_RSA:
276 if (!options.rsa_authentication) {
277 verbose("RSA authentication disabled.");
278 break;
279 }
280 /* RSA authentication requested. */
281 n = BN_new();
282 packet_get_bignum(n, &nlen);
283 packet_integrity_check(plen, nlen, type);
284 authenticated = auth_rsa(pw, n);
285 BN_clear_free(n);
286 break;
287
288 case SSH_CMSG_AUTH_PASSWORD:
289 if (!options.password_authentication) {
290 verbose("Password authentication disabled.");
291 break;
292 }
293 /*
294 * Read user password. It is in plain text, but was
295 * transmitted over the encrypted channel so it is
296 * not visible to an outside observer.
297 */
298 password = packet_get_string(&dlen);
299 packet_integrity_check(plen, 4 + dlen, type);
300
301#ifdef USE_PAM
302 /* Do PAM auth with password */
303 authenticated = auth_pam_password(pw, password);
304#else /* USE_PAM */
305 /* Try authentication with the password. */
306 authenticated = auth_password(pw, password);
307#endif /* USE_PAM */
308
309 memset(password, 0, strlen(password));
310 xfree(password);
311 break;
312
313#ifdef SKEY
314 case SSH_CMSG_AUTH_TIS:
315 debug("rcvd SSH_CMSG_AUTH_TIS");
316 if (options.skey_authentication == 1) {
317 char *skeyinfo = skey_keyinfo(pw->pw_name);
318 if (skeyinfo == NULL) {
319 debug("generating fake skeyinfo for %.100s.", pw->pw_name);
320 skeyinfo = skey_fake_keyinfo(pw->pw_name);
321 }
322 if (skeyinfo != NULL) {
323 /* we send our s/key- in tis-challenge messages */
324 debug("sending challenge '%s'", skeyinfo);
325 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
326 packet_put_string(skeyinfo, strlen(skeyinfo));
327 packet_send();
328 packet_write_wait();
329 continue;
330 }
331 }
332 break;
333 case SSH_CMSG_AUTH_TIS_RESPONSE:
334 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
335 if (options.skey_authentication == 1) {
336 char *response = packet_get_string(&dlen);
337 debug("skey response == '%s'", response);
338 packet_integrity_check(plen, 4 + dlen, type);
339 authenticated = (skey_haskey(pw->pw_name) == 0 &&
340 skey_passcheck(pw->pw_name, response) != -1);
341 xfree(response);
342 }
343 break;
344#else
345 case SSH_CMSG_AUTH_TIS:
346 /* TIS Authentication is unsupported */
347 log("TIS authentication unsupported.");
348 break;
349#endif
350
351 default:
352 /*
353 * Any unknown messages will be ignored (and failure
354 * returned) during authentication.
355 */
356 log("Unknown message during authentication: type %d", type);
357 break;
358 }
359
360 /*
361 * Check if the user is logging in as root and root logins
362 * are disallowed.
363 * Note that root login is allowed for forced commands.
364 */
365 if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
366 if (forced_command) {
367 log("Root login accepted for forced command.");
368 } else {
369 authenticated = 0;
370 log("ROOT LOGIN REFUSED FROM %.200s",
371 get_canonical_hostname());
372 }
373 }
374
375 /* Raise logging level */
376 if (authenticated ||
377 attempt == AUTH_FAIL_LOG ||
378 type == SSH_CMSG_AUTH_PASSWORD)
379 authlog = log;
380
381 authlog("%s %s for %.200s from %.200s port %d%s",
382 authenticated ? "Accepted" : "Failed",
383 get_authname(type),
384 pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
385 get_remote_ipaddr(),
386 get_remote_port(),
387 user);
388
389#ifdef USE_PAM
390 if (authenticated) {
391 if (!do_pam_account(pw->pw_name, client_user)) {
392 if (client_user != NULL) {
393 xfree(client_user);
394 client_user = NULL;
395 }
396 do_fake_authloop1(pw->pw_name);
397 }
398 return;
399 }
400#else /* USE_PAM */
401 if (authenticated) {
402 return;
403 }
404#endif /* USE_PAM */
405
406 if (client_user != NULL) {
407 xfree(client_user);
408 client_user = NULL;
409 }
410
411 if (attempt > AUTH_FAIL_MAX)
412 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
413
414 /* Send a message indicating that the authentication attempt failed. */
415 packet_start(SSH_SMSG_FAILURE);
416 packet_send();
417 packet_write_wait();
418 }
419}
420
421/*
422 * Performs authentication of an incoming connection. Session key has already
423 * been exchanged and encryption is enabled.
424 */
425void
426do_authentication()
427{
428 struct passwd *pw, pwcopy;
429 int plen;
430 unsigned int ulen;
431 char *user;
432#ifdef WITH_AIXAUTHENTICATE
433 char *loginmsg;
434#endif /* WITH_AIXAUTHENTICATE */
435
436 /* Get the name of the user that we wish to log in as. */
437 packet_read_expect(&plen, SSH_CMSG_USER);
438
439 /* Get the user name. */
440 user = packet_get_string(&ulen);
441 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
442
443 setproctitle("%s", user);
444
445#ifdef AFS
446 /* If machine has AFS, set process authentication group. */
447 if (k_hasafs()) {
448 k_setpag();
449 k_unlog();
450 }
451#endif /* AFS */
452
453 /* Verify that the user is a valid user. */
454 pw = getpwnam(user);
455 if (!pw || !allowed_user(pw))
456 do_fake_authloop1(user);
457 xfree(user);
458
459 /* Take a copy of the returned structure. */
460 memset(&pwcopy, 0, sizeof(pwcopy));
461 pwcopy.pw_name = xstrdup(pw->pw_name);
462 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
463 pwcopy.pw_uid = pw->pw_uid;
464 pwcopy.pw_gid = pw->pw_gid;
465 pwcopy.pw_dir = xstrdup(pw->pw_dir);
466 pwcopy.pw_shell = xstrdup(pw->pw_shell);
467 pw = &pwcopy;
468
469#ifdef USE_PAM
470 start_pam(pw);
471#endif
472
473 /*
474 * If we are not running as root, the user must have the same uid as
475 * the server.
476 */
477 if (getuid() != 0 && pw->pw_uid != getuid())
478 packet_disconnect("Cannot change user when server not running as root.");
479
480 debug("Attempting authentication for %.100s.", pw->pw_name);
481
482 /* If the user has no password, accept authentication immediately. */
483 if (options.password_authentication &&
484#ifdef KRB4
485 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
486#endif /* KRB4 */
487#ifdef USE_PAM
488 auth_pam_password(pw, "")) {
489#else /* USE_PAM */
490 auth_password(pw, "")) {
491#endif /* USE_PAM */
492 /* Authentication with empty password succeeded. */
493 log("Login for user %s from %.100s, accepted without authentication.",
494 pw->pw_name, get_remote_ipaddr());
495 } else {
496 /* Loop until the user has been authenticated or the
497 connection is closed, do_authloop() returns only if
498 authentication is successfull */
499 do_authloop(pw);
500 }
501
502 /* The user has been authenticated and accepted. */
503#ifdef WITH_AIXAUTHENTICATE
504 loginsuccess(user,get_canonical_hostname(),"ssh",&loginmsg);
505#endif /* WITH_AIXAUTHENTICATE */
506 packet_start(SSH_SMSG_SUCCESS);
507 packet_send();
508 packet_write_wait();
509
510 /* Perform session preparation. */
511 do_authenticated(pw);
512}
diff --git a/auth2.c b/auth2.c
new file mode 100644
index 000000000..9937ed678
--- /dev/null
+++ b/auth2.c
@@ -0,0 +1,459 @@
1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Markus Friedl.
15 * 4. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#include "includes.h"
30RCSID("$OpenBSD: auth2.c,v 1.3 2000/04/27 15:23:02 markus Exp $");
31
32#include <openssl/dsa.h>
33#include <openssl/rsa.h>
34#include <openssl/evp.h>
35
36#include "xmalloc.h"
37#include "rsa.h"
38#include "ssh.h"
39#include "pty.h"
40#include "packet.h"
41#include "buffer.h"
42#include "cipher.h"
43#include "servconf.h"
44#include "compat.h"
45#include "channels.h"
46#include "bufaux.h"
47#include "ssh2.h"
48#include "auth.h"
49#include "session.h"
50#include "dispatch.h"
51#include "auth.h"
52#include "key.h"
53#include "kex.h"
54
55#include "dsa.h"
56#include "uidswap.h"
57
58/* import */
59extern ServerOptions options;
60extern unsigned char *session_id2;
61extern int session_id2_len;
62
63/* protocol */
64
65void input_service_request(int type, int plen);
66void input_userauth_request(int type, int plen);
67void protocol_error(int type, int plen);
68
69/* auth */
70int ssh2_auth_none(struct passwd *pw);
71int ssh2_auth_password(struct passwd *pw);
72int ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen);
73
74/* helper */
75struct passwd* auth_set_user(char *u, char *s);
76int user_dsa_key_allowed(struct passwd *pw, Key *key);
77
78typedef struct Authctxt Authctxt;
79struct Authctxt {
80 char *user;
81 char *service;
82 struct passwd pw;
83 int valid;
84};
85static Authctxt *authctxt = NULL;
86static int userauth_success = 0;
87
88/*
89 * loop until userauth_success == TRUE
90 */
91
92void
93do_authentication2()
94{
95 dispatch_init(&protocol_error);
96 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
97 dispatch_run(DISPATCH_BLOCK, &userauth_success);
98 do_authenticated2();
99}
100
101void
102protocol_error(int type, int plen)
103{
104 log("auth: protocol error: type %d plen %d", type, plen);
105 packet_start(SSH2_MSG_UNIMPLEMENTED);
106 packet_put_int(0);
107 packet_send();
108 packet_write_wait();
109}
110
111void
112input_service_request(int type, int plen)
113{
114 unsigned int len;
115 int accept = 0;
116 char *service = packet_get_string(&len);
117 packet_done();
118
119 if (strcmp(service, "ssh-userauth") == 0) {
120 if (!userauth_success) {
121 accept = 1;
122 /* now we can handle user-auth requests */
123 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
124 }
125 }
126 /* XXX all other service requests are denied */
127
128 if (accept) {
129 packet_start(SSH2_MSG_SERVICE_ACCEPT);
130 packet_put_cstring(service);
131 packet_send();
132 packet_write_wait();
133 } else {
134 debug("bad service request %s", service);
135 packet_disconnect("bad service request %s", service);
136 }
137 xfree(service);
138}
139
140void
141input_userauth_request(int type, int plen)
142{
143 static void (*authlog) (const char *fmt,...) = verbose;
144 static int attempt = 0;
145 unsigned int len, rlen;
146 int authenticated = 0;
147 char *raw, *user, *service, *method, *authmsg = NULL;
148 struct passwd *pw;
149
150 if (++attempt == AUTH_FAIL_MAX)
151 packet_disconnect("too many failed userauth_requests");
152
153 raw = packet_get_raw(&rlen);
154 if (plen != rlen)
155 fatal("plen != rlen");
156 user = packet_get_string(&len);
157 service = packet_get_string(&len);
158 method = packet_get_string(&len);
159 debug("userauth-request for user %s service %s method %s", user, service, method);
160
161 /* XXX we only allow the ssh-connection service */
162 pw = auth_set_user(user, service);
163 if (pw && strcmp(service, "ssh-connection")==0) {
164 if (strcmp(method, "none") == 0) {
165 authenticated = ssh2_auth_none(pw);
166 } else if (strcmp(method, "password") == 0) {
167 authenticated = ssh2_auth_password(pw);
168 } else if (strcmp(method, "publickey") == 0) {
169 authenticated = ssh2_auth_pubkey(pw, raw, rlen);
170 }
171 }
172 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
173 authenticated = 0;
174 log("ROOT LOGIN REFUSED FROM %.200s",
175 get_canonical_hostname());
176 }
177
178#ifdef USE_PAM
179 if (authenticated && !do_pam_account(pw->pw_name, NULL))
180 authenticated = 0;
181#endif /* USE_PAM */
182
183 /* XXX todo: check if multiple auth methods are needed */
184 if (authenticated == 1) {
185 authmsg = "Accepted";
186 /* turn off userauth */
187 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error);
188 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
189 packet_send();
190 packet_write_wait();
191 /* now we can break out */
192 userauth_success = 1;
193 } else if (authenticated == 0) {
194 authmsg = "Failed";
195 packet_start(SSH2_MSG_USERAUTH_FAILURE);
196 packet_put_cstring("publickey,password"); /* XXX dynamic */
197 packet_put_char(0); /* XXX partial success, unused */
198 packet_send();
199 packet_write_wait();
200 } else {
201 authmsg = "Postponed";
202 }
203 /* Raise logging level */
204 if (authenticated == 1||
205 attempt == AUTH_FAIL_LOG ||
206 strcmp(method, "password") == 0)
207 authlog = log;
208
209 authlog("%s %s for %.200s from %.200s port %d ssh2",
210 authmsg,
211 method,
212 pw && pw->pw_uid == 0 ? "ROOT" : user,
213 get_remote_ipaddr(),
214 get_remote_port());
215
216 xfree(service);
217 xfree(user);
218 xfree(method);
219}
220
221int
222ssh2_auth_none(struct passwd *pw)
223{
224 packet_done();
225#ifdef USE_PAM
226 return auth_pam_password(pw, "");
227#else /* USE_PAM */
228 return auth_password(pw, "");
229#endif /* USE_PAM */
230}
231int
232ssh2_auth_password(struct passwd *pw)
233{
234 char *password;
235 int authenticated = 0;
236 int change;
237 unsigned int len;
238 change = packet_get_char();
239 if (change)
240 log("password change not supported");
241 password = packet_get_string(&len);
242 packet_done();
243 if (options.password_authentication &&
244#ifdef USE_PAM
245 auth_pam_password(pw, password) == 1)
246#else /* USE_PAM */
247 auth_password(pw, password) == 1)
248#endif /* USE_PAM */
249 authenticated = 1;
250 memset(password, 0, len);
251 xfree(password);
252 return authenticated;
253}
254int
255ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
256{
257 Buffer b;
258 Key *key;
259 char *pkalg, *pkblob, *sig;
260 unsigned int alen, blen, slen;
261 int have_sig;
262 int authenticated = 0;
263
264 if (options.rsa_authentication == 0) {
265 debug("pubkey auth disabled");
266 return 0;
267 }
268 have_sig = packet_get_char();
269 pkalg = packet_get_string(&alen);
270 if (strcmp(pkalg, KEX_DSS) != 0) {
271 xfree(pkalg);
272 log("bad pkalg %s", pkalg); /*XXX*/
273 return 0;
274 }
275 pkblob = packet_get_string(&blen);
276 key = dsa_key_from_blob(pkblob, blen);
277 if (key != NULL) {
278 if (have_sig) {
279 sig = packet_get_string(&slen);
280 packet_done();
281 buffer_init(&b);
282 buffer_append(&b, session_id2, session_id2_len);
283 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
284 if (slen + 4 > rlen)
285 fatal("bad rlen/slen");
286 buffer_append(&b, raw, rlen - slen - 4);
287#ifdef DEBUG_DSS
288 buffer_dump(&b);
289#endif
290 /* test for correct signature */
291 if (user_dsa_key_allowed(pw, key) &&
292 dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
293 authenticated = 1;
294 buffer_clear(&b);
295 xfree(sig);
296 } else {
297 packet_done();
298 debug("test key...");
299 /* test whether pkalg/pkblob are acceptable */
300 /* XXX fake reply and always send PK_OK ? */
301 if (user_dsa_key_allowed(pw, key)) {
302 packet_start(SSH2_MSG_USERAUTH_PK_OK);
303 packet_put_string(pkalg, alen);
304 packet_put_string(pkblob, blen);
305 packet_send();
306 packet_write_wait();
307 authenticated = -1;
308 }
309 }
310 key_free(key);
311 }
312 xfree(pkalg);
313 xfree(pkblob);
314 return authenticated;
315}
316
317/* set and get current user */
318
319struct passwd*
320auth_get_user(void)
321{
322 return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL;
323}
324
325struct passwd*
326auth_set_user(char *u, char *s)
327{
328 struct passwd *pw, *copy;
329
330 if (authctxt == NULL) {
331 authctxt = xmalloc(sizeof(*authctxt));
332 authctxt->valid = 0;
333 authctxt->user = xstrdup(u);
334 authctxt->service = xstrdup(s);
335 setproctitle("%s", u);
336 pw = getpwnam(u);
337 if (!pw || !allowed_user(pw)) {
338 log("auth_set_user: illegal user %s", u);
339 return NULL;
340 }
341#ifdef USE_PAM
342 start_pam(pw);
343#endif
344 copy = &authctxt->pw;
345 memset(copy, 0, sizeof(*copy));
346 copy->pw_name = xstrdup(pw->pw_name);
347 copy->pw_passwd = xstrdup(pw->pw_passwd);
348 copy->pw_uid = pw->pw_uid;
349 copy->pw_gid = pw->pw_gid;
350 copy->pw_dir = xstrdup(pw->pw_dir);
351 copy->pw_shell = xstrdup(pw->pw_shell);
352 authctxt->valid = 1;
353 } else {
354 if (strcmp(u, authctxt->user) != 0 ||
355 strcmp(s, authctxt->service) != 0) {
356 log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
357 u, s, authctxt->user, authctxt->service);
358 return NULL;
359 }
360 }
361 return auth_get_user();
362}
363
364/* return 1 if user allows given key */
365int
366user_dsa_key_allowed(struct passwd *pw, Key *key)
367{
368 char line[8192], file[1024];
369 int found_key = 0;
370 unsigned int bits = -1;
371 FILE *f;
372 unsigned long linenum = 0;
373 struct stat st;
374 Key *found;
375
376 /* Temporarily use the user's uid. */
377 temporarily_use_uid(pw->pw_uid);
378
379 /* The authorized keys. */
380 snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
381 SSH_USER_PERMITTED_KEYS2);
382
383 /* Fail quietly if file does not exist */
384 if (stat(file, &st) < 0) {
385 /* Restore the privileged uid. */
386 restore_uid();
387 return 0;
388 }
389 /* Open the file containing the authorized keys. */
390 f = fopen(file, "r");
391 if (!f) {
392 /* Restore the privileged uid. */
393 restore_uid();
394 return 0;
395 }
396 if (options.strict_modes) {
397 int fail = 0;
398 char buf[1024];
399 /* Check open file in order to avoid open/stat races */
400 if (fstat(fileno(f), &st) < 0 ||
401 (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
402 (st.st_mode & 022) != 0) {
403 snprintf(buf, sizeof buf, "DSA authentication refused for %.100s: "
404 "bad ownership or modes for '%s'.", pw->pw_name, file);
405 fail = 1;
406 } else {
407 /* Check path to SSH_USER_PERMITTED_KEYS */
408 int i;
409 static const char *check[] = {
410 "", SSH_USER_DIR, NULL
411 };
412 for (i = 0; check[i]; i++) {
413 snprintf(line, sizeof line, "%.500s/%.100s",
414 pw->pw_dir, check[i]);
415 if (stat(line, &st) < 0 ||
416 (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
417 (st.st_mode & 022) != 0) {
418 snprintf(buf, sizeof buf,
419 "DSA authentication refused for %.100s: "
420 "bad ownership or modes for '%s'.",
421 pw->pw_name, line);
422 fail = 1;
423 break;
424 }
425 }
426 }
427 if (fail) {
428 log(buf);
429 fclose(f);
430 restore_uid();
431 return 0;
432 }
433 }
434 found_key = 0;
435 found = key_new(KEY_DSA);
436
437 while (fgets(line, sizeof(line), f)) {
438 char *cp;
439 linenum++;
440 /* Skip leading whitespace, empty and comment lines. */
441 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
442 ;
443 if (!*cp || *cp == '\n' || *cp == '#')
444 continue;
445 bits = key_read(found, &cp);
446 if (bits == 0)
447 continue;
448 if (key_equal(found, key)) {
449 found_key = 1;
450 debug("matching key found: file %s, line %ld",
451 file, linenum);
452 break;
453 }
454 }
455 restore_uid();
456 fclose(f);
457 key_free(found);
458 return found_key;
459}
diff --git a/authfile.c b/authfile.c
index e17c60381..f93c9d470 100644
--- a/authfile.c
+++ b/authfile.c
@@ -15,14 +15,20 @@
15 */ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: authfile.c,v 1.11 2000/04/16 02:31:49 damien Exp $"); 18RCSID("$Id: authfile.c,v 1.12 2000/04/29 13:57:10 damien Exp $");
19 19
20#include <openssl/bn.h> 20#include <openssl/bn.h>
21#include <openssl/dsa.h>
22#include <openssl/rsa.h>
23#include <openssl/pem.h>
24#include <openssl/evp.h>
25
21#include "xmalloc.h" 26#include "xmalloc.h"
22#include "buffer.h" 27#include "buffer.h"
23#include "bufaux.h" 28#include "bufaux.h"
24#include "cipher.h" 29#include "cipher.h"
25#include "ssh.h" 30#include "ssh.h"
31#include "key.h"
26 32
27/* Version identification string for identity files. */ 33/* Version identification string for identity files. */
28#define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n" 34#define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n"
@@ -35,8 +41,8 @@ RCSID("$Id: authfile.c,v 1.11 2000/04/16 02:31:49 damien Exp $");
35 */ 41 */
36 42
37int 43int
38save_private_key(const char *filename, const char *passphrase, 44save_private_key_rsa(const char *filename, const char *passphrase,
39 RSA *key, const char *comment) 45 RSA *key, const char *comment)
40{ 46{
41 Buffer buffer, encrypted; 47 Buffer buffer, encrypted;
42 char buf[100], *cp; 48 char buf[100], *cp;
@@ -128,6 +134,63 @@ save_private_key(const char *filename, const char *passphrase,
128 return 1; 134 return 1;
129} 135}
130 136
137/* save DSA key in OpenSSL PEM format */
138
139int
140save_private_key_dsa(const char *filename, const char *passphrase,
141 DSA *dsa, const char *comment)
142{
143 FILE *fp;
144 int fd;
145 int success = 1;
146 int len = strlen(passphrase);
147
148 if (len > 0 && len <= 4) {
149 error("passphrase too short: %d bytes", len);
150 errno = 0;
151 return 0;
152 }
153 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
154 if (fd < 0) {
155 debug("open %s failed", filename);
156 return 0;
157 }
158 fp = fdopen(fd, "w");
159 if (fp == NULL ) {
160 debug("fdopen %s failed", filename);
161 close(fd);
162 return 0;
163 }
164 if (len > 0) {
165 if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(),
166 (char *)passphrase, strlen(passphrase), NULL, NULL))
167 success = 0;
168 } else {
169 if (!PEM_write_DSAPrivateKey(fp, dsa, NULL,
170 NULL, 0, NULL, NULL))
171 success = 0;
172 }
173 fclose(fp);
174 return success;
175}
176
177int
178save_private_key(const char *filename, const char *passphrase, Key *key,
179 const char *comment)
180{
181 switch (key->type) {
182 case KEY_RSA:
183 return save_private_key_rsa(filename, passphrase, key->rsa, comment);
184 break;
185 case KEY_DSA:
186 return save_private_key_dsa(filename, passphrase, key->dsa, comment);
187 break;
188 default:
189 break;
190 }
191 return 0;
192}
193
131/* 194/*
132 * Loads the public part of the key file. Returns 0 if an error was 195 * Loads the public part of the key file. Returns 0 if an error was
133 * encountered (the file does not exist or is not readable), and non-zero 196 * encountered (the file does not exist or is not readable), and non-zero
@@ -135,8 +198,7 @@ save_private_key(const char *filename, const char *passphrase,
135 */ 198 */
136 199
137int 200int
138load_public_key(const char *filename, RSA * pub, 201load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
139 char **comment_return)
140{ 202{
141 int fd, i; 203 int fd, i;
142 off_t len; 204 off_t len;
@@ -154,7 +216,7 @@ load_public_key(const char *filename, RSA * pub,
154 216
155 if (read(fd, cp, (size_t) len) != (size_t) len) { 217 if (read(fd, cp, (size_t) len) != (size_t) len) {
156 debug("Read from key file %.200s failed: %.100s", filename, 218 debug("Read from key file %.200s failed: %.100s", filename,
157 strerror(errno)); 219 strerror(errno));
158 buffer_free(&buffer); 220 buffer_free(&buffer);
159 close(fd); 221 close(fd);
160 return 0; 222 return 0;
@@ -183,9 +245,13 @@ load_public_key(const char *filename, RSA * pub,
183 245
184 /* Read the public key from the buffer. */ 246 /* Read the public key from the buffer. */
185 buffer_get_int(&buffer); 247 buffer_get_int(&buffer);
186 pub->n = BN_new(); 248 /* XXX alloc */
249 if (pub->n == NULL)
250 pub->n = BN_new();
187 buffer_get_bignum(&buffer, pub->n); 251 buffer_get_bignum(&buffer, pub->n);
188 pub->e = BN_new(); 252 /* XXX alloc */
253 if (pub->e == NULL)
254 pub->e = BN_new();
189 buffer_get_bignum(&buffer, pub->e); 255 buffer_get_bignum(&buffer, pub->e);
190 if (comment_return) 256 if (comment_return)
191 *comment_return = buffer_get_string(&buffer, NULL); 257 *comment_return = buffer_get_string(&buffer, NULL);
@@ -196,6 +262,20 @@ load_public_key(const char *filename, RSA * pub,
196 return 1; 262 return 1;
197} 263}
198 264
265int
266load_public_key(const char *filename, Key * key, char **comment_return)
267{
268 switch (key->type) {
269 case KEY_RSA:
270 return load_public_key_rsa(filename, key->rsa, comment_return);
271 break;
272 case KEY_DSA:
273 default:
274 break;
275 }
276 return 0;
277}
278
199/* 279/*
200 * Loads the private key from the file. Returns 0 if an error is encountered 280 * Loads the private key from the file. Returns 0 if an error is encountered
201 * (file does not exist or is not readable, or passphrase is bad). This 281 * (file does not exist or is not readable, or passphrase is bad). This
@@ -204,35 +284,17 @@ load_public_key(const char *filename, RSA * pub,
204 */ 284 */
205 285
206int 286int
207load_private_key(const char *filename, const char *passphrase, 287load_private_key_rsa(int fd, const char *filename,
208 RSA * prv, char **comment_return) 288 const char *passphrase, RSA * prv, char **comment_return)
209{ 289{
210 int fd, i, check1, check2, cipher_type; 290 int i, check1, check2, cipher_type;
211 off_t len; 291 off_t len;
212 Buffer buffer, decrypted; 292 Buffer buffer, decrypted;
213 char *cp; 293 char *cp;
214 CipherContext cipher; 294 CipherContext cipher;
215 BN_CTX *ctx; 295 BN_CTX *ctx;
216 BIGNUM *aux; 296 BIGNUM *aux;
217 struct stat st;
218
219 fd = open(filename, O_RDONLY);
220 if (fd < 0)
221 return 0;
222 297
223 /* check owner and modes */
224 if (fstat(fd, &st) < 0 ||
225 (st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) ||
226 (st.st_mode & 077) != 0) {
227 close(fd);
228 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
229 error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
230 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
231 error("Bad ownership or mode(0%3.3o) for '%s'.",
232 st.st_mode & 0777, filename);
233 error("It is recommended that your private key files are NOT accessible by others.");
234 return 0;
235 }
236 len = lseek(fd, (off_t) 0, SEEK_END); 298 len = lseek(fd, (off_t) 0, SEEK_END);
237 lseek(fd, (off_t) 0, SEEK_SET); 299 lseek(fd, (off_t) 0, SEEK_SET);
238 300
@@ -309,7 +371,9 @@ load_private_key(const char *filename, const char *passphrase,
309 buffer_free(&decrypted); 371 buffer_free(&decrypted);
310fail: 372fail:
311 BN_clear_free(prv->n); 373 BN_clear_free(prv->n);
374 prv->n = NULL;
312 BN_clear_free(prv->e); 375 BN_clear_free(prv->e);
376 prv->e = NULL;
313 if (comment_return) 377 if (comment_return)
314 xfree(*comment_return); 378 xfree(*comment_return);
315 return 0; 379 return 0;
@@ -343,3 +407,87 @@ fail:
343 407
344 return 1; 408 return 1;
345} 409}
410
411int
412load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return)
413{
414 DSA *dsa;
415 BIO *in;
416 FILE *fp;
417
418 in = BIO_new(BIO_s_file());
419 if (in == NULL) {
420 error("BIO_new failed");
421 return 0;
422 }
423 fp = fdopen(fd, "r");
424 if (fp == NULL) {
425 error("fdopen failed");
426 return 0;
427 }
428 BIO_set_fp(in, fp, BIO_NOCLOSE);
429 dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase);
430 if (dsa == NULL) {
431 debug("PEM_read_bio_DSAPrivateKey failed");
432 } else {
433 /* replace k->dsa with loaded key */
434 DSA_free(k->dsa);
435 k->dsa = dsa;
436 }
437 BIO_free(in);
438 fclose(fp);
439 if (comment_return)
440 *comment_return = xstrdup("dsa w/o comment");
441 debug("read DSA private key done");
442#ifdef DEBUG_DSS
443 DSA_print_fp(stderr, dsa, 8);
444#endif
445 return dsa != NULL ? 1 : 0;
446}
447
448int
449load_private_key(const char *filename, const char *passphrase, Key *key,
450 char **comment_return)
451{
452 int fd;
453 int ret = 0;
454 struct stat st;
455
456 fd = open(filename, O_RDONLY);
457 if (fd < 0)
458 return 0;
459
460 /* check owner and modes */
461 if (fstat(fd, &st) < 0 ||
462 (st.st_uid != 0 && st.st_uid != getuid()) ||
463 (st.st_mode & 077) != 0) {
464 close(fd);
465 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
466 error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
467 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
468 error("Bad ownership or mode(0%3.3o) for '%s'.",
469 st.st_mode & 0777, filename);
470 error("It is recommended that your private key files are NOT accessible by others.");
471 return 0;
472 }
473 switch (key->type) {
474 case KEY_RSA:
475 if (key->rsa->e != NULL) {
476 BN_clear_free(key->rsa->e);
477 key->rsa->e = NULL;
478 }
479 if (key->rsa->n != NULL) {
480 BN_clear_free(key->rsa->n);
481 key->rsa->n = NULL;
482 }
483 ret = load_private_key_rsa(fd, filename, passphrase,
484 key->rsa, comment_return);
485 break;
486 case KEY_DSA:
487 ret = load_private_key_dsa(fd, passphrase, key, comment_return);
488 default:
489 break;
490 }
491 close(fd);
492 return ret;
493}
diff --git a/authfile.h b/authfile.h
new file mode 100644
index 000000000..afec27d54
--- /dev/null
+++ b/authfile.h
@@ -0,0 +1,36 @@
1#ifndef AUTHFILE_H
2#define AUTHFILE_H
3
4/*
5 * Saves the authentication (private) key in a file, encrypting it with
6 * passphrase.
7 * For RSA keys: The identification of the file (lowest 64 bits of n)
8 * will precede the key to provide identification of the key without
9 * needing a passphrase.
10 */
11int
12save_private_key(const char *filename, const char *passphrase,
13 Key * private_key, const char *comment);
14
15/*
16 * Loads the public part of the key file (public key and comment). Returns 0
17 * if an error occurred; zero if the public key was successfully read. The
18 * comment of the key is returned in comment_return if it is non-NULL; the
19 * caller must free the value with xfree.
20 */
21int
22load_public_key(const char *filename, Key * pub,
23 char **comment_return);
24
25/*
26 * Loads the private key from the file. Returns 0 if an error is encountered
27 * (file does not exist or is not readable, or passphrase is bad). This
28 * initializes the private key. The comment of the key is returned in
29 * comment_return if it is non-NULL; the caller must free the value with
30 * xfree.
31 */
32int
33load_private_key(const char *filename, const char *passphrase,
34 Key * private_key, char **comment_return);
35
36#endif
diff --git a/compat.c b/compat.c
index 4673e3fbc..3bf45c122 100644
--- a/compat.c
+++ b/compat.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$Id: compat.c,v 1.8 2000/04/16 01:18:42 damien Exp $"); 31RCSID("$Id: compat.c,v 1.9 2000/04/29 13:57:10 damien Exp $");
32 32
33#include "ssh.h" 33#include "ssh.h"
34#include "packet.h" 34#include "packet.h"
@@ -44,7 +44,6 @@ enable_compat20(void)
44{ 44{
45 verbose("Enabling compatibility mode for protocol 2.0"); 45 verbose("Enabling compatibility mode for protocol 2.0");
46 compat20 = 1; 46 compat20 = 1;
47 packet_set_ssh2_format();
48} 47}
49void 48void
50enable_compat13(void) 49enable_compat13(void)
diff --git a/dsa.c b/dsa.c
index 1594c14f5..a4f6d3e78 100644
--- a/dsa.c
+++ b/dsa.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$Id: dsa.c,v 1.4 2000/04/14 10:30:31 markus Exp $"); 31RCSID("$Id: dsa.c,v 1.5 2000/04/26 20:56:29 markus Exp $");
32 32
33#include "ssh.h" 33#include "ssh.h"
34#include "xmalloc.h" 34#include "xmalloc.h"
@@ -47,13 +47,14 @@ RCSID("$Id: dsa.c,v 1.4 2000/04/14 10:30:31 markus Exp $");
47#include <openssl/hmac.h> 47#include <openssl/hmac.h>
48#include "kex.h" 48#include "kex.h"
49#include "key.h" 49#include "key.h"
50#include "uuencode.h"
50 51
51#define INTBLOB_LEN 20 52#define INTBLOB_LEN 20
52#define SIGBLOB_LEN (2*INTBLOB_LEN) 53#define SIGBLOB_LEN (2*INTBLOB_LEN)
53 54
54Key * 55Key *
55dsa_serverkey_from_blob( 56dsa_key_from_blob(
56 char *serverhostkey, int serverhostkeylen) 57 char *blob, int blen)
57{ 58{
58 Buffer b; 59 Buffer b;
59 char *ktype; 60 char *ktype;
@@ -61,14 +62,17 @@ dsa_serverkey_from_blob(
61 DSA *dsa; 62 DSA *dsa;
62 Key *key; 63 Key *key;
63 64
65#ifdef DEBUG_DSS
66 dump_base64(blob, blen);
67#endif
64 /* fetch & parse DSA/DSS pubkey */ 68 /* fetch & parse DSA/DSS pubkey */
65 key = key_new(KEY_DSA); 69 key = key_new(KEY_DSA);
66 dsa = key->dsa; 70 dsa = key->dsa;
67 buffer_init(&b); 71 buffer_init(&b);
68 buffer_append(&b, serverhostkey, serverhostkeylen); 72 buffer_append(&b, blob, blen);
69 ktype = buffer_get_string(&b, NULL); 73 ktype = buffer_get_string(&b, NULL);
70 if (strcmp(KEX_DSS, ktype) != 0) { 74 if (strcmp(KEX_DSS, ktype) != 0) {
71 error("dsa_serverkey_from_blob: cannot handle type %s", ktype); 75 error("dsa_key_from_blob: cannot handle type %s", ktype);
72 key_free(key); 76 key_free(key);
73 return NULL; 77 return NULL;
74 } 78 }
@@ -78,7 +82,7 @@ dsa_serverkey_from_blob(
78 buffer_get_bignum2(&b, dsa->pub_key); 82 buffer_get_bignum2(&b, dsa->pub_key);
79 rlen = buffer_len(&b); 83 rlen = buffer_len(&b);
80 if(rlen != 0) 84 if(rlen != 0)
81 error("dsa_serverkey_from_blob: remaining bytes in serverhostkey %d", rlen); 85 error("dsa_key_from_blob: remaining bytes in key blob %d", rlen);
82 buffer_free(&b); 86 buffer_free(&b);
83 87
84 debug("keytype %s", ktype); 88 debug("keytype %s", ktype);
@@ -87,37 +91,8 @@ dsa_serverkey_from_blob(
87#endif 91#endif
88 return key; 92 return key;
89} 93}
90DSA *
91dsa_load_private(char *filename)
92{
93 DSA *dsa;
94 BIO *in;
95
96 in = BIO_new(BIO_s_file());
97 if (in == NULL)
98 fatal("BIO_new failed");
99 if (BIO_read_filename(in, filename) <= 0)
100 fatal("BIO_read failed %s: %s", filename, strerror(errno));
101 fprintf(stderr, "read DSA private key\n");
102 dsa = PEM_read_bio_DSAPrivateKey(in,NULL,NULL,NULL);
103 if (dsa == NULL)
104 fatal("PEM_read_bio_DSAPrivateKey failed %s", filename);
105 BIO_free(in);
106 return dsa;
107}
108Key *
109dsa_get_serverkey(char *filename)
110{
111 Key *k = key_new(KEY_EMPTY);
112 k->type = KEY_DSA;
113 k->dsa = dsa_load_private(filename);
114#ifdef DEBUG_DSS
115 DSA_print_fp(stderr, dsa, 8);
116#endif
117 return k;
118}
119int 94int
120dsa_make_serverkey_blob(Key *key, unsigned char **blobp, unsigned int *lenp) 95dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
121{ 96{
122 Buffer b; 97 Buffer b;
123 int len; 98 int len;
@@ -146,7 +121,7 @@ int
146dsa_sign( 121dsa_sign(
147 Key *key, 122 Key *key,
148 unsigned char **sigp, int *lenp, 123 unsigned char **sigp, int *lenp,
149 unsigned char *hash, int hlen) 124 unsigned char *data, int datalen)
150{ 125{
151 unsigned char *digest; 126 unsigned char *digest;
152 unsigned char *ret; 127 unsigned char *ret;
@@ -165,10 +140,13 @@ dsa_sign(
165 } 140 }
166 digest = xmalloc(evp_md->md_size); 141 digest = xmalloc(evp_md->md_size);
167 EVP_DigestInit(&md, evp_md); 142 EVP_DigestInit(&md, evp_md);
168 EVP_DigestUpdate(&md, hash, hlen); 143 EVP_DigestUpdate(&md, data, datalen);
169 EVP_DigestFinal(&md, digest, NULL); 144 EVP_DigestFinal(&md, digest, NULL);
170 145
171 sig = DSA_do_sign(digest, evp_md->md_size, key->dsa); 146 sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
147 if (sig == NULL) {
148 fatal("dsa_sign: cannot sign");
149 }
172 150
173 rlen = BN_num_bytes(sig->r); 151 rlen = BN_num_bytes(sig->r);
174 slen = BN_num_bytes(sig->s); 152 slen = BN_num_bytes(sig->s);
@@ -212,7 +190,7 @@ int
212dsa_verify( 190dsa_verify(
213 Key *key, 191 Key *key,
214 unsigned char *signature, int signaturelen, 192 unsigned char *signature, int signaturelen,
215 unsigned char *hash, int hlen) 193 unsigned char *data, int datalen)
216{ 194{
217 Buffer b; 195 Buffer b;
218 unsigned char *digest; 196 unsigned char *digest;
@@ -269,10 +247,10 @@ dsa_verify(
269 xfree(sigblob); 247 xfree(sigblob);
270 } 248 }
271 249
272 /* sha1 the signed data (== session_id == hash) */ 250 /* sha1 the data */
273 digest = xmalloc(evp_md->md_size); 251 digest = xmalloc(evp_md->md_size);
274 EVP_DigestInit(&md, evp_md); 252 EVP_DigestInit(&md, evp_md);
275 EVP_DigestUpdate(&md, hash, hlen); 253 EVP_DigestUpdate(&md, data, datalen);
276 EVP_DigestFinal(&md, digest, NULL); 254 EVP_DigestFinal(&md, digest, NULL);
277 255
278 ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa); 256 ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa);
@@ -296,3 +274,21 @@ dsa_verify(
296 debug("dsa_verify: signature %s", txt); 274 debug("dsa_verify: signature %s", txt);
297 return ret; 275 return ret;
298} 276}
277
278Key *
279dsa_generate_key(unsigned int bits)
280{
281 DSA *dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
282 Key *k;
283 if (dsa == NULL) {
284 fatal("DSA_generate_parameters failed");
285 }
286 if (!DSA_generate_key(dsa)) {
287 fatal("DSA_generate_keys failed");
288 }
289
290 k = key_new(KEY_EMPTY);
291 k->type = KEY_DSA;
292 k->dsa = dsa;
293 return k;
294}
diff --git a/dsa.h b/dsa.h
index 65e651d9b..3cece7c1f 100644
--- a/dsa.h
+++ b/dsa.h
@@ -1,20 +1,22 @@
1#ifndef DSA_H 1#ifndef DSA_H
2#define DSA_H 2#define DSA_H
3 3
4Key *dsa_serverkey_from_blob(char *serverhostkey, int serverhostkeylen); 4Key *dsa_key_from_blob(char *blob, int blen);
5Key *dsa_get_serverkey(char *filename); 5int dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp);
6int dsa_make_serverkey_blob(Key *key, unsigned char **blobp, unsigned int *lenp);
7 6
8int 7int
9dsa_sign( 8dsa_sign(
10 Key *key, 9 Key *key,
11 unsigned char **sigp, int *lenp, 10 unsigned char **sigp, int *lenp,
12 unsigned char *hash, int hlen); 11 unsigned char *data, int datalen);
13 12
14int 13int
15dsa_verify( 14dsa_verify(
16 Key *key, 15 Key *key,
17 unsigned char *signature, int signaturelen, 16 unsigned char *signature, int signaturelen,
18 unsigned char *hash, int hlen); 17 unsigned char *data, int datalen);
18
19Key *
20dsa_generate_key(unsigned int bits);
19 21
20#endif 22#endif
diff --git a/hostfile.c b/hostfile.c
index 29efe5656..e1c2429bd 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: hostfile.c,v 1.16 2000/04/14 10:30:31 markus Exp $"); 17RCSID("$OpenBSD: hostfile.c,v 1.17 2000/04/26 20:56:29 markus Exp $");
18 18
19#include "packet.h" 19#include "packet.h"
20#include "match.h" 20#include "match.h"
@@ -39,13 +39,8 @@ hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
39 for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) 39 for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
40 ; 40 ;
41 41
42 /* Get number of bits. */ 42 bits = key_read(ret, &cp);
43 if (*cp < '0' || *cp > '9') 43 if (bits == 0)
44 return 0; /* Bad bit count... */
45 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
46 bits = 10 * bits + *cp - '0';
47
48 if (!key_read(ret, bits, &cp))
49 return 0; 44 return 0;
50 45
51 /* Skip trailing whitespace. */ 46 /* Skip trailing whitespace. */
@@ -182,24 +177,18 @@ add_host_to_hostfile(const char *filename, const char *host, Key *key)
182{ 177{
183 FILE *f; 178 FILE *f;
184 int success = 0; 179 int success = 0;
185
186 if (key == NULL) 180 if (key == NULL)
187 return 1; 181 return 1; /* XXX ? */
188
189 /* Open the file for appending. */
190 f = fopen(filename, "a"); 182 f = fopen(filename, "a");
191 if (!f) 183 if (!f)
192 return 0; 184 return 0;
193
194 fprintf(f, "%s ", host); 185 fprintf(f, "%s ", host);
195 if (key_write(key, f)) { 186 if (key_write(key, f)) {
196 fprintf(f, "\n");
197 success = 1; 187 success = 1;
198 } else { 188 } else {
199 error("add_host_to_hostfile: saving key failed"); 189 error("add_host_to_hostfile: saving key in %s failed", filename);
200 } 190 }
201 191 fprintf(f, "\n");
202 /* Close the file. */
203 fclose(f); 192 fclose(f);
204 return success; 193 return success;
205} 194}
diff --git a/key.c b/key.c
index 872313abc..583c52901 100644
--- a/key.c
+++ b/key.c
@@ -38,6 +38,10 @@
38#include <openssl/evp.h> 38#include <openssl/evp.h>
39#include "xmalloc.h" 39#include "xmalloc.h"
40#include "key.h" 40#include "key.h"
41#include "dsa.h"
42#include "uuencode.h"
43
44#define SSH_DSS "ssh-dss"
41 45
42Key * 46Key *
43key_new(int type) 47key_new(int type)
@@ -47,6 +51,8 @@ key_new(int type)
47 DSA *dsa; 51 DSA *dsa;
48 k = xmalloc(sizeof(*k)); 52 k = xmalloc(sizeof(*k));
49 k->type = type; 53 k->type = type;
54 k->dsa = NULL;
55 k->rsa = NULL;
50 switch (k->type) { 56 switch (k->type) {
51 case KEY_RSA: 57 case KEY_RSA:
52 rsa = RSA_new(); 58 rsa = RSA_new();
@@ -63,8 +69,6 @@ key_new(int type)
63 k->dsa = dsa; 69 k->dsa = dsa;
64 break; 70 break;
65 case KEY_EMPTY: 71 case KEY_EMPTY:
66 k->dsa = NULL;
67 k->rsa = NULL;
68 break; 72 break;
69 default: 73 default:
70 fatal("key_new: bad key type %d", k->type); 74 fatal("key_new: bad key type %d", k->type);
@@ -111,7 +115,7 @@ key_equal(Key *a, Key *b)
111 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; 115 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
112 break; 116 break;
113 default: 117 default:
114 fatal("key_free: bad key type %d", a->type); 118 fatal("key_equal: bad key type %d", a->type);
115 break; 119 break;
116 } 120 }
117 return 0; 121 return 0;
@@ -127,46 +131,37 @@ char *
127key_fingerprint(Key *k) 131key_fingerprint(Key *k)
128{ 132{
129 static char retval[80]; 133 static char retval[80];
130 unsigned char *buf = NULL; 134 unsigned char *blob = NULL;
131 int len = 0; 135 int len = 0;
132 int nlen, elen, plen, qlen, glen, publen; 136 int nlen, elen;
133 137
134 switch (k->type) { 138 switch (k->type) {
135 case KEY_RSA: 139 case KEY_RSA:
136 nlen = BN_num_bytes(k->rsa->n); 140 nlen = BN_num_bytes(k->rsa->n);
137 elen = BN_num_bytes(k->rsa->e); 141 elen = BN_num_bytes(k->rsa->e);
138 len = nlen + elen; 142 len = nlen + elen;
139 buf = xmalloc(len); 143 blob = xmalloc(len);
140 BN_bn2bin(k->rsa->n, buf); 144 BN_bn2bin(k->rsa->n, blob);
141 BN_bn2bin(k->rsa->e, buf + nlen); 145 BN_bn2bin(k->rsa->e, blob + nlen);
142 break; 146 break;
143 case KEY_DSA: 147 case KEY_DSA:
144 plen = BN_num_bytes(k->dsa->p); 148 dsa_make_key_blob(k, &blob, &len);
145 qlen = BN_num_bytes(k->dsa->q);
146 glen = BN_num_bytes(k->dsa->g);
147 publen = BN_num_bytes(k->dsa->pub_key);
148 len = qlen + qlen + glen + publen;
149 buf = xmalloc(len);
150 BN_bn2bin(k->dsa->p, buf);
151 BN_bn2bin(k->dsa->q, buf + plen);
152 BN_bn2bin(k->dsa->g, buf + plen + qlen);
153 BN_bn2bin(k->dsa->pub_key , buf + plen + qlen + glen);
154 break; 149 break;
155 default: 150 default:
156 fatal("key_fingerprint: bad key type %d", k->type); 151 fatal("key_fingerprint: bad key type %d", k->type);
157 break; 152 break;
158 } 153 }
159 if (buf != NULL) { 154 if (blob != NULL) {
160 unsigned char d[16]; 155 unsigned char d[16];
161 EVP_MD_CTX md; 156 EVP_MD_CTX md;
162 EVP_DigestInit(&md, EVP_md5()); 157 EVP_DigestInit(&md, EVP_md5());
163 EVP_DigestUpdate(&md, buf, len); 158 EVP_DigestUpdate(&md, blob, len);
164 EVP_DigestFinal(&md, d, NULL); 159 EVP_DigestFinal(&md, d, NULL);
165 snprintf(retval, sizeof(retval), FPRINT, 160 snprintf(retval, sizeof(retval), FPRINT,
166 d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], 161 d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
167 d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 162 d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
168 memset(buf, 0, len); 163 memset(blob, 0, len);
169 xfree(buf); 164 xfree(blob);
170 } 165 }
171 return retval; 166 return retval;
172} 167}
@@ -226,13 +221,27 @@ write_bignum(FILE *f, BIGNUM *num)
226 free(buf); 221 free(buf);
227 return 1; 222 return 1;
228} 223}
229int 224unsigned int
230key_read(Key *ret, unsigned int bits, char **cpp) 225key_read(Key *ret, char **cpp)
231{ 226{
227 Key *k;
228 unsigned int bits = 0;
229 char *cp;
230 int len, n;
231 unsigned char *blob;
232
233 cp = *cpp;
234
232 switch(ret->type) { 235 switch(ret->type) {
233 case KEY_RSA: 236 case KEY_RSA:
237 /* Get number of bits. */
238 if (*cp < '0' || *cp > '9')
239 return 0; /* Bad bit count... */
240 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
241 bits = 10 * bits + *cp - '0';
234 if (bits == 0) 242 if (bits == 0)
235 return 0; 243 return 0;
244 *cpp = cp;
236 /* Get public exponent, public modulus. */ 245 /* Get public exponent, public modulus. */
237 if (!read_bignum(cpp, ret->rsa->e)) 246 if (!read_bignum(cpp, ret->rsa->e))
238 return 0; 247 return 0;
@@ -240,22 +249,32 @@ key_read(Key *ret, unsigned int bits, char **cpp)
240 return 0; 249 return 0;
241 break; 250 break;
242 case KEY_DSA: 251 case KEY_DSA:
243 if (bits != 0) 252 if (strncmp(cp, SSH_DSS " ", 7) != 0)
244 return 0;
245 if (!read_bignum(cpp, ret->dsa->p))
246 return 0; 253 return 0;
247 if (!read_bignum(cpp, ret->dsa->q)) 254 cp += 7;
248 return 0; 255 len = 2*strlen(cp);
249 if (!read_bignum(cpp, ret->dsa->g)) 256 blob = xmalloc(len);
250 return 0; 257 n = uudecode(cp, blob, len);
251 if (!read_bignum(cpp, ret->dsa->pub_key)) 258 k = dsa_key_from_blob(blob, n);
259 if (k == NULL)
260 return 0;
261 xfree(blob);
262 if (ret->dsa != NULL)
263 DSA_free(ret->dsa);
264 ret->dsa = k->dsa;
265 k->dsa = NULL;
266 key_free(k);
267 bits = BN_num_bits(ret->dsa->p);
268 cp = strchr(cp, '=');
269 if (cp == NULL)
252 return 0; 270 return 0;
271 *cpp = cp + 1;
253 break; 272 break;
254 default: 273 default:
255 fatal("bad key type: %d", ret->type); 274 fatal("key_read: bad key type: %d", ret->type);
256 break; 275 break;
257 } 276 }
258 return 1; 277 return bits;
259} 278}
260int 279int
261key_write(Key *key, FILE *f) 280key_write(Key *key, FILE *f)
@@ -274,17 +293,15 @@ key_write(Key *key, FILE *f)
274 error("key_write: failed for RSA key"); 293 error("key_write: failed for RSA key");
275 } 294 }
276 } else if (key->type == KEY_DSA && key->dsa != NULL) { 295 } else if (key->type == KEY_DSA && key->dsa != NULL) {
277 /* bits == 0 means DSA key */ 296 int len, n;
278 bits = 0; 297 unsigned char *blob, *uu;
279 fprintf(f, "%u", bits); 298 dsa_make_key_blob(key, &blob, &len);
280 if (write_bignum(f, key->dsa->p) && 299 uu = xmalloc(2*len);
281 write_bignum(f, key->dsa->q) && 300 n = uuencode(blob, len, uu);
282 write_bignum(f, key->dsa->g) && 301 fprintf(f, "%s %s", SSH_DSS, uu);
283 write_bignum(f, key->dsa->pub_key)) { 302 xfree(blob);
284 success = 1; 303 xfree(uu);
285 } else { 304 success = 1;
286 error("key_write: failed for DSA key");
287 }
288 } 305 }
289 return success; 306 return success;
290} 307}
diff --git a/key.h b/key.h
index 70f0c518b..d1bcf3b1b 100644
--- a/key.h
+++ b/key.h
@@ -18,6 +18,7 @@ void key_free(Key *k);
18int key_equal(Key *a, Key *b); 18int key_equal(Key *a, Key *b);
19char *key_fingerprint(Key *k); 19char *key_fingerprint(Key *k);
20int key_write(Key *key, FILE *f); 20int key_write(Key *key, FILE *f);
21int key_read(Key *key, unsigned int bits, char **cpp); 21unsigned int
22key_read(Key *key, char **cpp);
22 23
23#endif 24#endif
diff --git a/radix.c b/radix.c
index 84e390fd1..9d1c999a1 100644
--- a/radix.c
+++ b/radix.c
@@ -1,109 +1,15 @@
1/* 1/*
2 * radix.c 2 * radix.c
3 * 3 *
4 * base-64 encoding pinched from lynx2-7-2, who pinched it from rpem.
5 * Originally written by Mark Riordan 12 August 1990 and 17 Feb 1991
6 * and placed in the public domain.
7 *
8 * Dug Song <dugsong@UMICH.EDU> 4 * Dug Song <dugsong@UMICH.EDU>
9 */ 5 */
10 6
11#include "includes.h" 7#include "includes.h"
8#include "uuencode.h"
12 9
13#ifdef AFS 10#ifdef AFS
14#include <krb.h> 11#include <krb.h>
15 12
16char six2pr[64] = {
17 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
18 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
19 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
20 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
21 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
22};
23
24unsigned char pr2six[256];
25
26int
27uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded)
28{
29 /* ENC is the basic 1 character encoding function to make a char printing */
30#define ENC(c) six2pr[c]
31
32 register char *outptr = bufcoded;
33 unsigned int i;
34
35 for (i = 0; i < nbytes; i += 3) {
36 *(outptr++) = ENC(*bufin >> 2); /* c1 */
37 *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /* c2 */
38 *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)); /* c3 */
39 *(outptr++) = ENC(bufin[2] & 077); /* c4 */
40 bufin += 3;
41 }
42 if (i == nbytes + 1) {
43 outptr[-1] = '=';
44 } else if (i == nbytes + 2) {
45 outptr[-1] = '=';
46 outptr[-2] = '=';
47 }
48 *outptr = '\0';
49 return (outptr - bufcoded);
50}
51
52int
53uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
54{
55 /* single character decode */
56#define DEC(c) pr2six[(unsigned char)c]
57#define MAXVAL 63
58
59 static int first = 1;
60 int nbytesdecoded, j;
61 const char *bufin = bufcoded;
62 register unsigned char *bufout = bufplain;
63 register int nprbytes;
64
65 /* If this is the first call, initialize the mapping table. */
66 if (first) {
67 first = 0;
68 for (j = 0; j < 256; j++)
69 pr2six[j] = MAXVAL + 1;
70 for (j = 0; j < 64; j++)
71 pr2six[(unsigned char) six2pr[j]] = (unsigned char) j;
72 }
73 /* Strip leading whitespace. */
74 while (*bufcoded == ' ' || *bufcoded == '\t')
75 bufcoded++;
76
77 /*
78 * Figure out how many characters are in the input buffer. If this
79 * would decode into more bytes than would fit into the output
80 * buffer, adjust the number of input bytes downwards.
81 */
82 bufin = bufcoded;
83 while (DEC(*(bufin++)) <= MAXVAL);
84 nprbytes = bufin - bufcoded - 1;
85 nbytesdecoded = ((nprbytes + 3) / 4) * 3;
86 if (nbytesdecoded > outbufsize)
87 nprbytes = (outbufsize * 4) / 3;
88
89 bufin = bufcoded;
90
91 while (nprbytes > 0) {
92 *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
93 *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
94 *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
95 bufin += 4;
96 nprbytes -= 4;
97 }
98 if (nprbytes & 03) {
99 if (DEC(bufin[-2]) > MAXVAL)
100 nbytesdecoded -= 2;
101 else
102 nbytesdecoded -= 1;
103 }
104 return (nbytesdecoded);
105}
106
107typedef unsigned char my_u_char; 13typedef unsigned char my_u_char;
108typedef unsigned int my_u_int32_t; 14typedef unsigned int my_u_int32_t;
109typedef unsigned short my_u_short; 15typedef unsigned short my_u_short;
diff --git a/readconf.c b/readconf.c
index 3b75290f3..529f8039b 100644
--- a/readconf.c
+++ b/readconf.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: readconf.c,v 1.11 2000/04/16 01:18:44 damien Exp $"); 17RCSID("$Id: readconf.c,v 1.12 2000/04/29 13:57:11 damien Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "cipher.h" 20#include "cipher.h"
@@ -104,7 +104,8 @@ typedef enum {
104 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, 104 oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
105 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, 105 oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
106 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication, 106 oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
107 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol 107 oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
108 oGlobalKnownHostsFile2, oUserKnownHostsFile2
108} OpCodes; 109} OpCodes;
109 110
110/* Textual representations of the tokens. */ 111/* Textual representations of the tokens. */
@@ -131,6 +132,7 @@ static struct {
131 { "fallbacktorsh", oFallBackToRsh }, 132 { "fallbacktorsh", oFallBackToRsh },
132 { "usersh", oUseRsh }, 133 { "usersh", oUseRsh },
133 { "identityfile", oIdentityFile }, 134 { "identityfile", oIdentityFile },
135 { "identityfile2", oIdentityFile2 },
134 { "hostname", oHostName }, 136 { "hostname", oHostName },
135 { "proxycommand", oProxyCommand }, 137 { "proxycommand", oProxyCommand },
136 { "port", oPort }, 138 { "port", oPort },
@@ -145,6 +147,8 @@ static struct {
145 { "rhostsrsaauthentication", oRhostsRSAAuthentication }, 147 { "rhostsrsaauthentication", oRhostsRSAAuthentication },
146 { "globalknownhostsfile", oGlobalKnownHostsFile }, 148 { "globalknownhostsfile", oGlobalKnownHostsFile },
147 { "userknownhostsfile", oUserKnownHostsFile }, 149 { "userknownhostsfile", oUserKnownHostsFile },
150 { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
151 { "userknownhostsfile2", oUserKnownHostsFile2 },
148 { "connectionattempts", oConnectionAttempts }, 152 { "connectionattempts", oConnectionAttempts },
149 { "batchmode", oBatchMode }, 153 { "batchmode", oBatchMode },
150 { "checkhostip", oCheckHostIP }, 154 { "checkhostip", oCheckHostIP },
@@ -368,14 +372,22 @@ parse_flag:
368 goto parse_int; 372 goto parse_int;
369 373
370 case oIdentityFile: 374 case oIdentityFile:
375 case oIdentityFile2:
371 cp = strtok(NULL, WHITESPACE); 376 cp = strtok(NULL, WHITESPACE);
372 if (!cp) 377 if (!cp)
373 fatal("%.200s line %d: Missing argument.", filename, linenum); 378 fatal("%.200s line %d: Missing argument.", filename, linenum);
374 if (*activep) { 379 if (*activep) {
375 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 380 intptr = (opcode == oIdentityFile) ?
381 &options->num_identity_files :
382 &options->num_identity_files2;
383 if (*intptr >= SSH_MAX_IDENTITY_FILES)
376 fatal("%.200s line %d: Too many identity files specified (max %d).", 384 fatal("%.200s line %d: Too many identity files specified (max %d).",
377 filename, linenum, SSH_MAX_IDENTITY_FILES); 385 filename, linenum, SSH_MAX_IDENTITY_FILES);
378 options->identity_files[options->num_identity_files++] = xstrdup(cp); 386 charptr = (opcode == oIdentityFile) ?
387 &options->identity_files[*intptr] :
388 &options->identity_files2[*intptr];
389 *charptr = xstrdup(cp);
390 *intptr = *intptr + 1;
379 } 391 }
380 break; 392 break;
381 393
@@ -397,6 +409,14 @@ parse_string:
397 charptr = &options->user_hostfile; 409 charptr = &options->user_hostfile;
398 goto parse_string; 410 goto parse_string;
399 411
412 case oGlobalKnownHostsFile2:
413 charptr = &options->system_hostfile2;
414 goto parse_string;
415
416 case oUserKnownHostsFile2:
417 charptr = &options->user_hostfile2;
418 goto parse_string;
419
400 case oHostName: 420 case oHostName:
401 charptr = &options->hostname; 421 charptr = &options->hostname;
402 goto parse_string; 422 goto parse_string;
@@ -642,12 +662,15 @@ initialize_options(Options * options)
642 options->ciphers = NULL; 662 options->ciphers = NULL;
643 options->protocol = SSH_PROTO_UNKNOWN; 663 options->protocol = SSH_PROTO_UNKNOWN;
644 options->num_identity_files = 0; 664 options->num_identity_files = 0;
665 options->num_identity_files2 = 0;
645 options->hostname = NULL; 666 options->hostname = NULL;
646 options->proxy_command = NULL; 667 options->proxy_command = NULL;
647 options->user = NULL; 668 options->user = NULL;
648 options->escape_char = -1; 669 options->escape_char = -1;
649 options->system_hostfile = NULL; 670 options->system_hostfile = NULL;
650 options->user_hostfile = NULL; 671 options->user_hostfile = NULL;
672 options->system_hostfile2 = NULL;
673 options->user_hostfile2 = NULL;
651 options->num_local_forwards = 0; 674 options->num_local_forwards = 0;
652 options->num_remote_forwards = 0; 675 options->num_remote_forwards = 0;
653 options->log_level = (LogLevel) - 1; 676 options->log_level = (LogLevel) - 1;
@@ -715,19 +738,31 @@ fill_default_options(Options * options)
715 if (options->cipher == -1) 738 if (options->cipher == -1)
716 options->cipher = SSH_CIPHER_NOT_SET; 739 options->cipher = SSH_CIPHER_NOT_SET;
717 if (options->protocol == SSH_PROTO_UNKNOWN) 740 if (options->protocol == SSH_PROTO_UNKNOWN)
718 options->protocol = SSH_PROTO_1; 741 options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
719 if (options->num_identity_files == 0) { 742 if (options->num_identity_files == 0) {
720 options->identity_files[0] = 743 options->identity_files[0] =
721 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1); 744 xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
722 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY); 745 sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
723 options->num_identity_files = 1; 746 options->num_identity_files = 1;
724 } 747 }
748#if 0
749 if (options->num_identity_files2 == 0) {
750 options->identity_files2[0] =
751 xmalloc(2 + strlen(SSH2_CLIENT_IDENTITY) + 1);
752 sprintf(options->identity_files2[0], "~/%.100s", SSH2_CLIENT_IDENTITY);
753 options->num_identity_files2 = 1;
754 }
755#endif
725 if (options->escape_char == -1) 756 if (options->escape_char == -1)
726 options->escape_char = '~'; 757 options->escape_char = '~';
727 if (options->system_hostfile == NULL) 758 if (options->system_hostfile == NULL)
728 options->system_hostfile = SSH_SYSTEM_HOSTFILE; 759 options->system_hostfile = SSH_SYSTEM_HOSTFILE;
729 if (options->user_hostfile == NULL) 760 if (options->user_hostfile == NULL)
730 options->user_hostfile = SSH_USER_HOSTFILE; 761 options->user_hostfile = SSH_USER_HOSTFILE;
762 if (options->system_hostfile2 == NULL)
763 options->system_hostfile2 = SSH_SYSTEM_HOSTFILE2;
764 if (options->user_hostfile2 == NULL)
765 options->user_hostfile2 = SSH_USER_HOSTFILE2;
731 if (options->log_level == (LogLevel) - 1) 766 if (options->log_level == (LogLevel) - 1)
732 options->log_level = SYSLOG_LEVEL_INFO; 767 options->log_level = SYSLOG_LEVEL_INFO;
733 /* options->proxy_command should not be set by default */ 768 /* options->proxy_command should not be set by default */
diff --git a/readconf.h b/readconf.h
index 0582a8f2e..bbef923ab 100644
--- a/readconf.h
+++ b/readconf.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: readconf.h,v 1.8 2000/04/16 01:18:44 damien Exp $"); */ 16/* RCSID("$Id: readconf.h,v 1.9 2000/04/29 13:57:11 damien Exp $"); */
17 17
18#ifndef READCONF_H 18#ifndef READCONF_H
19#define READCONF_H 19#define READCONF_H
@@ -73,9 +73,13 @@ typedef struct {
73 73
74 char *system_hostfile;/* Path for /etc/ssh_known_hosts. */ 74 char *system_hostfile;/* Path for /etc/ssh_known_hosts. */
75 char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */ 75 char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
76 char *system_hostfile2;
77 char *user_hostfile2;
76 78
77 int num_identity_files; /* Number of files for RSA identities. */ 79 int num_identity_files; /* Number of files for RSA identities. */
80 int num_identity_files2; /* DSA identities. */
78 char *identity_files[SSH_MAX_IDENTITY_FILES]; 81 char *identity_files[SSH_MAX_IDENTITY_FILES];
82 char *identity_files2[SSH_MAX_IDENTITY_FILES];
79 83
80 /* Local TCP/IP forward requests. */ 84 /* Local TCP/IP forward requests. */
81 int num_local_forwards; 85 int num_local_forwards;
diff --git a/servconf.c b/servconf.c
index fe72d2757..298fefbe2 100644
--- a/servconf.c
+++ b/servconf.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$Id: servconf.c,v 1.12 2000/04/16 01:18:45 damien Exp $"); 15RCSID("$Id: servconf.c,v 1.13 2000/04/29 13:57:11 damien Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "servconf.h" 18#include "servconf.h"
@@ -143,7 +143,7 @@ fill_default_server_options(ServerOptions *options)
143 if (options->use_login == -1) 143 if (options->use_login == -1)
144 options->use_login = 0; 144 options->use_login = 0;
145 if (options->protocol == SSH_PROTO_UNKNOWN) 145 if (options->protocol == SSH_PROTO_UNKNOWN)
146 options->protocol = SSH_PROTO_1; 146 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
147} 147}
148 148
149#define WHITESPACE " \t\r\n" 149#define WHITESPACE " \t\r\n"
diff --git a/serverloop.c b/serverloop.c
index 1a76b8da8..1e031873c 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -733,7 +733,7 @@ server_input_channel_open(int type, int plen)
733 rwindow = packet_get_int(); 733 rwindow = packet_get_int();
734 rmaxpack = packet_get_int(); 734 rmaxpack = packet_get_int();
735 735
736 log("channel_input_open: ctype %s rchan %d win %d max %d", 736 debug("channel_input_open: ctype %s rchan %d win %d max %d",
737 ctype, rchan, rwindow, rmaxpack); 737 ctype, rchan, rwindow, rmaxpack);
738 738
739 if (strcmp(ctype, "session") == 0) { 739 if (strcmp(ctype, "session") == 0) {
diff --git a/session.c b/session.c
index 68a016e0b..d5c53f11f 100644
--- a/session.c
+++ b/session.c
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10#include "includes.h" 10#include "includes.h"
11RCSID("$OpenBSD: session.c,v 1.5 2000/04/19 09:24:39 markus Exp $"); 11RCSID("$OpenBSD: session.c,v 1.6 2000/04/27 15:23:02 markus Exp $");
12 12
13#include "xmalloc.h" 13#include "xmalloc.h"
14#include "ssh.h" 14#include "ssh.h"
@@ -1474,6 +1474,5 @@ do_authenticated2(void)
1474 * authentication. 1474 * authentication.
1475 */ 1475 */
1476 alarm(0); 1476 alarm(0);
1477 log("do_authenticated2");
1478 server_loop2(); 1477 server_loop2();
1479} 1478}
diff --git a/ssh-add.c b/ssh-add.c
index f01cca5c8..0d388301d 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -7,13 +7,18 @@
7 */ 7 */
8 8
9#include "includes.h" 9#include "includes.h"
10RCSID("$Id: ssh-add.c,v 1.16 1999/12/06 00:47:29 damien Exp $"); 10RCSID("$Id: ssh-add.c,v 1.17 2000/04/29 13:57:12 damien Exp $");
11
12#include <openssl/rsa.h>
13#include <openssl/dsa.h>
11 14
12#include "rsa.h" 15#include "rsa.h"
13#include "ssh.h" 16#include "ssh.h"
14#include "xmalloc.h" 17#include "xmalloc.h"
15#include "authfd.h" 18#include "authfd.h"
16#include "fingerprint.h" 19#include "fingerprint.h"
20#include "key.h"
21#include "authfile.h"
17 22
18#ifdef HAVE___PROGNAME 23#ifdef HAVE___PROGNAME
19extern char *__progname; 24extern char *__progname;
@@ -24,19 +29,19 @@ const char *__progname = "ssh-add";
24void 29void
25delete_file(AuthenticationConnection *ac, const char *filename) 30delete_file(AuthenticationConnection *ac, const char *filename)
26{ 31{
27 RSA *key; 32 Key *public;
28 char *comment; 33 char *comment;
29 34
30 key = RSA_new(); 35 public = key_new(KEY_RSA);
31 if (!load_public_key(filename, key, &comment)) { 36 if (!load_public_key(filename, public, &comment)) {
32 printf("Bad key file %s: %s\n", filename, strerror(errno)); 37 printf("Bad key file %s: %s\n", filename, strerror(errno));
33 return; 38 return;
34 } 39 }
35 if (ssh_remove_identity(ac, key)) 40 if (ssh_remove_identity(ac, public->rsa))
36 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); 41 fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
37 else 42 else
38 fprintf(stderr, "Could not remove identity: %s\n", filename); 43 fprintf(stderr, "Could not remove identity: %s\n", filename);
39 RSA_free(key); 44 key_free(public);
40 xfree(comment); 45 xfree(comment);
41} 46}
42 47
@@ -91,20 +96,19 @@ ssh_askpass(char *askpass, char *msg)
91void 96void
92add_file(AuthenticationConnection *ac, const char *filename) 97add_file(AuthenticationConnection *ac, const char *filename)
93{ 98{
94 RSA *key; 99 Key *public;
95 RSA *public_key; 100 Key *private;
96 char *saved_comment, *comment, *askpass = NULL; 101 char *saved_comment, *comment, *askpass = NULL;
97 char buf[1024], msg[1024]; 102 char buf[1024], msg[1024];
98 int success; 103 int success;
99 int interactive = isatty(STDIN_FILENO); 104 int interactive = isatty(STDIN_FILENO);
100 105
101 key = RSA_new(); 106 public = key_new(KEY_RSA);
102 public_key = RSA_new(); 107 if (!load_public_key(filename, public, &saved_comment)) {
103 if (!load_public_key(filename, public_key, &saved_comment)) {
104 printf("Bad key file %s: %s\n", filename, strerror(errno)); 108 printf("Bad key file %s: %s\n", filename, strerror(errno));
105 return; 109 return;
106 } 110 }
107 RSA_free(public_key); 111 key_free(public);
108 112
109 if (!interactive && getenv("DISPLAY")) { 113 if (!interactive && getenv("DISPLAY")) {
110 if (getenv(SSH_ASKPASS_ENV)) 114 if (getenv(SSH_ASKPASS_ENV))
@@ -114,7 +118,8 @@ add_file(AuthenticationConnection *ac, const char *filename)
114 } 118 }
115 119
116 /* At first, try empty passphrase */ 120 /* At first, try empty passphrase */
117 success = load_private_key(filename, "", key, &comment); 121 private = key_new(KEY_RSA);
122 success = load_private_key(filename, "", private, &comment);
118 if (!success) { 123 if (!success) {
119 printf("Need passphrase for %.200s\n", filename); 124 printf("Need passphrase for %.200s\n", filename);
120 if (!interactive && askpass == NULL) { 125 if (!interactive && askpass == NULL) {
@@ -135,7 +140,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
135 xfree(saved_comment); 140 xfree(saved_comment);
136 return; 141 return;
137 } 142 }
138 success = load_private_key(filename, pass, key, &comment); 143 success = load_private_key(filename, pass, private, &comment);
139 memset(pass, 0, strlen(pass)); 144 memset(pass, 0, strlen(pass));
140 xfree(pass); 145 xfree(pass);
141 if (success) 146 if (success)
@@ -145,11 +150,11 @@ add_file(AuthenticationConnection *ac, const char *filename)
145 } 150 }
146 xfree(saved_comment); 151 xfree(saved_comment);
147 152
148 if (ssh_add_identity(ac, key, comment)) 153 if (ssh_add_identity(ac, private->rsa, comment))
149 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); 154 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
150 else 155 else
151 fprintf(stderr, "Could not add identity: %s\n", filename); 156 fprintf(stderr, "Could not add identity: %s\n", filename);
152 RSA_free(key); 157 key_free(private);
153 xfree(comment); 158 xfree(comment);
154} 159}
155 160
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index b809a1a5e..486de0421 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -9,7 +9,7 @@
9.\" 9.\"
10.\" Created: Sat Apr 22 23:55:14 1995 ylo 10.\" Created: Sat Apr 22 23:55:14 1995 ylo
11.\" 11.\"
12.\" $Id: ssh-keygen.1,v 1.12 2000/04/20 13:27:27 damien Exp $ 12.\" $Id: ssh-keygen.1,v 1.13 2000/04/29 13:57:12 damien Exp $
13.\" 13.\"
14.Dd September 25, 1999 14.Dd September 25, 1999
15.Dt SSH-KEYGEN 1 15.Dt SSH-KEYGEN 1
@@ -37,6 +37,8 @@
37.Nm ssh-keygen 37.Nm ssh-keygen
38.Fl l 38.Fl l
39.Op Fl f Ar keyfile 39.Op Fl f Ar keyfile
40.Nm ssh-keygen
41.Fl R
40.Sh DESCRIPTION 42.Sh DESCRIPTION
41.Nm 43.Nm
42generates and manages authentication keys for 44generates and manages authentication keys for
@@ -112,6 +114,10 @@ Provides the new comment.
112Provides the new passphrase. 114Provides the new passphrase.
113.It Fl P Ar passphrase 115.It Fl P Ar passphrase
114Provides the (old) passphrase. 116Provides the (old) passphrase.
117.It Fl R
118If RSA support is functional, immediately exits with code 0. If RSA
119support is not functional, exits with code 1. This flag will be
120removed once the RSA patent expires.
115.El 121.El
116.Sh FILES 122.Sh FILES
117.Bl -tag -width Ds 123.Bl -tag -width Ds
diff --git a/ssh-keygen.c b/ssh-keygen.c
index f2484a4b1..0155949fd 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -7,20 +7,23 @@
7 */ 7 */
8 8
9#include "includes.h" 9#include "includes.h"
10RCSID("$Id: ssh-keygen.c,v 1.13 2000/04/16 01:18:46 damien Exp $"); 10RCSID("$Id: ssh-keygen.c,v 1.14 2000/04/29 13:57:12 damien Exp $");
11
12#include <openssl/evp.h>
13#include <openssl/pem.h>
14#include <openssl/rsa.h>
15#include <openssl/dsa.h>
11 16
12#include "rsa.h"
13#include "ssh.h" 17#include "ssh.h"
14#include "xmalloc.h" 18#include "xmalloc.h"
15#include "fingerprint.h" 19#include "fingerprint.h"
20#include "key.h"
21#include "rsa.h"
22#include "dsa.h"
23#include "authfile.h"
24#include "uuencode.h"
16 25
17/* Generated private key. */ 26/* Number of bits in the RSA/DSA key. This value can be changed on the command line. */
18RSA *private_key;
19
20/* Generated public key. */
21RSA *public_key;
22
23/* Number of bits in the RSA key. This value can be changed on the command line. */
24int bits = 1024; 27int bits = 1024;
25 28
26/* 29/*
@@ -53,6 +56,12 @@ char *identity_new_passphrase = NULL;
53/* This is set to the new comment if given on the command line. */ 56/* This is set to the new comment if given on the command line. */
54char *identity_comment = NULL; 57char *identity_comment = NULL;
55 58
59/* Dump public key file in format used by real and the original SSH 2 */
60int convert_to_ssh2 = 0;
61int convert_from_ssh2 = 0;
62int print_public = 0;
63int dsa_mode = 0;
64
56/* argv0 */ 65/* argv0 */
57#ifdef HAVE___PROGNAME 66#ifdef HAVE___PROGNAME
58extern char *__progname; 67extern char *__progname;
@@ -60,6 +69,8 @@ extern char *__progname;
60const char *__progname = "ssh-keygen"; 69const char *__progname = "ssh-keygen";
61#endif /* HAVE___PROGNAME */ 70#endif /* HAVE___PROGNAME */
62 71
72char hostname[MAXHOSTNAMELEN];
73
63void 74void
64ask_filename(struct passwd *pw, const char *prompt) 75ask_filename(struct passwd *pw, const char *prompt)
65{ 76{
@@ -77,12 +88,140 @@ ask_filename(struct passwd *pw, const char *prompt)
77 have_identity = 1; 88 have_identity = 1;
78} 89}
79 90
91int
92try_load_key(char *filename, Key *k)
93{
94 int success = 1;
95 if (!load_private_key(filename, "", k, NULL)) {
96 char *pass = read_passphrase("Enter passphrase: ", 1);
97 if (!load_private_key(filename, pass, k, NULL)) {
98 success = 0;
99 }
100 memset(pass, 0, strlen(pass));
101 xfree(pass);
102 }
103 return success;
104}
105
106#define SSH_COM_MAGIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
107#define SSH_COM_MAGIC_END "---- END SSH2 PUBLIC KEY ----"
108
109void
110do_convert_to_ssh2(struct passwd *pw)
111{
112 Key *k;
113 int len;
114 unsigned char *blob;
115 struct stat st;
116
117 if (!have_identity)
118 ask_filename(pw, "Enter file in which the key is");
119 if (stat(identity_file, &st) < 0) {
120 perror(identity_file);
121 exit(1);
122 }
123 k = key_new(KEY_DSA);
124 if (!try_load_key(identity_file, k)) {
125 fprintf(stderr, "load failed\n");
126 exit(1);
127 }
128 dsa_make_key_blob(k, &blob, &len);
129 fprintf(stdout, SSH_COM_MAGIC_BEGIN "\n");
130 fprintf(stdout,
131 "Comment: \"%d-bit DSA, converted from openssh by %s@%s\"\n",
132 BN_num_bits(k->dsa->p),
133 pw->pw_name, hostname);
134 dump_base64(stdout, blob, len);
135 fprintf(stdout, SSH_COM_MAGIC_END "\n");
136 key_free(k);
137 xfree(blob);
138 exit(0);
139}
140
141void
142do_convert_from_ssh2(struct passwd *pw)
143{
144 Key *k;
145 int blen;
146 char line[1024], *p;
147 char blob[8096];
148 char encoded[8096];
149 struct stat st;
150 FILE *fp;
151
152 if (!have_identity)
153 ask_filename(pw, "Enter file in which the key is");
154 if (stat(identity_file, &st) < 0) {
155 perror(identity_file);
156 exit(1);
157 }
158 fp = fopen(identity_file, "r");
159 if (fp == NULL) {
160 perror(identity_file);
161 exit(1);
162 }
163 encoded[0] = '\0';
164 while (fgets(line, sizeof(line), fp)) {
165 if (strncmp(line, "----", 4) == 0 ||
166 strstr(line, ": ") != NULL) {
167 fprintf(stderr, "ignore: %s", line);
168 continue;
169 }
170 if (!(p = strchr(line, '\n'))) {
171 fprintf(stderr, "input line too long.\n");
172 exit(1);
173 }
174 *p = '\0';
175 strlcat(encoded, line, sizeof(encoded));
176 }
177 blen = uudecode(encoded, (unsigned char *)blob, sizeof(blob));
178 if (blen < 0) {
179 fprintf(stderr, "uudecode failed.\n");
180 exit(1);
181 }
182 k = dsa_key_from_blob(blob, blen);
183 if (!key_write(k, stdout))
184 fprintf(stderr, "key_write failed");
185 key_free(k);
186 fprintf(stdout, "\n");
187 fclose(fp);
188 exit(0);
189}
190
191void
192do_print_public(struct passwd *pw)
193{
194 Key *k;
195 int len;
196 unsigned char *blob;
197 struct stat st;
198
199 if (!have_identity)
200 ask_filename(pw, "Enter file in which the key is");
201 if (stat(identity_file, &st) < 0) {
202 perror(identity_file);
203 exit(1);
204 }
205 k = key_new(KEY_DSA);
206 if (!try_load_key(identity_file, k)) {
207 fprintf(stderr, "load failed\n");
208 exit(1);
209 }
210 dsa_make_key_blob(k, &blob, &len);
211 if (!key_write(k, stdout))
212 fprintf(stderr, "key_write failed");
213 key_free(k);
214 xfree(blob);
215 fprintf(stdout, "\n");
216 exit(0);
217}
218
80void 219void
81do_fingerprint(struct passwd *pw) 220do_fingerprint(struct passwd *pw)
82{ 221{
83 FILE *f; 222 FILE *f;
84 BIGNUM *e, *n; 223 BIGNUM *e, *n;
85 RSA *public_key; 224 Key *public;
86 char *comment = NULL, *cp, *ep, line[16*1024]; 225 char *comment = NULL, *cp, *ep, line[16*1024];
87 int i, skip = 0, num = 1, invalid = 1; 226 int i, skip = 0, num = 1, invalid = 1;
88 unsigned int ignore; 227 unsigned int ignore;
@@ -94,17 +233,16 @@ do_fingerprint(struct passwd *pw)
94 perror(identity_file); 233 perror(identity_file);
95 exit(1); 234 exit(1);
96 } 235 }
97 236 public = key_new(KEY_RSA);
98 public_key = RSA_new(); 237 if (load_public_key(identity_file, public, &comment)) {
99 if (load_public_key(identity_file, public_key, &comment)) { 238 printf("%d %s %s\n", BN_num_bits(public->rsa->n),
100 printf("%d %s %s\n", BN_num_bits(public_key->n), 239 key_fingerprint(public), comment);
101 fingerprint(public_key->e, public_key->n), 240 key_free(public);
102 comment);
103 RSA_free(public_key);
104 exit(0); 241 exit(0);
105 } 242 }
106 RSA_free(public_key); 243 key_free(public);
107 244
245 /* XXX */
108 f = fopen(identity_file, "r"); 246 f = fopen(identity_file, "r");
109 if (f != NULL) { 247 if (f != NULL) {
110 n = BN_new(); 248 n = BN_new();
@@ -172,7 +310,9 @@ do_change_passphrase(struct passwd *pw)
172 char *comment; 310 char *comment;
173 char *old_passphrase, *passphrase1, *passphrase2; 311 char *old_passphrase, *passphrase1, *passphrase2;
174 struct stat st; 312 struct stat st;
175 RSA *private_key; 313 Key *private;
314 Key *public;
315 int type = dsa_mode ? KEY_DSA : KEY_RSA;
176 316
177 if (!have_identity) 317 if (!have_identity)
178 ask_filename(pw, "Enter file in which the key is"); 318 ask_filename(pw, "Enter file in which the key is");
@@ -180,22 +320,26 @@ do_change_passphrase(struct passwd *pw)
180 perror(identity_file); 320 perror(identity_file);
181 exit(1); 321 exit(1);
182 } 322 }
183 public_key = RSA_new(); 323
184 if (!load_public_key(identity_file, public_key, NULL)) { 324 if (type == KEY_RSA) {
185 printf("%s is not a valid key file.\n", identity_file); 325 /* XXX this works currently only for RSA */
186 exit(1); 326 public = key_new(type);
327 if (!load_public_key(identity_file, public, NULL)) {
328 printf("%s is not a valid key file.\n", identity_file);
329 exit(1);
330 }
331 /* Clear the public key since we are just about to load the whole file. */
332 key_free(public);
187 } 333 }
188 /* Clear the public key since we are just about to load the whole file. */
189 RSA_free(public_key);
190 334
191 /* Try to load the file with empty passphrase. */ 335 /* Try to load the file with empty passphrase. */
192 private_key = RSA_new(); 336 private = key_new(type);
193 if (!load_private_key(identity_file, "", private_key, &comment)) { 337 if (!load_private_key(identity_file, "", private, &comment)) {
194 if (identity_passphrase) 338 if (identity_passphrase)
195 old_passphrase = xstrdup(identity_passphrase); 339 old_passphrase = xstrdup(identity_passphrase);
196 else 340 else
197 old_passphrase = read_passphrase("Enter old passphrase: ", 1); 341 old_passphrase = read_passphrase("Enter old passphrase: ", 1);
198 if (!load_private_key(identity_file, old_passphrase, private_key, &comment)) { 342 if (!load_private_key(identity_file, old_passphrase, private, &comment)) {
199 memset(old_passphrase, 0, strlen(old_passphrase)); 343 memset(old_passphrase, 0, strlen(old_passphrase));
200 xfree(old_passphrase); 344 xfree(old_passphrase);
201 printf("Bad passphrase.\n"); 345 printf("Bad passphrase.\n");
@@ -230,19 +374,19 @@ do_change_passphrase(struct passwd *pw)
230 } 374 }
231 375
232 /* Save the file using the new passphrase. */ 376 /* Save the file using the new passphrase. */
233 if (!save_private_key(identity_file, passphrase1, private_key, comment)) { 377 if (!save_private_key(identity_file, passphrase1, private, comment)) {
234 printf("Saving the key failed: %s: %s.\n", 378 printf("Saving the key failed: %s: %s.\n",
235 identity_file, strerror(errno)); 379 identity_file, strerror(errno));
236 memset(passphrase1, 0, strlen(passphrase1)); 380 memset(passphrase1, 0, strlen(passphrase1));
237 xfree(passphrase1); 381 xfree(passphrase1);
238 RSA_free(private_key); 382 key_free(private);
239 xfree(comment); 383 xfree(comment);
240 exit(1); 384 exit(1);
241 } 385 }
242 /* Destroy the passphrase and the copy of the key in memory. */ 386 /* Destroy the passphrase and the copy of the key in memory. */
243 memset(passphrase1, 0, strlen(passphrase1)); 387 memset(passphrase1, 0, strlen(passphrase1));
244 xfree(passphrase1); 388 xfree(passphrase1);
245 RSA_free(private_key); /* Destroys contents */ 389 key_free(private); /* Destroys contents */
246 xfree(comment); 390 xfree(comment);
247 391
248 printf("Your identification has been saved with the new passphrase.\n"); 392 printf("Your identification has been saved with the new passphrase.\n");
@@ -256,11 +400,11 @@ void
256do_change_comment(struct passwd *pw) 400do_change_comment(struct passwd *pw)
257{ 401{
258 char new_comment[1024], *comment; 402 char new_comment[1024], *comment;
259 RSA *private_key; 403 Key *private;
404 Key *public;
260 char *passphrase; 405 char *passphrase;
261 struct stat st; 406 struct stat st;
262 FILE *f; 407 FILE *f;
263 char *tmpbuf;
264 408
265 if (!have_identity) 409 if (!have_identity)
266 ask_filename(pw, "Enter file in which the key is"); 410 ask_filename(pw, "Enter file in which the key is");
@@ -272,14 +416,14 @@ do_change_comment(struct passwd *pw)
272 * Try to load the public key from the file the verify that it is 416 * Try to load the public key from the file the verify that it is
273 * readable and of the proper format. 417 * readable and of the proper format.
274 */ 418 */
275 public_key = RSA_new(); 419 public = key_new(KEY_RSA);
276 if (!load_public_key(identity_file, public_key, NULL)) { 420 if (!load_public_key(identity_file, public, NULL)) {
277 printf("%s is not a valid key file.\n", identity_file); 421 printf("%s is not a valid key file.\n", identity_file);
278 exit(1); 422 exit(1);
279 } 423 }
280 private_key = RSA_new();
281 424
282 if (load_private_key(identity_file, "", private_key, &comment)) 425 private = key_new(KEY_RSA);
426 if (load_private_key(identity_file, "", private, &comment))
283 passphrase = xstrdup(""); 427 passphrase = xstrdup("");
284 else { 428 else {
285 if (identity_passphrase) 429 if (identity_passphrase)
@@ -289,7 +433,7 @@ do_change_comment(struct passwd *pw)
289 else 433 else
290 passphrase = read_passphrase("Enter passphrase: ", 1); 434 passphrase = read_passphrase("Enter passphrase: ", 1);
291 /* Try to load using the passphrase. */ 435 /* Try to load using the passphrase. */
292 if (!load_private_key(identity_file, passphrase, private_key, &comment)) { 436 if (!load_private_key(identity_file, passphrase, private, &comment)) {
293 memset(passphrase, 0, strlen(passphrase)); 437 memset(passphrase, 0, strlen(passphrase));
294 xfree(passphrase); 438 xfree(passphrase);
295 printf("Bad passphrase.\n"); 439 printf("Bad passphrase.\n");
@@ -305,7 +449,7 @@ do_change_comment(struct passwd *pw)
305 fflush(stdout); 449 fflush(stdout);
306 if (!fgets(new_comment, sizeof(new_comment), stdin)) { 450 if (!fgets(new_comment, sizeof(new_comment), stdin)) {
307 memset(passphrase, 0, strlen(passphrase)); 451 memset(passphrase, 0, strlen(passphrase));
308 RSA_free(private_key); 452 key_free(private);
309 exit(1); 453 exit(1);
310 } 454 }
311 if (strchr(new_comment, '\n')) 455 if (strchr(new_comment, '\n'))
@@ -313,18 +457,18 @@ do_change_comment(struct passwd *pw)
313 } 457 }
314 458
315 /* Save the file using the new passphrase. */ 459 /* Save the file using the new passphrase. */
316 if (!save_private_key(identity_file, passphrase, private_key, new_comment)) { 460 if (!save_private_key(identity_file, passphrase, private, new_comment)) {
317 printf("Saving the key failed: %s: %s.\n", 461 printf("Saving the key failed: %s: %s.\n",
318 identity_file, strerror(errno)); 462 identity_file, strerror(errno));
319 memset(passphrase, 0, strlen(passphrase)); 463 memset(passphrase, 0, strlen(passphrase));
320 xfree(passphrase); 464 xfree(passphrase);
321 RSA_free(private_key); 465 key_free(private);
322 xfree(comment); 466 xfree(comment);
323 exit(1); 467 exit(1);
324 } 468 }
325 memset(passphrase, 0, strlen(passphrase)); 469 memset(passphrase, 0, strlen(passphrase));
326 xfree(passphrase); 470 xfree(passphrase);
327 RSA_free(private_key); 471 key_free(private);
328 472
329 strlcat(identity_file, ".pub", sizeof(identity_file)); 473 strlcat(identity_file, ".pub", sizeof(identity_file));
330 f = fopen(identity_file, "w"); 474 f = fopen(identity_file, "w");
@@ -332,13 +476,10 @@ do_change_comment(struct passwd *pw)
332 printf("Could not save your public key in %s\n", identity_file); 476 printf("Could not save your public key in %s\n", identity_file);
333 exit(1); 477 exit(1);
334 } 478 }
335 fprintf(f, "%d ", BN_num_bits(public_key->n)); 479 if (!key_write(public, f))
336 tmpbuf = BN_bn2dec(public_key->e); 480 fprintf(stderr, "write key failed");
337 fprintf(f, "%s ", tmpbuf); 481 key_free(public);
338 free(tmpbuf); 482 fprintf(f, " %s\n", new_comment);
339 tmpbuf = BN_bn2dec(public_key->n);
340 fprintf(f, "%s %s\n", tmpbuf, new_comment);
341 free(tmpbuf);
342 fclose(f); 483 fclose(f);
343 484
344 xfree(comment); 485 xfree(comment);
@@ -351,7 +492,7 @@ void
351usage(void) 492usage(void)
352{ 493{
353 printf("ssh-keygen version %s\n", SSH_VERSION); 494 printf("ssh-keygen version %s\n", SSH_VERSION);
354 printf("Usage: %s [-b bits] [-p] [-c] [-l] [-f file] [-P pass] [-N new-pass] [-C comment]\n", __progname); 495 printf("Usage: %s [-b bits] [-p] [-c] [-l] [-x] [-X] [-y] [-f file] [-P pass] [-N new-pass] [-C comment]\n", __progname);
355 exit(1); 496 exit(1);
356} 497}
357 498
@@ -363,29 +504,28 @@ main(int ac, char **av)
363{ 504{
364 char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2; 505 char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2;
365 struct passwd *pw; 506 struct passwd *pw;
366 char *tmpbuf;
367 int opt; 507 int opt;
368 struct stat st; 508 struct stat st;
369 FILE *f; 509 FILE *f;
370 char hostname[MAXHOSTNAMELEN]; 510 Key *private;
511 Key *public;
371 extern int optind; 512 extern int optind;
372 extern char *optarg; 513 extern char *optarg;
373 514
374 /* check if RSA support exists */ 515 OpenSSL_add_all_algorithms();
375 if (rsa_alive() == 0) { 516
376 fprintf(stderr,
377 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
378 __progname);
379 exit(1);
380 }
381 /* we need this for the home * directory. */ 517 /* we need this for the home * directory. */
382 pw = getpwuid(getuid()); 518 pw = getpwuid(getuid());
383 if (!pw) { 519 if (!pw) {
384 printf("You don't exist, go away!\n"); 520 printf("You don't exist, go away!\n");
385 exit(1); 521 exit(1);
386 } 522 }
523 if (gethostname(hostname, sizeof(hostname)) < 0) {
524 perror("gethostname");
525 exit(1);
526 }
387 527
388 while ((opt = getopt(ac, av, "qpclb:f:P:N:C:")) != EOF) { 528 while ((opt = getopt(ac, av, "dqpclRxXyb:f:P:N:C:")) != EOF) {
389 switch (opt) { 529 switch (opt) {
390 case 'b': 530 case 'b':
391 bits = atoi(optarg); 531 bits = atoi(optarg);
@@ -428,6 +568,29 @@ main(int ac, char **av)
428 quiet = 1; 568 quiet = 1;
429 break; 569 break;
430 570
571 case 'R':
572 if (rsa_alive() == 0)
573 exit(1);
574 else
575 exit(0);
576 break;
577
578 case 'x':
579 convert_to_ssh2 = 1;
580 break;
581
582 case 'X':
583 convert_from_ssh2 = 1;
584 break;
585
586 case 'y':
587 print_public = 1;
588 break;
589
590 case 'd':
591 dsa_mode = 1;
592 break;
593
431 case '?': 594 case '?':
432 default: 595 default:
433 usage(); 596 usage();
@@ -441,22 +604,44 @@ main(int ac, char **av)
441 printf("Can only have one of -p and -c.\n"); 604 printf("Can only have one of -p and -c.\n");
442 usage(); 605 usage();
443 } 606 }
607 /* check if RSA support is needed and exists */
608 if (dsa_mode == 0 && rsa_alive() == 0) {
609 fprintf(stderr,
610 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
611 __progname);
612 exit(1);
613 }
444 if (print_fingerprint) 614 if (print_fingerprint)
445 do_fingerprint(pw); 615 do_fingerprint(pw);
446 if (change_passphrase) 616 if (change_passphrase)
447 do_change_passphrase(pw); 617 do_change_passphrase(pw);
448 if (change_comment) 618 if (change_comment)
449 do_change_comment(pw); 619 do_change_comment(pw);
620 if (convert_to_ssh2)
621 do_convert_to_ssh2(pw);
622 if (convert_from_ssh2)
623 do_convert_from_ssh2(pw);
624 if (print_public)
625 do_print_public(pw);
450 626
451 arc4random_stir(); 627 arc4random_stir();
452 628
453 if (quiet) 629 if (dsa_mode != 0) {
454 rsa_set_verbose(0); 630 if (!quiet)
455 631 printf("Generating DSA parameter and key.\n");
456 /* Generate the rsa key pair. */ 632 public = private = dsa_generate_key(bits);
457 private_key = RSA_new(); 633 if (private == NULL) {
458 public_key = RSA_new(); 634 fprintf(stderr, "dsa_generate_keys failed");
459 rsa_generate_key(private_key, public_key, bits); 635 exit(1);
636 }
637 } else {
638 if (quiet)
639 rsa_set_verbose(0);
640 /* Generate the rsa key pair. */
641 public = key_new(KEY_RSA);
642 private = key_new(KEY_RSA);
643 rsa_generate_key(private->rsa, public->rsa, bits);
644 }
460 645
461 if (!have_identity) 646 if (!have_identity)
462 ask_filename(pw, "Enter file in which to save the key"); 647 ask_filename(pw, "Enter file in which to save the key");
@@ -509,17 +694,13 @@ passphrase_again:
509 strlcpy(comment, identity_comment, sizeof(comment)); 694 strlcpy(comment, identity_comment, sizeof(comment));
510 } else { 695 } else {
511 /* Create default commend field for the passphrase. */ 696 /* Create default commend field for the passphrase. */
512 if (gethostname(hostname, sizeof(hostname)) < 0) {
513 perror("gethostname");
514 exit(1);
515 }
516 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); 697 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
517 } 698 }
518 699
519 /* Save the key with the given passphrase and comment. */ 700 /* Save the key with the given passphrase and comment. */
520 if (!save_private_key(identity_file, passphrase1, private_key, comment)) { 701 if (!save_private_key(identity_file, passphrase1, private, comment)) {
521 printf("Saving the key failed: %s: %s.\n", 702 printf("Saving the key failed: %s: %s.\n",
522 identity_file, strerror(errno)); 703 identity_file, strerror(errno));
523 memset(passphrase1, 0, strlen(passphrase1)); 704 memset(passphrase1, 0, strlen(passphrase1));
524 xfree(passphrase1); 705 xfree(passphrase1);
525 exit(1); 706 exit(1);
@@ -529,7 +710,9 @@ passphrase_again:
529 xfree(passphrase1); 710 xfree(passphrase1);
530 711
531 /* Clear the private key and the random number generator. */ 712 /* Clear the private key and the random number generator. */
532 RSA_free(private_key); 713 if (private != public) {
714 key_free(private);
715 }
533 arc4random_stir(); 716 arc4random_stir();
534 717
535 if (!quiet) 718 if (!quiet)
@@ -541,21 +724,18 @@ passphrase_again:
541 printf("Could not save your public key in %s\n", identity_file); 724 printf("Could not save your public key in %s\n", identity_file);
542 exit(1); 725 exit(1);
543 } 726 }
544 fprintf(f, "%d ", BN_num_bits(public_key->n)); 727 if (!key_write(public, f))
545 tmpbuf = BN_bn2dec(public_key->e); 728 fprintf(stderr, "write key failed");
546 fprintf(f, "%s ", tmpbuf); 729 fprintf(f, " %s\n", comment);
547 free(tmpbuf);
548 tmpbuf = BN_bn2dec(public_key->n);
549 fprintf(f, "%s %s\n", tmpbuf, comment);
550 free(tmpbuf);
551 fclose(f); 730 fclose(f);
552 731
553 if (!quiet) { 732 if (!quiet) {
554 printf("Your public key has been saved in %s.\n", identity_file); 733 printf("Your public key has been saved in %s.\n",
734 identity_file);
555 printf("The key fingerprint is:\n"); 735 printf("The key fingerprint is:\n");
556 printf("%d %s %s\n", BN_num_bits(public_key->n), 736 printf("%s %s\n", key_fingerprint(public), comment);
557 fingerprint(public_key->e, public_key->n),
558 comment);
559 } 737 }
738
739 key_free(public);
560 exit(0); 740 exit(0);
561} 741}
diff --git a/ssh.c b/ssh.c
index 456570fc4..bdf6180c8 100644
--- a/ssh.c
+++ b/ssh.c
@@ -11,7 +11,11 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$Id: ssh.c,v 1.26 2000/04/16 01:18:46 damien Exp $"); 14RCSID("$Id: ssh.c,v 1.27 2000/04/29 13:57:12 damien Exp $");
15
16#include <openssl/evp.h>
17#include <openssl/dsa.h>
18#include <openssl/rsa.h>
15 19
16#include "xmalloc.h" 20#include "xmalloc.h"
17#include "ssh.h" 21#include "ssh.h"
@@ -24,6 +28,8 @@ RCSID("$Id: ssh.c,v 1.26 2000/04/16 01:18:46 damien Exp $");
24#include "ssh2.h" 28#include "ssh2.h"
25#include "compat.h" 29#include "compat.h"
26#include "channels.h" 30#include "channels.h"
31#include "key.h"
32#include "authfile.h"
27 33
28#ifdef HAVE___PROGNAME 34#ifdef HAVE___PROGNAME
29extern char *__progname; 35extern char *__progname;
@@ -358,10 +364,16 @@ main(int ac, char **av)
358 } 364 }
359 break; 365 break;
360 case 'c': 366 case 'c':
361 options.cipher = cipher_number(optarg); 367 if (ciphers_valid(optarg)) {
362 if (options.cipher == -1) { 368 /* SSH2 only */
363 fprintf(stderr, "Unknown cipher type '%s'\n", optarg); 369 options.ciphers = xstrdup(optarg);
364 exit(1); 370 } else {
371 /* SSH1 only */
372 options.cipher = cipher_number(optarg);
373 if (options.cipher == -1) {
374 fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
375 exit(1);
376 }
365 } 377 }
366 break; 378 break;
367 case 'p': 379 case 'p':
@@ -417,16 +429,11 @@ main(int ac, char **av)
417 if (!host) 429 if (!host)
418 usage(); 430 usage();
419 431
420 /* check if RSA support exists */
421 if (rsa_alive() == 0) {
422 fprintf(stderr,
423 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
424 __progname);
425 exit(1);
426 }
427 /* Initialize the command to execute on remote host. */ 432 /* Initialize the command to execute on remote host. */
428 buffer_init(&command); 433 buffer_init(&command);
429 434
435 OpenSSL_add_all_algorithms();
436
430 /* 437 /*
431 * Save the command to execute on the remote host in a buffer. There 438 * Save the command to execute on the remote host in a buffer. There
432 * is no limit on the length of the command, except by the maximum 439 * is no limit on the length of the command, except by the maximum
@@ -496,6 +503,20 @@ main(int ac, char **av)
496 /* reinit */ 503 /* reinit */
497 log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0); 504 log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
498 505
506 /* check if RSA support exists */
507 if ((options.protocol & SSH_PROTO_1) &&
508 rsa_alive() == 0) {
509 log("%s: no RSA support in libssl and libcrypto. See ssl(8).",
510 __progname);
511 log("Disabling protocol version 1");
512 options.protocol &= ~ (SSH_PROTO_1|SSH_PROTO_1_PREFERRED);
513 }
514 if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
515 fprintf(stderr, "%s: No protocol version available.\n",
516 __progname);
517 exit(1);
518 }
519
499 if (options.user == NULL) 520 if (options.user == NULL)
500 options.user = xstrdup(pw->pw_name); 521 options.user = xstrdup(pw->pw_name);
501 522
@@ -562,9 +583,12 @@ main(int ac, char **av)
562 * authentication. This must be done before releasing extra 583 * authentication. This must be done before releasing extra
563 * privileges, because the file is only readable by root. 584 * privileges, because the file is only readable by root.
564 */ 585 */
565 if (ok) { 586 if (ok && (options.protocol & SSH_PROTO_1)) {
587 Key k;
566 host_private_key = RSA_new(); 588 host_private_key = RSA_new();
567 if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL)) 589 k.type = KEY_RSA;
590 k.rsa = host_private_key;
591 if (load_private_key(HOST_KEY_FILE, "", &k, NULL))
568 host_private_key_loaded = 1; 592 host_private_key_loaded = 1;
569 } 593 }
570 /* 594 /*
@@ -610,15 +634,22 @@ main(int ac, char **av)
610 exit(1); 634 exit(1);
611 } 635 }
612 /* Expand ~ in options.identity_files. */ 636 /* Expand ~ in options.identity_files. */
637 /* XXX mem-leaks */
613 for (i = 0; i < options.num_identity_files; i++) 638 for (i = 0; i < options.num_identity_files; i++)
614 options.identity_files[i] = 639 options.identity_files[i] =
615 tilde_expand_filename(options.identity_files[i], original_real_uid); 640 tilde_expand_filename(options.identity_files[i], original_real_uid);
616 641 for (i = 0; i < options.num_identity_files2; i++)
642 options.identity_files2[i] =
643 tilde_expand_filename(options.identity_files2[i], original_real_uid);
617 /* Expand ~ in known host file names. */ 644 /* Expand ~ in known host file names. */
618 options.system_hostfile = tilde_expand_filename(options.system_hostfile, 645 options.system_hostfile = tilde_expand_filename(options.system_hostfile,
619 original_real_uid); 646 original_real_uid);
620 options.user_hostfile = tilde_expand_filename(options.user_hostfile, 647 options.user_hostfile = tilde_expand_filename(options.user_hostfile,
621 original_real_uid); 648 original_real_uid);
649 options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2,
650 original_real_uid);
651 options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2,
652 original_real_uid);
622 653
623 /* Log into the remote system. This never returns if the login fails. */ 654 /* Log into the remote system. This never returns if the login fails. */
624 ssh_login(host_private_key_loaded, host_private_key, 655 ssh_login(host_private_key_loaded, host_private_key,
diff --git a/ssh.h b/ssh.h
index 87821398c..57d78278f 100644
--- a/ssh.h
+++ b/ssh.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: ssh.h,v 1.34 2000/04/20 13:12:59 damien Exp $"); */ 16/* RCSID("$Id: ssh.h,v 1.35 2000/04/29 13:57:12 damien Exp $"); */
17 17
18#ifndef SSH_H 18#ifndef SSH_H
19#define SSH_H 19#define SSH_H
@@ -88,6 +88,7 @@
88 * world-readable. 88 * world-readable.
89 */ 89 */
90#define SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts" 90#define SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts"
91#define SSH_SYSTEM_HOSTFILE2 ETCDIR "/ssh_known_hosts2"
91 92
92/* 93/*
93 * Of these, ssh_host_key must be readable only by root, whereas ssh_config 94 * Of these, ssh_host_key must be readable only by root, whereas ssh_config
@@ -96,7 +97,7 @@
96#define HOST_KEY_FILE ETCDIR "/ssh_host_key" 97#define HOST_KEY_FILE ETCDIR "/ssh_host_key"
97#define SERVER_CONFIG_FILE ETCDIR "/sshd_config" 98#define SERVER_CONFIG_FILE ETCDIR "/sshd_config"
98#define HOST_CONFIG_FILE ETCDIR "/ssh_config" 99#define HOST_CONFIG_FILE ETCDIR "/ssh_config"
99#define DSA_KEY_FILE ETCDIR "/ssh_dsa_key" 100#define DSA_KEY_FILE ETCDIR "/ssh_host_dsa_key"
100 101
101#ifndef SSH_PROGRAM 102#ifndef SSH_PROGRAM
102#define SSH_PROGRAM "/usr/bin/ssh" 103#define SSH_PROGRAM "/usr/bin/ssh"
@@ -128,6 +129,7 @@
128 * contain anything particularly secret. 129 * contain anything particularly secret.
129 */ 130 */
130#define SSH_USER_HOSTFILE "~/.ssh/known_hosts" 131#define SSH_USER_HOSTFILE "~/.ssh/known_hosts"
132#define SSH_USER_HOSTFILE2 "~/.ssh/known_hosts2"
131 133
132/* 134/*
133 * Name of the default file containing client-side authentication key. This 135 * Name of the default file containing client-side authentication key. This
@@ -152,6 +154,7 @@
152 * running as root.) 154 * running as root.)
153 */ 155 */
154#define SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys" 156#define SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys"
157#define SSH_USER_PERMITTED_KEYS2 ".ssh/authorized_keys2"
155 158
156/* 159/*
157 * Per-user and system-wide ssh "rc" files. These files are executed with 160 * Per-user and system-wide ssh "rc" files. These files are executed with
@@ -407,36 +410,6 @@ int auth_rsa_challenge_dialog(RSA *pk);
407 */ 410 */
408char *read_passphrase(const char *prompt, int from_stdin); 411char *read_passphrase(const char *prompt, int from_stdin);
409 412
410/*
411 * Saves the authentication (private) key in a file, encrypting it with
412 * passphrase. The identification of the file (lowest 64 bits of n) will
413 * precede the key to provide identification of the key without needing a
414 * passphrase.
415 */
416int
417save_private_key(const char *filename, const char *passphrase,
418 RSA * private_key, const char *comment);
419
420/*
421 * Loads the public part of the key file (public key and comment). Returns 0
422 * if an error occurred; zero if the public key was successfully read. The
423 * comment of the key is returned in comment_return if it is non-NULL; the
424 * caller must free the value with xfree.
425 */
426int
427load_public_key(const char *filename, RSA * pub,
428 char **comment_return);
429
430/*
431 * Loads the private key from the file. Returns 0 if an error is encountered
432 * (file does not exist or is not readable, or passphrase is bad). This
433 * initializes the private key. The comment of the key is returned in
434 * comment_return if it is non-NULL; the caller must free the value with
435 * xfree.
436 */
437int
438load_private_key(const char *filename, const char *passphrase,
439 RSA * private_key, char **comment_return);
440 413
441/*------------ Definitions for logging. -----------------------*/ 414/*------------ Definitions for logging. -----------------------*/
442 415
diff --git a/sshconnect.c b/sshconnect.c
index f58289e7b..5554c0643 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -5,48 +5,29 @@
5 * Created: Sat Mar 18 22:15:47 1995 ylo 5 * Created: Sat Mar 18 22:15:47 1995 ylo
6 * Code to connect to a remote host, and to perform the client side of the 6 * Code to connect to a remote host, and to perform the client side of the
7 * login (authentication) dialog. 7 * login (authentication) dialog.
8 *
9 * SSH2 support added by Markus Friedl.
10 */ 8 */
11 9
12#include "includes.h" 10#include "includes.h"
13RCSID("$OpenBSD: sshconnect.c,v 1.69 2000/04/19 07:05:50 deraadt Exp $"); 11RCSID("$OpenBSD: sshconnect.c,v 1.71 2000/04/26 21:28:33 markus Exp $");
14 12
15#include <openssl/bn.h> 13#include <openssl/bn.h>
14#include <openssl/dsa.h>
15#include <openssl/rsa.h>
16
16#include "xmalloc.h" 17#include "xmalloc.h"
17#include "rsa.h" 18#include "rsa.h"
18#include "ssh.h" 19#include "ssh.h"
19#include "buffer.h" 20#include "buffer.h"
20#include "packet.h" 21#include "packet.h"
21#include "authfd.h"
22#include "cipher.h"
23#include "mpaux.h"
24#include "uidswap.h" 22#include "uidswap.h"
25#include "compat.h" 23#include "compat.h"
26#include "readconf.h" 24#include "readconf.h"
27
28#include "bufaux.h"
29#include <openssl/rsa.h>
30#include <openssl/dsa.h>
31
32#include "ssh2.h"
33#include <openssl/md5.h>
34#include <openssl/dh.h>
35#include <openssl/hmac.h>
36#include "kex.h"
37#include "myproposal.h"
38#include "key.h" 25#include "key.h"
39#include "dsa.h" 26#include "sshconnect.h"
40#include "hostfile.h" 27#include "hostfile.h"
41 28
42/* Session id for the current session. */ 29char *client_version_string = NULL;
43unsigned char session_id[16]; 30char *server_version_string = NULL;
44
45/* authentications supported by server */
46unsigned int supported_authentications;
47
48static char *client_version_string = NULL;
49static char *server_version_string = NULL;
50 31
51extern Options options; 32extern Options options;
52extern char *__progname; 33extern char *__progname;
@@ -316,653 +297,6 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
316 return 1; 297 return 1;
317} 298}
318 299
319/*
320 * Checks if the user has an authentication agent, and if so, tries to
321 * authenticate using the agent.
322 */
323int
324try_agent_authentication()
325{
326 int status, type;
327 char *comment;
328 AuthenticationConnection *auth;
329 unsigned char response[16];
330 unsigned int i;
331 BIGNUM *e, *n, *challenge;
332
333 /* Get connection to the agent. */
334 auth = ssh_get_authentication_connection();
335 if (!auth)
336 return 0;
337
338 e = BN_new();
339 n = BN_new();
340 challenge = BN_new();
341
342 /* Loop through identities served by the agent. */
343 for (status = ssh_get_first_identity(auth, e, n, &comment);
344 status;
345 status = ssh_get_next_identity(auth, e, n, &comment)) {
346 int plen, clen;
347
348 /* Try this identity. */
349 debug("Trying RSA authentication via agent with '%.100s'", comment);
350 xfree(comment);
351
352 /* Tell the server that we are willing to authenticate using this key. */
353 packet_start(SSH_CMSG_AUTH_RSA);
354 packet_put_bignum(n);
355 packet_send();
356 packet_write_wait();
357
358 /* Wait for server's response. */
359 type = packet_read(&plen);
360
361 /* The server sends failure if it doesn\'t like our key or
362 does not support RSA authentication. */
363 if (type == SSH_SMSG_FAILURE) {
364 debug("Server refused our key.");
365 continue;
366 }
367 /* Otherwise it should have sent a challenge. */
368 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
369 packet_disconnect("Protocol error during RSA authentication: %d",
370 type);
371
372 packet_get_bignum(challenge, &clen);
373
374 packet_integrity_check(plen, clen, type);
375
376 debug("Received RSA challenge from server.");
377
378 /* Ask the agent to decrypt the challenge. */
379 if (!ssh_decrypt_challenge(auth, e, n, challenge,
380 session_id, 1, response)) {
381 /* The agent failed to authenticate this identifier although it
382 advertised it supports this. Just return a wrong value. */
383 log("Authentication agent failed to decrypt challenge.");
384 memset(response, 0, sizeof(response));
385 }
386 debug("Sending response to RSA challenge.");
387
388 /* Send the decrypted challenge back to the server. */
389 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
390 for (i = 0; i < 16; i++)
391 packet_put_char(response[i]);
392 packet_send();
393 packet_write_wait();
394
395 /* Wait for response from the server. */
396 type = packet_read(&plen);
397
398 /* The server returns success if it accepted the authentication. */
399 if (type == SSH_SMSG_SUCCESS) {
400 debug("RSA authentication accepted by server.");
401 BN_clear_free(e);
402 BN_clear_free(n);
403 BN_clear_free(challenge);
404 return 1;
405 }
406 /* Otherwise it should return failure. */
407 if (type != SSH_SMSG_FAILURE)
408 packet_disconnect("Protocol error waiting RSA auth response: %d",
409 type);
410 }
411
412 BN_clear_free(e);
413 BN_clear_free(n);
414 BN_clear_free(challenge);
415
416 debug("RSA authentication using agent refused.");
417 return 0;
418}
419
420/*
421 * Computes the proper response to a RSA challenge, and sends the response to
422 * the server.
423 */
424void
425respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
426{
427 unsigned char buf[32], response[16];
428 MD5_CTX md;
429 int i, len;
430
431 /* Decrypt the challenge using the private key. */
432 rsa_private_decrypt(challenge, challenge, prv);
433
434 /* Compute the response. */
435 /* The response is MD5 of decrypted challenge plus session id. */
436 len = BN_num_bytes(challenge);
437 if (len <= 0 || len > sizeof(buf))
438 packet_disconnect("respond_to_rsa_challenge: bad challenge length %d",
439 len);
440
441 memset(buf, 0, sizeof(buf));
442 BN_bn2bin(challenge, buf + sizeof(buf) - len);
443 MD5_Init(&md);
444 MD5_Update(&md, buf, 32);
445 MD5_Update(&md, session_id, 16);
446 MD5_Final(response, &md);
447
448 debug("Sending response to host key RSA challenge.");
449
450 /* Send the response back to the server. */
451 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
452 for (i = 0; i < 16; i++)
453 packet_put_char(response[i]);
454 packet_send();
455 packet_write_wait();
456
457 memset(buf, 0, sizeof(buf));
458 memset(response, 0, sizeof(response));
459 memset(&md, 0, sizeof(md));
460}
461
462/*
463 * Checks if the user has authentication file, and if so, tries to authenticate
464 * the user using it.
465 */
466int
467try_rsa_authentication(const char *authfile)
468{
469 BIGNUM *challenge;
470 RSA *private_key;
471 RSA *public_key;
472 char *passphrase, *comment;
473 int type, i;
474 int plen, clen;
475
476 /* Try to load identification for the authentication key. */
477 public_key = RSA_new();
478 if (!load_public_key(authfile, public_key, &comment)) {
479 RSA_free(public_key);
480 /* Could not load it. Fail. */
481 return 0;
482 }
483 debug("Trying RSA authentication with key '%.100s'", comment);
484
485 /* Tell the server that we are willing to authenticate using this key. */
486 packet_start(SSH_CMSG_AUTH_RSA);
487 packet_put_bignum(public_key->n);
488 packet_send();
489 packet_write_wait();
490
491 /* We no longer need the public key. */
492 RSA_free(public_key);
493
494 /* Wait for server's response. */
495 type = packet_read(&plen);
496
497 /*
498 * The server responds with failure if it doesn\'t like our key or
499 * doesn\'t support RSA authentication.
500 */
501 if (type == SSH_SMSG_FAILURE) {
502 debug("Server refused our key.");
503 xfree(comment);
504 return 0;
505 }
506 /* Otherwise, the server should respond with a challenge. */
507 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
508 packet_disconnect("Protocol error during RSA authentication: %d", type);
509
510 /* Get the challenge from the packet. */
511 challenge = BN_new();
512 packet_get_bignum(challenge, &clen);
513
514 packet_integrity_check(plen, clen, type);
515
516 debug("Received RSA challenge from server.");
517
518 private_key = RSA_new();
519 /*
520 * Load the private key. Try first with empty passphrase; if it
521 * fails, ask for a passphrase.
522 */
523 if (!load_private_key(authfile, "", private_key, NULL)) {
524 char buf[300];
525 snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
526 comment);
527 if (!options.batch_mode)
528 passphrase = read_passphrase(buf, 0);
529 else {
530 debug("Will not query passphrase for %.100s in batch mode.",
531 comment);
532 passphrase = xstrdup("");
533 }
534
535 /* Load the authentication file using the pasphrase. */
536 if (!load_private_key(authfile, passphrase, private_key, NULL)) {
537 memset(passphrase, 0, strlen(passphrase));
538 xfree(passphrase);
539 error("Bad passphrase.");
540
541 /* Send a dummy response packet to avoid protocol error. */
542 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
543 for (i = 0; i < 16; i++)
544 packet_put_char(0);
545 packet_send();
546 packet_write_wait();
547
548 /* Expect the server to reject it... */
549 packet_read_expect(&plen, SSH_SMSG_FAILURE);
550 xfree(comment);
551 return 0;
552 }
553 /* Destroy the passphrase. */
554 memset(passphrase, 0, strlen(passphrase));
555 xfree(passphrase);
556 }
557 /* We no longer need the comment. */
558 xfree(comment);
559
560 /* Compute and send a response to the challenge. */
561 respond_to_rsa_challenge(challenge, private_key);
562
563 /* Destroy the private key. */
564 RSA_free(private_key);
565
566 /* We no longer need the challenge. */
567 BN_clear_free(challenge);
568
569 /* Wait for response from the server. */
570 type = packet_read(&plen);
571 if (type == SSH_SMSG_SUCCESS) {
572 debug("RSA authentication accepted by server.");
573 return 1;
574 }
575 if (type != SSH_SMSG_FAILURE)
576 packet_disconnect("Protocol error waiting RSA auth response: %d", type);
577 debug("RSA authentication refused.");
578 return 0;
579}
580
581/*
582 * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv
583 * authentication and RSA host authentication.
584 */
585int
586try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
587{
588 int type;
589 BIGNUM *challenge;
590 int plen, clen;
591
592 debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
593
594 /* Tell the server that we are willing to authenticate using this key. */
595 packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
596 packet_put_string(local_user, strlen(local_user));
597 packet_put_int(BN_num_bits(host_key->n));
598 packet_put_bignum(host_key->e);
599 packet_put_bignum(host_key->n);
600 packet_send();
601 packet_write_wait();
602
603 /* Wait for server's response. */
604 type = packet_read(&plen);
605
606 /* The server responds with failure if it doesn't admit our
607 .rhosts authentication or doesn't know our host key. */
608 if (type == SSH_SMSG_FAILURE) {
609 debug("Server refused our rhosts authentication or host key.");
610 return 0;
611 }
612 /* Otherwise, the server should respond with a challenge. */
613 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
614 packet_disconnect("Protocol error during RSA authentication: %d", type);
615
616 /* Get the challenge from the packet. */
617 challenge = BN_new();
618 packet_get_bignum(challenge, &clen);
619
620 packet_integrity_check(plen, clen, type);
621
622 debug("Received RSA challenge for host key from server.");
623
624 /* Compute a response to the challenge. */
625 respond_to_rsa_challenge(challenge, host_key);
626
627 /* We no longer need the challenge. */
628 BN_clear_free(challenge);
629
630 /* Wait for response from the server. */
631 type = packet_read(&plen);
632 if (type == SSH_SMSG_SUCCESS) {
633 debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
634 return 1;
635 }
636 if (type != SSH_SMSG_FAILURE)
637 packet_disconnect("Protocol error waiting RSA auth response: %d", type);
638 debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");
639 return 0;
640}
641
642#ifdef KRB4
643int
644try_kerberos_authentication()
645{
646 KTEXT_ST auth; /* Kerberos data */
647 char *reply;
648 char inst[INST_SZ];
649 char *realm;
650 CREDENTIALS cred;
651 int r, type, plen;
652 socklen_t slen;
653 Key_schedule schedule;
654 u_long checksum, cksum;
655 MSG_DAT msg_data;
656 struct sockaddr_in local, foreign;
657 struct stat st;
658
659 /* Don't do anything if we don't have any tickets. */
660 if (stat(tkt_string(), &st) < 0)
661 return 0;
662
663 strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
664
665 realm = (char *) krb_realmofhost(get_canonical_hostname());
666 if (!realm) {
667 debug("Kerberos V4: no realm for %s", get_canonical_hostname());
668 return 0;
669 }
670 /* This can really be anything. */
671 checksum = (u_long) getpid();
672
673 r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
674 if (r != KSUCCESS) {
675 debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]);
676 return 0;
677 }
678 /* Get session key to decrypt the server's reply with. */
679 r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred);
680 if (r != KSUCCESS) {
681 debug("get_cred failed: %s", krb_err_txt[r]);
682 return 0;
683 }
684 des_key_sched((des_cblock *) cred.session, schedule);
685
686 /* Send authentication info to server. */
687 packet_start(SSH_CMSG_AUTH_KERBEROS);
688 packet_put_string((char *) auth.dat, auth.length);
689 packet_send();
690 packet_write_wait();
691
692 /* Zero the buffer. */
693 (void) memset(auth.dat, 0, MAX_KTXT_LEN);
694
695 slen = sizeof(local);
696 memset(&local, 0, sizeof(local));
697 if (getsockname(packet_get_connection_in(),
698 (struct sockaddr *) & local, &slen) < 0)
699 debug("getsockname failed: %s", strerror(errno));
700
701 slen = sizeof(foreign);
702 memset(&foreign, 0, sizeof(foreign));
703 if (getpeername(packet_get_connection_in(),
704 (struct sockaddr *) & foreign, &slen) < 0) {
705 debug("getpeername failed: %s", strerror(errno));
706 fatal_cleanup();
707 }
708 /* Get server reply. */
709 type = packet_read(&plen);
710 switch (type) {
711 case SSH_SMSG_FAILURE:
712 /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
713 debug("Kerberos V4 authentication failed.");
714 return 0;
715 break;
716
717 case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
718 /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
719 debug("Kerberos V4 authentication accepted.");
720
721 /* Get server's response. */
722 reply = packet_get_string((unsigned int *) &auth.length);
723 memcpy(auth.dat, reply, auth.length);
724 xfree(reply);
725
726 packet_integrity_check(plen, 4 + auth.length, type);
727
728 /*
729 * If his response isn't properly encrypted with the session
730 * key, and the decrypted checksum fails to match, he's
731 * bogus. Bail out.
732 */
733 r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
734 &foreign, &local, &msg_data);
735 if (r != KSUCCESS) {
736 debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]);
737 packet_disconnect("Kerberos V4 challenge failed!");
738 }
739 /* Fetch the (incremented) checksum that we supplied in the request. */
740 (void) memcpy((char *) &cksum, (char *) msg_data.app_data, sizeof(cksum));
741 cksum = ntohl(cksum);
742
743 /* If it matches, we're golden. */
744 if (cksum == checksum + 1) {
745 debug("Kerberos V4 challenge successful.");
746 return 1;
747 } else
748 packet_disconnect("Kerberos V4 challenge failed!");
749 break;
750
751 default:
752 packet_disconnect("Protocol error on Kerberos V4 response: %d", type);
753 }
754 return 0;
755}
756
757#endif /* KRB4 */
758
759#ifdef AFS
760int
761send_kerberos_tgt()
762{
763 CREDENTIALS *creds;
764 char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
765 int r, type, plen;
766 char buffer[8192];
767 struct stat st;
768
769 /* Don't do anything if we don't have any tickets. */
770 if (stat(tkt_string(), &st) < 0)
771 return 0;
772
773 creds = xmalloc(sizeof(*creds));
774
775 if ((r = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm)) != KSUCCESS) {
776 debug("Kerberos V4 tf_fullname failed: %s", krb_err_txt[r]);
777 return 0;
778 }
779 if ((r = krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) {
780 debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]);
781 return 0;
782 }
783 if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {
784 debug("Kerberos V4 ticket expired: %s", TKT_FILE);
785 return 0;
786 }
787 creds_to_radix(creds, (unsigned char *)buffer);
788 xfree(creds);
789
790 packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
791 packet_put_string(buffer, strlen(buffer));
792 packet_send();
793 packet_write_wait();
794
795 type = packet_read(&plen);
796
797 if (type == SSH_SMSG_FAILURE)
798 debug("Kerberos TGT for realm %s rejected.", prealm);
799 else if (type != SSH_SMSG_SUCCESS)
800 packet_disconnect("Protocol error on Kerberos TGT response: %d", type);
801
802 return 1;
803}
804
805void
806send_afs_tokens(void)
807{
808 CREDENTIALS creds;
809 struct ViceIoctl parms;
810 struct ClearToken ct;
811 int i, type, len, plen;
812 char buf[2048], *p, *server_cell;
813 char buffer[8192];
814
815 /* Move over ktc_GetToken, here's something leaner. */
816 for (i = 0; i < 100; i++) { /* just in case */
817 parms.in = (char *) &i;
818 parms.in_size = sizeof(i);
819 parms.out = buf;
820 parms.out_size = sizeof(buf);
821 if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0)
822 break;
823 p = buf;
824
825 /* Get secret token. */
826 memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
827 if (creds.ticket_st.length > MAX_KTXT_LEN)
828 break;
829 p += sizeof(unsigned int);
830 memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
831 p += creds.ticket_st.length;
832
833 /* Get clear token. */
834 memcpy(&len, p, sizeof(len));
835 if (len != sizeof(struct ClearToken))
836 break;
837 p += sizeof(len);
838 memcpy(&ct, p, len);
839 p += len;
840 p += sizeof(len); /* primary flag */
841 server_cell = p;
842
843 /* Flesh out our credentials. */
844 strlcpy(creds.service, "afs", sizeof creds.service);
845 creds.instance[0] = '\0';
846 strlcpy(creds.realm, server_cell, REALM_SZ);
847 memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
848 creds.issue_date = ct.BeginTimestamp;
849 creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp);
850 creds.kvno = ct.AuthHandle;
851 snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
852 creds.pinst[0] = '\0';
853
854 /* Encode token, ship it off. */
855 if (!creds_to_radix(&creds, (unsigned char*) buffer))
856 break;
857 packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
858 packet_put_string(buffer, strlen(buffer));
859 packet_send();
860 packet_write_wait();
861
862 /* Roger, Roger. Clearance, Clarence. What's your vector,
863 Victor? */
864 type = packet_read(&plen);
865
866 if (type == SSH_SMSG_FAILURE)
867 debug("AFS token for cell %s rejected.", server_cell);
868 else if (type != SSH_SMSG_SUCCESS)
869 packet_disconnect("Protocol error on AFS token response: %d", type);
870 }
871}
872
873#endif /* AFS */
874
875/*
876 * Tries to authenticate with any string-based challenge/response system.
877 * Note that the client code is not tied to s/key or TIS.
878 */
879int
880try_skey_authentication()
881{
882 int type, i;
883 int payload_len;
884 unsigned int clen;
885 char *challenge, *response;
886
887 debug("Doing skey authentication.");
888
889 /* request a challenge */
890 packet_start(SSH_CMSG_AUTH_TIS);
891 packet_send();
892 packet_write_wait();
893
894 type = packet_read(&payload_len);
895 if (type != SSH_SMSG_FAILURE &&
896 type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
897 packet_disconnect("Protocol error: got %d in response "
898 "to skey-auth", type);
899 }
900 if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
901 debug("No challenge for skey authentication.");
902 return 0;
903 }
904 challenge = packet_get_string(&clen);
905 packet_integrity_check(payload_len, (4 + clen), type);
906 if (options.cipher == SSH_CIPHER_NONE)
907 log("WARNING: Encryption is disabled! "
908 "Reponse will be transmitted in clear text.");
909 fprintf(stderr, "%s\n", challenge);
910 xfree(challenge);
911 fflush(stderr);
912 for (i = 0; i < options.number_of_password_prompts; i++) {
913 if (i != 0)
914 error("Permission denied, please try again.");
915 response = read_passphrase("Response: ", 0);
916 packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
917 packet_put_string(response, strlen(response));
918 memset(response, 0, strlen(response));
919 xfree(response);
920 packet_send();
921 packet_write_wait();
922 type = packet_read(&payload_len);
923 if (type == SSH_SMSG_SUCCESS)
924 return 1;
925 if (type != SSH_SMSG_FAILURE)
926 packet_disconnect("Protocol error: got %d in response "
927 "to skey-auth-reponse", type);
928 }
929 /* failure */
930 return 0;
931}
932
933/*
934 * Tries to authenticate with plain passwd authentication.
935 */
936int
937try_password_authentication(char *prompt)
938{
939 int type, i, payload_len;
940 char *password;
941
942 debug("Doing password authentication.");
943 if (options.cipher == SSH_CIPHER_NONE)
944 log("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
945 for (i = 0; i < options.number_of_password_prompts; i++) {
946 if (i != 0)
947 error("Permission denied, please try again.");
948 password = read_passphrase(prompt, 0);
949 packet_start(SSH_CMSG_AUTH_PASSWORD);
950 packet_put_string(password, strlen(password));
951 memset(password, 0, strlen(password));
952 xfree(password);
953 packet_send();
954 packet_write_wait();
955
956 type = packet_read(&payload_len);
957 if (type == SSH_SMSG_SUCCESS)
958 return 1;
959 if (type != SSH_SMSG_FAILURE)
960 packet_disconnect("Protocol error: got %d in response to passwd auth", type);
961 }
962 /* failure */
963 return 0;
964}
965
966char * 300char *
967chop(char *s) 301chop(char *s)
968{ 302{
@@ -1060,7 +394,8 @@ ssh_exchange_identification()
1060 fatal("Protocol major versions differ: %d vs. %d", 394 fatal("Protocol major versions differ: %d vs. %d",
1061 (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 395 (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
1062 remote_major); 396 remote_major);
1063 397 if (compat20)
398 packet_set_ssh2_format();
1064 /* Send our own protocol version identification. */ 399 /* Send our own protocol version identification. */
1065 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 400 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
1066 compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 401 compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
@@ -1122,7 +457,8 @@ read_yes_or_no(const char *prompt, int defval)
1122 */ 457 */
1123 458
1124void 459void
1125check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) 460check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
461 const char *user_hostfile, const char *system_hostfile)
1126{ 462{
1127 Key *file_key; 463 Key *file_key;
1128 char *ip = NULL; 464 char *ip = NULL;
@@ -1141,6 +477,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1141 * essentially disables host authentication for localhost; however, 477 * essentially disables host authentication for localhost; however,
1142 * this is probably not a real problem. 478 * this is probably not a real problem.
1143 */ 479 */
480 /** hostaddr == 0! */
1144 switch (hostaddr->sa_family) { 481 switch (hostaddr->sa_family) {
1145 case AF_INET: 482 case AF_INET:
1146 local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; 483 local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
@@ -1184,19 +521,19 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1184 * Check if the host key is present in the user\'s list of known 521 * Check if the host key is present in the user\'s list of known
1185 * hosts or in the systemwide list. 522 * hosts or in the systemwide list.
1186 */ 523 */
1187 host_status = check_host_in_hostfile(options.user_hostfile, host, host_key, file_key); 524 host_status = check_host_in_hostfile(user_hostfile, host, host_key, file_key);
1188 if (host_status == HOST_NEW) 525 if (host_status == HOST_NEW)
1189 host_status = check_host_in_hostfile(options.system_hostfile, host, host_key, file_key); 526 host_status = check_host_in_hostfile(system_hostfile, host, host_key, file_key);
1190 /* 527 /*
1191 * Also perform check for the ip address, skip the check if we are 528 * Also perform check for the ip address, skip the check if we are
1192 * localhost or the hostname was an ip address to begin with 529 * localhost or the hostname was an ip address to begin with
1193 */ 530 */
1194 if (options.check_host_ip && !local && strcmp(host, ip)) { 531 if (options.check_host_ip && !local && strcmp(host, ip)) {
1195 Key *ip_key = key_new(host_key->type); 532 Key *ip_key = key_new(host_key->type);
1196 ip_status = check_host_in_hostfile(options.user_hostfile, ip, host_key, ip_key); 533 ip_status = check_host_in_hostfile(user_hostfile, ip, host_key, ip_key);
1197 534
1198 if (ip_status == HOST_NEW) 535 if (ip_status == HOST_NEW)
1199 ip_status = check_host_in_hostfile(options.system_hostfile, ip, host_key, ip_key); 536 ip_status = check_host_in_hostfile(system_hostfile, ip, host_key, ip_key);
1200 if (host_status == HOST_CHANGED && 537 if (host_status == HOST_CHANGED &&
1201 (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key))) 538 (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
1202 host_ip_differ = 1; 539 host_ip_differ = 1;
@@ -1213,9 +550,9 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1213 debug("Host '%.200s' is known and matches the host key.", host); 550 debug("Host '%.200s' is known and matches the host key.", host);
1214 if (options.check_host_ip) { 551 if (options.check_host_ip) {
1215 if (ip_status == HOST_NEW) { 552 if (ip_status == HOST_NEW) {
1216 if (!add_host_to_hostfile(options.user_hostfile, ip, host_key)) 553 if (!add_host_to_hostfile(user_hostfile, ip, host_key))
1217 log("Failed to add the host key for IP address '%.30s' to the list of known hosts (%.30s).", 554 log("Failed to add the host key for IP address '%.30s' to the list of known hosts (%.30s).",
1218 ip, options.user_hostfile); 555 ip, user_hostfile);
1219 else 556 else
1220 log("Warning: Permanently added host key for IP address '%.30s' to the list of known hosts.", 557 log("Warning: Permanently added host key for IP address '%.30s' to the list of known hosts.",
1221 ip); 558 ip);
@@ -1249,9 +586,9 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1249 hostp = host; 586 hostp = host;
1250 587
1251 /* If not in strict mode, add the key automatically to the local known_hosts file. */ 588 /* If not in strict mode, add the key automatically to the local known_hosts file. */
1252 if (!add_host_to_hostfile(options.user_hostfile, hostp, host_key)) 589 if (!add_host_to_hostfile(user_hostfile, hostp, host_key))
1253 log("Failed to add the host to the list of known hosts (%.500s).", 590 log("Failed to add the host to the list of known hosts (%.500s).",
1254 options.user_hostfile); 591 user_hostfile);
1255 else 592 else
1256 log("Warning: Permanently added '%.200s' to the list of known hosts.", 593 log("Warning: Permanently added '%.200s' to the list of known hosts.",
1257 hostp); 594 hostp);
@@ -1283,7 +620,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1283 error("It is also possible that the host key has just been changed."); 620 error("It is also possible that the host key has just been changed.");
1284 error("Please contact your system administrator."); 621 error("Please contact your system administrator.");
1285 error("Add correct host key in %.100s to get rid of this message.", 622 error("Add correct host key in %.100s to get rid of this message.",
1286 options.user_hostfile); 623 user_hostfile);
1287 624
1288 /* 625 /*
1289 * If strict host key checking is in use, the user will have 626 * If strict host key checking is in use, the user will have
@@ -1317,260 +654,22 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1317 if (options.check_host_ip) 654 if (options.check_host_ip)
1318 xfree(ip); 655 xfree(ip);
1319} 656}
1320void
1321check_rsa_host_key(char *host, struct sockaddr *hostaddr, RSA *host_key)
1322{
1323 Key k;
1324 k.type = KEY_RSA;
1325 k.rsa = host_key;
1326 check_host_key(host, hostaddr, &k);
1327}
1328 657
1329/* 658/*
1330 * SSH2 key exchange 659 * Starts a dialog with the server, and authenticates the current user on the
1331 */ 660 * server. This does not need any extra privileges. The basic connection
1332void 661 * to the server must already have been established before this is called.
1333ssh_kex2(char *host, struct sockaddr *hostaddr) 662 * If login fails, this function prints an error and never returns.
1334{ 663 * This function does not require super-user privileges.
1335 Kex *kex;
1336 char *cprop[PROPOSAL_MAX];
1337 char *sprop[PROPOSAL_MAX];
1338 Buffer *client_kexinit;
1339 Buffer *server_kexinit;
1340 int payload_len, dlen;
1341 unsigned int klen, kout;
1342 char *ptr;
1343 char *signature = NULL;
1344 unsigned int slen;
1345 char *server_host_key_blob = NULL;
1346 Key *server_host_key;
1347 unsigned int sbloblen;
1348 DH *dh;
1349 BIGNUM *dh_server_pub = 0;
1350 BIGNUM *shared_secret = 0;
1351 int i;
1352 unsigned char *kbuf;
1353 unsigned char *hash;
1354
1355/* KEXINIT */
1356
1357 debug("Sending KEX init.");
1358 if (options.ciphers != NULL) {
1359 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
1360 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
1361 } else if (
1362 options.cipher == SSH_CIPHER_ARCFOUR ||
1363 options.cipher == SSH_CIPHER_3DES_CBC ||
1364 options.cipher == SSH_CIPHER_CAST128_CBC ||
1365 options.cipher == SSH_CIPHER_BLOWFISH_CBC) {
1366 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
1367 myproposal[PROPOSAL_ENC_ALGS_STOC] = cipher_name(options.cipher);
1368 }
1369 if (options.compression) {
1370 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
1371 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
1372 } else {
1373 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
1374 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
1375 }
1376 for (i = 0; i < PROPOSAL_MAX; i++)
1377 cprop[i] = xstrdup(myproposal[i]);
1378
1379 client_kexinit = kex_init(cprop);
1380 packet_start(SSH2_MSG_KEXINIT);
1381 packet_put_raw(buffer_ptr(client_kexinit), buffer_len(client_kexinit));
1382 packet_send();
1383 packet_write_wait();
1384
1385 debug("done");
1386
1387 packet_read_expect(&payload_len, SSH2_MSG_KEXINIT);
1388
1389 /* save payload for session_id */
1390 server_kexinit = xmalloc(sizeof(*server_kexinit));
1391 buffer_init(server_kexinit);
1392 ptr = packet_get_raw(&payload_len);
1393 buffer_append(server_kexinit, ptr, payload_len);
1394
1395 /* skip cookie */
1396 for (i = 0; i < 16; i++)
1397 (void) packet_get_char();
1398 /* kex init proposal strings */
1399 for (i = 0; i < PROPOSAL_MAX; i++) {
1400 sprop[i] = packet_get_string(NULL);
1401 debug("got kexinit string: %s", sprop[i]);
1402 }
1403 i = (int) packet_get_char();
1404 debug("first kex follow == %d", i);
1405 i = packet_get_int();
1406 debug("reserved == %d", i);
1407 packet_done();
1408
1409 debug("done read kexinit");
1410 kex = kex_choose_conf(cprop, sprop, 0);
1411
1412/* KEXDH */
1413
1414 debug("Sending SSH2_MSG_KEXDH_INIT.");
1415
1416 /* generate and send 'e', client DH public key */
1417 dh = dh_new_group1();
1418 packet_start(SSH2_MSG_KEXDH_INIT);
1419 packet_put_bignum2(dh->pub_key);
1420 packet_send();
1421 packet_write_wait();
1422
1423#ifdef DEBUG_KEXDH
1424 fprintf(stderr, "\np= ");
1425 bignum_print(dh->p);
1426 fprintf(stderr, "\ng= ");
1427 bignum_print(dh->g);
1428 fprintf(stderr, "\npub= ");
1429 bignum_print(dh->pub_key);
1430 fprintf(stderr, "\n");
1431 DHparams_print_fp(stderr, dh);
1432#endif
1433
1434 debug("Wait SSH2_MSG_KEXDH_REPLY.");
1435
1436 packet_read_expect(&payload_len, SSH2_MSG_KEXDH_REPLY);
1437
1438 debug("Got SSH2_MSG_KEXDH_REPLY.");
1439
1440 /* key, cert */
1441 server_host_key_blob = packet_get_string(&sbloblen);
1442 server_host_key = dsa_serverkey_from_blob(server_host_key_blob, sbloblen);
1443 if (server_host_key == NULL)
1444 fatal("cannot decode server_host_key_blob");
1445
1446 check_host_key(host, hostaddr, server_host_key);
1447
1448 /* DH paramter f, server public DH key */
1449 dh_server_pub = BN_new();
1450 if (dh_server_pub == NULL)
1451 fatal("dh_server_pub == NULL");
1452 packet_get_bignum2(dh_server_pub, &dlen);
1453
1454#ifdef DEBUG_KEXDH
1455 fprintf(stderr, "\ndh_server_pub= ");
1456 bignum_print(dh_server_pub);
1457 fprintf(stderr, "\n");
1458 debug("bits %d", BN_num_bits(dh_server_pub));
1459#endif
1460
1461 /* signed H */
1462 signature = packet_get_string(&slen);
1463 packet_done();
1464
1465 if (!dh_pub_is_valid(dh, dh_server_pub))
1466 packet_disconnect("bad server public DH value");
1467
1468 klen = DH_size(dh);
1469 kbuf = xmalloc(klen);
1470 kout = DH_compute_key(kbuf, dh_server_pub, dh);
1471#ifdef DEBUG_KEXDH
1472 debug("shared secret: len %d/%d", klen, kout);
1473 fprintf(stderr, "shared secret == ");
1474 for (i = 0; i< kout; i++)
1475 fprintf(stderr, "%02x", (kbuf[i])&0xff);
1476 fprintf(stderr, "\n");
1477#endif
1478 shared_secret = BN_new();
1479
1480 BN_bin2bn(kbuf, kout, shared_secret);
1481 memset(kbuf, 0, klen);
1482 xfree(kbuf);
1483
1484 /* calc and verify H */
1485 hash = kex_hash(
1486 client_version_string,
1487 server_version_string,
1488 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
1489 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
1490 server_host_key_blob, sbloblen,
1491 dh->pub_key,
1492 dh_server_pub,
1493 shared_secret
1494 );
1495 buffer_free(client_kexinit);
1496 buffer_free(server_kexinit);
1497 xfree(client_kexinit);
1498 xfree(server_kexinit);
1499#ifdef DEBUG_KEXDH
1500 fprintf(stderr, "hash == ");
1501 for (i = 0; i< 20; i++)
1502 fprintf(stderr, "%02x", (hash[i])&0xff);
1503 fprintf(stderr, "\n");
1504#endif
1505 dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20);
1506 key_free(server_host_key);
1507
1508 kex_derive_keys(kex, hash, shared_secret);
1509 packet_set_kex(kex);
1510
1511 /* have keys, free DH */
1512 DH_free(dh);
1513
1514 debug("Wait SSH2_MSG_NEWKEYS.");
1515 packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
1516 packet_done();
1517 debug("GOT SSH2_MSG_NEWKEYS.");
1518
1519 debug("send SSH2_MSG_NEWKEYS.");
1520 packet_start(SSH2_MSG_NEWKEYS);
1521 packet_send();
1522 packet_write_wait();
1523 debug("done: send SSH2_MSG_NEWKEYS.");
1524
1525#ifdef DEBUG_KEXDH
1526 /* send 1st encrypted/maced/compressed message */
1527 packet_start(SSH2_MSG_IGNORE);
1528 packet_put_cstring("markus");
1529 packet_send();
1530 packet_write_wait();
1531#endif
1532 debug("done: KEX2.");
1533}
1534/*
1535 * Authenticate user
1536 */ 664 */
1537void 665void
1538ssh_userauth2(int host_key_valid, RSA *own_host_key, 666ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
1539 uid_t original_real_uid, char *host) 667 struct sockaddr *hostaddr, uid_t original_real_uid)
1540{ 668{
1541 int type;
1542 int plen;
1543 unsigned int dlen;
1544 int partial;
1545 struct passwd *pw; 669 struct passwd *pw;
1546 char prompt[80]; 670 char *host, *cp;
1547 char *server_user, *local_user; 671 char *server_user, *local_user;
1548 char *auths;
1549 char *password;
1550 char *service = "ssh-connection"; /* service name */
1551
1552 debug("send SSH2_MSG_SERVICE_REQUEST");
1553 packet_start(SSH2_MSG_SERVICE_REQUEST);
1554 packet_put_cstring("ssh-userauth");
1555 packet_send();
1556 packet_write_wait();
1557
1558 type = packet_read(&plen);
1559 if (type != SSH2_MSG_SERVICE_ACCEPT) {
1560 fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
1561 }
1562 if (packet_remaining() > 0) {
1563 char *reply = packet_get_string(&plen);
1564 debug("service_accept: %s", reply);
1565 xfree(reply);
1566 } else {
1567 /* payload empty for ssh-2.0.13 ?? */
1568 log("buggy server: service_accept w/o service");
1569 }
1570 packet_done();
1571 debug("got SSH2_MSG_SERVICE_ACCEPT");
1572 672
1573 /*XX COMMONCODE: */
1574 /* Get local user name. Use it as server user if no user name was given. */ 673 /* Get local user name. Use it as server user if no user name was given. */
1575 pw = getpwuid(original_real_uid); 674 pw = getpwuid(original_real_uid);
1576 if (!pw) 675 if (!pw)
@@ -1578,396 +677,6 @@ ssh_userauth2(int host_key_valid, RSA *own_host_key,
1578 local_user = xstrdup(pw->pw_name); 677 local_user = xstrdup(pw->pw_name);
1579 server_user = options.user ? options.user : local_user; 678 server_user = options.user ? options.user : local_user;
1580 679
1581 /* INITIAL request for auth */
1582 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1583 packet_put_cstring(server_user);
1584 packet_put_cstring(service);
1585 packet_put_cstring("none");
1586 packet_send();
1587 packet_write_wait();
1588
1589 for (;;) {
1590 type = packet_read(&plen);
1591 if (type == SSH2_MSG_USERAUTH_SUCCESS)
1592 break;
1593 if (type != SSH2_MSG_USERAUTH_FAILURE)
1594 fatal("access denied: %d", type);
1595 /* SSH2_MSG_USERAUTH_FAILURE means: try again */
1596 auths = packet_get_string(&dlen);
1597 debug("authentications that can continue: %s", auths);
1598 partial = packet_get_char();
1599 packet_done();
1600 if (partial)
1601 debug("partial success");
1602 if (strstr(auths, "password") == NULL)
1603 fatal("passwd auth not supported: %s", auths);
1604 xfree(auths);
1605 /* try passwd */
1606 snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
1607 server_user, host);
1608 password = read_passphrase(prompt, 0);
1609 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1610 packet_put_cstring(server_user);
1611 packet_put_cstring(service);
1612 packet_put_cstring("password");
1613 packet_put_char(0);
1614 packet_put_cstring(password);
1615 memset(password, 0, strlen(password));
1616 xfree(password);
1617 packet_send();
1618 packet_write_wait();
1619 }
1620 packet_done();
1621 debug("ssh-userauth2 successfull");
1622}
1623
1624/*
1625 * SSH1 key exchange
1626 */
1627void
1628ssh_kex(char *host, struct sockaddr *hostaddr)
1629{
1630 int i;
1631 BIGNUM *key;
1632 RSA *host_key;
1633 RSA *public_key;
1634 int bits, rbits;
1635 int ssh_cipher_default = SSH_CIPHER_3DES;
1636 unsigned char session_key[SSH_SESSION_KEY_LENGTH];
1637 unsigned char cookie[8];
1638 unsigned int supported_ciphers;
1639 unsigned int server_flags, client_flags;
1640 int payload_len, clen, sum_len = 0;
1641 u_int32_t rand = 0;
1642
1643 debug("Waiting for server public key.");
1644
1645 /* Wait for a public key packet from the server. */
1646 packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY);
1647
1648 /* Get cookie from the packet. */
1649 for (i = 0; i < 8; i++)
1650 cookie[i] = packet_get_char();
1651
1652 /* Get the public key. */
1653 public_key = RSA_new();
1654 bits = packet_get_int();/* bits */
1655 public_key->e = BN_new();
1656 packet_get_bignum(public_key->e, &clen);
1657 sum_len += clen;
1658 public_key->n = BN_new();
1659 packet_get_bignum(public_key->n, &clen);
1660 sum_len += clen;
1661
1662 rbits = BN_num_bits(public_key->n);
1663 if (bits != rbits) {
1664 log("Warning: Server lies about size of server public key: "
1665 "actual size is %d bits vs. announced %d.", rbits, bits);
1666 log("Warning: This may be due to an old implementation of ssh.");
1667 }
1668 /* Get the host key. */
1669 host_key = RSA_new();
1670 bits = packet_get_int();/* bits */
1671 host_key->e = BN_new();
1672 packet_get_bignum(host_key->e, &clen);
1673 sum_len += clen;
1674 host_key->n = BN_new();
1675 packet_get_bignum(host_key->n, &clen);
1676 sum_len += clen;
1677
1678 rbits = BN_num_bits(host_key->n);
1679 if (bits != rbits) {
1680 log("Warning: Server lies about size of server host key: "
1681 "actual size is %d bits vs. announced %d.", rbits, bits);
1682 log("Warning: This may be due to an old implementation of ssh.");
1683 }
1684
1685 /* Get protocol flags. */
1686 server_flags = packet_get_int();
1687 packet_set_protocol_flags(server_flags);
1688
1689 supported_ciphers = packet_get_int();
1690 supported_authentications = packet_get_int();
1691
1692 debug("Received server public key (%d bits) and host key (%d bits).",
1693 BN_num_bits(public_key->n), BN_num_bits(host_key->n));
1694
1695 packet_integrity_check(payload_len,
1696 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
1697 SSH_SMSG_PUBLIC_KEY);
1698
1699 check_rsa_host_key(host, hostaddr, host_key);
1700
1701 client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
1702
1703 compute_session_id(session_id, cookie, host_key->n, public_key->n);
1704
1705 /* Generate a session key. */
1706 arc4random_stir();
1707
1708 /*
1709 * Generate an encryption key for the session. The key is a 256 bit
1710 * random number, interpreted as a 32-byte key, with the least
1711 * significant 8 bits being the first byte of the key.
1712 */
1713 for (i = 0; i < 32; i++) {
1714 if (i % 4 == 0)
1715 rand = arc4random();
1716 session_key[i] = rand & 0xff;
1717 rand >>= 8;
1718 }
1719
1720 /*
1721 * According to the protocol spec, the first byte of the session key
1722 * is the highest byte of the integer. The session key is xored with
1723 * the first 16 bytes of the session id.
1724 */
1725 key = BN_new();
1726 BN_set_word(key, 0);
1727 for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
1728 BN_lshift(key, key, 8);
1729 if (i < 16)
1730 BN_add_word(key, session_key[i] ^ session_id[i]);
1731 else
1732 BN_add_word(key, session_key[i]);
1733 }
1734
1735 /*
1736 * Encrypt the integer using the public key and host key of the
1737 * server (key with smaller modulus first).
1738 */
1739 if (BN_cmp(public_key->n, host_key->n) < 0) {
1740 /* Public key has smaller modulus. */
1741 if (BN_num_bits(host_key->n) <
1742 BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED) {
1743 fatal("respond_to_rsa_challenge: host_key %d < public_key %d + "
1744 "SSH_KEY_BITS_RESERVED %d",
1745 BN_num_bits(host_key->n),
1746 BN_num_bits(public_key->n),
1747 SSH_KEY_BITS_RESERVED);
1748 }
1749 rsa_public_encrypt(key, key, public_key);
1750 rsa_public_encrypt(key, key, host_key);
1751 } else {
1752 /* Host key has smaller modulus (or they are equal). */
1753 if (BN_num_bits(public_key->n) <
1754 BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED) {
1755 fatal("respond_to_rsa_challenge: public_key %d < host_key %d + "
1756 "SSH_KEY_BITS_RESERVED %d",
1757 BN_num_bits(public_key->n),
1758 BN_num_bits(host_key->n),
1759 SSH_KEY_BITS_RESERVED);
1760 }
1761 rsa_public_encrypt(key, key, host_key);
1762 rsa_public_encrypt(key, key, public_key);
1763 }
1764
1765 /* Destroy the public keys since we no longer need them. */
1766 RSA_free(public_key);
1767 RSA_free(host_key);
1768
1769 if (options.cipher == SSH_CIPHER_NOT_SET) {
1770 if (cipher_mask1() & supported_ciphers & (1 << ssh_cipher_default))
1771 options.cipher = ssh_cipher_default;
1772 else {
1773 debug("Cipher %s not supported, using %.100s instead.",
1774 cipher_name(ssh_cipher_default),
1775 cipher_name(SSH_FALLBACK_CIPHER));
1776 options.cipher = SSH_FALLBACK_CIPHER;
1777 }
1778 }
1779 /* Check that the selected cipher is supported. */
1780 if (!(supported_ciphers & (1 << options.cipher)))
1781 fatal("Selected cipher type %.100s not supported by server.",
1782 cipher_name(options.cipher));
1783
1784 debug("Encryption type: %.100s", cipher_name(options.cipher));
1785
1786 /* Send the encrypted session key to the server. */
1787 packet_start(SSH_CMSG_SESSION_KEY);
1788 packet_put_char(options.cipher);
1789
1790 /* Send the cookie back to the server. */
1791 for (i = 0; i < 8; i++)
1792 packet_put_char(cookie[i]);
1793
1794 /* Send and destroy the encrypted encryption key integer. */
1795 packet_put_bignum(key);
1796 BN_clear_free(key);
1797
1798 /* Send protocol flags. */
1799 packet_put_int(client_flags);
1800
1801 /* Send the packet now. */
1802 packet_send();
1803 packet_write_wait();
1804
1805 debug("Sent encrypted session key.");
1806
1807 /* Set the encryption key. */
1808 packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher);
1809
1810 /* We will no longer need the session key here. Destroy any extra copies. */
1811 memset(session_key, 0, sizeof(session_key));
1812
1813 /*
1814 * Expect a success message from the server. Note that this message
1815 * will be received in encrypted form.
1816 */
1817 packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
1818
1819 debug("Received encrypted confirmation.");
1820}
1821
1822/*
1823 * Authenticate user
1824 */
1825void
1826ssh_userauth(int host_key_valid, RSA *own_host_key,
1827 uid_t original_real_uid, char *host)
1828{
1829 int i, type;
1830 int payload_len;
1831 struct passwd *pw;
1832 const char *server_user, *local_user;
1833
1834 /* Get local user name. Use it as server user if no user name was given. */
1835 pw = getpwuid(original_real_uid);
1836 if (!pw)
1837 fatal("User id %d not found from user database.", original_real_uid);
1838 local_user = xstrdup(pw->pw_name);
1839 server_user = options.user ? options.user : local_user;
1840
1841 /* Send the name of the user to log in as on the server. */
1842 packet_start(SSH_CMSG_USER);
1843 packet_put_string(server_user, strlen(server_user));
1844 packet_send();
1845 packet_write_wait();
1846
1847 /*
1848 * The server should respond with success if no authentication is
1849 * needed (the user has no password). Otherwise the server responds
1850 * with failure.
1851 */
1852 type = packet_read(&payload_len);
1853
1854 /* check whether the connection was accepted without authentication. */
1855 if (type == SSH_SMSG_SUCCESS)
1856 return;
1857 if (type != SSH_SMSG_FAILURE)
1858 packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER",
1859 type);
1860
1861#ifdef AFS
1862 /* Try Kerberos tgt passing if the server supports it. */
1863 if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
1864 options.kerberos_tgt_passing) {
1865 if (options.cipher == SSH_CIPHER_NONE)
1866 log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
1867 (void) send_kerberos_tgt();
1868 }
1869 /* Try AFS token passing if the server supports it. */
1870 if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
1871 options.afs_token_passing && k_hasafs()) {
1872 if (options.cipher == SSH_CIPHER_NONE)
1873 log("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
1874 send_afs_tokens();
1875 }
1876#endif /* AFS */
1877
1878#ifdef KRB4
1879 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
1880 options.kerberos_authentication) {
1881 debug("Trying Kerberos authentication.");
1882 if (try_kerberos_authentication()) {
1883 /* The server should respond with success or failure. */
1884 type = packet_read(&payload_len);
1885 if (type == SSH_SMSG_SUCCESS)
1886 return;
1887 if (type != SSH_SMSG_FAILURE)
1888 packet_disconnect("Protocol error: got %d in response to Kerberos auth", type);
1889 }
1890 }
1891#endif /* KRB4 */
1892
1893 /*
1894 * Use rhosts authentication if running in privileged socket and we
1895 * do not wish to remain anonymous.
1896 */
1897 if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) &&
1898 options.rhosts_authentication) {
1899 debug("Trying rhosts authentication.");
1900 packet_start(SSH_CMSG_AUTH_RHOSTS);
1901 packet_put_string(local_user, strlen(local_user));
1902 packet_send();
1903 packet_write_wait();
1904
1905 /* The server should respond with success or failure. */
1906 type = packet_read(&payload_len);
1907 if (type == SSH_SMSG_SUCCESS)
1908 return;
1909 if (type != SSH_SMSG_FAILURE)
1910 packet_disconnect("Protocol error: got %d in response to rhosts auth",
1911 type);
1912 }
1913 /*
1914 * Try .rhosts or /etc/hosts.equiv authentication with RSA host
1915 * authentication.
1916 */
1917 if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
1918 options.rhosts_rsa_authentication && host_key_valid) {
1919 if (try_rhosts_rsa_authentication(local_user, own_host_key))
1920 return;
1921 }
1922 /* Try RSA authentication if the server supports it. */
1923 if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
1924 options.rsa_authentication) {
1925 /*
1926 * Try RSA authentication using the authentication agent. The
1927 * agent is tried first because no passphrase is needed for
1928 * it, whereas identity files may require passphrases.
1929 */
1930 if (try_agent_authentication())
1931 return;
1932
1933 /* Try RSA authentication for each identity. */
1934 for (i = 0; i < options.num_identity_files; i++)
1935 if (try_rsa_authentication(options.identity_files[i]))
1936 return;
1937 }
1938 /* Try skey authentication if the server supports it. */
1939 if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
1940 options.skey_authentication && !options.batch_mode) {
1941 if (try_skey_authentication())
1942 return;
1943 }
1944 /* Try password authentication if the server supports it. */
1945 if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
1946 options.password_authentication && !options.batch_mode) {
1947 char prompt[80];
1948
1949 snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
1950 server_user, host);
1951 if (try_password_authentication(prompt))
1952 return;
1953 }
1954 /* All authentication methods have failed. Exit with an error message. */
1955 fatal("Permission denied.");
1956 /* NOTREACHED */
1957}
1958/*
1959 * Starts a dialog with the server, and authenticates the current user on the
1960 * server. This does not need any extra privileges. The basic connection
1961 * to the server must already have been established before this is called.
1962 * If login fails, this function prints an error and never returns.
1963 * This function does not require super-user privileges.
1964 */
1965void
1966ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
1967 struct sockaddr *hostaddr, uid_t original_real_uid)
1968{
1969 char *host, *cp;
1970
1971 /* Convert the user-supplied hostname into all lowercase. */ 680 /* Convert the user-supplied hostname into all lowercase. */
1972 host = xstrdup(orighost); 681 host = xstrdup(orighost);
1973 for (cp = host; *cp; cp++) 682 for (cp = host; *cp; cp++)
@@ -1984,12 +693,9 @@ ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
1984 /* authenticate user */ 693 /* authenticate user */
1985 if (compat20) { 694 if (compat20) {
1986 ssh_kex2(host, hostaddr); 695 ssh_kex2(host, hostaddr);
1987 ssh_userauth2(host_key_valid, own_host_key, original_real_uid, host); 696 ssh_userauth2(server_user, host);
1988 } else { 697 } else {
1989 supported_authentications = 0;
1990 ssh_kex(host, hostaddr); 698 ssh_kex(host, hostaddr);
1991 if (supported_authentications == 0) 699 ssh_userauth(local_user, server_user, host, host_key_valid, own_host_key);
1992 fatal("supported_authentications == 0.");
1993 ssh_userauth(host_key_valid, own_host_key, original_real_uid, host);
1994 } 700 }
1995} 701}
diff --git a/sshconnect.h b/sshconnect.h
new file mode 100644
index 000000000..13d395fd6
--- /dev/null
+++ b/sshconnect.h
@@ -0,0 +1,16 @@
1#ifndef SSHCONNECT_H
2#define SSHCONNECT_H
3
4void
5check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
6 const char *user_hostfile, const char *system_hostfile);
7
8void ssh_kex(char *host, struct sockaddr *hostaddr);
9void
10ssh_userauth(const char* local_user, const char* server_user, char *host,
11 int host_key_valid, RSA *own_host_key);
12
13void ssh_kex2(char *host, struct sockaddr *hostaddr);
14void ssh_userauth2(const char *server_user, char *host);
15
16#endif
diff --git a/sshconnect1.c b/sshconnect1.c
new file mode 100644
index 000000000..c5a76654b
--- /dev/null
+++ b/sshconnect1.c
@@ -0,0 +1,1020 @@
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
5 * Created: Sat Mar 18 22:15:47 1995 ylo
6 * Code to connect to a remote host, and to perform the client side of the
7 * login (authentication) dialog.
8 *
9 */
10
11#include "includes.h"
12RCSID("$OpenBSD: sshconnect1.c,v 1.1 2000/04/26 21:28:33 markus Exp $");
13
14#include <openssl/bn.h>
15#include <openssl/dsa.h>
16#include <openssl/rsa.h>
17#include <openssl/evp.h>
18
19#include "xmalloc.h"
20#include "rsa.h"
21#include "ssh.h"
22#include "buffer.h"
23#include "packet.h"
24#include "authfd.h"
25#include "cipher.h"
26#include "mpaux.h"
27#include "uidswap.h"
28#include "readconf.h"
29#include "key.h"
30#include "sshconnect.h"
31#include "authfile.h"
32
33/* Session id for the current session. */
34unsigned char session_id[16];
35unsigned int supported_authentications = 0;
36
37extern Options options;
38extern char *__progname;
39
40/*
41 * Checks if the user has an authentication agent, and if so, tries to
42 * authenticate using the agent.
43 */
44int
45try_agent_authentication()
46{
47 int status, type;
48 char *comment;
49 AuthenticationConnection *auth;
50 unsigned char response[16];
51 unsigned int i;
52 BIGNUM *e, *n, *challenge;
53
54 /* Get connection to the agent. */
55 auth = ssh_get_authentication_connection();
56 if (!auth)
57 return 0;
58
59 e = BN_new();
60 n = BN_new();
61 challenge = BN_new();
62
63 /* Loop through identities served by the agent. */
64 for (status = ssh_get_first_identity(auth, e, n, &comment);
65 status;
66 status = ssh_get_next_identity(auth, e, n, &comment)) {
67 int plen, clen;
68
69 /* Try this identity. */
70 debug("Trying RSA authentication via agent with '%.100s'", comment);
71 xfree(comment);
72
73 /* Tell the server that we are willing to authenticate using this key. */
74 packet_start(SSH_CMSG_AUTH_RSA);
75 packet_put_bignum(n);
76 packet_send();
77 packet_write_wait();
78
79 /* Wait for server's response. */
80 type = packet_read(&plen);
81
82 /* The server sends failure if it doesn\'t like our key or
83 does not support RSA authentication. */
84 if (type == SSH_SMSG_FAILURE) {
85 debug("Server refused our key.");
86 continue;
87 }
88 /* Otherwise it should have sent a challenge. */
89 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
90 packet_disconnect("Protocol error during RSA authentication: %d",
91 type);
92
93 packet_get_bignum(challenge, &clen);
94
95 packet_integrity_check(plen, clen, type);
96
97 debug("Received RSA challenge from server.");
98
99 /* Ask the agent to decrypt the challenge. */
100 if (!ssh_decrypt_challenge(auth, e, n, challenge,
101 session_id, 1, response)) {
102 /* The agent failed to authenticate this identifier although it
103 advertised it supports this. Just return a wrong value. */
104 log("Authentication agent failed to decrypt challenge.");
105 memset(response, 0, sizeof(response));
106 }
107 debug("Sending response to RSA challenge.");
108
109 /* Send the decrypted challenge back to the server. */
110 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
111 for (i = 0; i < 16; i++)
112 packet_put_char(response[i]);
113 packet_send();
114 packet_write_wait();
115
116 /* Wait for response from the server. */
117 type = packet_read(&plen);
118
119 /* The server returns success if it accepted the authentication. */
120 if (type == SSH_SMSG_SUCCESS) {
121 debug("RSA authentication accepted by server.");
122 BN_clear_free(e);
123 BN_clear_free(n);
124 BN_clear_free(challenge);
125 return 1;
126 }
127 /* Otherwise it should return failure. */
128 if (type != SSH_SMSG_FAILURE)
129 packet_disconnect("Protocol error waiting RSA auth response: %d",
130 type);
131 }
132
133 BN_clear_free(e);
134 BN_clear_free(n);
135 BN_clear_free(challenge);
136
137 debug("RSA authentication using agent refused.");
138 return 0;
139}
140
141/*
142 * Computes the proper response to a RSA challenge, and sends the response to
143 * the server.
144 */
145void
146respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
147{
148 unsigned char buf[32], response[16];
149 MD5_CTX md;
150 int i, len;
151
152 /* Decrypt the challenge using the private key. */
153 rsa_private_decrypt(challenge, challenge, prv);
154
155 /* Compute the response. */
156 /* The response is MD5 of decrypted challenge plus session id. */
157 len = BN_num_bytes(challenge);
158 if (len <= 0 || len > sizeof(buf))
159 packet_disconnect("respond_to_rsa_challenge: bad challenge length %d",
160 len);
161
162 memset(buf, 0, sizeof(buf));
163 BN_bn2bin(challenge, buf + sizeof(buf) - len);
164 MD5_Init(&md);
165 MD5_Update(&md, buf, 32);
166 MD5_Update(&md, session_id, 16);
167 MD5_Final(response, &md);
168
169 debug("Sending response to host key RSA challenge.");
170
171 /* Send the response back to the server. */
172 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
173 for (i = 0; i < 16; i++)
174 packet_put_char(response[i]);
175 packet_send();
176 packet_write_wait();
177
178 memset(buf, 0, sizeof(buf));
179 memset(response, 0, sizeof(response));
180 memset(&md, 0, sizeof(md));
181}
182
183/*
184 * Checks if the user has authentication file, and if so, tries to authenticate
185 * the user using it.
186 */
187int
188try_rsa_authentication(const char *authfile)
189{
190 BIGNUM *challenge;
191 Key *public;
192 Key *private;
193 char *passphrase, *comment;
194 int type, i;
195 int plen, clen;
196
197 /* Try to load identification for the authentication key. */
198 public = key_new(KEY_RSA);
199 if (!load_public_key(authfile, public, &comment)) {
200 key_free(public);
201 /* Could not load it. Fail. */
202 return 0;
203 }
204 debug("Trying RSA authentication with key '%.100s'", comment);
205
206 /* Tell the server that we are willing to authenticate using this key. */
207 packet_start(SSH_CMSG_AUTH_RSA);
208 packet_put_bignum(public->rsa->n);
209 packet_send();
210 packet_write_wait();
211
212 /* We no longer need the public key. */
213 key_free(public);
214
215 /* Wait for server's response. */
216 type = packet_read(&plen);
217
218 /*
219 * The server responds with failure if it doesn\'t like our key or
220 * doesn\'t support RSA authentication.
221 */
222 if (type == SSH_SMSG_FAILURE) {
223 debug("Server refused our key.");
224 xfree(comment);
225 return 0;
226 }
227 /* Otherwise, the server should respond with a challenge. */
228 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
229 packet_disconnect("Protocol error during RSA authentication: %d", type);
230
231 /* Get the challenge from the packet. */
232 challenge = BN_new();
233 packet_get_bignum(challenge, &clen);
234
235 packet_integrity_check(plen, clen, type);
236
237 debug("Received RSA challenge from server.");
238
239 private = key_new(KEY_RSA);
240 /*
241 * Load the private key. Try first with empty passphrase; if it
242 * fails, ask for a passphrase.
243 */
244 if (!load_private_key(authfile, "", private, NULL)) {
245 char buf[300];
246 snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
247 comment);
248 if (!options.batch_mode)
249 passphrase = read_passphrase(buf, 0);
250 else {
251 debug("Will not query passphrase for %.100s in batch mode.",
252 comment);
253 passphrase = xstrdup("");
254 }
255
256 /* Load the authentication file using the pasphrase. */
257 if (!load_private_key(authfile, passphrase, private, NULL)) {
258 memset(passphrase, 0, strlen(passphrase));
259 xfree(passphrase);
260 error("Bad passphrase.");
261
262 /* Send a dummy response packet to avoid protocol error. */
263 packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
264 for (i = 0; i < 16; i++)
265 packet_put_char(0);
266 packet_send();
267 packet_write_wait();
268
269 /* Expect the server to reject it... */
270 packet_read_expect(&plen, SSH_SMSG_FAILURE);
271 xfree(comment);
272 return 0;
273 }
274 /* Destroy the passphrase. */
275 memset(passphrase, 0, strlen(passphrase));
276 xfree(passphrase);
277 }
278 /* We no longer need the comment. */
279 xfree(comment);
280
281 /* Compute and send a response to the challenge. */
282 respond_to_rsa_challenge(challenge, private->rsa);
283
284 /* Destroy the private key. */
285 key_free(private);
286
287 /* We no longer need the challenge. */
288 BN_clear_free(challenge);
289
290 /* Wait for response from the server. */
291 type = packet_read(&plen);
292 if (type == SSH_SMSG_SUCCESS) {
293 debug("RSA authentication accepted by server.");
294 return 1;
295 }
296 if (type != SSH_SMSG_FAILURE)
297 packet_disconnect("Protocol error waiting RSA auth response: %d", type);
298 debug("RSA authentication refused.");
299 return 0;
300}
301
302/*
303 * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv
304 * authentication and RSA host authentication.
305 */
306int
307try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
308{
309 int type;
310 BIGNUM *challenge;
311 int plen, clen;
312
313 debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
314
315 /* Tell the server that we are willing to authenticate using this key. */
316 packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
317 packet_put_string(local_user, strlen(local_user));
318 packet_put_int(BN_num_bits(host_key->n));
319 packet_put_bignum(host_key->e);
320 packet_put_bignum(host_key->n);
321 packet_send();
322 packet_write_wait();
323
324 /* Wait for server's response. */
325 type = packet_read(&plen);
326
327 /* The server responds with failure if it doesn't admit our
328 .rhosts authentication or doesn't know our host key. */
329 if (type == SSH_SMSG_FAILURE) {
330 debug("Server refused our rhosts authentication or host key.");
331 return 0;
332 }
333 /* Otherwise, the server should respond with a challenge. */
334 if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
335 packet_disconnect("Protocol error during RSA authentication: %d", type);
336
337 /* Get the challenge from the packet. */
338 challenge = BN_new();
339 packet_get_bignum(challenge, &clen);
340
341 packet_integrity_check(plen, clen, type);
342
343 debug("Received RSA challenge for host key from server.");
344
345 /* Compute a response to the challenge. */
346 respond_to_rsa_challenge(challenge, host_key);
347
348 /* We no longer need the challenge. */
349 BN_clear_free(challenge);
350
351 /* Wait for response from the server. */
352 type = packet_read(&plen);
353 if (type == SSH_SMSG_SUCCESS) {
354 debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
355 return 1;
356 }
357 if (type != SSH_SMSG_FAILURE)
358 packet_disconnect("Protocol error waiting RSA auth response: %d", type);
359 debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");
360 return 0;
361}
362
363#ifdef KRB4
364int
365try_kerberos_authentication()
366{
367 KTEXT_ST auth; /* Kerberos data */
368 char *reply;
369 char inst[INST_SZ];
370 char *realm;
371 CREDENTIALS cred;
372 int r, type, plen;
373 socklen_t slen;
374 Key_schedule schedule;
375 u_long checksum, cksum;
376 MSG_DAT msg_data;
377 struct sockaddr_in local, foreign;
378 struct stat st;
379
380 /* Don't do anything if we don't have any tickets. */
381 if (stat(tkt_string(), &st) < 0)
382 return 0;
383
384 strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
385
386 realm = (char *) krb_realmofhost(get_canonical_hostname());
387 if (!realm) {
388 debug("Kerberos V4: no realm for %s", get_canonical_hostname());
389 return 0;
390 }
391 /* This can really be anything. */
392 checksum = (u_long) getpid();
393
394 r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
395 if (r != KSUCCESS) {
396 debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]);
397 return 0;
398 }
399 /* Get session key to decrypt the server's reply with. */
400 r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred);
401 if (r != KSUCCESS) {
402 debug("get_cred failed: %s", krb_err_txt[r]);
403 return 0;
404 }
405 des_key_sched((des_cblock *) cred.session, schedule);
406
407 /* Send authentication info to server. */
408 packet_start(SSH_CMSG_AUTH_KERBEROS);
409 packet_put_string((char *) auth.dat, auth.length);
410 packet_send();
411 packet_write_wait();
412
413 /* Zero the buffer. */
414 (void) memset(auth.dat, 0, MAX_KTXT_LEN);
415
416 slen = sizeof(local);
417 memset(&local, 0, sizeof(local));
418 if (getsockname(packet_get_connection_in(),
419 (struct sockaddr *) & local, &slen) < 0)
420 debug("getsockname failed: %s", strerror(errno));
421
422 slen = sizeof(foreign);
423 memset(&foreign, 0, sizeof(foreign));
424 if (getpeername(packet_get_connection_in(),
425 (struct sockaddr *) & foreign, &slen) < 0) {
426 debug("getpeername failed: %s", strerror(errno));
427 fatal_cleanup();
428 }
429 /* Get server reply. */
430 type = packet_read(&plen);
431 switch (type) {
432 case SSH_SMSG_FAILURE:
433 /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
434 debug("Kerberos V4 authentication failed.");
435 return 0;
436 break;
437
438 case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
439 /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
440 debug("Kerberos V4 authentication accepted.");
441
442 /* Get server's response. */
443 reply = packet_get_string((unsigned int *) &auth.length);
444 memcpy(auth.dat, reply, auth.length);
445 xfree(reply);
446
447 packet_integrity_check(plen, 4 + auth.length, type);
448
449 /*
450 * If his response isn't properly encrypted with the session
451 * key, and the decrypted checksum fails to match, he's
452 * bogus. Bail out.
453 */
454 r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
455 &foreign, &local, &msg_data);
456 if (r != KSUCCESS) {
457 debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]);
458 packet_disconnect("Kerberos V4 challenge failed!");
459 }
460 /* Fetch the (incremented) checksum that we supplied in the request. */
461 (void) memcpy((char *) &cksum, (char *) msg_data.app_data, sizeof(cksum));
462 cksum = ntohl(cksum);
463
464 /* If it matches, we're golden. */
465 if (cksum == checksum + 1) {
466 debug("Kerberos V4 challenge successful.");
467 return 1;
468 } else
469 packet_disconnect("Kerberos V4 challenge failed!");
470 break;
471
472 default:
473 packet_disconnect("Protocol error on Kerberos V4 response: %d", type);
474 }
475 return 0;
476}
477
478#endif /* KRB4 */
479
480#ifdef AFS
481int
482send_kerberos_tgt()
483{
484 CREDENTIALS *creds;
485 char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
486 int r, type, plen;
487 char buffer[8192];
488 struct stat st;
489
490 /* Don't do anything if we don't have any tickets. */
491 if (stat(tkt_string(), &st) < 0)
492 return 0;
493
494 creds = xmalloc(sizeof(*creds));
495
496 if ((r = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm)) != KSUCCESS) {
497 debug("Kerberos V4 tf_fullname failed: %s", krb_err_txt[r]);
498 return 0;
499 }
500 if ((r = krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) {
501 debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]);
502 return 0;
503 }
504 if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {
505 debug("Kerberos V4 ticket expired: %s", TKT_FILE);
506 return 0;
507 }
508 creds_to_radix(creds, (unsigned char *)buffer);
509 xfree(creds);
510
511 packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
512 packet_put_string(buffer, strlen(buffer));
513 packet_send();
514 packet_write_wait();
515
516 type = packet_read(&plen);
517
518 if (type == SSH_SMSG_FAILURE)
519 debug("Kerberos TGT for realm %s rejected.", prealm);
520 else if (type != SSH_SMSG_SUCCESS)
521 packet_disconnect("Protocol error on Kerberos TGT response: %d", type);
522
523 return 1;
524}
525
526void
527send_afs_tokens(void)
528{
529 CREDENTIALS creds;
530 struct ViceIoctl parms;
531 struct ClearToken ct;
532 int i, type, len, plen;
533 char buf[2048], *p, *server_cell;
534 char buffer[8192];
535
536 /* Move over ktc_GetToken, here's something leaner. */
537 for (i = 0; i < 100; i++) { /* just in case */
538 parms.in = (char *) &i;
539 parms.in_size = sizeof(i);
540 parms.out = buf;
541 parms.out_size = sizeof(buf);
542 if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0)
543 break;
544 p = buf;
545
546 /* Get secret token. */
547 memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
548 if (creds.ticket_st.length > MAX_KTXT_LEN)
549 break;
550 p += sizeof(unsigned int);
551 memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
552 p += creds.ticket_st.length;
553
554 /* Get clear token. */
555 memcpy(&len, p, sizeof(len));
556 if (len != sizeof(struct ClearToken))
557 break;
558 p += sizeof(len);
559 memcpy(&ct, p, len);
560 p += len;
561 p += sizeof(len); /* primary flag */
562 server_cell = p;
563
564 /* Flesh out our credentials. */
565 strlcpy(creds.service, "afs", sizeof creds.service);
566 creds.instance[0] = '\0';
567 strlcpy(creds.realm, server_cell, REALM_SZ);
568 memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
569 creds.issue_date = ct.BeginTimestamp;
570 creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp);
571 creds.kvno = ct.AuthHandle;
572 snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
573 creds.pinst[0] = '\0';
574
575 /* Encode token, ship it off. */
576 if (!creds_to_radix(&creds, (unsigned char*) buffer))
577 break;
578 packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
579 packet_put_string(buffer, strlen(buffer));
580 packet_send();
581 packet_write_wait();
582
583 /* Roger, Roger. Clearance, Clarence. What's your vector,
584 Victor? */
585 type = packet_read(&plen);
586
587 if (type == SSH_SMSG_FAILURE)
588 debug("AFS token for cell %s rejected.", server_cell);
589 else if (type != SSH_SMSG_SUCCESS)
590 packet_disconnect("Protocol error on AFS token response: %d", type);
591 }
592}
593
594#endif /* AFS */
595
596/*
597 * Tries to authenticate with any string-based challenge/response system.
598 * Note that the client code is not tied to s/key or TIS.
599 */
600int
601try_skey_authentication()
602{
603 int type, i;
604 int payload_len;
605 unsigned int clen;
606 char *challenge, *response;
607
608 debug("Doing skey authentication.");
609
610 /* request a challenge */
611 packet_start(SSH_CMSG_AUTH_TIS);
612 packet_send();
613 packet_write_wait();
614
615 type = packet_read(&payload_len);
616 if (type != SSH_SMSG_FAILURE &&
617 type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
618 packet_disconnect("Protocol error: got %d in response "
619 "to skey-auth", type);
620 }
621 if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
622 debug("No challenge for skey authentication.");
623 return 0;
624 }
625 challenge = packet_get_string(&clen);
626 packet_integrity_check(payload_len, (4 + clen), type);
627 if (options.cipher == SSH_CIPHER_NONE)
628 log("WARNING: Encryption is disabled! "
629 "Reponse will be transmitted in clear text.");
630 fprintf(stderr, "%s\n", challenge);
631 xfree(challenge);
632 fflush(stderr);
633 for (i = 0; i < options.number_of_password_prompts; i++) {
634 if (i != 0)
635 error("Permission denied, please try again.");
636 response = read_passphrase("Response: ", 0);
637 packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
638 packet_put_string(response, strlen(response));
639 memset(response, 0, strlen(response));
640 xfree(response);
641 packet_send();
642 packet_write_wait();
643 type = packet_read(&payload_len);
644 if (type == SSH_SMSG_SUCCESS)
645 return 1;
646 if (type != SSH_SMSG_FAILURE)
647 packet_disconnect("Protocol error: got %d in response "
648 "to skey-auth-reponse", type);
649 }
650 /* failure */
651 return 0;
652}
653
654/*
655 * Tries to authenticate with plain passwd authentication.
656 */
657int
658try_password_authentication(char *prompt)
659{
660 int type, i, payload_len;
661 char *password;
662
663 debug("Doing password authentication.");
664 if (options.cipher == SSH_CIPHER_NONE)
665 log("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
666 for (i = 0; i < options.number_of_password_prompts; i++) {
667 if (i != 0)
668 error("Permission denied, please try again.");
669 password = read_passphrase(prompt, 0);
670 packet_start(SSH_CMSG_AUTH_PASSWORD);
671 packet_put_string(password, strlen(password));
672 memset(password, 0, strlen(password));
673 xfree(password);
674 packet_send();
675 packet_write_wait();
676
677 type = packet_read(&payload_len);
678 if (type == SSH_SMSG_SUCCESS)
679 return 1;
680 if (type != SSH_SMSG_FAILURE)
681 packet_disconnect("Protocol error: got %d in response to passwd auth", type);
682 }
683 /* failure */
684 return 0;
685}
686
687/*
688 * SSH1 key exchange
689 */
690void
691ssh_kex(char *host, struct sockaddr *hostaddr)
692{
693 int i;
694 BIGNUM *key;
695 RSA *host_key;
696 RSA *public_key;
697 Key k;
698 int bits, rbits;
699 int ssh_cipher_default = SSH_CIPHER_3DES;
700 unsigned char session_key[SSH_SESSION_KEY_LENGTH];
701 unsigned char cookie[8];
702 unsigned int supported_ciphers;
703 unsigned int server_flags, client_flags;
704 int payload_len, clen, sum_len = 0;
705 u_int32_t rand = 0;
706
707 debug("Waiting for server public key.");
708
709 /* Wait for a public key packet from the server. */
710 packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY);
711
712 /* Get cookie from the packet. */
713 for (i = 0; i < 8; i++)
714 cookie[i] = packet_get_char();
715
716 /* Get the public key. */
717 public_key = RSA_new();
718 bits = packet_get_int();/* bits */
719 public_key->e = BN_new();
720 packet_get_bignum(public_key->e, &clen);
721 sum_len += clen;
722 public_key->n = BN_new();
723 packet_get_bignum(public_key->n, &clen);
724 sum_len += clen;
725
726 rbits = BN_num_bits(public_key->n);
727 if (bits != rbits) {
728 log("Warning: Server lies about size of server public key: "
729 "actual size is %d bits vs. announced %d.", rbits, bits);
730 log("Warning: This may be due to an old implementation of ssh.");
731 }
732 /* Get the host key. */
733 host_key = RSA_new();
734 bits = packet_get_int();/* bits */
735 host_key->e = BN_new();
736 packet_get_bignum(host_key->e, &clen);
737 sum_len += clen;
738 host_key->n = BN_new();
739 packet_get_bignum(host_key->n, &clen);
740 sum_len += clen;
741
742 rbits = BN_num_bits(host_key->n);
743 if (bits != rbits) {
744 log("Warning: Server lies about size of server host key: "
745 "actual size is %d bits vs. announced %d.", rbits, bits);
746 log("Warning: This may be due to an old implementation of ssh.");
747 }
748
749 /* Get protocol flags. */
750 server_flags = packet_get_int();
751 packet_set_protocol_flags(server_flags);
752
753 supported_ciphers = packet_get_int();
754 supported_authentications = packet_get_int();
755
756 debug("Received server public key (%d bits) and host key (%d bits).",
757 BN_num_bits(public_key->n), BN_num_bits(host_key->n));
758
759 packet_integrity_check(payload_len,
760 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
761 SSH_SMSG_PUBLIC_KEY);
762 k.type = KEY_RSA;
763 k.rsa = host_key;
764 check_host_key(host, hostaddr, &k,
765 options.user_hostfile, options.system_hostfile);
766
767 client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
768
769 compute_session_id(session_id, cookie, host_key->n, public_key->n);
770
771 /* Generate a session key. */
772 arc4random_stir();
773
774 /*
775 * Generate an encryption key for the session. The key is a 256 bit
776 * random number, interpreted as a 32-byte key, with the least
777 * significant 8 bits being the first byte of the key.
778 */
779 for (i = 0; i < 32; i++) {
780 if (i % 4 == 0)
781 rand = arc4random();
782 session_key[i] = rand & 0xff;
783 rand >>= 8;
784 }
785
786 /*
787 * According to the protocol spec, the first byte of the session key
788 * is the highest byte of the integer. The session key is xored with
789 * the first 16 bytes of the session id.
790 */
791 key = BN_new();
792 BN_set_word(key, 0);
793 for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
794 BN_lshift(key, key, 8);
795 if (i < 16)
796 BN_add_word(key, session_key[i] ^ session_id[i]);
797 else
798 BN_add_word(key, session_key[i]);
799 }
800
801 /*
802 * Encrypt the integer using the public key and host key of the
803 * server (key with smaller modulus first).
804 */
805 if (BN_cmp(public_key->n, host_key->n) < 0) {
806 /* Public key has smaller modulus. */
807 if (BN_num_bits(host_key->n) <
808 BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED) {
809 fatal("respond_to_rsa_challenge: host_key %d < public_key %d + "
810 "SSH_KEY_BITS_RESERVED %d",
811 BN_num_bits(host_key->n),
812 BN_num_bits(public_key->n),
813 SSH_KEY_BITS_RESERVED);
814 }
815 rsa_public_encrypt(key, key, public_key);
816 rsa_public_encrypt(key, key, host_key);
817 } else {
818 /* Host key has smaller modulus (or they are equal). */
819 if (BN_num_bits(public_key->n) <
820 BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED) {
821 fatal("respond_to_rsa_challenge: public_key %d < host_key %d + "
822 "SSH_KEY_BITS_RESERVED %d",
823 BN_num_bits(public_key->n),
824 BN_num_bits(host_key->n),
825 SSH_KEY_BITS_RESERVED);
826 }
827 rsa_public_encrypt(key, key, host_key);
828 rsa_public_encrypt(key, key, public_key);
829 }
830
831 /* Destroy the public keys since we no longer need them. */
832 RSA_free(public_key);
833 RSA_free(host_key);
834
835 if (options.cipher == SSH_CIPHER_NOT_SET) {
836 if (cipher_mask1() & supported_ciphers & (1 << ssh_cipher_default))
837 options.cipher = ssh_cipher_default;
838 else {
839 debug("Cipher %s not supported, using %.100s instead.",
840 cipher_name(ssh_cipher_default),
841 cipher_name(SSH_FALLBACK_CIPHER));
842 options.cipher = SSH_FALLBACK_CIPHER;
843 }
844 }
845 /* Check that the selected cipher is supported. */
846 if (!(supported_ciphers & (1 << options.cipher)))
847 fatal("Selected cipher type %.100s not supported by server.",
848 cipher_name(options.cipher));
849
850 debug("Encryption type: %.100s", cipher_name(options.cipher));
851
852 /* Send the encrypted session key to the server. */
853 packet_start(SSH_CMSG_SESSION_KEY);
854 packet_put_char(options.cipher);
855
856 /* Send the cookie back to the server. */
857 for (i = 0; i < 8; i++)
858 packet_put_char(cookie[i]);
859
860 /* Send and destroy the encrypted encryption key integer. */
861 packet_put_bignum(key);
862 BN_clear_free(key);
863
864 /* Send protocol flags. */
865 packet_put_int(client_flags);
866
867 /* Send the packet now. */
868 packet_send();
869 packet_write_wait();
870
871 debug("Sent encrypted session key.");
872
873 /* Set the encryption key. */
874 packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher);
875
876 /* We will no longer need the session key here. Destroy any extra copies. */
877 memset(session_key, 0, sizeof(session_key));
878
879 /*
880 * Expect a success message from the server. Note that this message
881 * will be received in encrypted form.
882 */
883 packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
884
885 debug("Received encrypted confirmation.");
886}
887
888/*
889 * Authenticate user
890 */
891void
892ssh_userauth(
893 const char* local_user,
894 const char* server_user,
895 char *host,
896 int host_key_valid, RSA *own_host_key)
897{
898 int i, type;
899 int payload_len;
900
901 if (supported_authentications == 0)
902 fatal("ssh_userauth: server supports no auth methods");
903
904 /* Send the name of the user to log in as on the server. */
905 packet_start(SSH_CMSG_USER);
906 packet_put_string(server_user, strlen(server_user));
907 packet_send();
908 packet_write_wait();
909
910 /*
911 * The server should respond with success if no authentication is
912 * needed (the user has no password). Otherwise the server responds
913 * with failure.
914 */
915 type = packet_read(&payload_len);
916
917 /* check whether the connection was accepted without authentication. */
918 if (type == SSH_SMSG_SUCCESS)
919 return;
920 if (type != SSH_SMSG_FAILURE)
921 packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER",
922 type);
923
924#ifdef AFS
925 /* Try Kerberos tgt passing if the server supports it. */
926 if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
927 options.kerberos_tgt_passing) {
928 if (options.cipher == SSH_CIPHER_NONE)
929 log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
930 (void) send_kerberos_tgt();
931 }
932 /* Try AFS token passing if the server supports it. */
933 if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
934 options.afs_token_passing && k_hasafs()) {
935 if (options.cipher == SSH_CIPHER_NONE)
936 log("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
937 send_afs_tokens();
938 }
939#endif /* AFS */
940
941#ifdef KRB4
942 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
943 options.kerberos_authentication) {
944 debug("Trying Kerberos authentication.");
945 if (try_kerberos_authentication()) {
946 /* The server should respond with success or failure. */
947 type = packet_read(&payload_len);
948 if (type == SSH_SMSG_SUCCESS)
949 return;
950 if (type != SSH_SMSG_FAILURE)
951 packet_disconnect("Protocol error: got %d in response to Kerberos auth", type);
952 }
953 }
954#endif /* KRB4 */
955
956 /*
957 * Use rhosts authentication if running in privileged socket and we
958 * do not wish to remain anonymous.
959 */
960 if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) &&
961 options.rhosts_authentication) {
962 debug("Trying rhosts authentication.");
963 packet_start(SSH_CMSG_AUTH_RHOSTS);
964 packet_put_string(local_user, strlen(local_user));
965 packet_send();
966 packet_write_wait();
967
968 /* The server should respond with success or failure. */
969 type = packet_read(&payload_len);
970 if (type == SSH_SMSG_SUCCESS)
971 return;
972 if (type != SSH_SMSG_FAILURE)
973 packet_disconnect("Protocol error: got %d in response to rhosts auth",
974 type);
975 }
976 /*
977 * Try .rhosts or /etc/hosts.equiv authentication with RSA host
978 * authentication.
979 */
980 if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
981 options.rhosts_rsa_authentication && host_key_valid) {
982 if (try_rhosts_rsa_authentication(local_user, own_host_key))
983 return;
984 }
985 /* Try RSA authentication if the server supports it. */
986 if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
987 options.rsa_authentication) {
988 /*
989 * Try RSA authentication using the authentication agent. The
990 * agent is tried first because no passphrase is needed for
991 * it, whereas identity files may require passphrases.
992 */
993 if (try_agent_authentication())
994 return;
995
996 /* Try RSA authentication for each identity. */
997 for (i = 0; i < options.num_identity_files; i++)
998 if (try_rsa_authentication(options.identity_files[i]))
999 return;
1000 }
1001 /* Try skey authentication if the server supports it. */
1002 if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
1003 options.skey_authentication && !options.batch_mode) {
1004 if (try_skey_authentication())
1005 return;
1006 }
1007 /* Try password authentication if the server supports it. */
1008 if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
1009 options.password_authentication && !options.batch_mode) {
1010 char prompt[80];
1011
1012 snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
1013 server_user, host);
1014 if (try_password_authentication(prompt))
1015 return;
1016 }
1017 /* All authentication methods have failed. Exit with an error message. */
1018 fatal("Permission denied.");
1019 /* NOTREACHED */
1020}
diff --git a/sshconnect2.c b/sshconnect2.c
new file mode 100644
index 000000000..31ef3084c
--- /dev/null
+++ b/sshconnect2.c
@@ -0,0 +1,449 @@
1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Markus Friedl.
15 * 4. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "includes.h"
31RCSID("$OpenBSD: sshconnect2.c,v 1.4 2000/04/27 17:54:01 markus Exp $");
32
33#include <openssl/bn.h>
34#include <openssl/rsa.h>
35#include <openssl/dsa.h>
36#include <openssl/md5.h>
37#include <openssl/dh.h>
38#include <openssl/hmac.h>
39
40#include "ssh.h"
41#include "xmalloc.h"
42#include "rsa.h"
43#include "buffer.h"
44#include "packet.h"
45#include "cipher.h"
46#include "uidswap.h"
47#include "compat.h"
48#include "readconf.h"
49#include "bufaux.h"
50#include "ssh2.h"
51#include "kex.h"
52#include "myproposal.h"
53#include "key.h"
54#include "dsa.h"
55#include "sshconnect.h"
56#include "authfile.h"
57
58/* import */
59extern char *client_version_string;
60extern char *server_version_string;
61extern Options options;
62
63/*
64 * SSH2 key exchange
65 */
66
67unsigned char *session_id2 = NULL;
68int session_id2_len = 0;
69
70void
71ssh_kex2(char *host, struct sockaddr *hostaddr)
72{
73 Kex *kex;
74 char *cprop[PROPOSAL_MAX];
75 char *sprop[PROPOSAL_MAX];
76 Buffer *client_kexinit;
77 Buffer *server_kexinit;
78 int payload_len, dlen;
79 unsigned int klen, kout;
80 char *ptr;
81 char *signature = NULL;
82 unsigned int slen;
83 char *server_host_key_blob = NULL;
84 Key *server_host_key;
85 unsigned int sbloblen;
86 DH *dh;
87 BIGNUM *dh_server_pub = 0;
88 BIGNUM *shared_secret = 0;
89 int i;
90 unsigned char *kbuf;
91 unsigned char *hash;
92
93/* KEXINIT */
94
95 debug("Sending KEX init.");
96 if (options.ciphers != NULL) {
97 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
98 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
99 } else if (
100 options.cipher == SSH_CIPHER_ARCFOUR ||
101 options.cipher == SSH_CIPHER_3DES_CBC ||
102 options.cipher == SSH_CIPHER_CAST128_CBC ||
103 options.cipher == SSH_CIPHER_BLOWFISH_CBC) {
104 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
105 myproposal[PROPOSAL_ENC_ALGS_STOC] = cipher_name(options.cipher);
106 }
107 if (options.compression) {
108 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
109 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
110 } else {
111 myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
112 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
113 }
114 for (i = 0; i < PROPOSAL_MAX; i++)
115 cprop[i] = xstrdup(myproposal[i]);
116
117 client_kexinit = kex_init(cprop);
118 packet_start(SSH2_MSG_KEXINIT);
119 packet_put_raw(buffer_ptr(client_kexinit), buffer_len(client_kexinit));
120 packet_send();
121 packet_write_wait();
122
123 debug("done");
124
125 packet_read_expect(&payload_len, SSH2_MSG_KEXINIT);
126
127 /* save payload for session_id */
128 server_kexinit = xmalloc(sizeof(*server_kexinit));
129 buffer_init(server_kexinit);
130 ptr = packet_get_raw(&payload_len);
131 buffer_append(server_kexinit, ptr, payload_len);
132
133 /* skip cookie */
134 for (i = 0; i < 16; i++)
135 (void) packet_get_char();
136 /* kex init proposal strings */
137 for (i = 0; i < PROPOSAL_MAX; i++) {
138 sprop[i] = packet_get_string(NULL);
139 debug("got kexinit string: %s", sprop[i]);
140 }
141 i = (int) packet_get_char();
142 debug("first kex follow == %d", i);
143 i = packet_get_int();
144 debug("reserved == %d", i);
145 packet_done();
146
147 debug("done read kexinit");
148 kex = kex_choose_conf(cprop, sprop, 0);
149
150/* KEXDH */
151
152 debug("Sending SSH2_MSG_KEXDH_INIT.");
153
154 /* generate and send 'e', client DH public key */
155 dh = dh_new_group1();
156 packet_start(SSH2_MSG_KEXDH_INIT);
157 packet_put_bignum2(dh->pub_key);
158 packet_send();
159 packet_write_wait();
160
161#ifdef DEBUG_KEXDH
162 fprintf(stderr, "\np= ");
163 bignum_print(dh->p);
164 fprintf(stderr, "\ng= ");
165 bignum_print(dh->g);
166 fprintf(stderr, "\npub= ");
167 bignum_print(dh->pub_key);
168 fprintf(stderr, "\n");
169 DHparams_print_fp(stderr, dh);
170#endif
171
172 debug("Wait SSH2_MSG_KEXDH_REPLY.");
173
174 packet_read_expect(&payload_len, SSH2_MSG_KEXDH_REPLY);
175
176 debug("Got SSH2_MSG_KEXDH_REPLY.");
177
178 /* key, cert */
179 server_host_key_blob = packet_get_string(&sbloblen);
180 server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
181 if (server_host_key == NULL)
182 fatal("cannot decode server_host_key_blob");
183
184 check_host_key(host, hostaddr, server_host_key,
185 options.user_hostfile2, options.system_hostfile2);
186
187 /* DH paramter f, server public DH key */
188 dh_server_pub = BN_new();
189 if (dh_server_pub == NULL)
190 fatal("dh_server_pub == NULL");
191 packet_get_bignum2(dh_server_pub, &dlen);
192
193#ifdef DEBUG_KEXDH
194 fprintf(stderr, "\ndh_server_pub= ");
195 bignum_print(dh_server_pub);
196 fprintf(stderr, "\n");
197 debug("bits %d", BN_num_bits(dh_server_pub));
198#endif
199
200 /* signed H */
201 signature = packet_get_string(&slen);
202 packet_done();
203
204 if (!dh_pub_is_valid(dh, dh_server_pub))
205 packet_disconnect("bad server public DH value");
206
207 klen = DH_size(dh);
208 kbuf = xmalloc(klen);
209 kout = DH_compute_key(kbuf, dh_server_pub, dh);
210#ifdef DEBUG_KEXDH
211 debug("shared secret: len %d/%d", klen, kout);
212 fprintf(stderr, "shared secret == ");
213 for (i = 0; i< kout; i++)
214 fprintf(stderr, "%02x", (kbuf[i])&0xff);
215 fprintf(stderr, "\n");
216#endif
217 shared_secret = BN_new();
218
219 BN_bin2bn(kbuf, kout, shared_secret);
220 memset(kbuf, 0, klen);
221 xfree(kbuf);
222
223 /* calc and verify H */
224 hash = kex_hash(
225 client_version_string,
226 server_version_string,
227 buffer_ptr(client_kexinit), buffer_len(client_kexinit),
228 buffer_ptr(server_kexinit), buffer_len(server_kexinit),
229 server_host_key_blob, sbloblen,
230 dh->pub_key,
231 dh_server_pub,
232 shared_secret
233 );
234 xfree(server_host_key_blob);
235 buffer_free(client_kexinit);
236 buffer_free(server_kexinit);
237 xfree(client_kexinit);
238 xfree(server_kexinit);
239#ifdef DEBUG_KEXDH
240 fprintf(stderr, "hash == ");
241 for (i = 0; i< 20; i++)
242 fprintf(stderr, "%02x", (hash[i])&0xff);
243 fprintf(stderr, "\n");
244#endif
245 if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
246 fatal("dsa_verify failed for server_host_key");
247 key_free(server_host_key);
248
249 kex_derive_keys(kex, hash, shared_secret);
250 packet_set_kex(kex);
251
252 /* have keys, free DH */
253 DH_free(dh);
254
255 /* save session id */
256 session_id2_len = 20;
257 session_id2 = xmalloc(session_id2_len);
258 memcpy(session_id2, hash, session_id2_len);
259
260 debug("Wait SSH2_MSG_NEWKEYS.");
261 packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS);
262 packet_done();
263 debug("GOT SSH2_MSG_NEWKEYS.");
264
265 debug("send SSH2_MSG_NEWKEYS.");
266 packet_start(SSH2_MSG_NEWKEYS);
267 packet_send();
268 packet_write_wait();
269 debug("done: send SSH2_MSG_NEWKEYS.");
270
271#ifdef DEBUG_KEXDH
272 /* send 1st encrypted/maced/compressed message */
273 packet_start(SSH2_MSG_IGNORE);
274 packet_put_cstring("markus");
275 packet_send();
276 packet_write_wait();
277#endif
278 debug("done: KEX2.");
279}
280/*
281 * Authenticate user
282 */
283int
284ssh2_try_passwd(const char *server_user, const char *host, const char *service)
285{
286 char prompt[80];
287 char *password;
288
289 snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
290 server_user, host);
291 password = read_passphrase(prompt, 0);
292 packet_start(SSH2_MSG_USERAUTH_REQUEST);
293 packet_put_cstring(server_user);
294 packet_put_cstring(service);
295 packet_put_cstring("password");
296 packet_put_char(0);
297 packet_put_cstring(password);
298 memset(password, 0, strlen(password));
299 xfree(password);
300 packet_send();
301 packet_write_wait();
302 return 1;
303}
304
305int
306ssh2_try_pubkey(char *filename,
307 const char *server_user, const char *host, const char *service)
308{
309 Buffer b;
310 Key *k;
311 unsigned char *blob, *signature;
312 int bloblen, slen;
313
314 debug("try pubkey: %s", filename);
315
316 k = key_new(KEY_DSA);
317 if (!load_private_key(filename, "", k, NULL)) {
318 int success = 0;
319 char *passphrase;
320 char prompt[300];
321 snprintf(prompt, sizeof prompt,
322 "Enter passphrase for DSA key '%.100s': ",
323 filename);
324 passphrase = read_passphrase(prompt, 0);
325 success = load_private_key(filename, passphrase, k, NULL);
326 memset(passphrase, 0, strlen(passphrase));
327 xfree(passphrase);
328 if (!success)
329 return 0;
330 }
331 dsa_make_key_blob(k, &blob, &bloblen);
332
333 /* data to be signed */
334 buffer_init(&b);
335 buffer_append(&b, session_id2, session_id2_len);
336 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
337 buffer_put_cstring(&b, server_user);
338 buffer_put_cstring(&b, service);
339 buffer_put_cstring(&b, "publickey");
340 buffer_put_char(&b, 1);
341 buffer_put_cstring(&b, KEX_DSS);
342 buffer_put_string(&b, blob, bloblen);
343 xfree(blob);
344
345 /* generate signature */
346 dsa_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
347 key_free(k);
348#ifdef DEBUG_DSS
349 buffer_dump(&b);
350#endif
351 /* append signature */
352 buffer_put_string(&b, signature, slen);
353 xfree(signature);
354
355 /* skip session id and packet type */
356 if (buffer_len(&b) < session_id2_len + 1)
357 fatal("ssh2_try_pubkey: internal error");
358 buffer_consume(&b, session_id2_len + 1);
359
360 /* put remaining data from buffer into packet */
361 packet_start(SSH2_MSG_USERAUTH_REQUEST);
362 packet_put_raw(buffer_ptr(&b), buffer_len(&b));
363 buffer_free(&b);
364
365 /* send */
366 packet_send();
367 packet_write_wait();
368 return 1;
369}
370
371void
372ssh_userauth2(const char *server_user, char *host)
373{
374 int type;
375 int plen;
376 int sent;
377 unsigned int dlen;
378 int partial;
379 int i = 0;
380 char *auths;
381 char *service = "ssh-connection"; /* service name */
382
383 debug("send SSH2_MSG_SERVICE_REQUEST");
384 packet_start(SSH2_MSG_SERVICE_REQUEST);
385 packet_put_cstring("ssh-userauth");
386 packet_send();
387 packet_write_wait();
388
389 type = packet_read(&plen);
390 if (type != SSH2_MSG_SERVICE_ACCEPT) {
391 fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
392 }
393 if (packet_remaining() > 0) {
394 char *reply = packet_get_string(&plen);
395 debug("service_accept: %s", reply);
396 xfree(reply);
397 } else {
398 /* payload empty for ssh-2.0.13 ?? */
399 log("buggy server: service_accept w/o service");
400 }
401 packet_done();
402 debug("got SSH2_MSG_SERVICE_ACCEPT");
403
404 /* INITIAL request for auth */
405 packet_start(SSH2_MSG_USERAUTH_REQUEST);
406 packet_put_cstring(server_user);
407 packet_put_cstring(service);
408 packet_put_cstring("none");
409 packet_send();
410 packet_write_wait();
411
412 for (;;) {
413 sent = 0;
414 type = packet_read(&plen);
415 if (type == SSH2_MSG_USERAUTH_SUCCESS)
416 break;
417 if (type != SSH2_MSG_USERAUTH_FAILURE)
418 fatal("access denied: %d", type);
419 /* SSH2_MSG_USERAUTH_FAILURE means: try again */
420 auths = packet_get_string(&dlen);
421 debug("authentications that can continue: %s", auths);
422 partial = packet_get_char();
423 packet_done();
424 if (partial)
425 debug("partial success");
426 if (options.rsa_authentication &&
427 strstr(auths, "publickey") != NULL) {
428 while (i < options.num_identity_files2) {
429 sent = ssh2_try_pubkey(
430 options.identity_files2[i++],
431 server_user, host, service);
432 if (sent)
433 break;
434 }
435 }
436 if (!sent) {
437 if (options.password_authentication &&
438 !options.batch_mode &&
439 strstr(auths, "password") != NULL) {
440 sent = ssh2_try_passwd(server_user, host, service);
441 }
442 }
443 if (!sent)
444 fatal("Permission denied (%s).", auths);
445 xfree(auths);
446 }
447 packet_done();
448 debug("ssh-userauth2 successfull");
449}
diff --git a/sshd.c b/sshd.c
index c1dcdd8e9..fc2d1d20e 100644
--- a/sshd.c
+++ b/sshd.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: sshd.c,v 1.107 2000/04/19 07:05:50 deraadt Exp $"); 17RCSID("$OpenBSD: sshd.c,v 1.111 2000/04/27 08:01:28 markus Exp $");
18 18
19#include "xmalloc.h" 19#include "xmalloc.h"
20#include "rsa.h" 20#include "rsa.h"
@@ -40,6 +40,7 @@ RCSID("$OpenBSD: sshd.c,v 1.107 2000/04/19 07:05:50 deraadt Exp $");
40 40
41#include "auth.h" 41#include "auth.h"
42#include "myproposal.h" 42#include "myproposal.h"
43#include "authfile.h"
43 44
44#ifdef LIBWRAP 45#ifdef LIBWRAP
45#include <tcpd.h> 46#include <tcpd.h>
@@ -112,8 +113,9 @@ char *server_version_string = NULL;
112 * not very useful. Currently, memory locking is not implemented. 113 * not very useful. Currently, memory locking is not implemented.
113 */ 114 */
114struct { 115struct {
115 RSA *private_key; /* Private part of server key. */ 116 RSA *private_key; /* Private part of empheral server key. */
116 RSA *host_key; /* Private part of host key. */ 117 RSA *host_key; /* Private part of host key. */
118 Key *dsa_host_key; /* Private DSA host key. */
117} sensitive_data; 119} sensitive_data;
118 120
119/* 121/*
@@ -132,6 +134,10 @@ RSA *public_key;
132/* session identifier, used by RSA-auth */ 134/* session identifier, used by RSA-auth */
133unsigned char session_id[16]; 135unsigned char session_id[16];
134 136
137/* same for ssh2 */
138unsigned char *session_id2 = NULL;
139int session_id2_len = 0;
140
135/* Prototypes for various functions defined later in this file. */ 141/* Prototypes for various functions defined later in this file. */
136void do_ssh1_kex(); 142void do_ssh1_kex();
137void do_ssh2_kex(); 143void do_ssh2_kex();
@@ -224,6 +230,7 @@ grace_alarm_handler(int sig)
224 * Thus there should be no concurrency control/asynchronous execution 230 * Thus there should be no concurrency control/asynchronous execution
225 * problems. 231 * problems.
226 */ 232 */
233/* XXX do we really want this work to be done in a signal handler ? -m */
227void 234void
228key_regeneration_alarm(int sig) 235key_regeneration_alarm(int sig)
229{ 236{
@@ -344,6 +351,13 @@ sshd_exchange_identification(int sock_in, int sock_out)
344 mismatch = 0; 351 mismatch = 0;
345 switch(remote_major) { 352 switch(remote_major) {
346 case 1: 353 case 1:
354 if (remote_minor == 99) {
355 if (options.protocol & SSH_PROTO_2)
356 enable_compat20();
357 else
358 mismatch = 1;
359 break;
360 }
347 if (!(options.protocol & SSH_PROTO_1)) { 361 if (!(options.protocol & SSH_PROTO_1)) {
348 mismatch = 1; 362 mismatch = 1;
349 break; 363 break;
@@ -355,12 +369,6 @@ sshd_exchange_identification(int sock_in, int sock_out)
355 /* note that this disables agent-forwarding */ 369 /* note that this disables agent-forwarding */
356 enable_compat13(); 370 enable_compat13();
357 } 371 }
358 if (remote_minor == 99) {
359 if (options.protocol & SSH_PROTO_2)
360 enable_compat20();
361 else
362 mismatch = 1;
363 }
364 break; 372 break;
365 case 2: 373 case 2:
366 if (options.protocol & SSH_PROTO_2) { 374 if (options.protocol & SSH_PROTO_2) {
@@ -386,6 +394,20 @@ sshd_exchange_identification(int sock_in, int sock_out)
386 server_version_string, client_version_string); 394 server_version_string, client_version_string);
387 fatal_cleanup(); 395 fatal_cleanup();
388 } 396 }
397 if (compat20)
398 packet_set_ssh2_format();
399}
400
401
402void
403destroy_sensitive_data(void)
404{
405 /* Destroy the private and public keys. They will no longer be needed. */
406 RSA_free(public_key);
407 RSA_free(sensitive_data.private_key);
408 RSA_free(sensitive_data.host_key);
409 if (sensitive_data.dsa_host_key != NULL)
410 key_free(sensitive_data.dsa_host_key);
389} 411}
390 412
391/* 413/*
@@ -399,12 +421,11 @@ main(int ac, char **av)
399 int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, on = 1; 421 int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, on = 1;
400 pid_t pid; 422 pid_t pid;
401 socklen_t fromlen; 423 socklen_t fromlen;
402 int silentrsa = 0; 424 int silent = 0;
403 fd_set *fdset; 425 fd_set *fdset;
404 struct sockaddr_storage from; 426 struct sockaddr_storage from;
405 const char *remote_ip; 427 const char *remote_ip;
406 int remote_port; 428 int remote_port;
407 char *comment;
408 FILE *f; 429 FILE *f;
409 struct linger linger; 430 struct linger linger;
410 struct addrinfo *ai; 431 struct addrinfo *ai;
@@ -441,7 +462,7 @@ main(int ac, char **av)
441 inetd_flag = 1; 462 inetd_flag = 1;
442 break; 463 break;
443 case 'Q': 464 case 'Q':
444 silentrsa = 1; 465 silent = 1;
445 break; 466 break;
446 case 'q': 467 case 'q':
447 options.log_level = SYSLOG_LEVEL_QUIET; 468 options.log_level = SYSLOG_LEVEL_QUIET;
@@ -497,27 +518,14 @@ main(int ac, char **av)
497 log_init(av0, 518 log_init(av0,
498 options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, 519 options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
499 options.log_facility == -1 ? SYSLOG_FACILITY_AUTH : options.log_facility, 520 options.log_facility == -1 ? SYSLOG_FACILITY_AUTH : options.log_facility,
500 !inetd_flag); 521 !silent && !inetd_flag);
501 522
502 /* check if RSA support exists */
503 if (rsa_alive() == 0) {
504 if (silentrsa == 0)
505 printf("sshd: no RSA support in libssl and libcrypto -- exiting. See ssl(8)\n");
506 log("no RSA support in libssl and libcrypto -- exiting. See ssl(8)");
507 exit(1);
508 }
509 /* Read server configuration options from the configuration file. */ 523 /* Read server configuration options from the configuration file. */
510 read_server_config(&options, config_file_name); 524 read_server_config(&options, config_file_name);
511 525
512 /* Fill in default values for those options not explicitly set. */ 526 /* Fill in default values for those options not explicitly set. */
513 fill_default_server_options(&options); 527 fill_default_server_options(&options);
514 528
515 /* Check certain values for sanity. */
516 if (options.server_key_bits < 512 ||
517 options.server_key_bits > 32768) {
518 fprintf(stderr, "Bad server key size.\n");
519 exit(1);
520 }
521 /* Check that there are no remaining arguments. */ 529 /* Check that there are no remaining arguments. */
522 if (optind < ac) { 530 if (optind < ac) {
523 fprintf(stderr, "Extra argument %s.\n", av[optind]); 531 fprintf(stderr, "Extra argument %s.\n", av[optind]);
@@ -526,26 +534,79 @@ main(int ac, char **av)
526 534
527 debug("sshd version %.100s", SSH_VERSION); 535 debug("sshd version %.100s", SSH_VERSION);
528 536
529 sensitive_data.host_key = RSA_new(); 537 sensitive_data.dsa_host_key = NULL;
530 errno = 0; 538 sensitive_data.host_key = NULL;
531 /* Load the host key. It must have empty passphrase. */ 539
532 if (!load_private_key(options.host_key_file, "", 540 /* check if RSA support exists */
533 sensitive_data.host_key, &comment)) { 541 if ((options.protocol & SSH_PROTO_1) &&
534 error("Could not load host key: %.200s: %.100s", 542 rsa_alive() == 0) {
535 options.host_key_file, strerror(errno)); 543 log("no RSA support in libssl and libcrypto. See ssl(8)");
544 log("Disabling protocol version 1");
545 options.protocol &= ~SSH_PROTO_1;
546 }
547 /* Load the RSA/DSA host key. It must have empty passphrase. */
548 if (options.protocol & SSH_PROTO_1) {
549 Key k;
550 sensitive_data.host_key = RSA_new();
551 k.type = KEY_RSA;
552 k.rsa = sensitive_data.host_key;
553 errno = 0;
554 if (!load_private_key(options.host_key_file, "", &k, NULL)) {
555 error("Could not load host key: %.200s: %.100s",
556 options.host_key_file, strerror(errno));
557 log("Disabling protocol version 1");
558 options.protocol &= ~SSH_PROTO_1;
559 }
560 k.rsa = NULL;
561 }
562 if (options.protocol & SSH_PROTO_2) {
563 sensitive_data.dsa_host_key = key_new(KEY_DSA);
564 if (!load_private_key(options.dsa_key_file, "", sensitive_data.dsa_host_key, NULL)) {
565 error("Could not load DSA host key: %.200s", options.dsa_key_file);
566 log("Disabling protocol version 2");
567 options.protocol &= ~SSH_PROTO_2;
568 }
569 }
570 if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
571 if (silent == 0)
572 fprintf(stderr, "sshd: no hostkeys available -- exiting.\n");
573 log("sshd: no hostkeys available -- exiting.\n");
536 exit(1); 574 exit(1);
537 } 575 }
538 xfree(comment);
539 576
540 /* Initialize the log (it is reinitialized below in case we 577 /* Check certain values for sanity. */
541 forked). */ 578 if (options.protocol & SSH_PROTO_1) {
579 if (options.server_key_bits < 512 ||
580 options.server_key_bits > 32768) {
581 fprintf(stderr, "Bad server key size.\n");
582 exit(1);
583 }
584 /*
585 * Check that server and host key lengths differ sufficiently. This
586 * is necessary to make double encryption work with rsaref. Oh, I
587 * hate software patents. I dont know if this can go? Niels
588 */
589 if (options.server_key_bits >
590 BN_num_bits(sensitive_data.host_key->n) - SSH_KEY_BITS_RESERVED &&
591 options.server_key_bits <
592 BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) {
593 options.server_key_bits =
594 BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED;
595 debug("Forcing server key to %d bits to make it differ from host key.",
596 options.server_key_bits);
597 }
598 }
599
600 /* Initialize the log (it is reinitialized below in case we forked). */
542 if (debug_flag && !inetd_flag) 601 if (debug_flag && !inetd_flag)
543 log_stderr = 1; 602 log_stderr = 1;
544 log_init(av0, options.log_level, options.log_facility, log_stderr); 603 log_init(av0, options.log_level, options.log_facility, log_stderr);
545 604
546 /* If not in debugging mode, and not started from inetd, 605 /*
547 disconnect from the controlling terminal, and fork. The 606 * If not in debugging mode, and not started from inetd, disconnect
548 original process exits. */ 607 * from the controlling terminal, and fork. The original process
608 * exits.
609 */
549 if (!debug_flag && !inetd_flag) { 610 if (!debug_flag && !inetd_flag) {
550#ifdef TIOCNOTTY 611#ifdef TIOCNOTTY
551 int fd; 612 int fd;
@@ -565,18 +626,6 @@ main(int ac, char **av)
565 /* Reinitialize the log (because of the fork above). */ 626 /* Reinitialize the log (because of the fork above). */
566 log_init(av0, options.log_level, options.log_facility, log_stderr); 627 log_init(av0, options.log_level, options.log_facility, log_stderr);
567 628
568 /* Check that server and host key lengths differ sufficiently.
569 This is necessary to make double encryption work with rsaref.
570 Oh, I hate software patents. I dont know if this can go? Niels */
571 if (options.server_key_bits >
572 BN_num_bits(sensitive_data.host_key->n) - SSH_KEY_BITS_RESERVED &&
573 options.server_key_bits <
574 BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) {
575 options.server_key_bits =
576 BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED;
577 debug("Forcing server key to %d bits to make it differ from host key.",
578 options.server_key_bits);
579 }
580 /* Do not display messages to stdout in RSA code. */ 629 /* Do not display messages to stdout in RSA code. */
581 rsa_set_verbose(0); 630 rsa_set_verbose(0);
582 631
@@ -594,20 +643,22 @@ main(int ac, char **av)
594 s2 = dup(s1); 643 s2 = dup(s1);
595 sock_in = dup(0); 644 sock_in = dup(0);
596 sock_out = dup(1); 645 sock_out = dup(1);
597 /* We intentionally do not close the descriptors 0, 1, and 2 646 /*
598 as our code for setting the descriptors won\'t work 647 * We intentionally do not close the descriptors 0, 1, and 2
599 if ttyfd happens to be one of those. */ 648 * as our code for setting the descriptors won\'t work if
649 * ttyfd happens to be one of those.
650 */
600 debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); 651 debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
601 652
602 public_key = RSA_new(); 653 if (options.protocol & SSH_PROTO_1) {
603 sensitive_data.private_key = RSA_new(); 654 public_key = RSA_new();
604 655 sensitive_data.private_key = RSA_new();
605 /* XXX check options.protocol */ 656 log("Generating %d bit RSA key.", options.server_key_bits);
606 log("Generating %d bit RSA key.", options.server_key_bits); 657 rsa_generate_key(sensitive_data.private_key, public_key,
607 rsa_generate_key(sensitive_data.private_key, public_key, 658 options.server_key_bits);
608 options.server_key_bits); 659 arc4random_stir();
609 arc4random_stir(); 660 log("RSA key generation complete.");
610 log("RSA key generation complete."); 661 }
611 } else { 662 } else {
612 for (ai = options.listen_addrs; ai; ai = ai->ai_next) { 663 for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
613 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 664 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
@@ -684,19 +735,20 @@ main(int ac, char **av)
684 fclose(f); 735 fclose(f);
685 } 736 }
686 } 737 }
738 if (options.protocol & SSH_PROTO_1) {
739 public_key = RSA_new();
740 sensitive_data.private_key = RSA_new();
687 741
688 public_key = RSA_new(); 742 log("Generating %d bit RSA key.", options.server_key_bits);
689 sensitive_data.private_key = RSA_new(); 743 rsa_generate_key(sensitive_data.private_key, public_key,
690 744 options.server_key_bits);
691 log("Generating %d bit RSA key.", options.server_key_bits); 745 arc4random_stir();
692 rsa_generate_key(sensitive_data.private_key, public_key, 746 log("RSA key generation complete.");
693 options.server_key_bits);
694 arc4random_stir();
695 log("RSA key generation complete.");
696 747
697 /* Schedule server key regeneration alarm. */ 748 /* Schedule server key regeneration alarm. */
698 signal(SIGALRM, key_regeneration_alarm); 749 signal(SIGALRM, key_regeneration_alarm);
699 alarm(options.key_regeneration_time); 750 alarm(options.key_regeneration_time);
751 }
700 752
701 /* Arrange to restart on SIGHUP. The handler needs listen_sock. */ 753 /* Arrange to restart on SIGHUP. The handler needs listen_sock. */
702 signal(SIGHUP, sighup_handler); 754 signal(SIGHUP, sighup_handler);
@@ -1069,9 +1121,7 @@ do_ssh1_kex()
1069 sensitive_data.private_key->n); 1121 sensitive_data.private_key->n);
1070 1122
1071 /* Destroy the private and public keys. They will no longer be needed. */ 1123 /* Destroy the private and public keys. They will no longer be needed. */
1072 RSA_free(public_key); 1124 destroy_sensitive_data();
1073 RSA_free(sensitive_data.private_key);
1074 RSA_free(sensitive_data.host_key);
1075 1125
1076 /* 1126 /*
1077 * Extract session key from the decrypted integer. The key is in the 1127 * Extract session key from the decrypted integer. The key is in the
@@ -1130,7 +1180,6 @@ do_ssh2_kex()
1130 unsigned char *kbuf; 1180 unsigned char *kbuf;
1131 unsigned char *hash; 1181 unsigned char *hash;
1132 Kex *kex; 1182 Kex *kex;
1133 Key *server_host_key;
1134 char *cprop[PROPOSAL_MAX]; 1183 char *cprop[PROPOSAL_MAX];
1135 char *sprop[PROPOSAL_MAX]; 1184 char *sprop[PROPOSAL_MAX];
1136 1185
@@ -1231,8 +1280,8 @@ do_ssh2_kex()
1231 memset(kbuf, 0, klen); 1280 memset(kbuf, 0, klen);
1232 xfree(kbuf); 1281 xfree(kbuf);
1233 1282
1234 server_host_key = dsa_get_serverkey(options.dsa_key_file); 1283 /* XXX precompute? */
1235 dsa_make_serverkey_blob(server_host_key, &server_host_key_blob, &sbloblen); 1284 dsa_make_key_blob(sensitive_data.dsa_host_key, &server_host_key_blob, &sbloblen);
1236 1285
1237 /* calc H */ /* XXX depends on 'kex' */ 1286 /* calc H */ /* XXX depends on 'kex' */
1238 hash = kex_hash( 1287 hash = kex_hash(
@@ -1255,10 +1304,17 @@ do_ssh2_kex()
1255 fprintf(stderr, "%02x", (hash[i])&0xff); 1304 fprintf(stderr, "%02x", (hash[i])&0xff);
1256 fprintf(stderr, "\n"); 1305 fprintf(stderr, "\n");
1257#endif 1306#endif
1307 /* save session id := H */
1308 /* XXX hashlen depends on KEX */
1309 session_id2_len = 20;
1310 session_id2 = xmalloc(session_id2_len);
1311 memcpy(session_id2, hash, session_id2_len);
1312
1258 /* sign H */ 1313 /* sign H */
1259 dsa_sign(server_host_key, &signature, &slen, hash, 20); 1314 /* XXX hashlen depends on KEX */
1260 /* hashlen depends on KEX */ 1315 dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20);
1261 key_free(server_host_key); 1316
1317 destroy_sensitive_data();
1262 1318
1263 /* send server hostkey, DH pubkey 'f' and singed H */ 1319 /* send server hostkey, DH pubkey 'f' and singed H */
1264 packet_start(SSH2_MSG_KEXDH_REPLY); 1320 packet_start(SSH2_MSG_KEXDH_REPLY);
@@ -1267,6 +1323,7 @@ do_ssh2_kex()
1267 packet_put_string((char *)signature, slen); 1323 packet_put_string((char *)signature, slen);
1268 packet_send(); 1324 packet_send();
1269 xfree(signature); 1325 xfree(signature);
1326 xfree(server_host_key_blob);
1270 packet_write_wait(); 1327 packet_write_wait();
1271 1328
1272 kex_derive_keys(kex, hash, shared_secret); 1329 kex_derive_keys(kex, hash, shared_secret);
diff --git a/uuencode.c b/uuencode.c
new file mode 100644
index 000000000..626890050
--- /dev/null
+++ b/uuencode.c
@@ -0,0 +1,120 @@
1/*
2 * base-64 encoding pinched from lynx2-7-2, who pinched it from rpem.
3 * Originally written by Mark Riordan 12 August 1990 and 17 Feb 1991
4 * and placed in the public domain.
5 *
6 * Dug Song <dugsong@UMICH.EDU>
7 */
8
9#include "includes.h"
10#include "xmalloc.h"
11
12char six2pr[64] = {
13 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
14 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
15 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
16 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
17 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
18};
19
20unsigned char pr2six[256];
21
22int
23uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded)
24{
25 /* ENC is the basic 1 character encoding function to make a char printing */
26#define ENC(c) six2pr[c]
27
28 register char *outptr = bufcoded;
29 unsigned int i;
30
31 for (i = 0; i < nbytes; i += 3) {
32 *(outptr++) = ENC(*bufin >> 2); /* c1 */
33 *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /* c2 */
34 *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)); /* c3 */
35 *(outptr++) = ENC(bufin[2] & 077); /* c4 */
36 bufin += 3;
37 }
38 if (i == nbytes + 1) {
39 outptr[-1] = '=';
40 } else if (i == nbytes + 2) {
41 outptr[-1] = '=';
42 outptr[-2] = '=';
43 } else if (i == nbytes) {
44 *(outptr++) = '=';
45 }
46 *outptr = '\0';
47 return (outptr - bufcoded);
48}
49
50int
51uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
52{
53 /* single character decode */
54#define DEC(c) pr2six[(unsigned char)c]
55#define MAXVAL 63
56
57 static int first = 1;
58 int nbytesdecoded, j;
59 const char *bufin = bufcoded;
60 register unsigned char *bufout = bufplain;
61 register int nprbytes;
62
63 /* If this is the first call, initialize the mapping table. */
64 if (first) {
65 first = 0;
66 for (j = 0; j < 256; j++)
67 pr2six[j] = MAXVAL + 1;
68 for (j = 0; j < 64; j++)
69 pr2six[(unsigned char) six2pr[j]] = (unsigned char) j;
70 }
71 /* Strip leading whitespace. */
72 while (*bufcoded == ' ' || *bufcoded == '\t')
73 bufcoded++;
74
75 /*
76 * Figure out how many characters are in the input buffer. If this
77 * would decode into more bytes than would fit into the output
78 * buffer, adjust the number of input bytes downwards.
79 */
80 bufin = bufcoded;
81 while (DEC(*(bufin++)) <= MAXVAL)
82 ;
83 nprbytes = bufin - bufcoded - 1;
84 nbytesdecoded = ((nprbytes + 3) / 4) * 3;
85 if (nbytesdecoded > outbufsize)
86 nprbytes = (outbufsize * 4) / 3;
87
88 bufin = bufcoded;
89
90 while (nprbytes > 0) {
91 *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
92 *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
93 *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
94 bufin += 4;
95 nprbytes -= 4;
96 }
97 if (nprbytes & 03) {
98 if (DEC(bufin[-2]) > MAXVAL)
99 nbytesdecoded -= 2;
100 else
101 nbytesdecoded -= 1;
102 }
103 return (nbytesdecoded);
104}
105
106void
107dump_base64(FILE *fp, unsigned char *data, int len)
108{
109 unsigned char *buf = xmalloc(2*len);
110 int i, n;
111 n = uuencode(data, len, buf);
112 for (i = 0; i < n; i++) {
113 fprintf(fp, "%c", buf[i]);
114 if (i % 70 == 69)
115 fprintf(fp, "\n");
116 }
117 if (i % 70 != 69)
118 fprintf(fp, "\n");
119 xfree(buf);
120}
diff --git a/uuencode.h b/uuencode.h
new file mode 100644
index 000000000..d3f446284
--- /dev/null
+++ b/uuencode.h
@@ -0,0 +1,6 @@
1#ifndef UUENCODE_H
2#define UUENCODE_H
3int uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded);
4int uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize);
5void dump_base64(FILE *fp, unsigned char *data, int len);
6#endif
diff --git a/version.h b/version.h
index fe2e876ea..5e7a38da0 100644
--- a/version.h
+++ b/version.h
@@ -1 +1 @@
#define SSH_VERSION "OpenSSH-1.2.3" #define SSH_VERSION "OpenSSH-2.0"