transport.h 9.84 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* transport.h
 *
 * Interface for the ssh transport protocol.
 */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 2005 Niels Möller
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

Niels Möller's avatar
Niels Möller committed
25
26
27
28
29
30
31
32
33
34
35
/* The transport layer, for both server (lshd) and client
   (lsh-transport), speaks the ssh protocol on one end (two fd:s), and
   clear-text ssh packets on the other end.
   
    --------+           +-----------+           +--------
            |  -------> | SSH       | --------> |
    Network |    SSH    | transport | Cleartext | Application
            |  <------- | protocol  | <-------- |
    --------+           +-----------+           +--------

   We use non-blocking mode for i/o, with essentially a single-packet
36
   read buffer for each fd. Write buffers are larger, to avoid
Niels Möller's avatar
Niels Möller committed
37
38
   deadlock in the conversation with the remote peer. To stop buffers
   from filling up, whenever the write-buffer for the encrypted
39
40
41
42
43
44
45
46
47
48
49
   channel is getting full, we stop reading from the unencrypted
   channel, and vice versa.

   The write buffer for encrypted packets can also fill up with
   transport-layer packets generated in response to received encrypted
   packets. E.g, when receiving a KEXINIT message we need to reply to
   it directly; it is not passed to the application. We reserve buffer
   space of SSH_MAX_TRANSPORT_RESPONSE for such responses, and stop
   reading unencrypted data when less space than this is available in
   the buffer. If the buffer is filled up completely in spite of this
   margin, we disconnect.
Niels Möller's avatar
Niels Möller committed
50
51
*/

52
53
#ifndef LSH_TRANSPORT_H_INCLUDED
#define LSH_TRANSPORT_H_INCLUDED
54

Niels Möller's avatar
Niels Möller committed
55
#include "compress.h"
56
#include "crypto.h"
57
#include "keyexchange.h"
Niels Möller's avatar
Niels Möller committed
58
#include "resource.h"
59
#include "ssh_read.h"
60
#include "ssh_write.h"
Niels Möller's avatar
Niels Möller committed
61

Niels Möller's avatar
Niels Möller committed
62
63
64
struct transport_read_state;
struct transport_connection;

Niels Möller's avatar
Niels Möller committed
65
66
67
68
enum transport_event {
  /* Initial keyexchange complete, time to transmit or accept a
     service request */
  TRANSPORT_EVENT_KEYEXCHANGE_COMPLETE,
69
  /* Connection is being closed. */
70
  TRANSPORT_EVENT_CLOSE,
71
72
73
  /* Push through any buffered data; no more is arriving on the ssh
     connection. */
  TRANSPORT_EVENT_PUSH,
74
  /* Transport buffer non-empty, or key exchange in progress. New
75
     application data is not allowed. */
Niels Möller's avatar
Niels Möller committed
76
77
78
79
80
  TRANSPORT_EVENT_STOP_APPLICATION,
  /* Transport buffer empty again, new data is encouraged */
  TRANSPORT_EVENT_START_APPLICATION,
};

81
82
83
84
#define GABA_DECLARE
# include "transport.h.x"
#undef GABA_DECLARE

Niels Möller's avatar
Niels Möller committed
85
86
87
struct transport_read_state *
make_transport_read_state(void);

88
89
90
91
92
/* FIXME: 1. Some of more of this could perhaps be generalized to work
   with the service reader too. 2. It would be desirable to get the
   push indication together with the last read packet. To get that to
   work, the reader must be able to decrypt the next packet header. To
   do this, the handling of SSH_MSG_NEWKEYS must be moved down to the
93
94
   reader layer, which does make some sense. */

95
enum ssh_read_status
Niels Möller's avatar
Niels Möller committed
96
97
98
99
transport_read_line(struct transport_read_state *self, int fd,
		    int *error, const char **msg,
		    uint32_t *length, const uint8_t **line);

100
enum ssh_read_status
Niels Möller's avatar
Niels Möller committed
101
102
103
transport_read_packet(struct transport_read_state *self, int fd,
		      int *error, const char **msg,
		      uint32_t *seqno,
104
		      uint32_t *length, struct lsh_string *packet);
