s3-lsa: Fix static list of luids in our privileges implementation.
[Samba/ekacnet.git] / source4 / auth / gensec / socket.c
blob6a03f0bcecaedca1b015d442a7ad2ed6c33c9972
1 /*
2 Unix SMB/CIFS implementation.
4 GENSEC socket interface
6 Copyright (C) Andrew Bartlett 2006
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.
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.
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/>.
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"
29 static const struct socket_ops gensec_socket_ops;
31 struct gensec_socket {
32 struct gensec_security *gensec_security;
33 struct socket_context *socket;
34 struct tevent_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? */
47 static NTSTATUS gensec_socket_init_fn(struct socket_context *sock)
49 switch (sock->type) {
50 case SOCKET_TYPE_STREAM:
51 break;
52 default:
53 return NT_STATUS_INVALID_PARAMETER;
56 sock->backend_name = "gensec";
58 return NT_STATUS_OK;
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)
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));
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;
84 *out = data_blob_talloc(mem_ctx, NULL, 4);
85 if (!out->data) {
86 return NT_STATUS_NO_MEMORY;
88 RSIVAL(out->data, 0, wrapped.length);
90 if (!data_blob_append(mem_ctx, out, wrapped.data, wrapped.length)) {
91 return NT_STATUS_NO_MEMORY;
93 *len_processed = unwrapped.length;
94 return NT_STATUS_OK;
96 return gensec_security->ops->wrap_packets(gensec_security, mem_ctx, in, out,
97 len_processed);
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)
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;
118 packet_size = RIVAL(in->data, 0);
120 wrapped = data_blob_const(in->data + 4, packet_size);
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;
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;
135 *len_processed = packet_size + 4;
136 return nt_status;
138 return gensec_security->ops->unwrap_packets(gensec_security, mem_ctx, in, out,
139 len_processed);
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)
147 if (gensec_security->ops->packet_full_request) {
148 return gensec_security->ops->packet_full_request(gensec_security,
149 blob, size);
151 if (gensec_security->ops->unwrap_packets) {
152 if (blob.length) {
153 *size = blob.length;
154 return NT_STATUS_OK;
156 return STATUS_MORE_ENTRIES;
158 return packet_full_request_u32(NULL, blob, size);
161 static NTSTATUS gensec_socket_full_request(void *private_data, DATA_BLOB blob, size_t *size)
163 struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
164 struct gensec_security *gensec_security = gensec_socket->gensec_security;
165 return gensec_packet_full_request(gensec_security, blob, size);
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)
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);
176 if (gensec_socket->read_buffer.length > 0) {
177 *npending = gensec_socket->read_buffer.length;
178 return NT_STATUS_OK;
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);
189 /* Note if an error occours, so we can return it up the stack */
190 static void gensec_socket_error_handler(void *private_data, NTSTATUS status)
192 struct gensec_socket *gensec_socket = talloc_get_type(private_data, 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;
200 static void gensec_socket_trigger_read(struct tevent_context *ev,
201 struct tevent_timer *te,
202 struct timeval t, void *private_data)
204 struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
206 gensec_socket->in_extra_read++;
207 gensec_socket->recv_handler(gensec_socket->recv_private, EVENT_FD_READ);
208 gensec_socket->in_extra_read--;
210 /* It may well be that, having run the recv handler, we still
211 * have even more data waiting for us!
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);
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)
225 struct gensec_socket *gensec_socket = talloc_get_type(sock->private_data, struct gensec_socket);
227 if (!gensec_socket->wrap) {
228 return socket_recv(gensec_socket->socket, buf, wantlen, nread);
231 gensec_socket->error = NT_STATUS_OK;
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);
239 if (gensec_socket->eof) {
240 *nread = 0;
241 return NT_STATUS_OK;
244 if (!NT_STATUS_IS_OK(gensec_socket->error)) {
245 return gensec_socket->error;
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;
257 *nread = MIN(wantlen, gensec_socket->read_buffer.length);
258 memcpy(buf, gensec_socket->read_buffer.data, *nread);
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);
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);
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);
282 return NT_STATUS_OK;
285 /* Completed SASL packet callback. When we have a 'whole' SASL
286 * packet, decrypt it, and add it to the read buffer
288 * This function (and anything under it) MUST NOT call the event system
290 static NTSTATUS gensec_socket_unwrap(void *private_data, DATA_BLOB blob)
292 struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
293 DATA_BLOB unwrapped;
294 NTSTATUS nt_status;
295 TALLOC_CTX *mem_ctx;
296 size_t packet_size;
298 mem_ctx = talloc_new(gensec_socket);
299 if (!mem_ctx) {
300 return NT_STATUS_NO_MEMORY;
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;
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;
317 /* We could change this into a linked list, and have
318 * gensec_socket_recv() and gensec_socket_pending() walk the
319 * linked list */
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;
327 talloc_free(mem_ctx);
328 return NT_STATUS_OK;
331 /* when the data is sent, we know we have not been interrupted */
332 static void send_callback(void *private_data)
334 struct gensec_socket *gensec_socket = talloc_get_type(private_data, struct gensec_socket);
335 gensec_socket->interrupted = false;
339 send data, but only as much as we allow in one packet.
341 If this returns STATUS_MORE_ENTRIES, the caller must retry with
342 exactly the same data, or a NULL blob.
344 static NTSTATUS gensec_socket_send(struct socket_context *sock,
345 const DATA_BLOB *blob, size_t *sendlen)
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;
352 if (!gensec_socket->wrap) {
353 return socket_send(gensec_socket->socket, blob, sendlen);
356 *sendlen = 0;
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);
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;
374 mem_ctx = talloc_new(gensec_socket);
375 if (!mem_ctx) {
376 return NT_STATUS_NO_MEMORY;
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;
388 gensec_socket->interrupted = true;
389 gensec_socket->error = NT_STATUS_OK;
391 nt_status = packet_send_callback(gensec_socket->packet,
392 wrapped,
393 send_callback, gensec_socket);
395 talloc_free(mem_ctx);
397 packet_queue_run(gensec_socket->packet);
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;
410 /* Turn a normal socket into a potentially GENSEC wrapped socket */
411 /* CAREFUL: this function will steal 'current_socket' */
413 NTSTATUS gensec_socket_init(struct gensec_security *gensec_security,
414 TALLOC_CTX *mem_ctx,
415 struct socket_context *current_socket,
416 struct tevent_context *ev,
417 void (*recv_handler)(void *, uint16_t),
418 void *recv_private,
419 struct socket_context **new_socket)
421 struct gensec_socket *gensec_socket;
422 struct socket_context *new_sock;
423 NTSTATUS nt_status;
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;
432 new_sock->state = current_socket->state;
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;
441 new_sock->private_data = gensec_socket;
442 gensec_socket->socket = current_socket;
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)) {
448 gensec_socket->wrap = false;
449 talloc_steal(gensec_socket, current_socket);
450 *new_socket = new_sock;
451 return NT_STATUS_OK;
454 gensec_socket->gensec_security = gensec_security;
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;
462 gensec_socket->read_buffer = data_blob(NULL, 0);
464 gensec_socket->recv_handler = recv_handler;
465 gensec_socket->recv_private = recv_private;
466 gensec_socket->ev = ev;
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;
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);
482 /* TODO: full-request that knows about maximum packet size */
484 talloc_steal(gensec_socket, current_socket);
485 *new_socket = new_sock;
486 return NT_STATUS_OK;
490 static NTSTATUS gensec_socket_set_option(struct socket_context *sock, const char *option, const char *val)
492 set_socket_options(socket_get_fd(sock), option);
493 return NT_STATUS_OK;
496 static char *gensec_socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
498 struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
499 return socket_get_peer_name(gensec->socket, mem_ctx);
502 static struct socket_address *gensec_socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
504 struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
505 return socket_get_peer_addr(gensec->socket, mem_ctx);
508 static struct socket_address *gensec_socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
510 struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
511 return socket_get_my_addr(gensec->socket, mem_ctx);
514 static int gensec_socket_get_fd(struct socket_context *sock)
516 struct gensec_socket *gensec = talloc_get_type(sock->private_data, struct gensec_socket);
517 return socket_get_fd(gensec->socket);
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,
527 .fn_set_option = gensec_socket_set_option,
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