]> andersk Git - openssh.git/blob - packet.c
Initial revision
[openssh.git] / packet.c
1 /*
2
3 packet.c
4
5 Author: Tatu Ylonen <ylo@cs.hut.fi>
6
7 Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8                    All rights reserved
9
10 Created: Sat Mar 18 02:40:40 1995 ylo
11
12 This file contains code implementing the packet protocol and communication
13 with the other side.  This same code is used both on client and server side.
14
15 */
16
17 #include "includes.h"
18 RCSID("$Id$");
19
20 #include "xmalloc.h"
21 #include "buffer.h"
22 #include "packet.h"
23 #include "bufaux.h"
24 #include "ssh.h"
25 #include "crc32.h"
26 #include "cipher.h"
27 #include "getput.h"
28
29 #include "compress.h"
30 #include "deattack.h"
31
32 /* This variable contains the file descriptors used for communicating with
33    the other side.  connection_in is used for reading; connection_out
34    for writing.  These can be the same descriptor, in which case it is
35    assumed to be a socket. */
36 static int connection_in = -1;
37 static int connection_out = -1;
38
39 /* Cipher type.  This value is only used to determine whether to pad the
40    packets with zeroes or random data. */
41 static int cipher_type = SSH_CIPHER_NONE;
42
43 /* Protocol flags for the remote side. */
44 static unsigned int remote_protocol_flags = 0;
45
46 /* Encryption context for receiving data.  This is only used for decryption. */
47 static CipherContext receive_context;
48 /* Encryption coontext for sending data.  This is only used for encryption. */
49 static CipherContext send_context;
50
51 /* Buffer for raw input data from the socket. */
52 static Buffer input;
53
54 /* Buffer for raw output data going to the socket. */
55 static Buffer output;
56
57 /* Buffer for the partial outgoing packet being constructed. */
58 static Buffer outgoing_packet;
59
60 /* Buffer for the incoming packet currently being processed. */
61 static Buffer incoming_packet;
62
63 /* Scratch buffer for packet compression/decompression. */
64 static Buffer compression_buffer;
65
66 /* Flag indicating whether packet compression/decompression is enabled. */
67 static int packet_compression = 0;
68
69 /* Flag indicating whether this module has been initialized. */
70 static int initialized = 0;
71
72 /* Set to true if the connection is interactive. */
73 static int interactive_mode = 0;
74
75 /* Sets the descriptors used for communication.  Disables encryption until
76    packet_set_encryption_key is called. */
77
78 void
79 packet_set_connection(int fd_in, int fd_out)
80 {
81   connection_in = fd_in;
82   connection_out = fd_out;
83   cipher_type = SSH_CIPHER_NONE;
84   cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 1);
85   cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 0);
86   if (!initialized)
87     {
88       initialized = 1;
89       buffer_init(&input);
90       buffer_init(&output);
91       buffer_init(&outgoing_packet);
92       buffer_init(&incoming_packet);
93     }
94
95   /* Kludge: arrange the close function to be called from fatal(). */
96   fatal_add_cleanup((void (*)(void *))packet_close, NULL);
97 }
98
99 /* Sets the connection into non-blocking mode. */
100
101 void
102 packet_set_nonblocking()
103 {
104   /* Set the socket into non-blocking mode. */
105   if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
106     error("fcntl O_NONBLOCK: %.100s", strerror(errno));
107
108   if (connection_out != connection_in)
109     {
110       if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
111         error("fcntl O_NONBLOCK: %.100s", strerror(errno));
112     }
113 }
114
115 /* Returns the socket used for reading. */
116
117 int
118 packet_get_connection_in()
119 {
120   return connection_in;
121 }
122
123 /* Returns the descriptor used for writing. */
124
125 int
126 packet_get_connection_out()
127 {
128   return connection_out;
129 }
130
131 /* Closes the connection and clears and frees internal data structures. */
132
133 void
134 packet_close()
135 {
136   if (!initialized)
137     return;
138   initialized = 0;
139   if (connection_in == connection_out)
140     {
141       shutdown(connection_out, SHUT_RDWR);
142       close(connection_out);
143     }
144   else
145     {
146       close(connection_in);
147       close(connection_out);
148     }
149   buffer_free(&input);
150   buffer_free(&output);
151   buffer_free(&outgoing_packet);
152   buffer_free(&incoming_packet);
153   if (packet_compression)
154     {
155       buffer_free(&compression_buffer);
156       buffer_compress_uninit();
157     }
158 }
159
160 /* Sets remote side protocol flags. */
161
162 void
163 packet_set_protocol_flags(unsigned int protocol_flags)
164 {
165   remote_protocol_flags = protocol_flags;
166   channel_set_options((protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0);
167 }
168
169 /* Returns the remote protocol flags set earlier by the above function. */
170
171 unsigned int
172 packet_get_protocol_flags()
173 {
174   return remote_protocol_flags;
175 }
176
177 /* Starts packet compression from the next packet on in both directions. 
178    Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */
179
180 void
181 packet_start_compression(int level)
182 {
183   if (packet_compression)
184     fatal("Compression already enabled.");
185   packet_compression = 1;
186   buffer_init(&compression_buffer);
187   buffer_compress_init(level);
188 }
189
190 /* Encrypts the given number of bytes, copying from src to dest.
191    bytes is known to be a multiple of 8. */
192
193 void
194 packet_encrypt(CipherContext *cc, void *dest, void *src, 
195                unsigned int bytes)
196 {
197   assert((bytes % 8) == 0);
198   cipher_encrypt(cc, dest, src, bytes);
199 }
200
201 /* Decrypts the given number of bytes, copying from src to dest.
202    bytes is known to be a multiple of 8. */
203
204 void
205 packet_decrypt(CipherContext *cc, void *dest, void *src, 
206                unsigned int bytes)
207 {
208   int i;
209   
210   assert((bytes % 8) == 0);
211   
212   /*
213     Cryptographic attack detector for ssh - Modifications for packet.c 
214     (C)1998 CORE-SDI, Buenos Aires Argentina
215     Ariel Futoransky(futo@core-sdi.com)
216   */
217   switch (cc->type)
218     {
219     case SSH_CIPHER_NONE:
220       i = DEATTACK_OK;
221       break;
222     default:
223       i = detect_attack(src, bytes, NULL);
224       break;
225     }
226   
227   if (i == DEATTACK_DETECTED)
228     packet_disconnect("crc32 compensation attack: network attack detected");
229   
230   cipher_decrypt(cc, dest, src, bytes);
231 }
232
233 /* Causes any further packets to be encrypted using the given key.  The same
234    key is used for both sending and reception.  However, both directions
235    are encrypted independently of each other. */
236
237 void
238 packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
239                           int cipher, int is_client)
240 {
241   cipher_type = cipher;
242   if (cipher == SSH_CIPHER_RC4)
243     {
244       if (is_client)
245         { /* In client: use first half for receiving, second for sending. */
246           cipher_set_key(&receive_context, cipher, key, keylen / 2, 0);
247           cipher_set_key(&send_context, cipher, key + keylen / 2, 
248                          keylen / 2, 1);
249         }
250       else
251         { /* In server: use first half for sending, second for receiving. */
252           cipher_set_key(&receive_context, cipher, key + keylen / 2, 
253                          keylen / 2, 0);
254           cipher_set_key(&send_context, cipher, key, keylen / 2, 1);
255         }
256     }
257   else
258     {
259       /* All other ciphers use the same key in both directions for now. */
260       cipher_set_key(&receive_context, cipher, key, keylen, 0);
261       cipher_set_key(&send_context, cipher, key, keylen, 1);
262     }
263 }
264
265 /* Starts constructing a packet to send. */
266
267 void
268 packet_start(int type)
269 {
270   char buf[9];
271
272   buffer_clear(&outgoing_packet);
273   memset(buf, 0, 8);
274   buf[8] = type;
275   buffer_append(&outgoing_packet, buf, 9);
276 }
277
278 /* Appends a character to the packet data. */
279
280 void
281 packet_put_char(int value)
282 {
283   char ch = value;
284   buffer_append(&outgoing_packet, &ch, 1);
285 }
286
287 /* Appends an integer to the packet data. */
288
289 void
290 packet_put_int(unsigned int value)
291 {
292   buffer_put_int(&outgoing_packet, value);
293 }
294
295 /* Appends a string to packet data. */
296
297 void
298 packet_put_string(const char *buf, unsigned int len)
299 {
300   buffer_put_string(&outgoing_packet, buf, len);
301 }
302
303 /* Appends an arbitrary precision integer to packet data. */
304
305 void
306 packet_put_bignum(BIGNUM *value)
307 {
308   buffer_put_bignum(&outgoing_packet, value);
309 }
310
311 /* Finalizes and sends the packet.  If the encryption key has been set,
312    encrypts the packet before sending. */
313   
314 void
315 packet_send()
316 {
317   char buf[8], *cp;
318   int i, padding, len;
319   unsigned int checksum;
320   u_int32_t rand = 0;
321
322   /* If using packet compression, compress the payload of the outgoing
323      packet. */
324   if (packet_compression)
325     {
326       buffer_clear(&compression_buffer);
327       buffer_consume(&outgoing_packet, 8); /* Skip padding. */
328       buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); /* padding */
329       buffer_compress(&outgoing_packet, &compression_buffer);
330       buffer_clear(&outgoing_packet);
331       buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
332                     buffer_len(&compression_buffer));
333     }
334
335   /* Compute packet length without padding (add checksum, remove padding). */
336   len = buffer_len(&outgoing_packet) + 4 - 8;
337   
338   /* Insert padding. */
339   padding = 8 - len % 8;
340   if (cipher_type != SSH_CIPHER_NONE)
341     {
342       cp = buffer_ptr(&outgoing_packet);
343       for (i = 0; i < padding; i++) {
344         if (i % 4 == 0)
345           rand = arc4random();
346         cp[7 - i] = rand & 0xff;
347         rand >>= 8;
348       }
349     }
350   buffer_consume(&outgoing_packet, 8 - padding);
351   
352   /* Add check bytes. */
353   checksum = crc32((unsigned char *)buffer_ptr(&outgoing_packet),
354                    buffer_len(&outgoing_packet));
355   PUT_32BIT(buf, checksum);
356   buffer_append(&outgoing_packet, buf, 4);
357
358 #ifdef PACKET_DEBUG
359   fprintf(stderr, "packet_send plain: ");
360   buffer_dump(&outgoing_packet);
361 #endif
362
363   /* Append to output. */
364   PUT_32BIT(buf, len);
365   buffer_append(&output, buf, 4);
366   buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
367   packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
368                  buffer_len(&outgoing_packet));
369   
370 #ifdef PACKET_DEBUG
371   fprintf(stderr, "encrypted: "); buffer_dump(&output);
372 #endif
373
374   buffer_clear(&outgoing_packet);
375
376   /* Note that the packet is now only buffered in output.  It won\'t be
377      actually sent until packet_write_wait or packet_write_poll is called. */
378 }
379
380 /* Waits until a packet has been received, and returns its type.  Note that
381    no other data is processed until this returns, so this function should
382    not be used during the interactive session. */
383
384 int
385 packet_read(int *payload_len_ptr)
386 {
387   int type, len;
388   fd_set set;
389   char buf[8192];
390
391   /* Since we are blocking, ensure that all written packets have been sent. */
392   packet_write_wait();
393
394   /* Stay in the loop until we have received a complete packet. */
395   for (;;)
396     {
397       /* Try to read a packet from the buffer. */
398       type = packet_read_poll(payload_len_ptr);
399       if (type == SSH_SMSG_SUCCESS
400           || type == SSH_SMSG_FAILURE
401           || type == SSH_CMSG_EOF
402           || type == SSH_CMSG_EXIT_CONFIRMATION)
403         packet_integrity_check(*payload_len_ptr, 0, type);
404       /* If we got a packet, return it. */
405       if (type != SSH_MSG_NONE)
406         return type;
407       /* Otherwise, wait for some data to arrive, add it to the buffer,
408          and try again. */
409       FD_ZERO(&set);
410       FD_SET(connection_in, &set);
411       /* Wait for some data to arrive. */
412       select(connection_in + 1, &set, NULL, NULL, NULL);
413       /* Read data from the socket. */
414       len = read(connection_in, buf, sizeof(buf));
415       if (len == 0)
416         fatal("Connection closed by remote host.");
417       if (len < 0)
418         fatal("Read from socket failed: %.100s", strerror(errno));
419       /* Append it to the buffer. */
420       packet_process_incoming(buf, len);
421     }
422   /*NOTREACHED*/
423 }
424
425 /* Waits until a packet has been received, verifies that its type matches
426    that given, and gives a fatal error and exits if there is a mismatch. */
427
428 void
429 packet_read_expect(int *payload_len_ptr, int expected_type)
430 {
431   int type;
432
433   type = packet_read(payload_len_ptr);
434   if (type != expected_type)
435     packet_disconnect("Protocol error: expected packet type %d, got %d",
436                       expected_type, type);
437 }
438
439 /* Checks if a full packet is available in the data received so far via
440    packet_process_incoming.  If so, reads the packet; otherwise returns
441    SSH_MSG_NONE.  This does not wait for data from the connection. 
442    
443    SSH_MSG_DISCONNECT is handled specially here.  Also,
444    SSH_MSG_IGNORE messages are skipped by this function and are never returned
445    to higher levels.
446
447    The returned payload_len does include space consumed by:
448    Packet length
449    Padding
450    Packet type
451    Check bytes
452
453    
454    */
455
456 int
457 packet_read_poll(int *payload_len_ptr)
458 {
459   unsigned int len, padded_len;
460   unsigned char *ucp;
461   char buf[8], *cp;
462   unsigned int checksum, stored_checksum;
463   
464  restart:
465
466   /* Check if input size is less than minimum packet size. */
467   if (buffer_len(&input) < 4 + 8)
468     return SSH_MSG_NONE;
469   /* Get length of incoming packet. */
470   ucp = (unsigned char *)buffer_ptr(&input);
471   len = GET_32BIT(ucp);
472   if (len < 1 + 2 + 2 || len > 256*1024)
473     packet_disconnect("Bad packet length %d.", len);
474   padded_len = (len + 8) & ~7;
475
476   /* Check if the packet has been entirely received. */
477   if (buffer_len(&input) < 4 + padded_len)
478     return SSH_MSG_NONE;
479
480   /* The entire packet is in buffer. */
481
482   /* Consume packet length. */
483   buffer_consume(&input, 4);
484
485   /* Copy data to incoming_packet. */
486   buffer_clear(&incoming_packet);
487   buffer_append_space(&incoming_packet, &cp, padded_len);
488   packet_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len);
489   buffer_consume(&input, padded_len);
490
491 #ifdef PACKET_DEBUG
492   fprintf(stderr, "read_poll plain: "); buffer_dump(&incoming_packet);
493 #endif
494   
495   /* Compute packet checksum. */
496   checksum = crc32((unsigned char *)buffer_ptr(&incoming_packet),
497                    buffer_len(&incoming_packet) - 4);
498
499   /* Skip padding. */
500   buffer_consume(&incoming_packet, 8 - len % 8);
501
502   /* Test check bytes. */
503   assert(len == buffer_len(&incoming_packet));
504   ucp = (unsigned char *)buffer_ptr(&incoming_packet) + len - 4;
505   stored_checksum = GET_32BIT(ucp);
506   if (checksum != stored_checksum)
507     packet_disconnect("Corrupted check bytes on input.");
508   buffer_consume_end(&incoming_packet, 4);
509
510   /* If using packet compression, decompress the packet. */
511   if (packet_compression)
512     {
513       buffer_clear(&compression_buffer);
514       buffer_uncompress(&incoming_packet, &compression_buffer);
515       buffer_clear(&incoming_packet);
516       buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
517                     buffer_len(&compression_buffer));
518     }
519
520   /* Get packet type. */
521   buffer_get(&incoming_packet, &buf[0], 1);
522
523   /* Return length of payload (without type field). */
524   *payload_len_ptr = buffer_len(&incoming_packet);
525
526   /* Handle disconnect message. */
527   if ((unsigned char)buf[0] == SSH_MSG_DISCONNECT)
528     fatal("%.900s", packet_get_string(NULL));
529
530   /* Ignore ignore messages. */
531   if ((unsigned char)buf[0] == SSH_MSG_IGNORE)
532     goto restart;
533
534   /* Send debug messages as debugging output. */
535   if ((unsigned char)buf[0] == SSH_MSG_DEBUG)
536     {
537       debug("Remote: %.900s", packet_get_string(NULL));
538       goto restart;
539     }
540
541   /* Return type. */
542   return (unsigned char)buf[0];
543 }
544   
545 /* Buffers the given amount of input characters.  This is intended to be
546    used together with packet_read_poll. */
547
548 void
549 packet_process_incoming(const char *buf, unsigned int len)
550 {
551   buffer_append(&input, buf, len);
552 }
553
554 /* Returns a character from the packet. */
555
556 unsigned int
557 packet_get_char()
558 {
559   char ch;
560   buffer_get(&incoming_packet, &ch, 1);
561   return (unsigned char)ch;
562 }
563
564 /* Returns an integer from the packet data. */
565
566 unsigned int
567 packet_get_int()
568 {
569   return buffer_get_int(&incoming_packet);
570 }
571
572 /* Returns an arbitrary precision integer from the packet data.  The integer
573    must have been initialized before this call. */
574
575 void
576 packet_get_bignum(BIGNUM *value, int *length_ptr)
577 {
578   *length_ptr = buffer_get_bignum(&incoming_packet, value);
579 }
580
581 /* Returns a string from the packet data.  The string is allocated using
582    xmalloc; it is the responsibility of the calling program to free it when
583    no longer needed.  The length_ptr argument may be NULL, or point to an
584    integer into which the length of the string is stored. */
585
586 char
587 *packet_get_string(unsigned int *length_ptr)
588 {
589   return buffer_get_string(&incoming_packet, length_ptr);
590 }
591
592 /* Sends a diagnostic message from the server to the client.  This message
593    can be sent at any time (but not while constructing another message).
594    The message is printed immediately, but only if the client is being
595    executed in verbose mode.  These messages are primarily intended to
596    ease debugging authentication problems.   The length of the formatted
597    message must not exceed 1024 bytes.  This will automatically call
598    packet_write_wait. */
599
600 void
601 packet_send_debug(const char *fmt, ...)
602 {
603   char buf[1024];
604   va_list args;
605   
606   va_start(args, fmt);
607   vsnprintf(buf, sizeof(buf), fmt, args);
608   va_end(args);
609   
610   packet_start(SSH_MSG_DEBUG);
611   packet_put_string(buf, strlen(buf));
612   packet_send();
613   packet_write_wait();
614 }
615
616 /* Logs the error plus constructs and sends a disconnect
617    packet, closes the connection, and exits.  This function never returns.
618    The error message should not contain a newline.  The length of the
619    formatted message must not exceed 1024 bytes. */
620
621 void
622 packet_disconnect(const char *fmt, ...)
623 {
624   char buf[1024];
625   va_list args;
626   static int disconnecting = 0;
627   if (disconnecting) /* Guard against recursive invocations. */
628     fatal("packet_disconnect called recursively.");
629   disconnecting = 1;
630
631   /* Format the message.  Note that the caller must make sure the message
632      is of limited size. */
633   va_start(args, fmt);
634   vsnprintf(buf, sizeof(buf), fmt, args);
635   va_end(args);
636
637   /* Send the disconnect message to the other side, and wait for it to get 
638      sent. */
639   packet_start(SSH_MSG_DISCONNECT);
640   packet_put_string(buf, strlen(buf));
641   packet_send();
642   packet_write_wait();
643
644   /* Stop listening for connections. */
645   channel_stop_listening();
646   
647   /* Close the connection. */
648   packet_close();
649
650   /* Display the error locally and exit. */
651   fatal("Local: %.100s", buf);
652 }
653
654 /* Checks if there is any buffered output, and tries to write some of the
655    output. */
656
657 void
658 packet_write_poll()
659 {
660   int len = buffer_len(&output);
661   if (len > 0)
662     {
663       len = write(connection_out, buffer_ptr(&output), len);
664       if (len <= 0) {
665         if (errno == EAGAIN)
666           return;
667         else
668           fatal("Write failed: %.100s", strerror(errno));
669       }
670       buffer_consume(&output, len);
671     }
672 }
673
674 /* Calls packet_write_poll repeatedly until all pending output data has
675    been written. */
676
677 void
678 packet_write_wait()
679 {
680   packet_write_poll();
681   while (packet_have_data_to_write())
682     {
683       fd_set set;
684       FD_ZERO(&set);
685       FD_SET(connection_out, &set);
686       select(connection_out + 1, NULL, &set, NULL, NULL);
687       packet_write_poll();
688     }
689 }
690
691 /* Returns true if there is buffered data to write to the connection. */
692
693 int
694 packet_have_data_to_write()
695 {
696   return buffer_len(&output) != 0;
697 }
698
699 /* Returns true if there is not too much data to write to the connection. */
700
701 int
702 packet_not_very_much_data_to_write()
703 {
704   if (interactive_mode)
705     return buffer_len(&output) < 16384;
706   else
707     return buffer_len(&output) < 128*1024;
708 }
709
710 /* Informs that the current session is interactive.  Sets IP flags for that. */
711
712 void
713 packet_set_interactive(int interactive, int keepalives)
714 {
715   int on = 1;
716
717   /* Record that we are in interactive mode. */
718   interactive_mode = interactive;
719
720   /* Only set socket options if using a socket (as indicated by the descriptors
721      being the same). */
722   if (connection_in != connection_out)
723     return;
724
725   if (keepalives)
726     {
727       /* Set keepalives if requested. */
728       if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, 
729                      sizeof(on)) < 0)
730         error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
731     }
732
733   if (interactive)
734     {
735       /* Set IP options for an interactive connection.  Use IPTOS_LOWDELAY
736          and TCP_NODELAY. */
737       int lowdelay = IPTOS_LOWDELAY;
738       if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&lowdelay, 
739                      sizeof(lowdelay)) < 0)
740         error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno));
741       if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&on, 
742                      sizeof(on)) < 0)
743         error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
744     }
745   else
746     {
747       /* Set IP options for a non-interactive connection.  Use 
748          IPTOS_THROUGHPUT. */
749       int throughput = IPTOS_THROUGHPUT;
750       if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&throughput, 
751                      sizeof(throughput)) < 0)
752         error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
753     }
754 }
755
756 /* Returns true if the current connection is interactive. */
757
758 int
759 packet_is_interactive()
760 {
761   return interactive_mode;
762 }
This page took 0.092015 seconds and 5 git commands to generate.