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