Merge branch 'master' of ssh://git.samba.org/data/git/samba into selftest
[tprouty/samba.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
29 static const struct socket_ops gensec_socket_ops;
30
31 struct gensec_socket {
32         struct gensec_security *gensec_security;
33         struct socket_context *socket;
34         struct event_context *ev;
35         struct packet_context *packet;
36         DATA_BLOB read_buffer;  /* SASL packets are turned into liniarlised data here, for reading */
37         size_t orig_send_len;
38         bool eof;
39         NTSTATUS error;
40         bool interrupted;
41         void (*recv_handler)(void *, uint16_t);
42         void *recv_private;
43         int in_extra_read;
44         bool wrap; /* Should we be wrapping on this socket at all? */
45 };
46
47 static NTSTATUS gensec_socket_init_fn(struct socket_context *sock)
48 {
49         switch (sock->type) {
50         case SOCKET_TYPE_STREAM:
51                 break;
52         default:
53                 return NT_STATUS_INVALID_PARAMETER;
54         }
55
56         sock->backend_name = "gensec";
57
58         return NT_STATUS_OK;
59 }
60
61 /* These functions are for use here only (public because SPNEGO must
62  * use them for recursion) */
63 _PUBLIC_ NTSTATUS gensec_wrap_packets(struct gensec_security *gensec_security, 
64                              TALLOC_CTX *mem_ctx, 
65                              const DATA_BLOB *in, 
66                              DATA_BLOB *out,
67                              size_t *len_processed) 
68 {
69         if (!gensec_security->ops->wrap_packets) {
70                 NTSTATUS nt_status;
71                 size_t max_input_size;
72                 DATA_BLOB unwrapped, wrapped;
73                 max_input_size = gensec_max_input_size(gensec_security);
74                 unwrapped = data_blob_const(in->data, MIN(max_input_size, (size_t)in->length));
75                 
76                 nt_status = gensec_wrap(gensec_security, 
77                                         mem_ctx,
78                                         &unwrapped, &wrapped);
79                 if (!NT_STATUS_IS_OK(nt_status)) {
80                         talloc_free(mem_ctx);
81                         return nt_status;
82                 }
83                 
84                 *out = data_blob_talloc(mem_ctx, NULL, 4);
85                 if (!out->data) {
86                         return NT_STATUS_NO_MEMORY;
87                 }
88                 RSIVAL(out->data, 0, wrapped.length);
89                 
90                 if (!data_blob_append(mem_ctx, out, wrapped.data, wrapped.length)) {
91                         return NT_STATUS_NO_MEMORY;
92                 }
93                 *len_processed = unwrapped.length;
94                 return NT_STATUS_OK;
95         }
96         return gensec_security->ops->wrap_packets(gensec_security, mem_ctx, in, out,
97                                                   len_processed);
98 }
99
100 /* These functions are for use here only (public because SPNEGO must
101  * use them for recursion) */
102 NTSTATUS gensec_unwrap_packets(struct gensec_security *gensec_security, 
103                                         TALLOC_CTX *mem_ctx, 
104                                         const DATA_BLOB *in, 
105                                         DATA_BLOB *out,
106                                         size_t *len_processed) 
107 {
108         if (!gensec_security->ops->unwrap_packets) {
109                 DATA_BLOB wrapped;
110                 NTSTATUS nt_status;
111                 size_t packet_size;
112                 if (in->length < 4) {
113                         /* Missing the header we already had! */
114                         DEBUG(0, ("Asked to unwrap packet of bogus length!  How did we get the short packet?!\n"));
115                         return NT_STATUS_INVALID_PARAMETER;
116                 }
117                 
118                 packet_size = RIVAL(in->data, 0);
119                 
120                 wrapped = data_blob_const(in->data + 4, packet_size);
121                 
122                 if (wrapped.length > (in->length - 4)) {
123                         DEBUG(0, ("Asked to unwrap packed of bogus length %d > %d!  How did we get this?!\n",
124                                   (int)wrapped.length, (int)(in->length - 4)));
125                         return NT_STATUS_INTERNAL_ERROR;
126                 }
127                 
128                 nt_status = gensec_unwrap(gensec_security, 
129                                           mem_ctx,
130                                           &wrapped, out);
131                 if (!NT_STATUS_IS_OK(nt_status)) {
132                         return nt_status;
133                 }
134                 
135                 *len_processed = packet_size + 4;
136                 return nt_status;
137         }
138         return gensec_security->ops->unwrap_packets(gensec_security, mem_ctx, in, out,
139                                                     len_processed);
140 }
141
142 /* These functions are for use here only (public because SPNEGO must
143  * use them for recursion) */
144 NTSTATUS gensec_packet_full_request(struct gensec_security *gensec_security,
145                                     DATA_BLOB blob, size_t *size) 
146 {
147         if (gensec_security->ops->packet_full_request) {
148                 return gensec_security->ops->packet_full_request(gensec_security,
149                                                                  blob, size);
150         }
151         if (gensec_security->ops->unwrap_packets) {
152                 if (blob.length) {
153                         *size = blob.length;
154                         return NT_STATUS_OK;
155                 }
156                 return STATUS_MORE_ENTRIES;
157         }
158         return packet_full_request_u32(NULL, blob, size);
159 }
160
161 static NTSTATUS gensec_socket_full_request(void *private, DATA_BLOB blob, size_t *size) 
162 {
163         struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
164         struct gensec_security *gensec_security = gensec_socket->gensec_security;
165         return gensec_packet_full_request(gensec_security, blob, size);
166 }
167
168 /* Try to figure out how much data is waiting to be read */
169 static NTSTATUS gensec_socket_pending(struct socket_context *sock, size_t *npending) 
170 {
171         struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
172         if (!gensec_socket->wrap) {
173                 return socket_pending(gensec_socket->socket, npending);
174         }
175
176         if (gensec_socket->read_buffer.length > 0) {
177                 *npending = gensec_socket->read_buffer.length;
178                 return NT_STATUS_OK;
179         }
180
181         /* This is a lie.  We hope the decrypted data will always be
182          * less than this value, so the application just gets a short
183          * read.  Without reading and decrypting it, we can't tell.
184          * If the SASL mech does compression, then we just need to
185          * manually trigger read events */
186         return socket_pending(gensec_socket->socket, npending);
187 }      
188
189 /* Note if an error occours, so we can return it up the stack */
190 static void gensec_socket_error_handler(void *private, NTSTATUS status)
191 {
192         struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
193         if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
194                 gensec_socket->eof = true;
195         } else {
196                 gensec_socket->error = status;
197         }
198 }
199
200 static void gensec_socket_trigger_read(struct event_context *ev, 
201                                        struct timed_event *te, 
202                                        struct timeval t, void *private)
203 {
204         struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
205
206         gensec_socket->in_extra_read++;
207         gensec_socket->recv_handler(gensec_socket->recv_private, EVENT_FD_READ);
208         gensec_socket->in_extra_read--;
209
210         /* It may well be that, having run the recv handler, we still
211          * have even more data waiting for us! 
212          */
213         if (gensec_socket->read_buffer.length && gensec_socket->recv_handler) {
214                 /* Schedule this funcion to run again */
215                 event_add_timed(gensec_socket->ev, gensec_socket, timeval_zero(), 
216                                 gensec_socket_trigger_read, gensec_socket);
217         }
218 }
219
220 /* These two routines could be changed to use a circular buffer of
221  * some kind, or linked lists, or ... */
222 static NTSTATUS gensec_socket_recv(struct socket_context *sock, void *buf,
223                                    size_t wantlen, size_t *nread) 
224 {
225         struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
226
227         if (!gensec_socket->wrap) {
228                 return socket_recv(gensec_socket->socket, buf, wantlen, nread);
229         }
230
231         gensec_socket->error = NT_STATUS_OK;
232
233         if (gensec_socket->read_buffer.length == 0) {
234                 /* Process any data on the socket, into the read buffer. At
235                  * this point, the socket is not available for read any
236                  * longer */
237                 packet_recv(gensec_socket->packet);
238
239                 if (gensec_socket->eof) {
240                         *nread = 0;
241                         return NT_STATUS_OK;
242                 }
243                 
244                 if (!NT_STATUS_IS_OK(gensec_socket->error)) {
245                         return gensec_socket->error;
246                 }
247
248                 if (gensec_socket->read_buffer.length == 0) {
249                         /* Clearly we don't have the entire SASL packet yet,
250                          * so it has not been written into the buffer */
251                         *nread = 0;
252                         return STATUS_MORE_ENTRIES;
253                 }
254         }
255
256
257         *nread = MIN(wantlen, gensec_socket->read_buffer.length);
258         memcpy(buf, gensec_socket->read_buffer.data, *nread);
259
260         if (gensec_socket->read_buffer.length > *nread) {
261                 memmove(gensec_socket->read_buffer.data, 
262                         gensec_socket->read_buffer.data + *nread, 
263                         gensec_socket->read_buffer.length - *nread);
264         }
265
266         gensec_socket->read_buffer.length -= *nread;
267         gensec_socket->read_buffer.data = talloc_realloc(gensec_socket, 
268                                                          gensec_socket->read_buffer.data, 
269                                                          uint8_t, 
270                                                          gensec_socket->read_buffer.length);
271
272         if (gensec_socket->read_buffer.length && 
273             gensec_socket->in_extra_read == 0 && 
274             gensec_socket->recv_handler) {
275                 /* Manually call a read event, to get this moving
276                  * again (as the socket should be dry, so the normal
277                  * event handler won't trigger) */
278                 event_add_timed(gensec_socket->ev, gensec_socket, timeval_zero(), 
279                                 gensec_socket_trigger_read, gensec_socket);
280         }
281
282         return NT_STATUS_OK;
283 }
284
285 /* Completed SASL packet callback.  When we have a 'whole' SASL
286  * packet, decrypt it, and add it to the read buffer
287  *
288  * This function (and anything under it) MUST NOT call the event system
289  */
290 static NTSTATUS gensec_socket_unwrap(void *private, DATA_BLOB blob)
291 {
292         struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
293         DATA_BLOB unwrapped;
294         NTSTATUS nt_status;
295         TALLOC_CTX *mem_ctx;
296         size_t packet_size;
297
298         mem_ctx = talloc_new(gensec_socket);
299         if (!mem_ctx) {
300                 return NT_STATUS_NO_MEMORY;
301         }
302         nt_status = gensec_unwrap_packets(gensec_socket->gensec_security, 
303                                           mem_ctx,
304                                           &blob, &unwrapped, 
305                                           &packet_size);
306         if (!NT_STATUS_IS_OK(nt_status)) {
307                 talloc_free(mem_ctx);
308                 return nt_status;
309         }
310
311         if (packet_size != blob.length) {
312                 DEBUG(0, ("gensec_socket_unwrap: Did not consume entire packet!\n"));
313                 talloc_free(mem_ctx);
314                 return NT_STATUS_INTERNAL_ERROR;
315         }
316
317         /* We could change this into a linked list, and have
318          * gensec_socket_recv() and gensec_socket_pending() walk the
319          * linked list */
320
321         if (!data_blob_append(gensec_socket, &gensec_socket->read_buffer, 
322                                      unwrapped.data, unwrapped.length)) {
323                 talloc_free(mem_ctx);
324                 return NT_STATUS_NO_MEMORY;
325         }
326
327         talloc_free(mem_ctx);
328         return NT_STATUS_OK;
329 }
330
331 /* when the data is sent, we know we have not been interrupted */
332 static void send_callback(void *private) 
333 {
334         struct gensec_socket *gensec_socket = talloc_get_type(private, struct gensec_socket);
335         gensec_socket->interrupted = false;
336 }
337
338 /*
339   send data, but only as much as we allow in one packet.  
340
341   If this returns STATUS_MORE_ENTRIES, the caller must retry with
342   exactly the same data, or a NULL blob.
343 */
344 static NTSTATUS gensec_socket_send(struct socket_context *sock, 
345                                    const DATA_BLOB *blob, size_t *sendlen)
346 {
347         NTSTATUS nt_status;
348         struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
349         DATA_BLOB wrapped;
350         TALLOC_CTX *mem_ctx;
351
352         if (!gensec_socket->wrap) {
353                 return socket_send(gensec_socket->socket, blob, sendlen);
354         }
355
356         *sendlen = 0;
357
358         /* We have have been interupted, so the caller should be
359          * giving us the same data again.  */
360         if (gensec_socket->interrupted) {
361                 packet_queue_run(gensec_socket->packet);
362
363                 if (!NT_STATUS_IS_OK(gensec_socket->error)) {
364                         return gensec_socket->error;
365                 } else if (gensec_socket->interrupted) {
366                         return STATUS_MORE_ENTRIES;
367                 } else {
368                         *sendlen = gensec_socket->orig_send_len;
369                         gensec_socket->orig_send_len = 0;
370                         return NT_STATUS_OK;
371                 }
372         }
373
374         mem_ctx = talloc_new(gensec_socket);
375         if (!mem_ctx) {
376                 return NT_STATUS_NO_MEMORY;
377         }
378
379         nt_status = gensec_wrap_packets(gensec_socket->gensec_security, 
380                                         mem_ctx,
381                                         blob, &wrapped, 
382                                         &gensec_socket->orig_send_len);
383         if (!NT_STATUS_IS_OK(nt_status)) {
384                 talloc_free(mem_ctx);
385                 return nt_status;
386         }
387         
388         gensec_socket->interrupted = true;
389         gensec_socket->error = NT_STATUS_OK;
390
391         nt_status = packet_send_callback(gensec_socket->packet, 
392                                          wrapped,
393                                          send_callback, gensec_socket);
394
395         talloc_free(mem_ctx);
396
397         packet_queue_run(gensec_socket->packet);
398
399         if (!NT_STATUS_IS_OK(gensec_socket->error)) {
400                 return gensec_socket->error;
401         } else if (gensec_socket->interrupted) {
402                 return STATUS_MORE_ENTRIES;
403         } else {
404                 *sendlen = gensec_socket->orig_send_len;
405                 gensec_socket->orig_send_len = 0;
406                 return NT_STATUS_OK;
407         }
408 }
409
410 /* Turn a normal socket into a potentially GENSEC wrapped socket */
411 /* CAREFUL: this function will steal 'current_socket' */
412
413 NTSTATUS gensec_socket_init(struct gensec_security *gensec_security,
414                             TALLOC_CTX *mem_ctx,
415                             struct socket_context *current_socket,
416                             struct event_context *ev,
417                             void (*recv_handler)(void *, uint16_t),
418                             void *recv_private,
419                             struct socket_context **new_socket)
420 {
421         struct gensec_socket *gensec_socket;
422         struct socket_context *new_sock;
423         NTSTATUS nt_status;
424
425         nt_status = socket_create_with_ops(mem_ctx, &gensec_socket_ops, &new_sock, 
426                                            SOCKET_TYPE_STREAM, current_socket->flags | SOCKET_FLAG_ENCRYPT);
427         if (!NT_STATUS_IS_OK(nt_status)) {
428                 *new_socket = NULL;
429                 return nt_status;
430         }
431
432         new_sock->state = current_socket->state;
433
434         gensec_socket = talloc(new_sock, struct gensec_socket);
435         if (gensec_socket == NULL) {
436                 *new_socket = NULL;
437                 talloc_free(new_sock);
438                 return NT_STATUS_NO_MEMORY;
439         }
440
441         new_sock->private_data       = gensec_socket;
442         gensec_socket->socket        = current_socket;
443
444         /* Nothing to do here, if we are not actually wrapping on this socket */
445         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL) &&
446             !gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
447                 
448                 gensec_socket->wrap = false;
449                 talloc_steal(gensec_socket, current_socket);
450                 *new_socket = new_sock;
451                 return NT_STATUS_OK;
452         }
453
454         gensec_socket->gensec_security = gensec_security;
455
456         gensec_socket->wrap          = true;
457         gensec_socket->eof           = false;
458         gensec_socket->error         = NT_STATUS_OK;
459         gensec_socket->interrupted   = false;
460         gensec_socket->in_extra_read = 0;
461
462         gensec_socket->read_buffer   = data_blob(NULL, 0);
463
464         gensec_socket->recv_handler  = recv_handler;
465         gensec_socket->recv_private  = recv_private;
466         gensec_socket->ev            = ev;
467
468         gensec_socket->packet = packet_init(gensec_socket);
469         if (gensec_socket->packet == NULL) {
470                 *new_socket = NULL;
471                 talloc_free(new_sock);
472                 return NT_STATUS_NO_MEMORY;
473         }
474
475         packet_set_private(gensec_socket->packet, gensec_socket);
476         packet_set_socket(gensec_socket->packet, gensec_socket->socket);
477         packet_set_callback(gensec_socket->packet, gensec_socket_unwrap);
478         packet_set_full_request(gensec_socket->packet, gensec_socket_full_request);
479         packet_set_error_handler(gensec_socket->packet, gensec_socket_error_handler);
480         packet_set_serialise(gensec_socket->packet);
481
482         /* TODO: full-request that knows about maximum packet size */
483
484         talloc_steal(gensec_socket, current_socket);
485         *new_socket = new_sock;
486         return NT_STATUS_OK;
487 }
488
489
490 static NTSTATUS gensec_socket_set_option(struct socket_context *sock, const char *option, const char *val)
491 {
492         set_socket_options(socket_get_fd(sock), option);
493         return NT_STATUS_OK;
494 }
495
496 static char *gensec_socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
497 {
498         struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
499         return socket_get_peer_name(gensec->socket, mem_ctx);
500 }
501
502 static struct socket_address *gensec_socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
503 {
504         struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
505         return socket_get_peer_addr(gensec->socket, mem_ctx);
506 }
507
508 static struct socket_address *gensec_socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
509 {
510         struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
511         return socket_get_my_addr(gensec->socket, mem_ctx);
512 }
513
514 static int gensec_socket_get_fd(struct socket_context *sock)
515 {
516         struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
517         return socket_get_fd(gensec->socket);
518 }
519
520 static const struct socket_ops gensec_socket_ops = {
521         .name                   = "gensec",
522         .fn_init                = gensec_socket_init_fn,
523         .fn_recv                = gensec_socket_recv,
524         .fn_send                = gensec_socket_send,
525         .fn_pending             = gensec_socket_pending,
526
527         .fn_set_option          = gensec_socket_set_option,
528
529         .fn_get_peer_name       = gensec_socket_get_peer_name,
530         .fn_get_peer_addr       = gensec_socket_get_peer_addr,
531         .fn_get_my_addr         = gensec_socket_get_my_addr,
532         .fn_get_fd              = gensec_socket_get_fd
533 };
534