1bc5531deSDag-Erling Smørgrav /* $OpenBSD: dispatch.c,v 1.26 2015/02/12 20:34:19 dtucker Exp $ */ 2a04a10f8SKris Kennaway /* 3a04a10f8SKris Kennaway * Copyright (c) 2000 Markus Friedl. All rights reserved. 4a04a10f8SKris Kennaway * 5a04a10f8SKris Kennaway * Redistribution and use in source and binary forms, with or without 6a04a10f8SKris Kennaway * modification, are permitted provided that the following conditions 7a04a10f8SKris Kennaway * are met: 8a04a10f8SKris Kennaway * 1. Redistributions of source code must retain the above copyright 9a04a10f8SKris Kennaway * notice, this list of conditions and the following disclaimer. 10a04a10f8SKris Kennaway * 2. Redistributions in binary form must reproduce the above copyright 11a04a10f8SKris Kennaway * notice, this list of conditions and the following disclaimer in the 12a04a10f8SKris Kennaway * documentation and/or other materials provided with the distribution. 13a04a10f8SKris Kennaway * 14a04a10f8SKris Kennaway * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15a04a10f8SKris Kennaway * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16a04a10f8SKris Kennaway * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17a04a10f8SKris Kennaway * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18a04a10f8SKris Kennaway * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19a04a10f8SKris Kennaway * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20a04a10f8SKris Kennaway * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21a04a10f8SKris Kennaway * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22a04a10f8SKris Kennaway * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23a04a10f8SKris Kennaway * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24a04a10f8SKris Kennaway */ 25761efaa7SDag-Erling Smørgrav 26a04a10f8SKris Kennaway #include "includes.h" 27761efaa7SDag-Erling Smørgrav 28761efaa7SDag-Erling Smørgrav #include <sys/types.h> 29761efaa7SDag-Erling Smørgrav 30761efaa7SDag-Erling Smørgrav #include <signal.h> 31761efaa7SDag-Erling Smørgrav #include <stdarg.h> 321e8db6e2SBrian Feldman 331e8db6e2SBrian Feldman #include "ssh1.h" 341e8db6e2SBrian Feldman #include "ssh2.h" 351e8db6e2SBrian Feldman #include "log.h" 36a04a10f8SKris Kennaway #include "dispatch.h" 37a04a10f8SKris Kennaway #include "packet.h" 381e8db6e2SBrian Feldman #include "compat.h" 39bc5531deSDag-Erling Smørgrav #include "ssherr.h" 40a04a10f8SKris Kennaway 41bc5531deSDag-Erling Smørgrav int 42bc5531deSDag-Erling Smørgrav dispatch_protocol_error(int type, u_int32_t seq, void *ctx) 43a04a10f8SKris Kennaway { 44bc5531deSDag-Erling Smørgrav struct ssh *ssh = active_state; /* XXX */ 45bc5531deSDag-Erling Smørgrav int r; 46bc5531deSDag-Erling Smørgrav 47d95e11bfSDag-Erling Smørgrav logit("dispatch_protocol_error: type %d seq %u", type, seq); 48ae1f160dSDag-Erling Smørgrav if (!compat20) 49ae1f160dSDag-Erling Smørgrav fatal("protocol error"); 50bc5531deSDag-Erling Smørgrav if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || 51bc5531deSDag-Erling Smørgrav (r = sshpkt_put_u32(ssh, seq)) != 0 || 52bc5531deSDag-Erling Smørgrav (r = sshpkt_send(ssh)) != 0 || 53bc5531deSDag-Erling Smørgrav (r = ssh_packet_write_wait(ssh)) != 0) 54bc5531deSDag-Erling Smørgrav sshpkt_fatal(ssh, __func__, r); 55bc5531deSDag-Erling Smørgrav return 0; 56ae1f160dSDag-Erling Smørgrav } 57bc5531deSDag-Erling Smørgrav 58bc5531deSDag-Erling Smørgrav int 59bc5531deSDag-Erling Smørgrav dispatch_protocol_ignore(int type, u_int32_t seq, void *ssh) 60ae1f160dSDag-Erling Smørgrav { 61d95e11bfSDag-Erling Smørgrav logit("dispatch_protocol_ignore: type %d seq %u", type, seq); 62bc5531deSDag-Erling Smørgrav return 0; 63a04a10f8SKris Kennaway } 64bc5531deSDag-Erling Smørgrav 65a04a10f8SKris Kennaway void 66bc5531deSDag-Erling Smørgrav ssh_dispatch_init(struct ssh *ssh, dispatch_fn *dflt) 67a04a10f8SKris Kennaway { 68ae1f160dSDag-Erling Smørgrav u_int i; 69a04a10f8SKris Kennaway for (i = 0; i < DISPATCH_MAX; i++) 70bc5531deSDag-Erling Smørgrav ssh->dispatch[i] = dflt; 71a04a10f8SKris Kennaway } 72bc5531deSDag-Erling Smørgrav 73a04a10f8SKris Kennaway void 74bc5531deSDag-Erling Smørgrav ssh_dispatch_range(struct ssh *ssh, u_int from, u_int to, dispatch_fn *fn) 75ae1f160dSDag-Erling Smørgrav { 76ae1f160dSDag-Erling Smørgrav u_int i; 77ae1f160dSDag-Erling Smørgrav 78ae1f160dSDag-Erling Smørgrav for (i = from; i <= to; i++) { 79ae1f160dSDag-Erling Smørgrav if (i >= DISPATCH_MAX) 80ae1f160dSDag-Erling Smørgrav break; 81bc5531deSDag-Erling Smørgrav ssh->dispatch[i] = fn; 82ae1f160dSDag-Erling Smørgrav } 83ae1f160dSDag-Erling Smørgrav } 84bc5531deSDag-Erling Smørgrav 85ae1f160dSDag-Erling Smørgrav void 86bc5531deSDag-Erling Smørgrav ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn) 87a04a10f8SKris Kennaway { 88bc5531deSDag-Erling Smørgrav ssh->dispatch[type] = fn; 89a04a10f8SKris Kennaway } 90bc5531deSDag-Erling Smørgrav 91bc5531deSDag-Erling Smørgrav int 92bc5531deSDag-Erling Smørgrav ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, 93bc5531deSDag-Erling Smørgrav void *ctxt) 94a04a10f8SKris Kennaway { 95bc5531deSDag-Erling Smørgrav int r; 96bc5531deSDag-Erling Smørgrav u_char type; 97ae1f160dSDag-Erling Smørgrav u_int32_t seqnr; 98a04a10f8SKris Kennaway 99bc5531deSDag-Erling Smørgrav for (;;) { 100a04a10f8SKris Kennaway if (mode == DISPATCH_BLOCK) { 101bc5531deSDag-Erling Smørgrav r = ssh_packet_read_seqnr(ssh, &type, &seqnr); 102bc5531deSDag-Erling Smørgrav if (r != 0) 103bc5531deSDag-Erling Smørgrav return r; 104a04a10f8SKris Kennaway } else { 105bc5531deSDag-Erling Smørgrav r = ssh_packet_read_poll_seqnr(ssh, &type, &seqnr); 106bc5531deSDag-Erling Smørgrav if (r != 0) 107bc5531deSDag-Erling Smørgrav return r; 108a04a10f8SKris Kennaway if (type == SSH_MSG_NONE) 109bc5531deSDag-Erling Smørgrav return 0; 110a04a10f8SKris Kennaway } 111bc5531deSDag-Erling Smørgrav if (type > 0 && type < DISPATCH_MAX && 112bc5531deSDag-Erling Smørgrav ssh->dispatch[type] != NULL) { 113bc5531deSDag-Erling Smørgrav if (ssh->dispatch_skip_packets) { 114bc5531deSDag-Erling Smørgrav debug2("skipped packet (type %u)", type); 115bc5531deSDag-Erling Smørgrav ssh->dispatch_skip_packets--; 116bc5531deSDag-Erling Smørgrav continue; 117bc5531deSDag-Erling Smørgrav } 118bc5531deSDag-Erling Smørgrav /* XXX 'ssh' will replace 'ctxt' later */ 119bc5531deSDag-Erling Smørgrav r = (*ssh->dispatch[type])(type, seqnr, ctxt); 120bc5531deSDag-Erling Smørgrav if (r != 0) 121bc5531deSDag-Erling Smørgrav return r; 122bc5531deSDag-Erling Smørgrav } else { 123bc5531deSDag-Erling Smørgrav r = sshpkt_disconnect(ssh, 124bc5531deSDag-Erling Smørgrav "protocol error: rcvd type %d", type); 125bc5531deSDag-Erling Smørgrav if (r != 0) 126bc5531deSDag-Erling Smørgrav return r; 127bc5531deSDag-Erling Smørgrav return SSH_ERR_DISCONNECTED; 128bc5531deSDag-Erling Smørgrav } 129a04a10f8SKris Kennaway if (done != NULL && *done) 130bc5531deSDag-Erling Smørgrav return 0; 131bc5531deSDag-Erling Smørgrav } 132bc5531deSDag-Erling Smørgrav } 133bc5531deSDag-Erling Smørgrav 134bc5531deSDag-Erling Smørgrav void 135bc5531deSDag-Erling Smørgrav ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done, 136bc5531deSDag-Erling Smørgrav void *ctxt) 137bc5531deSDag-Erling Smørgrav { 138bc5531deSDag-Erling Smørgrav int r; 139bc5531deSDag-Erling Smørgrav 140bc5531deSDag-Erling Smørgrav if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0) { 141bc5531deSDag-Erling Smørgrav switch (r) { 142bc5531deSDag-Erling Smørgrav case SSH_ERR_CONN_CLOSED: 143bc5531deSDag-Erling Smørgrav logit("Connection closed by %.200s", 144bc5531deSDag-Erling Smørgrav ssh_remote_ipaddr(ssh)); 145bc5531deSDag-Erling Smørgrav cleanup_exit(255); 146bc5531deSDag-Erling Smørgrav case SSH_ERR_CONN_TIMEOUT: 147bc5531deSDag-Erling Smørgrav logit("Connection to %.200s timed out while " 148bc5531deSDag-Erling Smørgrav "waiting to read", ssh_remote_ipaddr(ssh)); 149bc5531deSDag-Erling Smørgrav cleanup_exit(255); 150bc5531deSDag-Erling Smørgrav case SSH_ERR_DISCONNECTED: 151bc5531deSDag-Erling Smørgrav logit("Disconnected from %.200s", 152bc5531deSDag-Erling Smørgrav ssh_remote_ipaddr(ssh)); 153bc5531deSDag-Erling Smørgrav cleanup_exit(255); 154bc5531deSDag-Erling Smørgrav default: 155bc5531deSDag-Erling Smørgrav fatal("%s: %s", __func__, ssh_err(r)); 156bc5531deSDag-Erling Smørgrav } 157a04a10f8SKris Kennaway } 158a04a10f8SKris Kennaway } 159