1/* 2 * Copyright (c) 2010-2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77#include "config.h" 78#include <dce/smb.h> 79#include <commonp.h> 80#include <com.h> 81#include <comprot.h> 82#include <comnaf.h> 83#include <comp.h> 84#include <comsoc_smb.h> 85#include <cnassm.h> 86#include <fcntl.h> 87#include <sys/un.h> 88#include <sys/types.h> 89#include <sys/stat.h> 90#include <cnp.h> 91#include <npnaf.h> 92#include <stddef.h> 93#include <sys/param.h> 94#include <sys/mount.h> 95 96#if HAVE_SMBCLIENT_FRAMEWORK 97#include <SMBClient/smbclient.h> 98#include <nttypes.h> 99rpc_socket_error_t rpc_smb_ntstatus_to_rpc_error(NTSTATUS status); 100 101#if !defined(kSMBOptionAllowGuestAuth) 102#define kSMBOptionAllowGuestAuth 0 103#endif 104 105#if !defined(kSMBOptionAllowAnonymousAuth) 106#define kSMBOptionAllowAnonymousAuth 0 107#endif 108 109#if defined(kPropertiesVersion) 110#define HAVE_SMBCLIENT_SMBGETSERVERPROPERTIES 1 111#endif 112 113#define SMBCLIENT_CONNECTION_FLAGS ( \ 114 kSMBOptionNoPrompt | \ 115 kSMBOptionAllowGuestAuth | \ 116 kSMBOptionAllowAnonymousAuth \ 117) 118 119#endif /* HAVE_SMBCLIENT_FRAMEWORK */ 120 121#if HAVE_LW_BASE_H 122#include <lw/base.h> 123#endif 124 125#if HAVE_LWIO_LWIO_H 126#include <lwio/lwio.h> 127#endif 128 129#if HAVE_LWMAPSECURITY_LWMAPSECURITY_H 130#include <lwmapsecurity/lwmapsecurity.h> 131#endif 132 133#define SMB_SOCKET_LOCK(sock) (rpc__smb_socket_lock(sock)) 134#define SMB_SOCKET_UNLOCK(sock) (rpc__smb_socket_unlock(sock)) 135 136#ifndef RPC_C_SOCKET_MAX_RCVBUF 137# define RPC_C_SOCKET_MAX_RCVBUF (64 * 1024) 138#endif 139 140#ifndef RPC_C_SOCKET_MAX_SNDBUF 141# define RPC_C_SOCKET_MAX_SNDBUF (64 * 1024) 142#endif 143 144typedef struct rpc_smb_transport_info_s 145{ 146 char* peer_principal; 147 struct 148 { 149 unsigned16 length; 150 unsigned char* data; 151 } session_key; 152#if HAVE_LIKEWISE_LWIO 153 PIO_CREDS creds; 154#endif 155} rpc_smb_transport_info_t, *rpc_smb_transport_info_p_t; 156 157typedef enum rpc_smb_state_e 158{ 159 SMB_STATE_SEND, 160 SMB_STATE_RECV, 161 SMB_STATE_LISTEN, 162 SMB_STATE_ERROR 163} rpc_smb_state_t; 164 165typedef struct rpc_smb_buffer_s 166{ 167 size_t capacity; 168 unsigned char* base; 169 unsigned char* start_cursor; 170 unsigned char* end_cursor; 171} rpc_smb_buffer_t, *rpc_smb_buffer_p_t; 172 173typedef struct rpc_smb_socket_s 174{ 175 rpc_smb_state_t volatile state; 176 rpc_np_addr_t peeraddr; 177 rpc_np_addr_t localaddr; 178 rpc_smb_transport_info_t info; 179#if HAVE_LIKEWISE_LWIO 180 PIO_CONTEXT context; 181 IO_FILE_HANDLE np; 182#elif HAVE_SMBCLIENT_FRAMEWORK 183 SMBHANDLE handle; 184 SMBFID hFile; 185#endif 186 size_t maxSendBufferSize; 187 size_t maxRecvBufferSize; 188 rpc_smb_buffer_t sendbuffer; 189 rpc_smb_buffer_t recvbuffer; 190 struct 191 { 192#if HAVE_LIKEWISE_LWIO 193 IO_FILE_HANDLE* queue; 194#endif 195 size_t capacity; 196 size_t length; 197 int selectfd[2]; 198 } accept_backlog; 199 dcethread* listen_thread; 200 dcethread_mutex lock; 201 dcethread_cond event; 202} rpc_smb_socket_t, *rpc_smb_socket_p_t; 203 204#if HAVE_SMBCLIENT_FRAMEWORK 205rpc_socket_error_t 206rpc_smb_ntstatus_to_rpc_error( 207 NTSTATUS status 208 ) 209{ 210 switch (status) { 211 212 case STATUS_SUCCESS: 213 return RPC_C_SOCKET_OK; 214 215 case STATUS_UNEXPECTED_IO_ERROR: 216 return RPC_C_SOCKET_EIO; 217 218 case STATUS_CONNECTION_REFUSED: 219 return RPC_C_SOCKET_ECONNREFUSED; 220 221 case STATUS_NO_SUCH_DEVICE: 222 return RPC_C_SOCKET_ENETUNREACH; 223 224 case STATUS_BUFFER_OVERFLOW: 225 return RPC_C_SOCKET_ENOSPC; 226 227 case STATUS_NO_MEMORY: 228 return RPC_C_SOCKET_ENOMEM; 229 230 case STATUS_OBJECT_PATH_SYNTAX_BAD: 231 case STATUS_INVALID_HANDLE: 232 case STATUS_INVALID_PARAMETER: 233 case STATUS_UNSUCCESSFUL: 234 return RPC_C_SOCKET_EINVAL; 235 236 case STATUS_LOGON_FAILURE: 237 return RPC_C_SOCKET_EAUTH; 238 239 case STATUS_BAD_NETWORK_NAME: 240 return RPC_C_SOCKET_ENOENT; 241 242 default: 243 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc_smb_ntstatus_to_rpc_error - unmapped ntstatus 0x%x\n", status)); 244 return (RPC_C_SOCKET_EIO); 245 } 246} 247 248#endif 249 250void 251rpc_smb_transport_info_from_lwio_creds( 252 void* creds ATTRIBUTE_UNUSED, 253 rpc_transport_info_handle_t* info, 254 unsigned32* st 255 ) 256{ 257 rpc_smb_transport_info_p_t smb_info = NULL; 258 259 smb_info = calloc(1, sizeof(*smb_info)); 260 261 if (!smb_info) 262 { 263 *st = rpc_s_no_memory; 264 goto error; 265 } 266 267#if HAVE_LIKEWISE_LWIO 268 if (LwIoCopyCreds(creds, &smb_info->creds) != 0) 269 { 270 *st = rpc_s_no_memory; 271 goto error; 272 } 273#endif 274 275 *info = (rpc_transport_info_handle_t) smb_info; 276 277 *st = rpc_s_ok; 278 279error: 280 281 if (*st != rpc_s_ok && smb_info) 282 { 283 rpc_smb_transport_info_free((rpc_transport_info_handle_t) smb_info); 284 } 285 286 return; 287} 288 289INTERNAL 290void 291rpc__smb_transport_info_destroy( 292 rpc_smb_transport_info_p_t smb_info 293 ) 294{ 295 assert(smb_info != NULL); 296 297#if HAVE_LIKEWISE_LWIO 298 if (smb_info->creds) 299 { 300 LwIoDeleteCreds(smb_info->creds); 301 } 302#endif 303 304 if (smb_info->session_key.data) 305 { 306 free(smb_info->session_key.data); 307 } 308 309 if (smb_info->peer_principal) 310 { 311 free(smb_info->peer_principal); 312 } 313} 314 315void 316rpc_smb_transport_info_free( 317 rpc_transport_info_handle_t info 318 ) 319{ 320 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc_smb_transport_info_free called\n")); 321 322 if (info) 323 { 324 rpc__smb_transport_info_destroy((rpc_smb_transport_info_p_t) info); 325 free(info); 326 } 327} 328 329void 330rpc_smb_transport_info_inq_session_key( 331 rpc_transport_info_handle_t info, 332 unsigned char** sess_key, 333 unsigned16* sess_key_len 334 ) 335{ 336 rpc_smb_transport_info_p_t smb_info = (rpc_smb_transport_info_p_t) info; 337 338 if (sess_key) 339 { 340 *sess_key = smb_info->session_key.data; 341 } 342 343 if (sess_key_len) 344 { 345 *sess_key_len = (unsigned32) smb_info->session_key.length; 346 } 347} 348 349void 350rpc_smb_transport_info_inq_peer_principal_name( 351 rpc_transport_info_handle_t info, 352 unsigned char** principal 353 ) 354{ 355 rpc_smb_transport_info_p_t smb_info = (rpc_smb_transport_info_p_t) info; 356 357 if (principal) 358 { 359 *principal = (unsigned char*) smb_info->peer_principal; 360 } 361} 362 363INTERNAL 364boolean 365rpc__smb_transport_info_equal( 366 rpc_transport_info_handle_t info1, 367 rpc_transport_info_handle_t info2 368 ) 369{ 370 rpc_smb_transport_info_p_t smb_info1 = (rpc_smb_transport_info_p_t) info1; 371 rpc_smb_transport_info_p_t smb_info2 = (rpc_smb_transport_info_p_t) info2; 372 373 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_transport_info_equal called\n")); 374 375#if HAVE_LIKEWISE_LWIO 376 return 377 (smb_info2 == NULL 378 && smb_info1->creds == NULL) || 379 (smb_info2 != NULL && 380 ((smb_info1->creds == NULL && smb_info2->creds == NULL) || 381 (smb_info1->creds != NULL && smb_info2->creds != NULL && 382 LwIoCompareCredss(smb_info1->creds, smb_info2->creds)))); 383#else 384 return (smb_info1 == smb_info2); 385#endif 386} 387 388INTERNAL 389inline 390size_t 391rpc__smb_buffer_pending( 392 rpc_smb_buffer_p_t buffer 393 ) 394{ 395 return buffer->end_cursor - buffer->start_cursor; 396} 397 398INTERNAL 399inline 400size_t 401rpc__smb_buffer_length( 402 rpc_smb_buffer_p_t buffer 403 ) 404{ 405 return buffer->end_cursor - buffer->base; 406} 407 408INTERNAL 409inline 410size_t 411rpc__smb_buffer_available( 412 rpc_smb_buffer_p_t buffer 413 ) 414{ 415 return (buffer->base + buffer->capacity) - buffer->end_cursor; 416} 417 418INTERNAL 419inline 420rpc_socket_error_t 421rpc__smb_buffer_ensure_available( 422 rpc_smb_buffer_p_t buffer, 423 size_t space 424 ) 425{ 426 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 427 unsigned char* new_base = NULL; 428 429 if (!buffer->base) 430 { 431 buffer->capacity = 2048; 432 buffer->base = malloc(buffer->capacity); 433 434 if (!buffer->base) 435 { 436 serr = RPC_C_SOCKET_ENOMEM; 437 goto error; 438 } 439 440 buffer->end_cursor = buffer->start_cursor = buffer->base; 441 } 442 443 if (space > rpc__smb_buffer_available(buffer)) 444 { 445 while (space > rpc__smb_buffer_available(buffer)) 446 { 447 buffer->capacity *= 2; 448 } 449 450 new_base = realloc(buffer->base, buffer->capacity); 451 452 if (!new_base) 453 { 454 serr = RPC_C_SOCKET_ENOMEM; 455 goto error; 456 } 457 458 buffer->start_cursor = new_base + (buffer->start_cursor - buffer->base); 459 buffer->end_cursor = new_base + (buffer->end_cursor - buffer->base); 460 461 buffer->base = new_base; 462 } 463 464error: 465 466 return serr; 467} 468 469INTERNAL 470size_t 471rpc__smb_fragment_size( 472 rpc_cn_common_hdr_p_t packet 473 ) 474{ 475 uint16_t result; 476 int packet_order = ((packet->drep[0] >> 4) & 1); 477 int native_order; 478 479#if __LITTLE_ENDIAN__ 480 native_order = (NDR_LOCAL_INT_REP == ndr_c_int_big_endian) ? 0 : 1; 481#else 482 native_order = (NDR_LOCAL_INT_REP == ndr_c_int_little_endian) ? 0 : 1; 483#endif 484 485 if (packet_order != native_order) 486 { 487 result = SWAB_16(packet->frag_len); 488 } 489 else 490 { 491 result = packet->frag_len; 492 } 493 494 return (size_t) result; 495} 496 497INTERNAL 498inline 499size_t 500rpc__smb_buffer_packet_size( 501 rpc_smb_buffer_p_t buffer 502 ) 503{ 504 rpc_cn_common_hdr_p_t packet = (rpc_cn_common_hdr_p_t) buffer->start_cursor; 505 506 if (rpc__smb_buffer_pending(buffer) < sizeof(*packet)) 507 { 508 return sizeof(*packet); 509 } 510 else 511 { 512 return (rpc__smb_fragment_size(packet)); 513 } 514} 515 516INTERNAL 517inline 518boolean 519rpc__smb_buffer_packet_is_last( 520 rpc_smb_buffer_p_t buffer 521 ) 522{ 523 rpc_cn_common_hdr_p_t packet = (rpc_cn_common_hdr_p_t) buffer->start_cursor; 524 525 return (packet->flags & RPC_C_CN_FLAGS_LAST_FRAG) == RPC_C_CN_FLAGS_LAST_FRAG; 526} 527 528INTERNAL 529inline 530rpc_socket_error_t 531rpc__smb_buffer_append( 532 rpc_smb_buffer_p_t buffer, 533 void* data, 534 size_t data_size 535 ) 536{ 537 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 538 539 serr = rpc__smb_buffer_ensure_available(buffer, data_size); 540 if (serr) 541 { 542 goto error; 543 } 544 545 memcpy(buffer->end_cursor, data, data_size); 546 547 buffer->end_cursor += data_size; 548 549error: 550 551 return serr; 552} 553 554INTERNAL 555inline 556void 557rpc__smb_buffer_settle( 558 rpc_smb_buffer_p_t buffer 559 ) 560{ 561 size_t filled = buffer->end_cursor - buffer->start_cursor; 562 memmove(buffer->base, buffer->start_cursor, filled); 563 buffer->start_cursor = buffer->base; 564 buffer->end_cursor = buffer->base + filled; 565} 566 567/* Advance buffer start_cursor to the end of the last packet 568 or the last packet that is the final fragment in a series, 569 whichever comes first. If the final fragment is found, 570 return true, otherwise false. 571*/ 572INTERNAL 573inline 574boolean 575rpc__smb_buffer_advance_cursor(rpc_smb_buffer_p_t buffer, size_t* amount) 576{ 577 boolean last; 578 size_t packet_size; 579 580 while (rpc__smb_buffer_packet_size(buffer) <= rpc__smb_buffer_pending(buffer)) 581 { 582 last = rpc__smb_buffer_packet_is_last(buffer); 583 packet_size = rpc__smb_buffer_packet_size(buffer); 584 585 buffer->start_cursor += packet_size; 586 587 if (last) 588 { 589 if (amount) 590 { 591 *amount = buffer->start_cursor - buffer->base; 592 } 593 594 return true; 595 } 596 } 597 598 return false; 599} 600 601INTERNAL 602rpc_socket_error_t 603rpc__smb_socket_create( 604 rpc_smb_socket_p_t* out 605 ) 606{ 607 rpc_smb_socket_p_t sock = NULL; 608 int err = 0; 609 610 sock = calloc(1, sizeof(*sock)); 611 612 if (!sock) 613 { 614 err = RPC_C_SOCKET_ENOMEM; 615 goto done; 616 } 617 618 sock->accept_backlog.selectfd[0] = -1; 619 sock->accept_backlog.selectfd[1] = -1; 620 621 /* Set up reasonable default local endpoint */ 622 sock->localaddr.rpc_protseq_id = rpc_c_protseq_id_ncacn_np; 623 sock->localaddr.len = offsetof(rpc_np_addr_t, remote_host) + sizeof(sock->localaddr.remote_host); 624 sock->localaddr.sa.sun_family = AF_UNIX; 625 sock->localaddr.sa.sun_path[0] = '\0'; 626 sock->localaddr.remote_host[0] = '\0'; 627 628 dcethread_mutex_init_throw(&sock->lock, NULL); 629 dcethread_cond_init_throw(&sock->event, NULL); 630 631#if HAVE_SMBCLIENT_FRAMEWORK 632 sock->handle = NULL; 633 sock->hFile = 0; 634 sock->maxSendBufferSize = 0; 635 sock->maxRecvBufferSize = 0; 636#else 637 sock->maxSendBufferSize = 8192; 638 sock->maxRecvBufferSize = 8192; 639#endif 640 641#if HAVE_LIKEWISE_LWIO 642 err = LwNtStatusToErrno(LwIoOpenContextShared(&sock->context)); 643 if (err) 644 { 645 goto error; 646 } 647#endif 648 649 *out = sock; 650 651done: 652 653 return err; 654 655#if HAVE_LIKEWISE_LWIO 656error: 657 658 if (sock) 659 { 660 if (sock->context) 661 { 662 LwIoCloseContext(sock->context); 663 } 664 665 dcethread_mutex_destroy_throw(&sock->lock); 666 dcethread_cond_destroy_throw(&sock->event); 667 } 668 669 goto done; 670#endif 671} 672 673INTERNAL 674void 675rpc__smb_socket_destroy( 676 rpc_smb_socket_p_t sock 677 ) 678{ 679#if HAVE_LIKEWISE_LWIO 680 size_t i; 681#endif 682 683 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_destroy called\n")); 684 685 if (!sock) 686 { 687 return; 688 } 689 690#if HAVE_LIKEWISE_LWIO 691 if (sock->accept_backlog.queue) 692 { 693 for (i = 0; i < sock->accept_backlog.capacity; i++) 694 { 695 if (sock->accept_backlog.queue[i]) 696 { 697 NtCtxCloseFile(sock->context, sock->accept_backlog.queue[i]); 698 } 699 } 700 701 close(sock->accept_backlog.selectfd[0]); 702 close(sock->accept_backlog.selectfd[1]); 703 704 free(sock->accept_backlog.queue); 705 } 706 707 if (sock->np && sock->context) 708 { 709 NtCtxCloseFile(sock->context, sock->np); 710 } 711 712 if (sock->context) 713 { 714 LwIoCloseContext(sock->context); 715 } 716 717#elif HAVE_SMBCLIENT_FRAMEWORK 718 719 if (sock->hFile != 0) 720 { 721 SMBCloseFile(sock->handle, sock->hFile); 722 sock->hFile = 0; 723 } 724 725 if (sock->handle) 726 { 727 SMBReleaseServer(sock->handle); 728 sock->handle = NULL; 729 } 730 731#endif 732 733 if (sock->sendbuffer.base) 734 { 735 free(sock->sendbuffer.base); 736 } 737 738 if (sock->recvbuffer.base) 739 { 740 free(sock->recvbuffer.base); 741 } 742 743 rpc__smb_transport_info_destroy(&sock->info); 744 745 dcethread_mutex_destroy_throw(&sock->lock); 746 dcethread_cond_destroy_throw(&sock->event); 747 748 free(sock); 749} 750 751INTERNAL 752inline 753void 754rpc__smb_socket_lock( 755 rpc_smb_socket_p_t sock 756 ) 757{ 758 dcethread_mutex_lock_throw(&sock->lock); 759} 760 761INTERNAL 762inline 763void 764rpc__smb_socket_unlock( 765 rpc_smb_socket_p_t sock 766 ) 767{ 768 dcethread_mutex_unlock_throw(&sock->lock); 769} 770 771INTERNAL 772inline 773void 774rpc__smb_socket_change_state( 775 rpc_smb_socket_p_t sock, 776 rpc_smb_state_t state 777 ) 778{ 779 sock->state = state; 780 dcethread_cond_broadcast_throw(&sock->event); 781} 782 783INTERNAL 784inline 785void 786rpc__smb_socket_wait( 787 rpc_smb_socket_p_t sock 788 ) 789{ 790 DCETHREAD_TRY 791 { 792 dcethread_cond_wait_throw(&sock->event, &sock->lock); 793 } 794 DCETHREAD_CATCH_ALL(e) 795 { 796 dcethread_mutex_unlock(&sock->lock); 797 DCETHREAD_RAISE(*e); 798 } 799 DCETHREAD_ENDTRY; 800} 801 802INTERNAL 803rpc_socket_error_t 804rpc__smb_socket_construct( 805 rpc_socket_t sock, 806 rpc_protseq_id_t pseq_id ATTRIBUTE_UNUSED, 807#if HAVE_LIKEWISE_LWIO 808 rpc_transport_info_handle_t info 809#else 810 rpc_transport_info_handle_t info ATTRIBUTE_UNUSED 811#endif 812 ) 813{ 814 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 815 rpc_smb_socket_p_t smb_sock = NULL; 816#if HAVE_LIKEWISE_LWIO 817 rpc_smb_transport_info_p_t smb_info = (rpc_smb_transport_info_p_t) info; 818#endif 819 820 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_construct called\n")); 821 822 serr = rpc__smb_socket_create(&smb_sock); 823 824 if (serr) 825 { 826 goto error; 827 } 828 829#if HAVE_LIKEWISE_LWIO 830 if (smb_info) 831 { 832 if (smb_info->creds) 833 { 834 serr = NtStatusToErrno(LwIoCopyCreds(smb_info->creds, &smb_sock->info.creds)); 835 if (serr) 836 { 837 goto error; 838 } 839 } 840 } 841#endif 842 843 sock->data.pointer = (void*) smb_sock; 844 845done: 846 847 return serr; 848 849error: 850 851 if (smb_sock) 852 { 853 rpc__smb_socket_destroy(smb_sock); 854 } 855 856 goto done; 857} 858 859INTERNAL 860rpc_socket_error_t 861rpc__smb_socket_destruct( 862 rpc_socket_t sock 863 ) 864{ 865 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 866 867 rpc__smb_socket_destroy(smb); 868 sock->data.pointer = NULL; 869 870 return RPC_C_SOCKET_OK; 871} 872 873INTERNAL 874rpc_socket_error_t 875rpc__smb_socket_bind( 876 rpc_socket_t sock, 877 rpc_addr_p_t addr 878 ) 879{ 880 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 881 rpc_np_addr_p_t npaddr = (rpc_np_addr_p_t) addr; 882 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 883 884 smb->localaddr = *npaddr; 885 886 return serr; 887} 888 889#if HAVE_SMBCLIENT_FRAMEWORK 890INTERNAL 891rpc_socket_error_t 892rpc__smbclient_connect( 893 rpc_smb_socket_p_t smb, 894 const char * netaddr, 895 const char * pipename 896) 897{ 898 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 899 char * smbpath = NULL; 900 NTSTATUS status; 901 boolean have_mountpath = false; 902 unsigned_char_p_t unescaped_netaddr; 903 904 if (netaddr[0] == '/') 905 { 906 struct statfs fsBuf; 907 908 /* see if its a mountpath instead of a host addr */ 909 if (statfs ((char *) netaddr, &fsBuf) != 0) 910 { 911 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 912 ("rpc__smb_socket_connect - statfs failed errno %d\n", errno)); 913 } 914 else 915 { 916 /* its a mountpath, so use a different api 917 to find the existing smb session to share */ 918 have_mountpath = 1; 919 } 920 } 921 922 if (have_mountpath == 0) 923 { 924 /* its not a mount path, so just pass in the URL string */ 925 926#if defined(kPropertiesVersion) 927 /* unescape the netaddr */ 928 rpc__string_netaddr_unescape((unsigned_char_p_t) netaddr, 929 &unescaped_netaddr, 930 &status); 931 932 smbpath = SMBCreateURLString(NULL, NULL, NULL, 933 (const char *) unescaped_netaddr, 934 NULL, -1); 935 /* free the escaped netaddr */ 936 rpc_string_free (&unescaped_netaddr, &status); 937#else 938 /* Ick. Max OS 10.6 or earlier ... only have the old API. */ 939 asprintf(&smbpath, "smb://%s", netaddr); 940#endif 941 if (smbpath == NULL) 942 { 943 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 944 ("rpc__smb_socket_connect - smbpath malloc failed\n")); 945 serr = RPC_C_SOCKET_ENOMEM; 946 goto error; 947 } 948 } 949 950 /* Never have a username or password here. Either we use an already 951 * existing authenticated session, or log in as guest, or fail. Never 952 * prompt for a username or password so always set kSMBOptionNoPrompt, 953 * but do allow guest or anonymous logins. 954 */ 955 956 if (have_mountpath == 0) 957 { 958 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 959 ("rpc__smb_socket_connect - SMBOpenServerEx <%s>\n", 960 smbpath)); 961 status = SMBOpenServerEx(smbpath, &smb->handle, SMBCLIENT_CONNECTION_FLAGS); 962 } 963 else 964 { 965 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 966 ("rpc__smb_socket_connect - SMBOpenServerWithMountPoint <%s>\n", 967 netaddr)); 968#if defined(kPropertiesVersion) 969 status = SMBOpenServerWithMountPoint(netaddr, NULL, 970 &smb->handle, SMBCLIENT_CONNECTION_FLAGS); 971#else 972 status = 0xC00000CC; /* STATUS_BAD_NETWORK_NAME */ 973#endif 974 } 975 976 if (!NT_SUCCESS(status)) 977 { 978 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 979 ("rpc__smb_socket_connect - SMBOpenServerEx failed 0x%x\n", 980 status)); 981 serr = rpc_smb_ntstatus_to_rpc_error (status); 982 goto error; 983 } 984 985 status = SMBCreateFile(smb->handle, pipename, 986 GENERIC_READ | GENERIC_WRITE, /* dwDesiredAccess */ 987 FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ 988 NULL, /* lpSecurityAttributes */ 989 FILE_OPEN, /* dwCreateDisposition */ 990 0x0000, /* dwFlagsAndAttributes */ 991 &smb->hFile); 992 993 if (!NT_SUCCESS(status)) 994 { 995 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 996 ("rpc__smb_socket_connect - SMBCreateFile failed 0x%x\n", 997 status)); 998 serr = rpc_smb_ntstatus_to_rpc_error (status); 999 goto error; 1000 } 1001 1002error: 1003 if (smbpath) 1004 free(smbpath); 1005 1006 return serr; 1007} 1008 1009#endif /* HAVE_SMBCLIENT_FRAMEWORK */ 1010 1011INTERNAL 1012rpc_socket_error_t 1013rpc__smb_socket_connect( 1014 rpc_socket_t sock, 1015 rpc_addr_p_t addr, 1016 rpc_cn_assoc_t *assoc ATTRIBUTE_UNUSED 1017 ) 1018{ 1019 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1020 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 1021 char *netaddr = NULL; 1022 unsigned_char_t *endpoint = NULL; 1023 char *pipename = NULL; 1024 unsigned32 dbg_status = 0; 1025#if HAVE_LIKEWISE_LWIO 1026 PSTR smbpath = NULL; 1027 PBYTE sesskey = NULL; 1028 USHORT sesskeylen = 0; 1029 IO_FILE_NAME filename = { 0 }; 1030 IO_STATUS_BLOCK io_status = { 0 }; 1031 size_t len; 1032#endif 1033 1034 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_connect called\n")); 1035 1036 SMB_SOCKET_LOCK(smb); 1037 1038 /* Break address into host and endpoint */ 1039 rpc__naf_addr_inq_netaddr (addr, 1040 (unsigned_char_t**) &netaddr, 1041 &dbg_status); 1042 rpc__naf_addr_inq_endpoint (addr, 1043 (unsigned_char_t**) &endpoint, 1044 &dbg_status); 1045 1046 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1047 ("rpc__smb_socket_connect - netaddr <%s>\n", netaddr)); 1048 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1049 ("rpc__smb_socket_connect - ep <%s>\n", endpoint)); 1050 1051 if (rpc__np_is_valid_endpoint(endpoint, &dbg_status)) 1052 { 1053 pipename = (char *)endpoint + sizeof("\\pipe\\") - 1; 1054 } 1055 else 1056 { 1057 serr = RPC_C_SOCKET_EINVAL; 1058 goto error; 1059 } 1060 1061 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1062 ("rpc__smb_socket_connect - pipename <%s>\n", pipename)); 1063 1064#if HAVE_LIKEWISE_LWIO 1065 len = strlen(netaddr) + strlen(pipename) + strlen("\\rdr\\\\IPC$\\") + 1; 1066 smbpath = malloc(len); 1067 if (smbpath == NULL) { 1068 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1069 ("rpc__smb_socket_connect - smbpath malloc failed\n")); 1070 serr = RPC_C_SOCKET_ENOMEM; 1071 goto error; 1072 } 1073 snprintf (smbpath, len, "\\rdr\\%s\\IPC$\\%s", 1074 (char*) netaddr, (char*) pipename); 1075#elif HAVE_SMBCLIENT_FRAMEWORK 1076 serr = rpc__smbclient_connect(smb, netaddr, pipename); 1077#else 1078 serr = RPC_C_SOCKET_ENOTSUP; 1079 goto error; 1080#endif 1081 1082#if HAVE_LIKEWISE_LWIO 1083 1084 serr = NtStatusToErrno( 1085 LwRtlCStringAllocatePrintf( 1086 &smbpath, 1087 "\\rdr\\%s\\IPC$\\%s", 1088 (char*) netaddr, 1089 (char*) pipename)); 1090 if (serr) 1091 { 1092 goto error; 1093 } 1094 1095 serr = NtStatusToErrno( 1096 LwRtlWC16StringAllocateFromCString( 1097 &filename.FileName, 1098 smbpath)); 1099 if (serr) 1100 { 1101 goto error; 1102 } 1103 1104 serr = NtStatusToErrno( 1105 NtCtxCreateFile( 1106 smb->context, /* IO context */ 1107 smb->info.creds, /* Security token */ 1108 &smb->np, /* Created handle */ 1109 NULL, /* Async control block */ 1110 &io_status, /* Status block */ 1111 &filename, /* Filename */ 1112 NULL, /* Security descriptor */ 1113 NULL, /* Security QOS */ 1114 GENERIC_READ | GENERIC_WRITE, /* Access mode */ 1115 0, /* Allocation size */ 1116 0, /* File attributes */ 1117 FILE_SHARE_READ | FILE_SHARE_WRITE, /* Sharing mode */ 1118 FILE_OPEN, /* Create disposition */ 1119 FILE_CREATE_TREE_CONNECTION, /* Create options */ 1120 NULL, /* EA buffer */ 1121 0, /* EA buffer length */ 1122 NULL /* ECP List */ 1123 )); 1124 if (serr) 1125 { 1126 goto error; 1127 } 1128 1129 serr = NtStatusToErrno( 1130 LwIoCtxGetSessionKey( 1131 smb->context, 1132 smb->np, 1133 &sesskeylen, 1134 &sesskey)); 1135 if (serr) 1136 { 1137 goto error; 1138 } 1139 1140 smb->info.session_key.length = sesskeylen; 1141 smb->info.session_key.data = malloc(sesskeylen); 1142 if (!smb->info.session_key.data) 1143 { 1144 serr = RPC_C_SOCKET_ENOMEM; 1145 goto error; 1146 } 1147 memcpy(smb->info.session_key.data, sesskey, sesskeylen); 1148#endif 1149 1150 /* Save address for future inquiries on this socket */ 1151 memcpy(&smb->peeraddr, addr, sizeof(smb->peeraddr)); 1152 1153 /* Since we did a connect, we will be sending first */ 1154 smb->state = SMB_STATE_SEND; 1155 1156done: 1157 1158#if HAVE_LIKEWISE_LWIO 1159 if (sesskey) 1160 { 1161 RtlMemoryFree(sesskey); 1162 } 1163 1164 if (filename.FileName) 1165 { 1166 RtlMemoryFree(filename.FileName); 1167 } 1168 1169 if (smbpath) 1170 { 1171 free(smbpath); 1172 } 1173#endif 1174 1175 SMB_SOCKET_UNLOCK(smb); 1176 1177 // rpc_string_free handles when *ptr is NULL 1178 rpc_string_free((unsigned_char_t**) &netaddr, &dbg_status); 1179 rpc_string_free((unsigned_char_t**) &endpoint, &dbg_status); 1180 1181 return serr; 1182 1183error: 1184 1185 goto done; 1186} 1187 1188INTERNAL 1189rpc_socket_error_t 1190rpc__smb_socket_accept( 1191#if HAVE_LIKEWISE_LWIO 1192 rpc_socket_t sock, 1193 rpc_addr_p_t addr, 1194 rpc_socket_t *newsock 1195#else 1196 rpc_socket_t sock ATTRIBUTE_UNUSED, 1197 rpc_addr_p_t addr ATTRIBUTE_UNUSED, 1198 rpc_socket_t *newsock ATTRIBUTE_UNUSED 1199#endif 1200 ) 1201{ 1202 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1203 1204 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_accept called\n")); 1205 1206#if !defined(HAVE_LIKEWISE_LWIO) 1207 serr = RPC_C_SOCKET_ENOTSUP; 1208#else 1209 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 1210 rpc_socket_t npsock = NULL; 1211 rpc_smb_socket_p_t npsmb = NULL; 1212 IO_FILE_HANDLE np = NULL; 1213 size_t i; 1214 char c = 0; 1215 BYTE clientaddr[4] = {0, 0, 0, 0}; 1216 USHORT clientaddrlen = sizeof(clientaddr); 1217 1218 *newsock = NULL; 1219 1220 SMB_SOCKET_LOCK(smb); 1221 1222 while (smb->accept_backlog.length == 0) 1223 { 1224 if (smb->state == SMB_STATE_ERROR) 1225 { 1226 serr = -1; 1227 goto error; 1228 } 1229 1230 rpc__smb_socket_wait(smb); 1231 } 1232 1233 for (i = 0; i < smb->accept_backlog.capacity; i++) 1234 { 1235 if (smb->accept_backlog.queue[i] != NULL) 1236 { 1237 np = smb->accept_backlog.queue[i]; 1238 smb->accept_backlog.queue[i] = NULL; 1239 smb->accept_backlog.length--; 1240 if (read(smb->accept_backlog.selectfd[0], &c, sizeof(c)) != sizeof(c)) 1241 { 1242 serr = errno; 1243 goto error; 1244 } 1245 dcethread_cond_broadcast_throw(&smb->event); 1246 break; 1247 } 1248 } 1249 1250 serr = rpc__socket_open(sock->pseq_id, NULL, &npsock); 1251 if (serr) 1252 { 1253 goto error; 1254 } 1255 1256 npsmb = (rpc_smb_socket_p_t) npsock->data.pointer; 1257 1258 npsmb->np = np; 1259 np = NULL; 1260 1261 npsmb->state = SMB_STATE_RECV; 1262 1263 memcpy(&npsmb->localaddr, &smb->localaddr, sizeof(npsmb->localaddr)); 1264 1265 /* Use our address as a template for client address */ 1266 memcpy(&npsmb->peeraddr, &smb->localaddr, sizeof(npsmb->peeraddr)); 1267 1268 /* Query for client address */ 1269 serr = NtStatusToErrno( 1270 LwIoCtxGetPeerAddress( 1271 npsmb->context, 1272 npsmb->np, 1273 clientaddr, 1274 &clientaddrlen)); 1275 if (serr) 1276 { 1277 goto error; 1278 } 1279 1280 if (clientaddrlen == sizeof(clientaddr)) 1281 { 1282 snprintf(npsmb->peeraddr.remote_host, sizeof(npsmb->peeraddr.remote_host) - 1, 1283 "%u.%u.%u.%u", clientaddr[0], clientaddr[1], clientaddr[2], clientaddr[3]); 1284 } 1285 1286 if (addr) 1287 { 1288 memcpy(addr, &npsmb->peeraddr, sizeof(npsmb->peeraddr)); 1289 } 1290 1291 serr = NtStatusToErrno( 1292 LwIoCtxGetPeerPrincipalName( 1293 npsmb->context, 1294 npsmb->np, 1295 &npsmb->info.peer_principal)); 1296 if (serr) 1297 { 1298 goto error; 1299 } 1300 1301 serr = NtStatusToErrno( 1302 LwIoCtxGetSessionKey( 1303 npsmb->context, 1304 npsmb->np, 1305 &npsmb->info.session_key.length, 1306 &npsmb->info.session_key.data)); 1307 if (serr) 1308 { 1309 goto error; 1310 } 1311 1312 *newsock = npsock; 1313 1314error: 1315 1316 if (np) 1317 { 1318 NtCtxCloseFile(smb->context, np); 1319 } 1320 1321 SMB_SOCKET_UNLOCK(smb); 1322#endif 1323 1324 return serr; 1325} 1326 1327#if HAVE_LIKEWISE_LWIO 1328INTERNAL 1329void* 1330rpc__smb_socket_listen_thread(void* data) 1331{ 1332 int serr = RPC_C_SOCKET_OK; 1333 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) data; 1334 IO_STATUS_BLOCK status_block = { 0 }; 1335 char *endpoint = NULL; 1336 char *pipename = NULL; 1337 unsigned32 dbg_status = 0; 1338 PSTR smbpath = NULL; 1339 IO_FILE_NAME filename = { 0 }; 1340 size_t i; 1341 char c = 0; 1342 LONG64 default_timeout = 0; 1343 1344 SMB_SOCKET_LOCK(smb); 1345 1346 while (smb->state != SMB_STATE_LISTEN) 1347 { 1348 if (smb->state == SMB_STATE_ERROR) 1349 { 1350 goto error; 1351 } 1352 1353 rpc__smb_socket_wait(smb); 1354 } 1355 1356 /* Extract endpoint */ 1357 rpc__naf_addr_inq_endpoint ((rpc_addr_p_t) &smb->localaddr, 1358 (unsigned_char_t**) &endpoint, 1359 &dbg_status); 1360 1361 if (rpc__np_is_valid_endpoint(endpoint, &dbg_status)) 1362 { 1363 pipename = endpoint + sizeof("\\pipe\\") - 1; 1364 } 1365 else 1366 { 1367 serr = RPC_C_SOCKET_EINVAL; 1368 goto error; 1369 } 1370 1371 serr = NtStatusToErrno( 1372 LwRtlCStringAllocatePrintf( 1373 &smbpath, 1374 "\\npfs\\%s", 1375 (char*) pipename)); 1376 if (serr) 1377 { 1378 goto error; 1379 } 1380 1381 serr = NtStatusToErrno( 1382 LwRtlWC16StringAllocateFromCString( 1383 &filename.FileName, 1384 smbpath)); 1385 if (serr) 1386 { 1387 goto error; 1388 } 1389 1390 while (smb->state == SMB_STATE_LISTEN) 1391 { 1392 SMB_SOCKET_UNLOCK(smb); 1393 1394 serr = NtStatusToErrno( 1395 LwNtCtxCreateNamedPipeFile( 1396 smb->context, /* IO context */ 1397 NULL, /* Security token */ 1398 &smb->np, /* NP handle */ 1399 NULL, /* Async control */ 1400 &status_block, /* IO status block */ 1401 &filename, /* Filename */ 1402 NULL, /* Security descriptor */ 1403 NULL, /* Security QOS */ 1404 GENERIC_READ | GENERIC_WRITE, /* Desired access mode */ 1405 FILE_SHARE_READ | FILE_SHARE_WRITE, /* Share access mode */ 1406 FILE_CREATE, /* Create disposition */ 1407 0, /* Create options */ 1408 0, /* Named pipe type */ 1409 0, /* Read mode */ 1410 0, /* Completion mode */ 1411 smb->accept_backlog.capacity, /* Maximum instances */ 1412 0, /* Inbound quota */ 1413 0, /* Outbound quota */ 1414 &default_timeout /* Default timeout */ 1415 )); 1416 if (serr) 1417 { 1418 SMB_SOCKET_LOCK(smb); 1419 goto error; 1420 } 1421 1422 serr = NtStatusToErrno( 1423 LwIoCtxConnectNamedPipe( 1424 smb->context, 1425 smb->np, 1426 NULL, 1427 &status_block)); 1428 if (serr) 1429 { 1430 SMB_SOCKET_LOCK(smb); 1431 goto error; 1432 } 1433 1434 SMB_SOCKET_LOCK(smb); 1435 1436 /* Wait for a slot to open in the accept queue */ 1437 while (smb->accept_backlog.length == smb->accept_backlog.capacity) 1438 { 1439 if (smb->state == SMB_STATE_ERROR) 1440 { 1441 goto error; 1442 } 1443 1444 rpc__smb_socket_wait(smb); 1445 } 1446 1447 /* Put the handle into the accept queue */ 1448 for (i = 0; i < smb->accept_backlog.capacity; i++) 1449 { 1450 if (smb->accept_backlog.queue[i] == NULL) 1451 { 1452 smb->accept_backlog.queue[i] = smb->np; 1453 smb->np = NULL; 1454 smb->accept_backlog.length++; 1455 if (write(smb->accept_backlog.selectfd[1], &c, sizeof(c)) != sizeof(c)) 1456 { 1457 serr = errno; 1458 goto error; 1459 } 1460 dcethread_cond_broadcast_throw(&smb->event); 1461 break; 1462 } 1463 } 1464 } 1465 1466error: 1467 if (filename.FileName) 1468 { 1469 RtlMemoryFree(filename.FileName); 1470 } 1471 1472 if (smbpath) 1473 { 1474 RtlMemoryFree(smbpath); 1475 } 1476 1477 // rpc_string_free handles when *ptr is NULL 1478 rpc_string_free((unsigned_char_t**) &endpoint, &dbg_status); 1479 1480 if (serr) 1481 { 1482 rpc__smb_socket_change_state(smb, SMB_STATE_ERROR); 1483 } 1484 1485 SMB_SOCKET_UNLOCK(smb); 1486 1487 return NULL; 1488} 1489#endif 1490 1491INTERNAL 1492rpc_socket_error_t 1493rpc__smb_socket_listen( 1494#if HAVE_LIKEWISE_LWIO 1495 rpc_socket_t sock, 1496 int backlog 1497#else 1498 rpc_socket_t sock ATTRIBUTE_UNUSED, 1499 int backlog ATTRIBUTE_UNUSED 1500#endif 1501 ) 1502{ 1503 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1504 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_listen called\n")); 1505 1506#if !defined(HAVE_LIKEWISE_LWIO) 1507 serr = RPC_C_SOCKET_ENOTSUP; 1508 return serr; 1509#else 1510 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 1511 1512 SMB_SOCKET_LOCK(smb); 1513 1514 smb->accept_backlog.capacity = backlog; 1515 smb->accept_backlog.length = 0; 1516 smb->accept_backlog.queue = calloc(backlog, sizeof(*smb->accept_backlog.queue)); 1517 1518 if (!smb->accept_backlog.queue) 1519 { 1520 serr = RPC_C_SOCKET_ENOMEM; 1521 goto error; 1522 } 1523 1524 if (pipe(smb->accept_backlog.selectfd) != 0) 1525 { 1526 serr = errno; 1527 goto error; 1528 } 1529 1530 smb->state = SMB_STATE_LISTEN; 1531 1532 dcethread_create_throw(&smb->listen_thread, NULL, rpc__smb_socket_listen_thread, smb); 1533 1534error: 1535 1536 SMB_SOCKET_UNLOCK(smb); 1537#endif 1538 return serr; 1539} 1540 1541#if HAVE_SMBCLIENT_FRAMEWORK 1542INTERNAL 1543rpc_socket_error_t 1544smb_data_send( 1545#if SMB_NP_NO_TRANSACTIONS 1546 rpc_socket_t sock 1547#else 1548 rpc_socket_t sock ATTRIBUTE_UNUSED 1549#endif 1550 ) 1551{ 1552 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1553 rpc_smb_socket_p_t smb; 1554 unsigned char* cursor; 1555 size_t bytes_written = 0; 1556#if SMB_NP_NO_TRANSACTIONS 1557 NTSTATUS status; 1558 1559 smb = (rpc_smb_socket_p_t) sock->data.pointer; 1560 cursor = smb->sendbuffer.base; 1561#endif 1562 1563 do 1564 { 1565#if SMB_NP_NO_TRANSACTIONS 1566 /* <bms> Write the data out without using transactions */ 1567 status = SMBWriteFile(smb->handle, 1568 smb->hFile, 1569 cursor, 1570 0, 1571 smb->sendbuffer.start_cursor - cursor, 1572 &bytes_written); 1573 1574 if (!NT_SUCCESS(status)) 1575 { 1576 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_do_send - SMBWriteFile failed 0x%x\n", status)); 1577 serr = rpc_smb_ntstatus_to_rpc_error (status); 1578 } 1579#else 1580 /* <bms> for transactions, do nothing here. Later in the 1581 receive, we will do the send and receive in a single 1582 transaction. */ 1583 serr = RPC_C_SOCKET_OK; 1584 goto error; 1585#endif 1586 1587 if (serr) 1588 { 1589 goto error; 1590 } 1591 1592 cursor += bytes_written; 1593 } while (cursor < smb->sendbuffer.start_cursor); 1594 1595 /* Settle the remaining data (which hopefully should be zero if 1596 the runtime calls us with complete packets) to the start of 1597 the send buffer */ 1598 rpc__smb_buffer_settle(&smb->sendbuffer); 1599 1600error: 1601 1602 return serr; 1603} 1604 1605INTERNAL 1606rpc_socket_error_t 1607smb_data_do_recv( 1608 rpc_socket_t sock, 1609 size_t* count 1610) 1611{ 1612 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1613 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 1614 size_t bytes_requested = 0; 1615 size_t bytes_read = 0; 1616 NTSTATUS status = STATUS_SUCCESS; 1617#if !SMB_NP_NO_TRANSACTIONS 1618 unsigned char* cursor = smb->sendbuffer.base; 1619 rpc_cn_common_hdr_p_t packet; 1620 size_t frag_len; 1621 size_t bytes_written; 1622 int sent_data = 0; 1623#endif 1624 1625 *count = 0; 1626 1627 do 1628 { 1629 serr = rpc__smb_buffer_ensure_available(&smb->recvbuffer, smb->maxRecvBufferSize); 1630 if (serr) 1631 { 1632 goto error; 1633 } 1634 1635 bytes_read = 0; 1636 bytes_requested = rpc__smb_buffer_available(&smb->recvbuffer); 1637#if SMB_NP_NO_TRANSACTIONS 1638 /* <bms> Read the data in without using transactions */ 1639 status = SMBReadFile(smb->handle, 1640 smb->hFile, 1641 smb->recvbuffer.end_cursor, 1642 0, 1643 bytes_requested, 1644 &bytes_read); 1645 1646 if (!NT_SUCCESS(status)) 1647 { 1648 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1649 ("rpc__smb_socket_do_recv - SMBReadFile failed 0x%x\n", 1650 status)); 1651 serr = rpc_smb_ntstatus_to_rpc_error (status); 1652 } 1653#else 1654 if ((smb->sendbuffer.start_cursor - cursor) != 0) 1655 { 1656 /* Check to see if this is a last fragment or not */ 1657 packet = (rpc_cn_common_hdr_p_t) cursor; 1658 while (!(packet->flags & RPC_C_CN_FLAGS_LAST_FRAG)) 1659 { 1660 /* its not a last fragment, so send with SMBWriteFile */ 1661 frag_len = rpc__smb_fragment_size(packet); 1662 1663 /* Safety check to make sure we are not past the end 1664 of the sendbuffer */ 1665 if ( (cursor + frag_len) > smb->sendbuffer.start_cursor) 1666 { 1667 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1668 ("rpc__smb_socket_do_recv - past end of send buffer\n")); 1669 serr = RPC_C_SOCKET_EIO; 1670 goto error; 1671 } 1672 1673 bytes_written = 0; 1674 sent_data = 1; 1675 status = SMBWriteFile(smb->handle, 1676 smb->hFile, 1677 cursor, 1678 0, 1679 frag_len, 1680 &bytes_written); 1681 1682 if (!NT_SUCCESS(status)) 1683 { 1684 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1685 ("rpc__smb_socket_do_send - SMBWriteFile failed 0x%x\n", 1686 status)); 1687 serr = rpc_smb_ntstatus_to_rpc_error (status); 1688 } 1689 1690 if (serr) 1691 { 1692 goto error; 1693 } 1694 cursor += bytes_written; 1695 packet = (rpc_cn_common_hdr_p_t) cursor; 1696 } 1697 } 1698 1699 if ((smb->sendbuffer.start_cursor - cursor) == 0) 1700 { 1701 /* <bms> Must be reading in a fragment, so read the data in 1702 without using transactions */ 1703 status = SMBReadFile(smb->handle, 1704 smb->hFile, 1705 smb->recvbuffer.end_cursor, 1706 0, 1707 bytes_requested, 1708 &bytes_read); 1709 if (!NT_SUCCESS(status)) 1710 { 1711 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1712 ("rpc__smb_socket_do_recv - SMBReadFile failed 0x%x\n", 1713 status)); 1714 serr = rpc_smb_ntstatus_to_rpc_error (status); 1715 } 1716 } 1717 else 1718 { 1719 /* <bms> for transactions, do send and rcv in a single transaction. */ 1720 sent_data = 1; 1721 status = SMBTransactNamedPipe(smb->handle, 1722 smb->hFile, 1723 cursor, 1724 smb->sendbuffer.start_cursor - cursor, 1725 smb->recvbuffer.end_cursor, 1726 bytes_requested, 1727 &bytes_read); 1728 1729 if (!NT_SUCCESS(status)) 1730 { 1731 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, 1732 ("rpc__smb_socket_do_recv - SMBTransactNamedPipe failed 0x%x\n", 1733 status)); 1734 serr = rpc_smb_ntstatus_to_rpc_error (status); 1735 } 1736 } 1737 1738 if (sent_data == 1) 1739 { 1740 /* assume all the data got sent */ 1741 rpc__smb_buffer_settle(&smb->sendbuffer); 1742 sent_data = 0; 1743 cursor = smb->sendbuffer.base; 1744 } 1745#endif 1746 1747 if (status == STATUS_END_OF_FILE) 1748 { 1749 serr = RPC_C_SOCKET_OK; 1750 bytes_read = 0; 1751 } 1752 else 1753 { 1754 smb->recvbuffer.end_cursor += bytes_read; 1755 } 1756 1757 if (((size_t)*count + bytes_read) > SIZE_T_MAX || 1758 ((size_t)*count + bytes_read) < (size_t)*count) { 1759 serr = RPC_C_SOCKET_ENOSPC; 1760 goto error; 1761 } 1762 1763 *count += (size_t)bytes_read; 1764 } while (NT_SUCCESS(status) && bytes_read == bytes_requested); 1765 1766error: 1767 1768 return serr; 1769} 1770#endif 1771 1772INTERNAL 1773rpc_socket_error_t 1774rpc__smb_socket_do_send( 1775 rpc_socket_t sock 1776 ) 1777{ 1778#if HAVE_SMBCLIENT_FRAMEWORK 1779 return (smb_data_send (sock)); 1780#elif HAVE_LIKEWISE_LWIO 1781 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1782 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 1783 unsigned char* cursor = smb->sendbuffer.base; 1784 DWORD bytes_written = 0; 1785 IO_STATUS_BLOCK io_status = { 0 }; 1786 1787 do 1788 { 1789 serr = NtStatusToErrno( 1790 NtCtxWriteFile( 1791 smb->context, /* IO context */ 1792 smb->np, /* File handle */ 1793 NULL, /* Async control block */ 1794 &io_status, /* IO status block */ 1795 smb->sendbuffer.base, /* Buffer */ 1796 smb->sendbuffer.start_cursor - cursor, /* Length */ 1797 NULL, /* Byte offset */ 1798 NULL /* Key */ 1799 )); 1800 1801 if (serr) 1802 { 1803 goto error; 1804 } 1805 1806 bytes_written = io_status.BytesTransferred; 1807 cursor += bytes_written; 1808 } while (cursor < smb->sendbuffer.start_cursor); 1809 1810 /* Settle the remaining data (which hopefully should be zero if 1811 the runtime calls us with complete packets) to the start of 1812 the send buffer */ 1813 rpc__smb_buffer_settle(&smb->sendbuffer); 1814 1815error: 1816 1817 return serr; 1818#else 1819 return RPC_C_SOCKET_ENOTSUP; 1820#endif 1821} 1822 1823INTERNAL 1824rpc_socket_error_t 1825rpc__smb_socket_do_recv( 1826 rpc_socket_t sock, 1827 size_t* count 1828 ) 1829{ 1830#if HAVE_SMBCLIENT_FRAMEWORK 1831 return (smb_data_do_recv (sock, count)); 1832#elif HAVE_LIKEWISE_LWIO 1833 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1834 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 1835 DWORD bytes_requested = 0; 1836 DWORD bytes_read = 0; 1837 IO_STATUS_BLOCK io_status = { 0 }; 1838 NTSTATUS status = STATUS_SUCCESS; 1839 1840 *count = 0; 1841 1842 do 1843 { 1844 serr = rpc__smb_buffer_ensure_available(&smb->recvbuffer, smb->maxRecvBufferSize); 1845 if (serr) 1846 { 1847 goto error; 1848 } 1849 1850 bytes_read = 0; 1851 bytes_requested = rpc__smb_buffer_available(&smb->recvbuffer); 1852 1853 status = NtCtxReadFile( 1854 smb->context, /* IO context */ 1855 smb->np, /* File handle */ 1856 NULL, /* Async control block */ 1857 &io_status, /* IO status block */ 1858 smb->recvbuffer.end_cursor, /* Buffer */ 1859 bytes_requested, /* Length */ 1860 NULL, /* Byte offset */ 1861 NULL /* Key */ 1862 ); 1863 if (status == STATUS_END_OF_FILE) 1864 { 1865 serr = 0; 1866 bytes_read = 0; 1867 } 1868 else 1869 { 1870 serr = NtStatusToErrno(status); 1871 bytes_read = io_status.BytesTransferred; 1872 smb->recvbuffer.end_cursor += bytes_read; 1873 } 1874 1875 if (((off_t)*count + bytes_read) > SIZE_T_MAX || 1876 ((off_t)*count + bytes_read) < (off_t)*count) { 1877 serr = RPC_C_SOCKET_ENOSPC; 1878 goto error; 1879 } 1880 1881 *count += bytes_read; 1882 } while (NT_SUCCESS(status) && bytes_read == bytes_requested); 1883 1884error: 1885 1886 return serr; 1887#else 1888 return RPC_C_SOCKET_ENOTSUP; 1889#endif 1890 1891} 1892 1893INTERNAL 1894rpc_socket_error_t 1895rpc__smb_socket_sendmsg( 1896 rpc_socket_t sock, 1897 rpc_socket_iovec_p_t iov, 1898 int iov_len, 1899 rpc_addr_p_t addr ATTRIBUTE_UNUSED, 1900 size_t *cc 1901 ) 1902{ 1903 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1904 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 1905 int i; 1906 size_t pending = 0; 1907 1908 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_sendmsg called\n")); 1909 1910 SMB_SOCKET_LOCK(smb); 1911 1912 /* Wait until we are in a state where we can send */ 1913 while (smb->state != SMB_STATE_SEND) 1914 { 1915 if (smb->state == SMB_STATE_ERROR) 1916 { 1917 serr = -1; 1918 goto error; 1919 } 1920 rpc__smb_socket_wait(smb); 1921 } 1922 1923 *cc = 0; 1924 1925 /* Append all fragments into a single buffer */ 1926 for (i = 0; i < iov_len; i++) 1927 { 1928 serr = rpc__smb_buffer_append(&smb->sendbuffer, iov[i].iov_base, iov[i].iov_len); 1929 1930 if (serr) 1931 { 1932 goto error; 1933 } 1934 1935 *cc += (int)iov[i].iov_len; 1936 } 1937 1938 /* Look for the last fragment and do send if we find it */ 1939 if (rpc__smb_buffer_advance_cursor(&smb->sendbuffer, &pending)) 1940 { 1941 serr = rpc__smb_socket_do_send(sock); 1942 if (serr) 1943 { 1944 goto error; 1945 } 1946 1947 /* Switch into recv mode */ 1948 rpc__smb_socket_change_state(smb, SMB_STATE_RECV); 1949 } 1950 1951cleanup: 1952 1953 SMB_SOCKET_UNLOCK(smb); 1954 1955 return serr; 1956 1957error: 1958 1959 rpc__smb_socket_change_state(smb, SMB_STATE_ERROR); 1960 1961 goto cleanup; 1962} 1963 1964INTERNAL 1965rpc_socket_error_t 1966rpc__smb_socket_recvfrom( 1967 rpc_socket_t sock ATTRIBUTE_UNUSED, 1968 byte_p_t buf ATTRIBUTE_UNUSED, 1969 int len ATTRIBUTE_UNUSED, 1970 rpc_addr_p_t from ATTRIBUTE_UNUSED, 1971 size_t *cc ATTRIBUTE_UNUSED 1972) 1973{ 1974 rpc_socket_error_t serr = RPC_C_SOCKET_ENOTSUP; 1975 1976 fprintf(stderr, "WARNING: unsupported smb socket function %s\n", __FUNCTION__); 1977 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_recvfrom called\n")); 1978 1979 return serr; 1980} 1981 1982INTERNAL 1983rpc_socket_error_t 1984rpc__smb_socket_recvmsg( 1985 rpc_socket_t sock, 1986 rpc_socket_iovec_p_t iov, 1987 int iov_len, 1988 rpc_addr_p_t addr, 1989 size_t *cc 1990) 1991{ 1992 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 1993 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 1994 int i; 1995 size_t pending; 1996 size_t count; 1997 1998 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_recvmsg called\n")); 1999 2000 SMB_SOCKET_LOCK(smb); 2001 2002 while (smb->state != SMB_STATE_RECV) 2003 { 2004 if (smb->state == SMB_STATE_ERROR) 2005 { 2006 serr = -1; 2007 goto error; 2008 } 2009 rpc__smb_socket_wait(smb); 2010 } 2011 2012 *cc = 0; 2013 2014 if (rpc__smb_buffer_length(&smb->recvbuffer) == 0) 2015 { 2016 /* Nothing in buffer, read a complete message */ 2017 do 2018 { 2019 serr = rpc__smb_socket_do_recv(sock, &count); 2020 if (serr) 2021 { 2022 goto error; 2023 } 2024 if (count == 0) 2025 { 2026 break; 2027 } 2028 } while (!rpc__smb_buffer_advance_cursor(&smb->recvbuffer, NULL)); 2029 2030 /* Reset cursor back to start to begin disperal into scatter buffer */ 2031 smb->recvbuffer.start_cursor = smb->recvbuffer.base; 2032 } 2033 2034 for (i = 0; i < iov_len; i++) 2035 { 2036 pending = rpc__smb_buffer_pending(&smb->recvbuffer); 2037 if (iov[i].iov_len < pending) 2038 { 2039 memcpy(iov[i].iov_base, smb->recvbuffer.start_cursor, iov[i].iov_len); 2040 2041 smb->recvbuffer.start_cursor += iov[i].iov_len; 2042 *cc += (int)iov[i].iov_len; 2043 } 2044 else 2045 { 2046 memcpy(iov[i].iov_base, smb->recvbuffer.start_cursor, pending); 2047 2048 *cc += (int)pending; 2049 2050 /* Reset buffer because we have emptied it */ 2051 smb->recvbuffer.start_cursor = smb->recvbuffer.end_cursor = smb->recvbuffer.base; 2052 /* Switch into send mode */ 2053 rpc__smb_socket_change_state(smb, SMB_STATE_SEND); 2054 } 2055 } 2056 2057 if (addr) 2058 { 2059 memcpy(addr, &smb->peeraddr, sizeof(smb->peeraddr)); 2060 } 2061 2062cleanup: 2063 2064 SMB_SOCKET_UNLOCK(smb); 2065 2066 return serr; 2067 2068error: 2069 2070 rpc__smb_socket_change_state(smb, SMB_STATE_ERROR); 2071 2072 goto cleanup; 2073} 2074 2075INTERNAL 2076rpc_socket_error_t 2077rpc__smb_socket_inq_endpoint( 2078 rpc_socket_t sock, 2079 rpc_addr_p_t addr 2080) 2081{ 2082 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_inq_endpoint called\n")); 2083 2084 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2085 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 2086 2087 if (addr->len == 0) 2088 { 2089 addr->len = sizeof(addr->sa); 2090 } 2091 2092 addr->rpc_protseq_id = smb->localaddr.rpc_protseq_id; 2093 memcpy(&addr->sa, &smb->localaddr.sa, addr->len); 2094 2095 return serr; 2096} 2097 2098INTERNAL 2099rpc_socket_error_t 2100rpc__smb_socket_set_broadcast( 2101 rpc_socket_t sock ATTRIBUTE_UNUSED 2102) 2103{ 2104 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_set_broadcast called\n")); 2105 2106 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2107 2108 return serr; 2109} 2110 2111#if HAVE_SMBCLIENT_FRAMEWORK && HAVE_SMBCLIENT_SMBGETSERVERPROPERTIES 2112INTERNAL 2113rpc__smbclient_set_bufs( 2114 rpc_socket_t sock, 2115 unsigned32 *ntxsize, 2116 unsigned32 *nrxsize 2117) 2118{ 2119 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 2120 SMBServerPropertiesV1 server_properties; 2121 NTSTATUS status; 2122 2123 if ( !smb->handle || (smb->maxSendBufferSize != 0) ) 2124 { 2125 return (RPC_C_SOCKET_OK); 2126 } 2127 2128 memset(&server_properties, 0, sizeof(server_properties)); 2129 2130 /* try to get the max transaction size that is supported */ 2131 status = SMBGetServerProperties(smb->handle, &server_properties, 2132 kPropertiesVersion, sizeof(server_properties)); 2133 if (NT_SUCCESS(status)) 2134 { 2135 smb->maxSendBufferSize = (unsigned32) MIN (server_properties.maxWriteBytes, server_properties.maxTransactBytes); 2136 smb->maxRecvBufferSize = (unsigned32) MIN (server_properties.maxReadBytes, server_properties.maxTransactBytes); 2137 2138 /* round down to nearest 1K */ 2139 smb->maxSendBufferSize = (smb->maxSendBufferSize / 1024) * 1024; 2140 smb->maxRecvBufferSize = (smb->maxRecvBufferSize / 1024) * 1024; 2141 2142 /* fragments can not be bigger than UInt16 */ 2143 if (smb->maxSendBufferSize > UINT16_MAX) 2144 smb->maxSendBufferSize = UINT16_MAX; 2145 2146 if (smb->maxRecvBufferSize > UINT16_MAX) 2147 smb->maxRecvBufferSize = UINT16_MAX; 2148 } 2149 2150 *ntxsize = (unsigned32) smb->maxSendBufferSize; 2151 *nrxsize = (unsigned32) smb->maxRecvBufferSize; 2152 2153 return (RPC_C_SOCKET_OK); 2154} 2155#endif 2156 2157INTERNAL 2158rpc_socket_error_t 2159rpc__smb_socket_set_bufs( 2160 rpc_socket_t sock ATTRIBUTE_UNUSED, 2161 unsigned32 txsize ATTRIBUTE_UNUSED, 2162 unsigned32 rxsize ATTRIBUTE_UNUSED, 2163 unsigned32 *ntxsize ATTRIBUTE_UNUSED, 2164 unsigned32 *nrxsize ATTRIBUTE_UNUSED 2165) 2166{ 2167 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2168 2169 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_set_bufs called\n")); 2170 2171#if HAVE_SMBCLIENT_FRAMEWORK && HAVE_SMBCLIENT_SMBGETSERVERPROPERTIES 2172 serr = rpc__smbclient_set_bufs(sock, ntxsize, nrxsize); 2173#else 2174 *ntxsize = MIN(RPC_C_CN_LARGE_FRAG_SIZE, RPC_C_SOCKET_MAX_SNDBUF); 2175 *nrxsize = MIN(RPC_C_CN_LARGE_FRAG_SIZE, RPC_C_SOCKET_MAX_RCVBUF); 2176#endif 2177 2178 return serr; 2179} 2180 2181INTERNAL 2182rpc_socket_error_t 2183rpc__smb_socket_set_nbio( 2184 rpc_socket_t sock ATTRIBUTE_UNUSED 2185 ) 2186{ 2187 rpc_socket_error_t serr = RPC_C_SOCKET_ENOTSUP; 2188 2189 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_set_nbio called\n")); 2190 fprintf(stderr, "WARNING: unsupported smb socket function %s\n", __FUNCTION__); 2191 2192 return serr; 2193} 2194 2195INTERNAL 2196rpc_socket_error_t 2197rpc__smb_socket_set_close_on_exec( 2198 rpc_socket_t sock ATTRIBUTE_UNUSED 2199 ) 2200{ 2201 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_set_close_on_exec called\n")); 2202 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2203 2204 return serr; 2205} 2206 2207INTERNAL 2208rpc_socket_error_t 2209rpc__smb_socket_getpeername( 2210 rpc_socket_t sock, 2211 rpc_addr_p_t addr 2212 ) 2213{ 2214 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2215 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 2216 2217 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_getpeername called\n")); 2218 SMB_SOCKET_LOCK(smb); 2219 2220#if HAVE_LIKEWISE_LWIO 2221 if (!smb->np) 2222 { 2223 serr = RPC_C_SOCKET_EINVAL; 2224 goto error; 2225 } 2226#endif 2227 2228 memcpy(addr, &smb->peeraddr, sizeof(smb->peeraddr)); 2229 2230error: 2231 2232 SMB_SOCKET_UNLOCK(smb); 2233 2234 return serr; 2235} 2236 2237INTERNAL 2238rpc_socket_error_t 2239rpc__smb_socket_get_if_id( 2240 rpc_socket_t sock ATTRIBUTE_UNUSED, 2241 rpc_network_if_id_t *network_if_id ATTRIBUTE_UNUSED 2242 ) 2243{ 2244 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2245 2246 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_get_if_id called\n")); 2247 *network_if_id = SOCK_STREAM; 2248 2249 return serr; 2250} 2251 2252INTERNAL 2253rpc_socket_error_t 2254rpc__smb_socket_set_keepalive( 2255 rpc_socket_t sock ATTRIBUTE_UNUSED 2256 ) 2257{ 2258 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_set_keepalive called\n")); 2259 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2260 2261 return serr; 2262} 2263 2264INTERNAL 2265rpc_socket_error_t 2266rpc__smb_socket_nowriteblock_wait( 2267 rpc_socket_t sock ATTRIBUTE_UNUSED, 2268 struct timeval *tmo ATTRIBUTE_UNUSED 2269 ) 2270{ 2271 rpc_socket_error_t serr = RPC_C_SOCKET_ENOTSUP; 2272 2273 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_nowriteblock_wait called\n")); 2274 fprintf(stderr, "WARNING: unsupported smb socket function %s\n", __FUNCTION__); 2275 2276 return serr; 2277} 2278 2279INTERNAL 2280rpc_socket_error_t 2281rpc__smb_socket_set_rcvtimeo( 2282 rpc_socket_t sock ATTRIBUTE_UNUSED, 2283 struct timeval *tmo ATTRIBUTE_UNUSED 2284 ) 2285{ 2286 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2287 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_set_rcvtimeo called\n")); 2288 2289 return serr; 2290} 2291 2292INTERNAL 2293rpc_socket_error_t 2294rpc__smb_socket_getpeereid( 2295 rpc_socket_t sock ATTRIBUTE_UNUSED, 2296 uid_t *euid ATTRIBUTE_UNUSED, 2297 gid_t *egid ATTRIBUTE_UNUSED 2298 ) 2299{ 2300 rpc_socket_error_t serr = RPC_C_SOCKET_ENOTSUP; 2301 2302 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_getpeereid called\n")); 2303 fprintf(stderr, "WARNING: unsupported smb socket function %s\n", __FUNCTION__); 2304 2305 return serr; 2306} 2307 2308INTERNAL 2309int 2310rpc__smb_socket_get_select_desc( 2311 rpc_socket_t sock 2312 ) 2313{ 2314 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_get_select_desc called\n")); 2315 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 2316 return smb->accept_backlog.selectfd[0]; 2317} 2318 2319INTERNAL 2320rpc_socket_error_t 2321rpc__smb_socket_enum_ifaces( 2322 rpc_socket_t sock ATTRIBUTE_UNUSED, 2323 rpc_socket_enum_iface_fn_p_t efun ATTRIBUTE_UNUSED, 2324 rpc_addr_vector_p_t *rpc_addr_vec ATTRIBUTE_UNUSED, 2325 rpc_addr_vector_p_t *netmask_addr_vec ATTRIBUTE_UNUSED, 2326 rpc_addr_vector_p_t *broadcast_addr_vec ATTRIBUTE_UNUSED 2327 ) 2328{ 2329 rpc_socket_error_t serr = RPC_C_SOCKET_ENOTSUP; 2330 2331 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_enum_ifaces called\n")); 2332 fprintf(stderr, "WARNING: unsupported smb socket function %s\n", __FUNCTION__); 2333 2334 return serr; 2335} 2336 2337INTERNAL 2338rpc_socket_error_t 2339rpc__smb_socket_inq_transport_info( 2340#if HAVE_LIKEWISE_LWIO 2341 rpc_socket_t sock, 2342#else 2343 rpc_socket_t sock ATTRIBUTE_UNUSED, 2344#endif 2345 rpc_transport_info_handle_t* info 2346 ) 2347{ 2348 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2349#if HAVE_LIKEWISE_LWIO 2350 rpc_smb_socket_p_t smb = (rpc_smb_socket_p_t) sock->data.pointer; 2351#endif 2352 rpc_smb_transport_info_p_t smb_info = NULL; 2353 2354 RPC_DBG_PRINTF(rpc_e_dbg_general, 7, ("rpc__smb_socket_inq_transport_info called\n")); 2355 2356#if !defined(HAVE_LIKEWISE_LWIO) 2357 serr = RPC_C_SOCKET_ENOTSUP; 2358 goto error; 2359#else 2360 smb_info = calloc(1, sizeof(*smb_info)); 2361 2362 if (!smb_info) 2363 { 2364 serr = RPC_C_SOCKET_ENOMEM; 2365 goto error; 2366 } 2367 2368 if (smb->info.creds) 2369 { 2370 serr = NtStatusToErrno(LwIoCopyCreds(smb->info.creds, &smb_info->creds)); 2371 if (serr) 2372 { 2373 goto error; 2374 } 2375 } 2376 2377 if (smb->info.peer_principal) 2378 { 2379 smb_info->peer_principal = strdup(smb->info.peer_principal); 2380 if (!smb_info->peer_principal) 2381 { 2382 serr = RPC_C_SOCKET_ENOMEM; 2383 goto error; 2384 } 2385 } 2386 2387 if (smb->info.session_key.data) 2388 { 2389 smb_info->session_key.data = malloc(smb->info.session_key.length); 2390 if (!smb_info->session_key.data) 2391 { 2392 serr = RPC_C_SOCKET_ENOMEM; 2393 goto error; 2394 } 2395 2396 memcpy(smb_info->session_key.data, smb->info.session_key.data, smb->info.session_key.length); 2397 smb_info->session_key.length = smb->info.session_key.length; 2398 } 2399 2400 *info = (rpc_transport_info_handle_t) smb_info; 2401#endif 2402 2403error: 2404 2405 if (serr) 2406 { 2407 *info = NULL; 2408 2409 if (smb_info) 2410 { 2411 rpc_smb_transport_info_free((rpc_transport_info_handle_t) smb_info); 2412 } 2413 } 2414 return serr; 2415} 2416 2417/* ======================================================================== */ 2418/* 2419 * R P C _ _ S M B _ S O C K E T _ D U P L I C A T E 2420 * 2421 * Wrap the native socket representation in a rpc_socket_t. We duplicate the 2422 * socket file descriptor because we will eventually end up close(2)ing it. 2423 * 2424 * Note that we sneakily replace the socket's vtable, thereby turning it into 2425 * a BSD socket. This is necessary because the native socket representation 2426 * that comes down from inetd or launchd is a file descriptor. If we used the 2427 * real SMB vtable, then we would be hooked into the Likewise SMB redirector 2428 * codem which is not what we want. 2429 */ 2430 2431INTERNAL rpc_socket_error_t 2432rpc__smb_socket_duplicate( 2433 rpc_socket_t sock, 2434 rpc_protseq_id_t protseq_id, 2435 const void * sockrep /* pointer to native representation */ 2436 ) 2437{ 2438 const int * sockfd = (const int *)sockrep; 2439 rpc_socket_error_t serr = RPC_C_SOCKET_OK; 2440 2441 RPC_DBG_GPRINTF(("(rpc__smb_socket_duplicate) sockfd=%d\n", 2442 sockfd ? *sockfd : -1)); 2443 2444 if (sockfd == NULL || *sockfd == -1) { 2445 return RPC_C_SOCKET_ENOTSOCK; 2446 } 2447 2448 if (protseq_id != rpc_c_protseq_id_ncacn_np) 2449 { 2450 return RPC_C_SOCKET_EINVAL; 2451 } 2452 2453 rpc__smb_socket_destruct(sock); 2454 2455 serr = rpc_g_bsd_socket_vtbl.socket_construct(sock, 2456 rpc_c_protseq_id_ncalrpc, NULL); 2457 if (RPC_SOCKET_IS_ERR(serr)) { 2458 return serr; 2459 } 2460 2461 // Flip the rpc_socket_t info ASAP in case some higer level 2462 // calls a generic rpc__socket routine. 2463 sock->vtbl = &rpc_g_bsd_socket_vtbl; 2464 sock->pseq_id = protseq_id; 2465 2466 serr = rpc_g_bsd_socket_vtbl.socket_duplicate(sock, 2467 rpc_c_protseq_id_ncacn_np, sockrep); 2468 if (RPC_SOCKET_IS_ERR(serr)) { 2469 return serr; 2470 } 2471 2472 return serr; 2473} 2474 2475INTERNAL 2476rpc_socket_error_t 2477rpc__smb_socket_transport_inq_access_token( 2478#if HAVE_LIKEWISE_LWMAPSECURITY 2479 rpc_transport_info_handle_t info, 2480 rpc_access_token_p_t* token 2481#else 2482 rpc_transport_info_handle_t info ATTRIBUTE_UNUSED, 2483 rpc_access_token_p_t* token ATTRIBUTE_UNUSED 2484#endif 2485 ) 2486{ 2487#if HAVE_LIKEWISE_LWMAPSECURITY 2488 rpc_smb_transport_info_p_t smb_info = (rpc_smb_transport_info_p_t) info; 2489 NTSTATUS status = STATUS_SUCCESS; 2490 PLW_MAP_SECURITY_CONTEXT context = NULL; 2491 2492 status = LwMapSecurityCreateContext(&context); 2493 if (status) goto error; 2494 2495 status = LwMapSecurityCreateAccessTokenFromCStringUsername( 2496 context, 2497 token, 2498 smb_info->peer_principal); 2499 if (status) goto error; 2500 2501error: 2502 2503 LwMapSecurityFreeContext(&context); 2504 2505 return LwNtStatusToErrno(status); 2506#else 2507 return RPC_C_SOCKET_ENOTSUP; 2508#endif 2509} 2510 2511rpc_socket_vtbl_t const rpc_g_smb_socket_vtbl = 2512{ 2513 .socket_duplicate = rpc__smb_socket_duplicate, 2514 .socket_construct = rpc__smb_socket_construct, 2515 .socket_destruct = rpc__smb_socket_destruct, 2516 .socket_bind = rpc__smb_socket_bind, 2517 .socket_connect = rpc__smb_socket_connect, 2518 .socket_accept = rpc__smb_socket_accept, 2519 .socket_listen = rpc__smb_socket_listen, 2520 .socket_sendmsg = rpc__smb_socket_sendmsg, 2521 .socket_recvfrom = rpc__smb_socket_recvfrom, 2522 .socket_recvmsg = rpc__smb_socket_recvmsg, 2523 .socket_inq_endpoint = rpc__smb_socket_inq_endpoint, 2524 .socket_set_broadcast = rpc__smb_socket_set_broadcast, 2525 .socket_set_bufs = rpc__smb_socket_set_bufs, 2526 .socket_set_nbio = rpc__smb_socket_set_nbio, 2527 .socket_set_close_on_exec = rpc__smb_socket_set_close_on_exec, 2528 .socket_getpeername = rpc__smb_socket_getpeername, 2529 .socket_get_if_id = rpc__smb_socket_get_if_id, 2530 .socket_set_keepalive = rpc__smb_socket_set_keepalive, 2531 .socket_nowriteblock_wait = rpc__smb_socket_nowriteblock_wait, 2532 .socket_set_rcvtimeo = rpc__smb_socket_set_rcvtimeo, 2533 .socket_getpeereid = rpc__smb_socket_getpeereid, 2534 .socket_get_select_desc = rpc__smb_socket_get_select_desc, 2535 .socket_enum_ifaces = rpc__smb_socket_enum_ifaces, 2536 .socket_inq_transport_info = rpc__smb_socket_inq_transport_info, 2537 .transport_info_free = rpc_smb_transport_info_free, 2538 .transport_info_equal = rpc__smb_transport_info_equal, 2539 .transport_inq_access_token = rpc__smb_socket_transport_inq_access_token 2540}; 2541