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/>.
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 */
41 void (*recv_handler
)(void *, uint16_t);
44 bool wrap
; /* Should we be wrapping on this socket at all? */
47 static NTSTATUS
gensec_socket_init_fn(struct socket_context
*sock
)
50 case SOCKET_TYPE_STREAM
:
53 return NT_STATUS_INVALID_PARAMETER
;
56 sock
->backend_name
= "gensec";
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
,
67 size_t *len_processed
)
69 if (!gensec_security
->ops
->wrap_packets
) {
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
,
78 &unwrapped
, &wrapped
);
79 if (!NT_STATUS_IS_OK(nt_status
)) {
83 *out
= data_blob_talloc(mem_ctx
, NULL
, 4);
85 return NT_STATUS_NO_MEMORY
;
87 RSIVAL(out
->data
, 0, wrapped
.length
);
89 if (!data_blob_append(mem_ctx
, out
, wrapped
.data
, wrapped
.length
)) {
90 return NT_STATUS_NO_MEMORY
;
92 *len_processed
= unwrapped
.length
;
95 return gensec_security
->ops
->wrap_packets(gensec_security
, mem_ctx
, in
, out
,
99 /* These functions are for use here only (public because SPNEGO must
100 * use them for recursion) */
101 NTSTATUS
gensec_unwrap_packets(struct gensec_security
*gensec_security
,
105 size_t *len_processed
)
107 if (!gensec_security
->ops
->unwrap_packets
) {
111 if (in
->length
< 4) {
112 /* Missing the header we already had! */
113 DEBUG(0, ("Asked to unwrap packet of bogus length! How did we get the short packet?!\n"));
114 return NT_STATUS_INVALID_PARAMETER
;
117 packet_size
= RIVAL(in
->data
, 0);
119 wrapped
= data_blob_const(in
->data
+ 4, packet_size
);
121 if (wrapped
.length
> (in
->length
- 4)) {
122 DEBUG(0, ("Asked to unwrap packed of bogus length %d > %d! How did we get this?!\n",
123 (int)wrapped
.length
, (int)(in
->length
- 4)));
124 return NT_STATUS_INTERNAL_ERROR
;
127 nt_status
= gensec_unwrap(gensec_security
,
130 if (!NT_STATUS_IS_OK(nt_status
)) {
134 *len_processed
= packet_size
+ 4;
137 return gensec_security
->ops
->unwrap_packets(gensec_security
, mem_ctx
, in
, out
,
141 /* These functions are for use here only (public because SPNEGO must
142 * use them for recursion) */
143 NTSTATUS
gensec_packet_full_request(struct gensec_security
*gensec_security
,
144 DATA_BLOB blob
, size_t *size
)
146 if (gensec_security
->ops
->packet_full_request
) {
147 return gensec_security
->ops
->packet_full_request(gensec_security
,
150 if (gensec_security
->ops
->unwrap_packets
) {
155 return STATUS_MORE_ENTRIES
;
157 return packet_full_request_u32(NULL
, blob
, size
);
160 static NTSTATUS
gensec_socket_full_request(void *private_data
, DATA_BLOB blob
, size_t *size
)
162 struct gensec_socket
*gensec_socket
= talloc_get_type(private_data
, struct gensec_socket
);
163 struct gensec_security
*gensec_security
= gensec_socket
->gensec_security
;
164 return gensec_packet_full_request(gensec_security
, blob
, size
);
167 /* Try to figure out how much data is waiting to be read */
168 static NTSTATUS
gensec_socket_pending(struct socket_context
*sock
, size_t *npending
)
170 struct gensec_socket
*gensec_socket
= talloc_get_type(sock
->private_data
, struct gensec_socket
);
171 if (!gensec_socket
->wrap
) {
172 return socket_pending(gensec_socket
->socket
, npending
);
175 if (gensec_socket
->read_buffer
.length
> 0) {
176 *npending
= gensec_socket
->read_buffer
.length
;
180 /* This is a lie. We hope the decrypted data will always be
181 * less than this value, so the application just gets a short
182 * read. Without reading and decrypting it, we can't tell.
183 * If the SASL mech does compression, then we just need to
184 * manually trigger read events */
185 return socket_pending(gensec_socket
->socket
, npending
);
188 /* Note if an error occours, so we can return it up the stack */
189 static void gensec_socket_error_handler(void *private_data
, NTSTATUS status
)
191 struct gensec_socket
*gensec_socket
= talloc_get_type(private_data
, struct gensec_socket
);
192 if (NT_STATUS_EQUAL(status
, NT_STATUS_END_OF_FILE
)) {
193 gensec_socket
->eof
= true;
195 gensec_socket
->error
= status
;
199 static void gensec_socket_trigger_read(struct tevent_context
*ev
,
200 struct tevent_timer
*te
,
201 struct timeval t
, void *private_data
)
203 struct gensec_socket
*gensec_socket
= talloc_get_type(private_data
, struct gensec_socket
);
205 gensec_socket
->in_extra_read
++;
206 gensec_socket
->recv_handler(gensec_socket
->recv_private
, EVENT_FD_READ
);
207 gensec_socket
->in_extra_read
--;
209 /* It may well be that, having run the recv handler, we still
210 * have even more data waiting for us!
212 if (gensec_socket
->read_buffer
.length
&& gensec_socket
->recv_handler
) {
213 /* Schedule this funcion to run again */
214 event_add_timed(gensec_socket
->ev
, gensec_socket
, timeval_zero(),
215 gensec_socket_trigger_read
, gensec_socket
);
219 /* These two routines could be changed to use a circular buffer of
220 * some kind, or linked lists, or ... */
221 static NTSTATUS
gensec_socket_recv(struct socket_context
*sock
, void *buf
,
222 size_t wantlen
, size_t *nread
)
224 struct gensec_socket
*gensec_socket
= talloc_get_type(sock
->private_data
, struct gensec_socket
);
226 if (!gensec_socket
->wrap
) {
227 return socket_recv(gensec_socket
->socket
, buf
, wantlen
, nread
);
230 gensec_socket
->error
= NT_STATUS_OK
;
232 if (gensec_socket
->read_buffer
.length
== 0) {
233 /* Process any data on the socket, into the read buffer. At
234 * this point, the socket is not available for read any
236 packet_recv(gensec_socket
->packet
);
238 if (gensec_socket
->eof
) {
243 if (!NT_STATUS_IS_OK(gensec_socket
->error
)) {
244 return gensec_socket
->error
;
247 if (gensec_socket
->read_buffer
.length
== 0) {
248 /* Clearly we don't have the entire SASL packet yet,
249 * so it has not been written into the buffer */
251 return STATUS_MORE_ENTRIES
;
256 *nread
= MIN(wantlen
, gensec_socket
->read_buffer
.length
);
257 memcpy(buf
, gensec_socket
->read_buffer
.data
, *nread
);
259 if (gensec_socket
->read_buffer
.length
> *nread
) {
260 memmove(gensec_socket
->read_buffer
.data
,
261 gensec_socket
->read_buffer
.data
+ *nread
,
262 gensec_socket
->read_buffer
.length
- *nread
);
265 gensec_socket
->read_buffer
.length
-= *nread
;
266 gensec_socket
->read_buffer
.data
= talloc_realloc(gensec_socket
,
267 gensec_socket
->read_buffer
.data
,
269 gensec_socket
->read_buffer
.length
);
271 if (gensec_socket
->read_buffer
.length
&&
272 gensec_socket
->in_extra_read
== 0 &&
273 gensec_socket
->recv_handler
) {
274 /* Manually call a read event, to get this moving
275 * again (as the socket should be dry, so the normal
276 * event handler won't trigger) */
277 event_add_timed(gensec_socket
->ev
, gensec_socket
, timeval_zero(),
278 gensec_socket_trigger_read
, gensec_socket
);
284 /* Completed SASL packet callback. When we have a 'whole' SASL
285 * packet, decrypt it, and add it to the read buffer
287 * This function (and anything under it) MUST NOT call the event system
289 static NTSTATUS
gensec_socket_unwrap(void *private_data
, DATA_BLOB blob
)
291 struct gensec_socket
*gensec_socket
= talloc_get_type(private_data
, struct gensec_socket
);
297 mem_ctx
= talloc_new(gensec_socket
);
299 return NT_STATUS_NO_MEMORY
;
301 nt_status
= gensec_unwrap_packets(gensec_socket
->gensec_security
,
305 if (!NT_STATUS_IS_OK(nt_status
)) {
306 talloc_free(mem_ctx
);
310 if (packet_size
!= blob
.length
) {
311 DEBUG(0, ("gensec_socket_unwrap: Did not consume entire packet!\n"));
312 talloc_free(mem_ctx
);
313 return NT_STATUS_INTERNAL_ERROR
;
316 /* We could change this into a linked list, and have
317 * gensec_socket_recv() and gensec_socket_pending() walk the
320 if (!data_blob_append(gensec_socket
, &gensec_socket
->read_buffer
,
321 unwrapped
.data
, unwrapped
.length
)) {
322 talloc_free(mem_ctx
);
323 return NT_STATUS_NO_MEMORY
;
326 talloc_free(mem_ctx
);
330 /* when the data is sent, we know we have not been interrupted */
331 static void send_callback(void *private_data
)
333 struct gensec_socket
*gensec_socket
= talloc_get_type(private_data
, struct gensec_socket
);
334 gensec_socket
->interrupted
= false;
338 send data, but only as much as we allow in one packet.
340 If this returns STATUS_MORE_ENTRIES, the caller must retry with
341 exactly the same data, or a NULL blob.
343 static NTSTATUS
gensec_socket_send(struct socket_context
*sock
,
344 const DATA_BLOB
*blob
, size_t *sendlen
)
347 struct gensec_socket
*gensec_socket
= talloc_get_type(sock
->private_data
, struct gensec_socket
);
351 if (!gensec_socket
->wrap
) {
352 return socket_send(gensec_socket
->socket
, blob
, sendlen
);
357 /* We have have been interupted, so the caller should be
358 * giving us the same data again. */
359 if (gensec_socket
->interrupted
) {
360 packet_queue_run(gensec_socket
->packet
);
362 if (!NT_STATUS_IS_OK(gensec_socket
->error
)) {
363 return gensec_socket
->error
;
364 } else if (gensec_socket
->interrupted
) {
365 return STATUS_MORE_ENTRIES
;
367 *sendlen
= gensec_socket
->orig_send_len
;
368 gensec_socket
->orig_send_len
= 0;
373 mem_ctx
= talloc_new(gensec_socket
);
375 return NT_STATUS_NO_MEMORY
;
378 nt_status
= gensec_wrap_packets(gensec_socket
->gensec_security
,
381 &gensec_socket
->orig_send_len
);
382 if (!NT_STATUS_IS_OK(nt_status
)) {
383 talloc_free(mem_ctx
);
387 gensec_socket
->interrupted
= true;
388 gensec_socket
->error
= NT_STATUS_OK
;
390 nt_status
= packet_send_callback(gensec_socket
->packet
,
392 send_callback
, gensec_socket
);
394 talloc_free(mem_ctx
);
396 packet_queue_run(gensec_socket
->packet
);
398 if (!NT_STATUS_IS_OK(gensec_socket
->error
)) {
399 return gensec_socket
->error
;
400 } else if (gensec_socket
->interrupted
) {
401 return STATUS_MORE_ENTRIES
;
403 *sendlen
= gensec_socket
->orig_send_len
;
404 gensec_socket
->orig_send_len
= 0;
409 /* Turn a normal socket into a potentially GENSEC wrapped socket */
410 /* CAREFUL: this function will steal 'current_socket' */
412 NTSTATUS
gensec_socket_init(struct gensec_security
*gensec_security
,
414 struct socket_context
*current_socket
,
415 struct tevent_context
*ev
,
416 void (*recv_handler
)(void *, uint16_t),
418 struct socket_context
**new_socket
)
420 struct gensec_socket
*gensec_socket
;
421 struct socket_context
*new_sock
;
424 nt_status
= socket_create_with_ops(mem_ctx
, &gensec_socket_ops
, &new_sock
,
425 SOCKET_TYPE_STREAM
, current_socket
->flags
| SOCKET_FLAG_ENCRYPT
);
426 if (!NT_STATUS_IS_OK(nt_status
)) {
431 new_sock
->state
= current_socket
->state
;
433 gensec_socket
= talloc(new_sock
, struct gensec_socket
);
434 if (gensec_socket
== NULL
) {
436 talloc_free(new_sock
);
437 return NT_STATUS_NO_MEMORY
;
440 new_sock
->private_data
= gensec_socket
;
441 gensec_socket
->socket
= current_socket
;
443 /* Nothing to do here, if we are not actually wrapping on this socket */
444 if (!gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
) &&
445 !gensec_have_feature(gensec_security
, GENSEC_FEATURE_SIGN
)) {
447 gensec_socket
->wrap
= false;
448 talloc_steal(gensec_socket
, current_socket
);
449 *new_socket
= new_sock
;
453 gensec_socket
->gensec_security
= gensec_security
;
455 gensec_socket
->wrap
= true;
456 gensec_socket
->eof
= false;
457 gensec_socket
->error
= NT_STATUS_OK
;
458 gensec_socket
->interrupted
= false;
459 gensec_socket
->in_extra_read
= 0;
461 gensec_socket
->read_buffer
= data_blob(NULL
, 0);
463 gensec_socket
->recv_handler
= recv_handler
;
464 gensec_socket
->recv_private
= recv_private
;
465 gensec_socket
->ev
= ev
;
467 gensec_socket
->packet
= packet_init(gensec_socket
);
468 if (gensec_socket
->packet
== NULL
) {
470 talloc_free(new_sock
);
471 return NT_STATUS_NO_MEMORY
;
474 packet_set_private(gensec_socket
->packet
, gensec_socket
);
475 packet_set_socket(gensec_socket
->packet
, gensec_socket
->socket
);
476 packet_set_callback(gensec_socket
->packet
, gensec_socket_unwrap
);
477 packet_set_full_request(gensec_socket
->packet
, gensec_socket_full_request
);
478 packet_set_error_handler(gensec_socket
->packet
, gensec_socket_error_handler
);
479 packet_set_serialise(gensec_socket
->packet
);
481 /* TODO: full-request that knows about maximum packet size */
483 talloc_steal(gensec_socket
, current_socket
);
484 *new_socket
= new_sock
;
489 static NTSTATUS
gensec_socket_set_option(struct socket_context
*sock
, const char *option
, const char *val
)
491 set_socket_options(socket_get_fd(sock
), option
);
495 static char *gensec_socket_get_peer_name(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
497 struct gensec_socket
*gensec
= talloc_get_type(sock
->private_data
, struct gensec_socket
);
498 return socket_get_peer_name(gensec
->socket
, mem_ctx
);
501 static struct socket_address
*gensec_socket_get_peer_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
503 struct gensec_socket
*gensec
= talloc_get_type(sock
->private_data
, struct gensec_socket
);
504 return socket_get_peer_addr(gensec
->socket
, mem_ctx
);
507 static struct socket_address
*gensec_socket_get_my_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
509 struct gensec_socket
*gensec
= talloc_get_type(sock
->private_data
, struct gensec_socket
);
510 return socket_get_my_addr(gensec
->socket
, mem_ctx
);
513 static int gensec_socket_get_fd(struct socket_context
*sock
)
515 struct gensec_socket
*gensec
= talloc_get_type(sock
->private_data
, struct gensec_socket
);
516 return socket_get_fd(gensec
->socket
);
519 static const struct socket_ops gensec_socket_ops
= {
521 .fn_init
= gensec_socket_init_fn
,
522 .fn_recv
= gensec_socket_recv
,
523 .fn_send
= gensec_socket_send
,
524 .fn_pending
= gensec_socket_pending
,
526 .fn_set_option
= gensec_socket_set_option
,
528 .fn_get_peer_name
= gensec_socket_get_peer_name
,
529 .fn_get_peer_addr
= gensec_socket_get_peer_addr
,
530 .fn_get_my_addr
= gensec_socket_get_my_addr
,
531 .fn_get_fd
= gensec_socket_get_fd