• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/auth/gensec/
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
29static const struct socket_ops gensec_socket_ops;
30
31struct 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? */
45};
46
47static 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) */
102NTSTATUS 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) */
144NTSTATUS 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
161static NTSTATUS gensec_socket_full_request(void *private_data, DATA_BLOB blob, size_t *size)
162{
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);
166}
167
168/* Try to figure out how much data is waiting to be read */
169static 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 */
190static void gensec_socket_error_handler(void *private_data, NTSTATUS status)
191{
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;
197	}
198}
199
200static void gensec_socket_trigger_read(struct tevent_context *ev,
201				       struct tevent_timer *te,
202				       struct timeval t, void *private_data)
203{
204	struct gensec_socket *gensec_socket = talloc_get_type(private_data, 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 ... */
222static 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 */
290static NTSTATUS gensec_socket_unwrap(void *private_data, DATA_BLOB blob)
291{
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;
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 */
332static void send_callback(void *private_data)
333{
334	struct gensec_socket *gensec_socket = talloc_get_type(private_data, 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*/
344static 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
413NTSTATUS 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)
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
490static 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
496static 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
502static 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
508static 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
514static 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
520static 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
535