Niels Möller's avatar
Niels Möller committed
105
106
107
108
109
110
111
112

void
transport_read_new_keys(struct transport_read_state *self,
			struct mac_instance *mac,
			struct crypto_instance *crypto,
			struct compress_instance *inflate);


113
114
115
116
117
/* GABA:
   (class
     (name transport_write_state)
     (super ssh_write_state)
     (vars     
118
       ; The preferred packet size, and amount of data we try to
119
       ; collect before actually writing anything.
120
121
122
       (threshold . uint32_t)
       ; Amount of unimportant data at end of buffer
       (ignore . uint32_t)
123
124
125
126
127
128
       (mac object mac_instance)
       (crypto object crypto_instance)
       (deflate object compress_instance)
       (seqno . uint32_t)))
*/

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Error codes are negative */
enum transport_write_status
{
  /* I/O error (see errno) */
  TRANSPORT_WRITE_IO_ERROR = -1,
  /* Buffer grew too large */
  TRANSPORT_WRITE_OVERFLOW = -2,
  /* All buffered data (except ignore data) written successfully. */
  TRANSPORT_WRITE_COMPLETE = 1,
  /* Buffered data still pending; call transport_write_flush. */
  TRANSPORT_WRITE_PENDING = 2
};

enum transport_write_flag
{
  TRANSPORT_WRITE_FLAG_PUSH = 1,
  TRANSPORT_WRITE_FLAG_IGNORE = 2,
};

Niels Möller's avatar
Niels Möller committed
148
struct transport_write_state *
Niels Möller's avatar
Niels Möller committed
149
150
make_transport_write_state(void);

151
enum transport_write_status
152
transport_write_packet(struct transport_write_state *self,
153
		       int fd, enum transport_write_flag flags,
154
		       struct lsh_string *packet);
Niels Möller's avatar
Niels Möller committed
155

156
enum transport_write_status
Niels Möller's avatar
Niels Möller committed
157
158
159
160
161
162
163
164
165
166
transport_write_line(struct transport_write_state *self,
		     int fd,
		     struct lsh_string *line);

void
transport_write_new_keys(struct transport_write_state *self,
			 struct mac_instance *mac,
			 struct crypto_instance *crypto,
			 struct compress_instance *deflate);

Niels Möller's avatar
Niels Möller committed
167
168
/* Attempt to send pending data, and maybe add an extra SSH_MSG_IGNORE
   packet */
169
enum transport_write_status
170
transport_write_flush(struct transport_write_state *self,
171
		      int fd);
Niels Möller's avatar
Niels Möller committed
172
173

/* Fixed state used by all connections. */
174
175
/* GABA:
   (class
Niels Möller's avatar
Niels Möller committed
176
     (name transport_context)
177
     (vars
178
       (is_server . int)
Niels Möller's avatar
Niels Möller committed
179
       (algorithms object alist)
180
       (kexinit object make_kexinit)))
181
182
*/

Niels Möller's avatar
Niels Möller committed
183
/* Uses for the key exchange method */
Niels Möller's avatar
Niels Möller committed
184

185
186
/* GABA:
   (class
Niels Möller's avatar
Niels Möller committed
187
     (name transport_handler)
188
     (vars
Niels Möller's avatar
Niels Möller committed
189
190
191
       (handler method void
		       "struct transport_connection *connection"
		       "uint32_t length" "const uint8_t *packet")))
192
193
*/

Niels Möller's avatar
Niels Möller committed
194

