1 /* 2 * Dropbear - a SSH2 server 3 * 4 * Copyright (c) 2002-2004 Matt Johnston 5 * All rights reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. */ 24 25 #include "includes.h" 26 #include "packet.h" 27 #include "session.h" 28 #include "dbutil.h" 29 #include "ssh.h" 30 #include "algo.h" 31 #include "buffer.h" 32 #include "kex.h" 33 #include "random.h" 34 #include "service.h" 35 #include "auth.h" 36 #include "channel.h" 37 38 #define MAX_UNAUTH_PACKET_TYPE SSH_MSG_USERAUTH_PK_OK 39 40 static void recv_unimplemented(); 41 42 /* process a decrypted packet, call the appropriate handler */ 43 void process_packet() { 44 45 unsigned char type; 46 unsigned int i; 47 48 TRACE(("enter process_packet")) 49 50 type = buf_getbyte(ses.payload); 51 TRACE(("process_packet: packet type = %d", type)) 52 53 ses.lastpacket = type; 54 55 /* These packets we can receive at any time */ 56 switch(type) { 57 58 case SSH_MSG_IGNORE: 59 case SSH_MSG_DEBUG: 60 TRACE(("received SSH_MSG_IGNORE or SSH_MSG_DEBUG")) 61 goto out; 62 63 case SSH_MSG_UNIMPLEMENTED: 64 /* debugging XXX */ 65 TRACE(("SSH_MSG_UNIMPLEMENTED")) 66 dropbear_exit("received SSH_MSG_UNIMPLEMENTED"); 67 68 case SSH_MSG_DISCONNECT: 69 /* TODO cleanup? */ 70 dropbear_close("Disconnect received"); 71 } 72 73 74 /* This applies for KEX, where the spec says the next packet MUST be 75 * NEWKEYS */ 76 if (ses.requirenext != 0) { 77 if (ses.requirenext != type) { 78 /* TODO send disconnect? */ 79 dropbear_exit("unexpected packet type %d, expected %d", type, 80 ses.requirenext); 81 } else { 82 /* Got what we expected */ 83 ses.requirenext = 0; 84 } 85 } 86 87 /* Check if we should ignore this packet. Used currently only for 88 * KEX code, with first_kex_packet_follows */ 89 if (ses.ignorenext) { 90 TRACE(("Ignoring packet, type = %d", type)) 91 ses.ignorenext = 0; 92 goto out; 93 } 94 95 96 /* Kindly the protocol authors gave all the preauth packets type values 97 * less-than-or-equal-to 60 ( == MAX_UNAUTH_PACKET_TYPE ). 98 * NOTE: if the protocol changes and new types are added, revisit this 99 * assumption */ 100 if ( !ses.authstate.authdone && type > MAX_UNAUTH_PACKET_TYPE ) { 101 dropbear_exit("received message %d before userauth", type); 102 } 103 104 for (i = 0; ; i++) { 105 if (ses.packettypes[i].type == 0) { 106 /* end of list */ 107 break; 108 } 109 110 if (ses.packettypes[i].type == type) { 111 ses.packettypes[i].handler(); 112 goto out; 113 } 114 } 115 116 117 /* TODO do something more here? */ 118 TRACE(("preauth unknown packet")) 119 recv_unimplemented(); 120 121 out: 122 buf_free(ses.payload); 123 ses.payload = NULL; 124 125 TRACE(("leave process_packet")) 126 } 127 128 129 130 /* This must be called directly after receiving the unimplemented packet. 131 * Isn't the most clean implementation, it relies on packet processing 132 * occurring directly after decryption (direct use of ses.recvseq). 133 * This is reasonably valid, since there is only a single decryption buffer */ 134 static void recv_unimplemented() { 135 136 CHECKCLEARTOWRITE(); 137 138 buf_putbyte(ses.writepayload, SSH_MSG_UNIMPLEMENTED); 139 /* the decryption routine increments the sequence number, we must 140 * decrement */ 141 buf_putint(ses.writepayload, ses.recvseq - 1); 142 143 encrypt_packet(); 144 } 145