diff options
author | Damien Miller <djm@mindrot.org> | 2000-10-14 16:23:11 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-10-14 16:23:11 +1100 |
commit | 874d77bb134a21a5cf625956b60173376a993ba8 (patch) | |
tree | 93dd73b2ff1fbf0ad5f3978a2c4e0d8438a0bf7c /sshd.c | |
parent | 89d9796fbedef4eed6956a2c095c7cc25330c28d (diff) |
- (djm) Big OpenBSD sync:
- markus@cvs.openbsd.org 2000/09/30 10:27:44
[log.c]
allow loglevel debug
- markus@cvs.openbsd.org 2000/10/03 11:59:57
[packet.c]
hmac->mac
- markus@cvs.openbsd.org 2000/10/03 12:03:03
[auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c]
move fake-auth from auth1.c to individual auth methods, disables s/key in
debug-msg
- markus@cvs.openbsd.org 2000/10/03 12:16:48
ssh.c
do not resolve canonname, i have no idea why this was added oin ossh
- markus@cvs.openbsd.org 2000/10/09 15:30:44
ssh-keygen.1 ssh-keygen.c
-X now reads private ssh.com DSA keys, too.
- markus@cvs.openbsd.org 2000/10/09 15:32:34
auth-options.c
clear options on every call.
- markus@cvs.openbsd.org 2000/10/09 15:51:00
authfd.c authfd.h
interop with ssh-agent2, from <res@shore.net>
- markus@cvs.openbsd.org 2000/10/10 14:20:45
compat.c
use rexexp for version string matching
- provos@cvs.openbsd.org 2000/10/10 22:02:18
[kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h]
First rough implementation of the diffie-hellman group exchange. The
client can ask the server for bigger groups to perform the diffie-hellman
in, thus increasing the attack complexity when using ciphers with longer
keys. University of Windsor provided network, T the company.
- markus@cvs.openbsd.org 2000/10/11 13:59:52
[auth-rsa.c auth2.c]
clear auth options unless auth sucessfull
- markus@cvs.openbsd.org 2000/10/11 14:00:27
[auth-options.h]
clear auth options unless auth sucessfull
- markus@cvs.openbsd.org 2000/10/11 14:03:27
[scp.1 scp.c]
support 'scp -o' with help from mouring@pconline.com
- markus@cvs.openbsd.org 2000/10/11 14:11:35
[dh.c]
Wall
- markus@cvs.openbsd.org 2000/10/11 14:14:40
[auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h]
[ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h]
add support for s/key (kbd-interactive) to ssh2, based on work by
mkiernan@avantgo.com and me
- markus@cvs.openbsd.org 2000/10/11 14:27:24
[auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h]
[myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c]
[sshconnect2.c sshd.c]
new cipher framework
- markus@cvs.openbsd.org 2000/10/11 14:45:21
[cipher.c]
remove DES
- markus@cvs.openbsd.org 2000/10/12 03:59:20
[cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c]
enable DES in SSH-1 clients only
- markus@cvs.openbsd.org 2000/10/12 08:21:13
[kex.h packet.c]
remove unused
- markus@cvs.openbsd.org 2000/10/13 12:34:46
[sshd.c]
Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se
- markus@cvs.openbsd.org 2000/10/13 12:59:15
[cipher.c cipher.h myproposal.h rijndael.c rijndael.h]
rijndael/aes support
- markus@cvs.openbsd.org 2000/10/13 13:10:54
[sshd.8]
more info about -V
- markus@cvs.openbsd.org 2000/10/13 13:12:02
[myproposal.h]
prefer no compression
Diffstat (limited to 'sshd.c')
-rw-r--r-- | sshd.c | 225 |
1 files changed, 197 insertions, 28 deletions
@@ -40,14 +40,13 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $"); | 43 | RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $"); |
44 | 44 | ||
45 | #include "xmalloc.h" | 45 | #include "xmalloc.h" |
46 | #include "rsa.h" | 46 | #include "rsa.h" |
47 | #include "ssh.h" | 47 | #include "ssh.h" |
48 | #include "pty.h" | 48 | #include "pty.h" |
49 | #include "packet.h" | 49 | #include "packet.h" |
50 | #include "cipher.h" | ||
51 | #include "mpaux.h" | 50 | #include "mpaux.h" |
52 | #include "servconf.h" | 51 | #include "servconf.h" |
53 | #include "uidswap.h" | 52 | #include "uidswap.h" |
@@ -63,6 +62,7 @@ RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $"); | |||
63 | #include <openssl/rsa.h> | 62 | #include <openssl/rsa.h> |
64 | #include "key.h" | 63 | #include "key.h" |
65 | #include "dsa.h" | 64 | #include "dsa.h" |
65 | #include "dh.h" | ||
66 | 66 | ||
67 | #include "auth.h" | 67 | #include "auth.h" |
68 | #include "myproposal.h" | 68 | #include "myproposal.h" |
@@ -172,6 +172,9 @@ unsigned int utmp_len = MAXHOSTNAMELEN; | |||
172 | void do_ssh1_kex(); | 172 | void do_ssh1_kex(); |
173 | void do_ssh2_kex(); | 173 | void do_ssh2_kex(); |
174 | 174 | ||
175 | void ssh_dh1_server(Kex *, Buffer *_kexinit, Buffer *); | ||
176 | void ssh_dhgex_server(Kex *, Buffer *_kexinit, Buffer *); | ||
177 | |||
175 | /* | 178 | /* |
176 | * Close all listening sockets | 179 | * Close all listening sockets |
177 | */ | 180 | */ |
@@ -333,6 +336,10 @@ sshd_exchange_identification(int sock_in, int sock_out) | |||
333 | if (buf[i] == '\r') { | 336 | if (buf[i] == '\r') { |
334 | buf[i] = '\n'; | 337 | buf[i] = '\n'; |
335 | buf[i + 1] = 0; | 338 | buf[i + 1] = 0; |
339 | /* Kludge for F-Secure Macintosh < 1.0.2 */ | ||
340 | if (i == 12 && | ||
341 | strncmp(buf, "SSH-1.5-W1.0", 12) == 0) | ||
342 | break; | ||
336 | continue; | 343 | continue; |
337 | } | 344 | } |
338 | if (buf[i] == '\n') { | 345 | if (buf[i] == '\n') { |
@@ -1151,7 +1158,7 @@ do_ssh1_kex() | |||
1151 | packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); | 1158 | packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); |
1152 | 1159 | ||
1153 | /* Declare which ciphers we support. */ | 1160 | /* Declare which ciphers we support. */ |
1154 | packet_put_int(cipher_mask1()); | 1161 | packet_put_int(cipher_mask_ssh1(0)); |
1155 | 1162 | ||
1156 | /* Declare supported authentication types. */ | 1163 | /* Declare supported authentication types. */ |
1157 | auth_mask = 0; | 1164 | auth_mask = 0; |
@@ -1192,7 +1199,7 @@ do_ssh1_kex() | |||
1192 | /* Get cipher type and check whether we accept this. */ | 1199 | /* Get cipher type and check whether we accept this. */ |
1193 | cipher_type = packet_get_char(); | 1200 | cipher_type = packet_get_char(); |
1194 | 1201 | ||
1195 | if (!(cipher_mask() & (1 << cipher_type))) | 1202 | if (!(cipher_mask_ssh1(0) & (1 << cipher_type))) |
1196 | packet_disconnect("Warning: client selects unsupported cipher."); | 1203 | packet_disconnect("Warning: client selects unsupported cipher."); |
1197 | 1204 | ||
1198 | /* Get check bytes from the packet. These must match those we | 1205 | /* Get check bytes from the packet. These must match those we |
@@ -1296,18 +1303,8 @@ do_ssh2_kex() | |||
1296 | { | 1303 | { |
1297 | Buffer *server_kexinit; | 1304 | Buffer *server_kexinit; |
1298 | Buffer *client_kexinit; | 1305 | Buffer *client_kexinit; |
1299 | int payload_len, dlen; | 1306 | int payload_len; |
1300 | int slen; | ||
1301 | unsigned int klen, kout; | ||
1302 | unsigned char *signature = NULL; | ||
1303 | unsigned char *server_host_key_blob = NULL; | ||
1304 | unsigned int sbloblen; | ||
1305 | DH *dh; | ||
1306 | BIGNUM *dh_client_pub = 0; | ||
1307 | BIGNUM *shared_secret = 0; | ||
1308 | int i; | 1307 | int i; |
1309 | unsigned char *kbuf; | ||
1310 | unsigned char *hash; | ||
1311 | Kex *kex; | 1308 | Kex *kex; |
1312 | char *cprop[PROPOSAL_MAX]; | 1309 | char *cprop[PROPOSAL_MAX]; |
1313 | 1310 | ||
@@ -1327,8 +1324,63 @@ do_ssh2_kex() | |||
1327 | for (i = 0; i < PROPOSAL_MAX; i++) | 1324 | for (i = 0; i < PROPOSAL_MAX; i++) |
1328 | xfree(cprop[i]); | 1325 | xfree(cprop[i]); |
1329 | 1326 | ||
1330 | /* KEXDH */ | 1327 | switch (kex->kex_type) { |
1328 | case DH_GRP1_SHA1: | ||
1329 | ssh_dh1_server(kex, client_kexinit, server_kexinit); | ||
1330 | break; | ||
1331 | case DH_GEX_SHA1: | ||
1332 | ssh_dhgex_server(kex, client_kexinit, server_kexinit); | ||
1333 | break; | ||
1334 | default: | ||
1335 | fatal("Unsupported key exchange %d", kex->kex_type); | ||
1336 | } | ||
1337 | |||
1338 | debug("send SSH2_MSG_NEWKEYS."); | ||
1339 | packet_start(SSH2_MSG_NEWKEYS); | ||
1340 | packet_send(); | ||
1341 | packet_write_wait(); | ||
1342 | debug("done: send SSH2_MSG_NEWKEYS."); | ||
1343 | |||
1344 | debug("Wait SSH2_MSG_NEWKEYS."); | ||
1345 | packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS); | ||
1346 | debug("GOT SSH2_MSG_NEWKEYS."); | ||
1347 | |||
1348 | #ifdef DEBUG_KEXDH | ||
1349 | /* send 1st encrypted/maced/compressed message */ | ||
1350 | packet_start(SSH2_MSG_IGNORE); | ||
1351 | packet_put_cstring("markus"); | ||
1352 | packet_send(); | ||
1353 | packet_write_wait(); | ||
1354 | #endif | ||
1355 | |||
1356 | debug("done: KEX2."); | ||
1357 | } | ||
1358 | |||
1359 | /* | ||
1360 | * SSH2 key exchange | ||
1361 | */ | ||
1362 | |||
1363 | /* diffie-hellman-group1-sha1 */ | ||
1364 | |||
1365 | void | ||
1366 | ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | ||
1367 | { | ||
1368 | #ifdef DEBUG_KEXDH | ||
1369 | int i; | ||
1370 | #endif | ||
1371 | int payload_len, dlen; | ||
1372 | int slen; | ||
1373 | unsigned char *signature = NULL; | ||
1374 | unsigned char *server_host_key_blob = NULL; | ||
1375 | unsigned int sbloblen; | ||
1376 | unsigned int klen, kout; | ||
1377 | unsigned char *kbuf; | ||
1378 | unsigned char *hash; | ||
1379 | BIGNUM *shared_secret = 0; | ||
1380 | DH *dh; | ||
1381 | BIGNUM *dh_client_pub = 0; | ||
1331 | 1382 | ||
1383 | /* KEXDH */ | ||
1332 | debug("Wait SSH2_MSG_KEXDH_INIT."); | 1384 | debug("Wait SSH2_MSG_KEXDH_INIT."); |
1333 | packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT); | 1385 | packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT); |
1334 | 1386 | ||
@@ -1379,7 +1431,8 @@ do_ssh2_kex() | |||
1379 | xfree(kbuf); | 1431 | xfree(kbuf); |
1380 | 1432 | ||
1381 | /* XXX precompute? */ | 1433 | /* XXX precompute? */ |
1382 | dsa_make_key_blob(sensitive_data.dsa_host_key, &server_host_key_blob, &sbloblen); | 1434 | dsa_make_key_blob(sensitive_data.dsa_host_key, |
1435 | &server_host_key_blob, &sbloblen); | ||
1383 | 1436 | ||
1384 | /* calc H */ /* XXX depends on 'kex' */ | 1437 | /* calc H */ /* XXX depends on 'kex' */ |
1385 | hash = kex_hash( | 1438 | hash = kex_hash( |
@@ -1429,23 +1482,139 @@ do_ssh2_kex() | |||
1429 | 1482 | ||
1430 | /* have keys, free DH */ | 1483 | /* have keys, free DH */ |
1431 | DH_free(dh); | 1484 | DH_free(dh); |
1485 | } | ||
1432 | 1486 | ||
1433 | debug("send SSH2_MSG_NEWKEYS."); | 1487 | /* diffie-hellman-group-exchange-sha1 */ |
1434 | packet_start(SSH2_MSG_NEWKEYS); | 1488 | |
1489 | void | ||
1490 | ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit) | ||
1491 | { | ||
1492 | #ifdef DEBUG_KEXDH | ||
1493 | int i; | ||
1494 | #endif | ||
1495 | int payload_len, dlen; | ||
1496 | int slen, nbits; | ||
1497 | unsigned char *signature = NULL; | ||
1498 | unsigned char *server_host_key_blob = NULL; | ||
1499 | unsigned int sbloblen; | ||
1500 | unsigned int klen, kout; | ||
1501 | unsigned char *kbuf; | ||
1502 | unsigned char *hash; | ||
1503 | BIGNUM *shared_secret = 0; | ||
1504 | DH *dh; | ||
1505 | BIGNUM *dh_client_pub = 0; | ||
1506 | |||
1507 | /* KEXDHGEX */ | ||
1508 | debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST."); | ||
1509 | packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_REQUEST); | ||
1510 | nbits = packet_get_int(); | ||
1511 | dh = choose_dh(nbits); | ||
1512 | |||
1513 | debug("Sending SSH2_MSG_KEX_DH_GEX_GROUP."); | ||
1514 | packet_start(SSH2_MSG_KEX_DH_GEX_GROUP); | ||
1515 | packet_put_bignum2(dh->p); | ||
1516 | packet_put_bignum2(dh->g); | ||
1435 | packet_send(); | 1517 | packet_send(); |
1436 | packet_write_wait(); | 1518 | packet_write_wait(); |
1437 | debug("done: send SSH2_MSG_NEWKEYS."); | ||
1438 | 1519 | ||
1439 | debug("Wait SSH2_MSG_NEWKEYS."); | 1520 | debug("Wait SSH2_MSG_KEX_DH_GEX_INIT."); |
1440 | packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS); | 1521 | packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_INIT); |
1441 | debug("GOT SSH2_MSG_NEWKEYS."); | 1522 | |
1523 | /* key, cert */ | ||
1524 | dh_client_pub = BN_new(); | ||
1525 | if (dh_client_pub == NULL) | ||
1526 | fatal("dh_client_pub == NULL"); | ||
1527 | packet_get_bignum2(dh_client_pub, &dlen); | ||
1442 | 1528 | ||
1443 | #ifdef DEBUG_KEXDH | 1529 | #ifdef DEBUG_KEXDH |
1444 | /* send 1st encrypted/maced/compressed message */ | 1530 | fprintf(stderr, "\ndh_client_pub= "); |
1445 | packet_start(SSH2_MSG_IGNORE); | 1531 | BN_print_fp(stderr, dh_client_pub); |
1446 | packet_put_cstring("markus"); | 1532 | fprintf(stderr, "\n"); |
1533 | debug("bits %d", BN_num_bits(dh_client_pub)); | ||
1534 | #endif | ||
1535 | |||
1536 | #ifdef DEBUG_KEXDH | ||
1537 | fprintf(stderr, "\np= "); | ||
1538 | BN_print_fp(stderr, dh->p); | ||
1539 | fprintf(stderr, "\ng= "); | ||
1540 | bn_print(dh->g); | ||
1541 | fprintf(stderr, "\npub= "); | ||
1542 | BN_print_fp(stderr, dh->pub_key); | ||
1543 | fprintf(stderr, "\n"); | ||
1544 | DHparams_print_fp(stderr, dh); | ||
1545 | #endif | ||
1546 | if (!dh_pub_is_valid(dh, dh_client_pub)) | ||
1547 | packet_disconnect("bad client public DH value"); | ||
1548 | |||
1549 | klen = DH_size(dh); | ||
1550 | kbuf = xmalloc(klen); | ||
1551 | kout = DH_compute_key(kbuf, dh_client_pub, dh); | ||
1552 | |||
1553 | #ifdef DEBUG_KEXDH | ||
1554 | debug("shared secret: len %d/%d", klen, kout); | ||
1555 | fprintf(stderr, "shared secret == "); | ||
1556 | for (i = 0; i< kout; i++) | ||
1557 | fprintf(stderr, "%02x", (kbuf[i])&0xff); | ||
1558 | fprintf(stderr, "\n"); | ||
1559 | #endif | ||
1560 | shared_secret = BN_new(); | ||
1561 | |||
1562 | BN_bin2bn(kbuf, kout, shared_secret); | ||
1563 | memset(kbuf, 0, klen); | ||
1564 | xfree(kbuf); | ||
1565 | |||
1566 | /* XXX precompute? */ | ||
1567 | dsa_make_key_blob(sensitive_data.dsa_host_key, | ||
1568 | &server_host_key_blob, &sbloblen); | ||
1569 | |||
1570 | /* calc H */ /* XXX depends on 'kex' */ | ||
1571 | hash = kex_hash_gex( | ||
1572 | client_version_string, | ||
1573 | server_version_string, | ||
1574 | buffer_ptr(client_kexinit), buffer_len(client_kexinit), | ||
1575 | buffer_ptr(server_kexinit), buffer_len(server_kexinit), | ||
1576 | (char *)server_host_key_blob, sbloblen, | ||
1577 | nbits, dh->p, dh->g, | ||
1578 | dh_client_pub, | ||
1579 | dh->pub_key, | ||
1580 | shared_secret | ||
1581 | ); | ||
1582 | buffer_free(client_kexinit); | ||
1583 | buffer_free(server_kexinit); | ||
1584 | xfree(client_kexinit); | ||
1585 | xfree(server_kexinit); | ||
1586 | #ifdef DEBUG_KEXDH | ||
1587 | fprintf(stderr, "hash == "); | ||
1588 | for (i = 0; i< 20; i++) | ||
1589 | fprintf(stderr, "%02x", (hash[i])&0xff); | ||
1590 | fprintf(stderr, "\n"); | ||
1591 | #endif | ||
1592 | /* save session id := H */ | ||
1593 | /* XXX hashlen depends on KEX */ | ||
1594 | session_id2_len = 20; | ||
1595 | session_id2 = xmalloc(session_id2_len); | ||
1596 | memcpy(session_id2, hash, session_id2_len); | ||
1597 | |||
1598 | /* sign H */ | ||
1599 | /* XXX hashlen depends on KEX */ | ||
1600 | dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20); | ||
1601 | |||
1602 | destroy_sensitive_data(); | ||
1603 | |||
1604 | /* send server hostkey, DH pubkey 'f' and singed H */ | ||
1605 | packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); | ||
1606 | packet_put_string((char *)server_host_key_blob, sbloblen); | ||
1607 | packet_put_bignum2(dh->pub_key); /* f */ | ||
1608 | packet_put_string((char *)signature, slen); | ||
1447 | packet_send(); | 1609 | packet_send(); |
1610 | xfree(signature); | ||
1611 | xfree(server_host_key_blob); | ||
1448 | packet_write_wait(); | 1612 | packet_write_wait(); |
1449 | #endif | 1613 | |
1450 | debug("done: KEX2."); | 1614 | kex_derive_keys(kex, hash, shared_secret); |
1615 | packet_set_kex(kex); | ||
1616 | |||
1617 | /* have keys, free DH */ | ||
1618 | DH_free(dh); | ||
1451 | } | 1619 | } |
1620 | |||