99b4108a398128ff014d8d747d49936ba0aa6449
[obnox/samba/samba-obnox.git] / source4 / auth / gensec / socket.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    GENSEC socket interface
5
6    Copyright (C) Andrew Bartlett 2006
7  
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/events/events.h"
24 #include "lib/socket/socket.h"
25 #include "lib/stream/packet.h"
26 #include "auth/gensec/gensec.h"
27 #include "auth/gensec/gensec_proto.h"
28 #include "auth/gensec/gensec_socket.h"
29
30 static const struct socket_ops gensec_socket_ops;
31
32 struct gensec_socket {
33         struct gensec_security *gensec_security;
34         struct socket_context *socket;
35         struct tevent_context *ev;
36         struct packet_context *packet;
37         DATA_BLOB read_buffer;  /* SASL packets are turned into liniarlised data here, for reading */
38         size_t orig_send_len;
39         bool eof;
40         NTSTATUS error;
41         bool interrupted;
42         void (*recv_handler)(void *, uint16_t);
43         void *recv_private;
44         int in_extra_read;
45         bool wrap; /* Should we be wrapping on this socket at all? */
46 };
47
48 static NTSTATUS gensec_socket_init_fn(struct socket_context *sock)
49 {
50         switch (sock->type) {
51         case SOCKET_TYPE_STREAM:
52                 break;
53         default:
54                 return NT_STATUS_INVALID_PARAMETER;
55         }
56
57         sock->backend_name = "gensec";
58
59         return NT_STATUS_OK;
60 }
61
62 static NTSTATUS gensec_socket_full_request(void *private_data, DATA_BLOB blob, size_t *size)
63 {
64         struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
65         struct gensec_security *gensec_security = gensec_socket->gensec_security;
66         return gensec_packet_full_request(gensec_security, blob, size);
67 }
68
69 /* Try to figure out how much data is waiting to be read */
70 static NTSTATUS gensec_socket_pending(struct socket_context *sock, size_t *npending) 
71 {
72         struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
73         if (!gensec_socket->wrap) {
74                 return socket_pending(gensec_socket->socket, npending);
75         }
76
77         if (gensec_socket->read_buffer.length > 0) {
78                 *npending = gensec_socket->read_buffer.length;
79                 return NT_STATUS_OK;
80         }
81
82         /* This is a lie.  We hope the decrypted data will always be
83          * less than this value, so the application just gets a short
84          * read.  Without reading and decrypting it, we can't tell.
85          * If the SASL mech does compression, then we just need to
86          * manually trigger read events */
87         return socket_pending(gensec_socket->socket, npending);
88 }      
89
90 /* Note if an error occours, so we can return it up the stack */
91 static void gensec_socket_error_handler(void *private_data, NTSTATUS status)
92 {
93         struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
94         if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
95                 gensec_socket->eof = true;
96         } else {
97                 gensec_socket->error = status;
98         }
99 }
100
101 static void gensec_socket_trigger_read(struct tevent_context *ev, 
102                                        struct tevent_timer *te, 
103                                        struct timeval t, void *private_data)
104 {
105         struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
106
107         gensec_socket->in_extra_read++;
108         gensec_socket->recv_handler(gensec_socket->recv_private, TEVENT_FD_READ);
109         gensec_socket->in_extra_read--;
110
111         /* It may well be that, having run the recv handler, we still
112          * have even more data waiting for us! 
113          */
114         if (gensec_socket->read_buffer.length && gensec_socket->recv_handler) {
115                 /* Schedule this funcion to run again */
116                 tevent_add_timer(gensec_socket->ev, gensec_socket, timeval_zero(), 
117                                 gensec_socket_trigger_read, gensec_socket);
118         }
119 }
120
121 /* These two routines could be changed to use a circular buffer of
122  * some kind, or linked lists, or ... */
123 static NTSTATUS gensec_socket_recv(struct socket_context *sock, void *buf,
124                                    size_t wantlen, size_t *nread) 
125 {
126         struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
127
128         if (!gensec_socket->wrap) {
129                 return socket_recv(gensec_socket->socket, buf, wantlen, nread);
130         }
131
132         gensec_socket->error = NT_STATUS_OK;
133
134         if (gensec_socket->read_buffer.length == 0) {
135                 /* Process any data on the socket, into the read buffer. At
136                  * this point, the socket is not available for read any
137                  * longer */
138                 packet_recv(gensec_socket->packet);
139
140                 if (gensec_socket->eof) {
141                         *nread = 0;
142                         return NT_STATUS_OK;
143                 }
144                 
145                 if (!NT_STATUS_IS_OK(gensec_socket->error)) {
146                         return gensec_socket->error;
147                 }
148
149                 if (gensec_socket->read_buffer.length == 0) {
150                         /* Clearly we don't have the entire SASL packet yet,
151                          * so it has not been written into the buffer */
152                         *nread = 0;
153                         return STATUS_MORE_ENTRIES;
154                 }
155         }
156
157
158         *nread = MIN(wantlen, gensec_socket->read_buffer.length);
159         memcpy(buf, gensec_socket->read_buffer.data, *nread);
160
161         if (gensec_socket->read_buffer.length > *nread) {
162                 memmove(gensec_socket->read_buffer.data, 
163                         gensec_socket->read_buffer.data + *nread, 
164                         gensec_socket->read_buffer.length - *nread);
165         }
166
167         gensec_socket->read_buffer.length -= *nread;
168         gensec_socket->read_buffer.data = talloc_realloc(gensec_socket, 
169                                                          gensec_socket->read_buffer.data, 
170                                                          uint8_t, 
171                                                          gensec_socket->read_buffer.length);
172
173         if (gensec_socket->read_buffer.length && 
174             gensec_socket->in_extra_read == 0 && 
175             gensec_socket->recv_handler) {
176                 /* Manually call a read event, to get this moving
177                  * again (as the socket should be dry, so the normal
178                  * event handler won't trigger) */
179                 tevent_add_timer(gensec_socket->ev, gensec_socket, timeval_zero(), 
180                                 gensec_socket_trigger_read, gensec_socket);
181         }
182
183         return NT_STATUS_OK;
184 }
185
186 /* Completed SASL packet callback.  When we have a 'whole' SASL
187  * packet, decrypt it, and add it to the read buffer
188  *
189  * This function (and anything under it) MUST NOT call the event system
190  */
191 static NTSTATUS gensec_socket_unwrap(void *private_data, DATA_BLOB blob)
192 {
193         struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
194         DATA_BLOB unwrapped;
195         NTSTATUS nt_status;
196         TALLOC_CTX *mem_ctx;
197         size_t packet_size;
198
199         mem_ctx = talloc_new(gensec_socket);
200         if (!mem_ctx) {
201                 return NT_STATUS_NO_MEMORY;
202         }
203         nt_status = gensec_unwrap_packets(gensec_socket->gensec_security, 
204                                           mem_ctx,
205                                           &blob, &unwrapped, 
206                                           &packet_size);
207         if (!NT_STATUS_IS_OK(nt_status)) {
208                 talloc_free(mem_ctx);
209                 return nt_status;
210         }
211
212         if (packet_size != blob.length) {
213                 DEBUG(0, ("gensec_socket_unwrap: Did not consume entire packet!\n"));
214                 talloc_free(mem_ctx);
215                 return NT_STATUS_INTERNAL_ERROR;
216         }
217
218         /* We could change this into a linked list, and have
219          * gensec_socket_recv() and gensec_socket_pending() walk the
220          * linked list */
221
222         if (!data_blob_append(gensec_socket, &gensec_socket->read_buffer, 
223                                      unwrapped.data, unwrapped.length)) {
224                 talloc_free(mem_ctx);
225                 return NT_STATUS_NO_MEMORY;
226         }
227
228         talloc_free(mem_ctx);
229         return NT_STATUS_OK;
230 }
231
232 /* when the data is sent, we know we have not been interrupted */
233 static void send_callback(void *private_data)
234 {
235         struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
236         gensec_socket->interrupted = false;
237 }
238
239 /*
240   send data, but only as much as we allow in one packet.  
241
242   If this returns STATUS_MORE_ENTRIES, the caller must retry with
243   exactly the same data, or a NULL blob.
244 */
245 static NTSTATUS gensec_socket_send(struct socket_context *sock, 
246                                    const DATA_BLOB *blob, size_t *sendlen)
247 {
248         NTSTATUS nt_status;
249         struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
250         DATA_BLOB wrapped;
251         TALLOC_CTX *mem_ctx;
252
253         if (!gensec_socket->wrap) {
254                 return socket_send(gensec_socket->socket, blob, sendlen);
255         }
256
257         *sendlen = 0;
258
259         /* We have have been interupted, so the caller should be
260          * giving us the same data again.  */
261         if (gensec_socket->interrupted) {
262                 packet_queue_run(gensec_socket->packet);
263
264                 if (!NT_STATUS_IS_OK(gensec_socket->error)) {
265                         return gensec_socket->error;
266                 } else if (gensec_socket->interrupted) {
267                         return STATUS_MORE_ENTRIES;
268                 } else {
269                         *sendlen = gensec_socket->orig_send_len;
270                         gensec_socket->orig_send_len = 0;
271                         return NT_STATUS_OK;
272                 }
273         }
274
275         mem_ctx = talloc_new(gensec_socket);
276         if (!mem_ctx) {
277                 return NT_STATUS_NO_MEMORY;
278         }
279
280         nt_status = gensec_wrap_packets(gensec_socket->gensec_security, 
281                                         mem_ctx,
282                                         blob, &wrapped, 
283                                         &gensec_socket->orig_send_len);
284         if (!NT_STATUS_IS_OK(nt_status)) {
285                 talloc_free(mem_ctx);
286                 return nt_status;
287         }
288         
289         gensec_socket->interrupted = true;
290         gensec_socket->error = NT_STATUS_OK;
291
292         nt_status = packet_send_callback(gensec_socket->packet, 
293                                          wrapped,
294                                          send_callback, gensec_socket);
295
296         talloc_free(mem_ctx);
297
298         packet_queue_run(gensec_socket->packet);
299
300         if (!NT_STATUS_IS_OK(gensec_socket->error)) {
301                 return gensec_socket->error;
302         } else if (gensec_socket->interrupted) {
303                 return STATUS_MORE_ENTRIES;
304         } else {
305                 *sendlen = gensec_socket->orig_send_len;
306                 gensec_socket->orig_send_len = 0;
307                 return NT_STATUS_OK;
308         }
309 }
310
311 /* Turn a normal socket into a potentially GENSEC wrapped socket */
312 /* CAREFUL: this function will steal 'current_socket' */
313
314 NTSTATUS gensec_socket_init(struct gensec_security *gensec_security,
315                             TALLOC_CTX *mem_ctx,
316                             struct socket_context *current_socket,
317                             struct tevent_context *ev,
318                             void (*recv_handler)(void *, uint16_t),
319                             void *recv_private,
320                             struct socket_context **new_socket)
321 {
322         struct gensec_socket *gensec_socket;
323         struct socket_context *new_sock;
324         NTSTATUS nt_status;
325
326         nt_status = socket_create_with_ops(mem_ctx, &gensec_socket_ops, &new_sock, 
327                                            SOCKET_TYPE_STREAM, current_socket->flags | SOCKET_FLAG_ENCRYPT);
328         if (!NT_STATUS_IS_OK(nt_status)) {
329                 *new_socket = NULL;
330                 return nt_status;
331         }
332
333         new_sock->state = current_socket->state;
334
335         gensec_socket = talloc(new_sock, struct gensec_socket);
336         if (gensec_socket == NULL) {
337                 *new_socket = NULL;
338                 talloc_free(new_sock);
339                 return NT_STATUS_NO_MEMORY;
340         }
341
342         new_sock->private_data       = gensec_socket;
343         gensec_socket->socket        = current_socket;
344
345         /* Nothing to do here, if we are not actually wrapping on this socket */
346         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL) &&
347             !gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
348                 
349                 gensec_socket->wrap = false;
350                 talloc_steal(gensec_socket, current_socket);
351                 *new_socket = new_sock;
352                 return NT_STATUS_OK;
353         }
354
355         gensec_socket->gensec_security = gensec_security;
356
357         gensec_socket->wrap          = true;
358         gensec_socket->eof           = false;
359         gensec_socket->error         = NT_STATUS_OK;
360         gensec_socket->interrupted   = false;
361         gensec_socket->in_extra_read = 0;
362
363         gensec_socket->read_buffer   = data_blob(NULL, 0);
364
365         gensec_socket->recv_handler  = recv_handler;
366         gensec_socket->recv_private  = recv_private;
367         gensec_socket->ev            = ev;
368
369         gensec_socket->packet = packet_init(gensec_socket);
370         if (gensec_socket->packet == NULL) {
371                 *new_socket = NULL;
372                 talloc_free(new_sock);
373                 return NT_STATUS_NO_MEMORY;
374         }
375
376         packet_set_private(gensec_socket->packet, gensec_socket);
377         packet_set_socket(gensec_socket->packet, gensec_socket->socket);
378         packet_set_callback(gensec_socket->packet, gensec_socket_unwrap);
379         packet_set_full_request(gensec_socket->packet, gensec_socket_full_request);
380         packet_set_error_handler(gensec_socket->packet, gensec_socket_error_handler);
381         packet_set_serialise(gensec_socket->packet);
382
383         /* TODO: full-request that knows about maximum packet size */
384
385         talloc_steal(gensec_socket, current_socket);
386         *new_socket = new_sock;
387         return NT_STATUS_OK;
388 }
389
390
391 static NTSTATUS gensec_socket_set_option(struct socket_context *sock, const char *option, const char *val)
392 {
393         set_socket_options(socket_get_fd(sock), option);
394         return NT_STATUS_OK;
395 }
396
397 static char *gensec_socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
398 {
399         struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
400         return socket_get_peer_name(gensec->socket, mem_ctx);
401 }
402
403 static struct socket_address *gensec_socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
404 {
405         struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
406         return socket_get_peer_addr(gensec->socket, mem_ctx);
407 }
408
409 static struct socket_address *gensec_socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
410 {
411         struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
412         return socket_get_my_addr(gensec->socket, mem_ctx);
413 }
414
415 static int gensec_socket_get_fd(struct socket_context *sock)
416 {
417         struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
418         return socket_get_fd(gensec->socket);
419 }
420
421 static const struct socket_ops gensec_socket_ops = {
422         .name                   = "gensec",
423         .fn_init                = gensec_socket_init_fn,
424         .fn_recv                = gensec_socket_recv,
425         .fn_send                = gensec_socket_send,
426         .fn_pending             = gensec_socket_pending,
427
428         .fn_set_option          = gensec_socket_set_option,
429
430         .fn_get_peer_name       = gensec_socket_get_peer_name,
431         .fn_get_peer_addr       = gensec_socket_get_peer_addr,
432         .fn_get_my_addr         = gensec_socket_get_my_addr,
433         .fn_get_fd              = gensec_socket_get_fd
434 };
435