diff options
author | markus@openbsd.org <markus@openbsd.org> | 2015-01-19 19:52:16 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-01-20 09:13:01 +1100 |
commit | 091c302829210c41e7f57c3f094c7b9c054306f0 (patch) | |
tree | 800de5dc85b877a85d1f269ae5bb09b0dc3fa7a7 /monitor_wrap.c | |
parent | 4e62cc68ce4ba20245d208b252e74e91d3785b74 (diff) |
upstream commit
update packet.c & isolate, introduce struct ssh a) switch
packet.c to buffer api and isolate per-connection info into struct ssh b)
(de)serialization of the state is moved from monitor to packet.c c) the old
packet.c API is implemented in opacket.[ch] d) compress.c/h is removed and
integrated into packet.c with and ok djm@
Diffstat (limited to 'monitor_wrap.c')
-rw-r--r-- | monitor_wrap.c | 244 |
1 files changed, 14 insertions, 230 deletions
diff --git a/monitor_wrap.c b/monitor_wrap.c index b0dbb3f70..84df481d8 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor_wrap.c,v 1.81 2015/01/13 19:31:40 markus Exp $ */ | 1 | /* $OpenBSD: monitor_wrap.c,v 1.82 2015/01/19 19:52:16 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -82,6 +82,8 @@ | |||
82 | #include "servconf.h" | 82 | #include "servconf.h" |
83 | #include "roaming.h" | 83 | #include "roaming.h" |
84 | 84 | ||
85 | #include "ssherr.h" | ||
86 | |||
85 | /* Imports */ | 87 | /* Imports */ |
86 | extern int compat20; | 88 | extern int compat20; |
87 | extern z_stream incoming_stream; | 89 | extern z_stream incoming_stream; |
@@ -470,239 +472,21 @@ mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) | |||
470 | return (verified); | 472 | return (verified); |
471 | } | 473 | } |
472 | 474 | ||
473 | /* Export key state after authentication */ | ||
474 | Newkeys * | ||
475 | mm_newkeys_from_blob(u_char *blob, int blen) | ||
476 | { | ||
477 | Buffer b; | ||
478 | u_int len; | ||
479 | Newkeys *newkey = NULL; | ||
480 | Enc *enc; | ||
481 | Mac *mac; | ||
482 | Comp *comp; | ||
483 | |||
484 | debug3("%s: %p(%d)", __func__, blob, blen); | ||
485 | #ifdef DEBUG_PK | ||
486 | dump_base64(stderr, blob, blen); | ||
487 | #endif | ||
488 | buffer_init(&b); | ||
489 | buffer_append(&b, blob, blen); | ||
490 | |||
491 | newkey = xcalloc(1, sizeof(*newkey)); | ||
492 | enc = &newkey->enc; | ||
493 | mac = &newkey->mac; | ||
494 | comp = &newkey->comp; | ||
495 | |||
496 | /* Enc structure */ | ||
497 | enc->name = buffer_get_string(&b, NULL); | ||
498 | buffer_get(&b, &enc->cipher, sizeof(enc->cipher)); | ||
499 | enc->enabled = buffer_get_int(&b); | ||
500 | enc->block_size = buffer_get_int(&b); | ||
501 | enc->key = buffer_get_string(&b, &enc->key_len); | ||
502 | enc->iv = buffer_get_string(&b, &enc->iv_len); | ||
503 | |||
504 | if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher) | ||
505 | fatal("%s: bad cipher name %s or pointer %p", __func__, | ||
506 | enc->name, enc->cipher); | ||
507 | |||
508 | /* Mac structure */ | ||
509 | if (cipher_authlen(enc->cipher) == 0) { | ||
510 | mac->name = buffer_get_string(&b, NULL); | ||
511 | if (mac->name == NULL || mac_setup(mac, mac->name) != 0) | ||
512 | fatal("%s: can not setup mac %s", __func__, mac->name); | ||
513 | mac->enabled = buffer_get_int(&b); | ||
514 | mac->key = buffer_get_string(&b, &len); | ||
515 | if (len > mac->key_len) | ||
516 | fatal("%s: bad mac key length: %u > %d", __func__, len, | ||
517 | mac->key_len); | ||
518 | mac->key_len = len; | ||
519 | } | ||
520 | |||
521 | /* Comp structure */ | ||
522 | comp->type = buffer_get_int(&b); | ||
523 | comp->enabled = buffer_get_int(&b); | ||
524 | comp->name = buffer_get_string(&b, NULL); | ||
525 | |||
526 | len = buffer_len(&b); | ||
527 | if (len != 0) | ||
528 | error("newkeys_from_blob: remaining bytes in blob %u", len); | ||
529 | buffer_free(&b); | ||
530 | return (newkey); | ||
531 | } | ||
532 | |||
533 | int | ||
534 | mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp) | ||
535 | { | ||
536 | Buffer b; | ||
537 | int len; | ||
538 | Enc *enc; | ||
539 | Mac *mac; | ||
540 | Comp *comp; | ||
541 | Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode); | ||
542 | |||
543 | debug3("%s: converting %p", __func__, newkey); | ||
544 | |||
545 | if (newkey == NULL) { | ||
546 | error("%s: newkey == NULL", __func__); | ||
547 | return 0; | ||
548 | } | ||
549 | enc = &newkey->enc; | ||
550 | mac = &newkey->mac; | ||
551 | comp = &newkey->comp; | ||
552 | |||
553 | buffer_init(&b); | ||
554 | /* Enc structure */ | ||
555 | buffer_put_cstring(&b, enc->name); | ||
556 | /* The cipher struct is constant and shared, you export pointer */ | ||
557 | buffer_append(&b, &enc->cipher, sizeof(enc->cipher)); | ||
558 | buffer_put_int(&b, enc->enabled); | ||
559 | buffer_put_int(&b, enc->block_size); | ||
560 | buffer_put_string(&b, enc->key, enc->key_len); | ||
561 | packet_get_keyiv(mode, enc->iv, enc->iv_len); | ||
562 | buffer_put_string(&b, enc->iv, enc->iv_len); | ||
563 | |||
564 | /* Mac structure */ | ||
565 | if (cipher_authlen(enc->cipher) == 0) { | ||
566 | buffer_put_cstring(&b, mac->name); | ||
567 | buffer_put_int(&b, mac->enabled); | ||
568 | buffer_put_string(&b, mac->key, mac->key_len); | ||
569 | } | ||
570 | |||
571 | /* Comp structure */ | ||
572 | buffer_put_int(&b, comp->type); | ||
573 | buffer_put_int(&b, comp->enabled); | ||
574 | buffer_put_cstring(&b, comp->name); | ||
575 | |||
576 | len = buffer_len(&b); | ||
577 | if (lenp != NULL) | ||
578 | *lenp = len; | ||
579 | if (blobp != NULL) { | ||
580 | *blobp = xmalloc(len); | ||
581 | memcpy(*blobp, buffer_ptr(&b), len); | ||
582 | } | ||
583 | explicit_bzero(buffer_ptr(&b), len); | ||
584 | buffer_free(&b); | ||
585 | return len; | ||
586 | } | ||
587 | |||
588 | static void | ||
589 | mm_send_kex(Buffer *m, Kex *kex) | ||
590 | { | ||
591 | buffer_put_string(m, kex->session_id, kex->session_id_len); | ||
592 | buffer_put_int(m, kex->we_need); | ||
593 | buffer_put_int(m, kex->hostkey_type); | ||
594 | buffer_put_int(m, kex->kex_type); | ||
595 | buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my)); | ||
596 | buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer)); | ||
597 | buffer_put_int(m, kex->flags); | ||
598 | buffer_put_cstring(m, kex->client_version_string); | ||
599 | buffer_put_cstring(m, kex->server_version_string); | ||
600 | } | ||
601 | |||
602 | void | 475 | void |
603 | mm_send_keystate(struct monitor *monitor) | 476 | mm_send_keystate(struct monitor *monitor) |
604 | { | 477 | { |
605 | Buffer m, *input, *output; | 478 | struct ssh *ssh = active_state; /* XXX */ |
606 | u_char *blob, *p; | 479 | struct sshbuf *m; |
607 | u_int bloblen, plen; | 480 | int r; |
608 | u_int32_t seqnr, packets; | 481 | |
609 | u_int64_t blocks, bytes; | 482 | if ((m = sshbuf_new()) == NULL) |
610 | 483 | fatal("%s: sshbuf_new failed", __func__); | |
611 | buffer_init(&m); | 484 | if ((r = ssh_packet_get_state(ssh, m)) != 0) |
612 | 485 | fatal("%s: get_state failed: %s", | |
613 | if (!compat20) { | 486 | __func__, ssh_err(r)); |
614 | u_char iv[24]; | 487 | mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m); |
615 | u_char *key; | ||
616 | u_int ivlen, keylen; | ||
617 | |||
618 | buffer_put_int(&m, packet_get_protocol_flags()); | ||
619 | |||
620 | buffer_put_int(&m, packet_get_ssh1_cipher()); | ||
621 | |||
622 | debug3("%s: Sending ssh1 KEY+IV", __func__); | ||
623 | keylen = packet_get_encryption_key(NULL); | ||
624 | key = xmalloc(keylen+1); /* add 1 if keylen == 0 */ | ||
625 | keylen = packet_get_encryption_key(key); | ||
626 | buffer_put_string(&m, key, keylen); | ||
627 | explicit_bzero(key, keylen); | ||
628 | free(key); | ||
629 | |||
630 | ivlen = packet_get_keyiv_len(MODE_OUT); | ||
631 | packet_get_keyiv(MODE_OUT, iv, ivlen); | ||
632 | buffer_put_string(&m, iv, ivlen); | ||
633 | ivlen = packet_get_keyiv_len(MODE_IN); | ||
634 | packet_get_keyiv(MODE_IN, iv, ivlen); | ||
635 | buffer_put_string(&m, iv, ivlen); | ||
636 | goto skip; | ||
637 | } else { | ||
638 | /* Kex for rekeying */ | ||
639 | mm_send_kex(&m, *monitor->m_pkex); | ||
640 | } | ||
641 | |||
642 | debug3("%s: Sending new keys: %p %p", | ||
643 | __func__, packet_get_newkeys(MODE_OUT), | ||
644 | packet_get_newkeys(MODE_IN)); | ||
645 | |||
646 | /* Keys from Kex */ | ||
647 | if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen)) | ||
648 | fatal("%s: conversion of newkeys failed", __func__); | ||
649 | |||
650 | buffer_put_string(&m, blob, bloblen); | ||
651 | free(blob); | ||
652 | |||
653 | if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) | ||
654 | fatal("%s: conversion of newkeys failed", __func__); | ||
655 | |||
656 | buffer_put_string(&m, blob, bloblen); | ||
657 | free(blob); | ||
658 | |||
659 | packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes); | ||
660 | buffer_put_int(&m, seqnr); | ||
661 | buffer_put_int64(&m, blocks); | ||
662 | buffer_put_int(&m, packets); | ||
663 | buffer_put_int64(&m, bytes); | ||
664 | packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes); | ||
665 | buffer_put_int(&m, seqnr); | ||
666 | buffer_put_int64(&m, blocks); | ||
667 | buffer_put_int(&m, packets); | ||
668 | buffer_put_int64(&m, bytes); | ||
669 | |||
670 | debug3("%s: New keys have been sent", __func__); | ||
671 | skip: | ||
672 | /* More key context */ | ||
673 | plen = packet_get_keycontext(MODE_OUT, NULL); | ||
674 | p = xmalloc(plen+1); | ||
675 | packet_get_keycontext(MODE_OUT, p); | ||
676 | buffer_put_string(&m, p, plen); | ||
677 | free(p); | ||
678 | |||
679 | plen = packet_get_keycontext(MODE_IN, NULL); | ||
680 | p = xmalloc(plen+1); | ||
681 | packet_get_keycontext(MODE_IN, p); | ||
682 | buffer_put_string(&m, p, plen); | ||
683 | free(p); | ||
684 | |||
685 | /* Compression state */ | ||
686 | debug3("%s: Sending compression state", __func__); | ||
687 | buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream)); | ||
688 | buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream)); | ||
689 | |||
690 | /* Network I/O buffers */ | ||
691 | input = (Buffer *)packet_get_input(); | ||
692 | output = (Buffer *)packet_get_output(); | ||
693 | buffer_put_string(&m, buffer_ptr(input), buffer_len(input)); | ||
694 | buffer_put_string(&m, buffer_ptr(output), buffer_len(output)); | ||
695 | |||
696 | /* Roaming */ | ||
697 | if (compat20) { | ||
698 | buffer_put_int64(&m, get_sent_bytes()); | ||
699 | buffer_put_int64(&m, get_recv_bytes()); | ||
700 | } | ||
701 | |||
702 | mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); | ||
703 | debug3("%s: Finished sending state", __func__); | 488 | debug3("%s: Finished sending state", __func__); |
704 | 489 | sshbuf_free(m); | |
705 | buffer_free(&m); | ||
706 | } | 490 | } |
707 | 491 | ||
708 | int | 492 | int |