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