195
196
197
198
199
/* GABA:
   (class
     (name transport_connection)
     (super resource)
     (vars
Niels Möller's avatar
Niels Möller committed
200
       (ctx object transport_context)
201

202
203
       ; Key exchange
       ; The state for the receiving direction is reflected by kex.state
204
       (kex struct kexinit_state)
205
       
206
207
       (session_id string)
       ; Packet handler for the keyexchange range of messages
Niels Möller's avatar
Niels Möller committed
208
       (keyexchange_handler object transport_handler)
209
       ; New state to be taken into use after NEWKEYS
Niels Möller's avatar
Niels Möller committed
210
211
       (new_mac object mac_instance)
       (new_crypto object crypto_instance)
212
       (new_inflate object compress_instance)
Niels Möller's avatar
Niels Möller committed
213

214
215
       ; Timer for kexexchange, reexchange, and disconnect
       (expire object resource)
Niels Möller's avatar
Niels Möller committed
216

217
218
219
220
       ; Receiving encrypted packets
       ; Input fd for the ssh connection
       (ssh_input . int)
       (reader object transport_read_state)
221
       (read_active . int)
222
223
224
225
226
227
228
       ; Buffer for the latest read packet.
       (read_packet string)
       ; If non-zero, we should let the application process the
       ; previous packet again.
       (retry_length . uint32_t)
       (retry_seqno . uint32_t)
       
229
230
231
       ; Sending encrypted packets
       ; Output fd for the ssh connection, ; may equal ssh_input
       (ssh_output . int)
Niels Möller's avatar
Niels Möller committed
232
       (writer object transport_write_state)
233
       (write_active . int)
234
235
236
237
238
       ; Space we want to have left in the write buffer. We need space
       ; for one full packet, plus transport level responses such as
       ; KEXINIT, KEXDH_INIT, KEXDH_REPLY and UNIMPLEMENTED.
       (write_margin . uint32_t)
       
239
240
241
       ; If non-zero, it's the number of buffers that we are waiting on.
       (closing . unsigned)

242
       (event_handler method void "enum transport_event event")
243
244
245
246

       ; Handles all non-transport messages. Returns 1 on success, or
       ; 0 if the application's buffers are full. FIXME: Call should
       ; include a push indication.
247
       (packet_handler method int "uint32_t seqno" "uint32_t length"
Niels Möller's avatar
Niels Möller committed
248
249
250
                                   "const uint8_t *packet")
       (line_handler method void "uint32_t length"
                                 "const uint8_t *line")))
251
252
253
254
*/

void
init_transport_connection(struct transport_connection *self,
Niels Möller's avatar
Niels Möller committed
255
256
257
			  void (*kill)(struct resource *s),
			  struct transport_context *ctx,
			  int ssh_input, int ssh_output,
258
259
			  void (*event)(struct transport_connection *,
					enum transport_event event));
260
261

void
262
transport_connection_kill(struct transport_connection *connection);
263

Niels Möller's avatar
Niels Möller committed
264
/* If flush is 1, try sending buffered data before closing. */
265
void
Niels Möller's avatar
Niels Möller committed
266
transport_close(struct transport_connection *self, int flush);
267
268

void
269
transport_send_packet(struct transport_connection *connection,
270
		      enum transport_write_flag flags, struct lsh_string *packet);
271
272

void
Niels Möller's avatar
Niels Möller committed
273
transport_write_pending(struct transport_connection *connection, int pending);
Niels Möller's avatar
Niels Möller committed
274

275
276
277
278
279
280
void
transport_start_read(struct transport_connection *connection);

void
transport_stop_read(struct transport_connection *connection);

281
282
283
284
285
286
287
void
transport_disconnect(struct transport_connection *connection,
		     int reason, const uint8_t *msg);

#define transport_protocol_error(connection, msg) \
  transport_disconnect((connection), SSH_DISCONNECT_PROTOCOL_ERROR, (msg))

Niels Möller's avatar
Niels Möller committed
288
289
290
void
transport_kexinit_handler(struct transport_connection *connection,
			  uint32_t length, const uint8_t *packet);
291

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
void
transport_send_kexinit(struct transport_connection *connection);

void
transport_keyexchange_finish(struct transport_connection *connection,
			     const struct hash_algorithm *H,
			     struct lsh_string *exchange_hash,
			     struct lsh_string *K);

void
transport_handshake(struct transport_connection *connection,
		    struct lsh_string *version,
		    void (*line_handler)
		      (struct transport_connection *connection,
		       uint32_t length,
		       const uint8_t *line));

309
#endif /* LSH_TRANSPORT_H_INCLUDED */