1/* 2 Unix SMB/Netbios implementation. 3 SMB client library implementation 4 Copyright (C) Andrew Tridgell 1998 5 Copyright (C) Richard Sharpe 2000, 2002 6 Copyright (C) John Terpstra 2000 7 Copyright (C) Tom Jansen (Ninja ISD) 2002 8 Copyright (C) Derrell Lipman 2003-2008 9 Copyright (C) Jeremy Allison 2007, 2008 10 Copyright (C) SATOH Fumiyasu <fumiyas@osstech.co.jp> 2009. 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 3 of the License, or 15 (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program. If not, see <http://www.gnu.org/licenses/>. 24*/ 25 26#include "includes.h" 27#include "libsmbclient.h" 28#include "libsmb_internal.h" 29 30 31/* 32 * Check a server for being alive and well. 33 * returns 0 if the server is in shape. Returns 1 on error 34 * 35 * Also useable outside libsmbclient to enable external cache 36 * to do some checks too. 37 */ 38int 39SMBC_check_server(SMBCCTX * context, 40 SMBCSRV * server) 41{ 42 socklen_t size; 43 struct sockaddr addr; 44 45 size = sizeof(addr); 46 return (getpeername(server->cli->fd, &addr, &size) == -1); 47} 48 49/* 50 * Remove a server from the cached server list it's unused. 51 * On success, 0 is returned. 1 is returned if the server could not be removed. 52 * 53 * Also useable outside libsmbclient 54 */ 55int 56SMBC_remove_unused_server(SMBCCTX * context, 57 SMBCSRV * srv) 58{ 59 SMBCFILE * file; 60 61 /* are we being fooled ? */ 62 if (!context || !context->internal->initialized || !srv) { 63 return 1; 64 } 65 66 /* Check all open files/directories for a relation with this server */ 67 for (file = context->internal->files; file; file = file->next) { 68 if (file->srv == srv) { 69 /* Still used */ 70 DEBUG(3, ("smbc_remove_usused_server: " 71 "%p still used by %p.\n", 72 srv, file)); 73 return 1; 74 } 75 } 76 77 DLIST_REMOVE(context->internal->servers, srv); 78 79 cli_shutdown(srv->cli); 80 srv->cli = NULL; 81 82 DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv)); 83 84 smbc_getFunctionRemoveCachedServer(context)(context, srv); 85 86 SAFE_FREE(srv); 87 return 0; 88} 89 90/**************************************************************** 91 * Call the auth_fn with fixed size (fstring) buffers. 92 ***************************************************************/ 93void 94SMBC_call_auth_fn(TALLOC_CTX *ctx, 95 SMBCCTX *context, 96 const char *server, 97 const char *share, 98 char **pp_workgroup, 99 char **pp_username, 100 char **pp_password) 101{ 102 fstring workgroup; 103 fstring username; 104 fstring password; 105 smbc_get_auth_data_with_context_fn auth_with_context_fn; 106 107 strlcpy(workgroup, *pp_workgroup, sizeof(workgroup)); 108 strlcpy(username, *pp_username, sizeof(username)); 109 strlcpy(password, *pp_password, sizeof(password)); 110 111 /* See if there's an authentication with context function provided */ 112 auth_with_context_fn = smbc_getFunctionAuthDataWithContext(context); 113 if (auth_with_context_fn) 114 { 115 (* auth_with_context_fn)(context, 116 server, share, 117 workgroup, sizeof(workgroup), 118 username, sizeof(username), 119 password, sizeof(password)); 120 } 121 else 122 { 123 smbc_getFunctionAuthData(context)(server, share, 124 workgroup, sizeof(workgroup), 125 username, sizeof(username), 126 password, sizeof(password)); 127 } 128 129 TALLOC_FREE(*pp_workgroup); 130 TALLOC_FREE(*pp_username); 131 TALLOC_FREE(*pp_password); 132 133 *pp_workgroup = talloc_strdup(ctx, workgroup); 134 *pp_username = talloc_strdup(ctx, username); 135 *pp_password = talloc_strdup(ctx, password); 136} 137 138 139void 140SMBC_get_auth_data(const char *server, const char *share, 141 char *workgroup_buf, int workgroup_buf_len, 142 char *username_buf, int username_buf_len, 143 char *password_buf, int password_buf_len) 144{ 145 /* Default function just uses provided data. Nothing to do. */ 146} 147 148 149 150SMBCSRV * 151SMBC_find_server(TALLOC_CTX *ctx, 152 SMBCCTX *context, 153 const char *server, 154 const char *share, 155 char **pp_workgroup, 156 char **pp_username, 157 char **pp_password) 158{ 159 SMBCSRV *srv; 160 int auth_called = 0; 161 162 if (!pp_workgroup || !pp_username || !pp_password) { 163 return NULL; 164 } 165 166check_server_cache: 167 168 srv = smbc_getFunctionGetCachedServer(context)(context, 169 server, share, 170 *pp_workgroup, 171 *pp_username); 172 173 if (!auth_called && !srv && (!*pp_username || !(*pp_username)[0] || 174 !*pp_password || !(*pp_password)[0])) { 175 SMBC_call_auth_fn(ctx, context, server, share, 176 pp_workgroup, pp_username, pp_password); 177 178 /* 179 * However, smbc_auth_fn may have picked up info relating to 180 * an existing connection, so try for an existing connection 181 * again ... 182 */ 183 auth_called = 1; 184 goto check_server_cache; 185 186 } 187 188 if (srv) { 189 if (smbc_getFunctionCheckServer(context)(context, srv)) { 190 /* 191 * This server is no good anymore 192 * Try to remove it and check for more possible 193 * servers in the cache 194 */ 195 if (smbc_getFunctionRemoveUnusedServer(context)(context, 196 srv)) { 197 /* 198 * We could not remove the server completely, 199 * remove it from the cache so we will not get 200 * it again. It will be removed when the last 201 * file/dir is closed. 202 */ 203 smbc_getFunctionRemoveCachedServer(context)(context, 204 srv); 205 } 206 207 /* 208 * Maybe there are more cached connections to this 209 * server 210 */ 211 goto check_server_cache; 212 } 213 214 return srv; 215 } 216 217 return NULL; 218} 219 220/* 221 * Connect to a server, possibly on an existing connection 222 * 223 * Here, what we want to do is: If the server and username 224 * match an existing connection, reuse that, otherwise, establish a 225 * new connection. 226 * 227 * If we have to create a new connection, call the auth_fn to get the 228 * info we need, unless the username and password were passed in. 229 */ 230 231static SMBCSRV * 232SMBC_server_internal(TALLOC_CTX *ctx, 233 SMBCCTX *context, 234 bool connect_if_not_found, 235 const char *server, 236 const char *share, 237 char **pp_workgroup, 238 char **pp_username, 239 char **pp_password, 240 bool *in_cache) 241{ 242 SMBCSRV *srv=NULL; 243 char *workgroup = NULL; 244 struct cli_state *c; 245 struct nmb_name called, calling; 246 const char *server_n = server; 247 struct sockaddr_storage ss; 248 int tried_reverse = 0; 249 int port_try_first; 250 int port_try_next; 251 int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0); 252 uint32 fs_attrs = 0; 253 const char *username_used; 254 NTSTATUS status; 255 char *newserver, *newshare; 256 257 zero_sockaddr(&ss); 258 ZERO_STRUCT(c); 259 *in_cache = false; 260 261 if (server[0] == 0) { 262 errno = EPERM; 263 return NULL; 264 } 265 266 /* Look for a cached connection */ 267 srv = SMBC_find_server(ctx, context, server, share, 268 pp_workgroup, pp_username, pp_password); 269 270 /* 271 * If we found a connection and we're only allowed one share per 272 * server... 273 */ 274 if (srv && 275 *share != '\0' && 276 smbc_getOptionOneSharePerServer(context)) { 277 278 /* 279 * ... then if there's no current connection to the share, 280 * connect to it. SMBC_find_server(), or rather the function 281 * pointed to by context->get_cached_srv_fn which 282 * was called by SMBC_find_server(), will have issued a tree 283 * disconnect if the requested share is not the same as the 284 * one that was already connected. 285 */ 286 287 /* 288 * Use srv->cli->desthost and srv->cli->share instead of 289 * server and share below to connect to the actual share, 290 * i.e., a normal share or a referred share from 291 * 'msdfs proxy' share. 292 */ 293 if (srv->cli->cnum == (uint16) -1) { 294 /* Ensure we have accurate auth info */ 295 SMBC_call_auth_fn(ctx, context, 296 srv->cli->desthost, 297 srv->cli->share, 298 pp_workgroup, 299 pp_username, 300 pp_password); 301 302 if (!*pp_workgroup || !*pp_username || !*pp_password) { 303 errno = ENOMEM; 304 cli_shutdown(srv->cli); 305 srv->cli = NULL; 306 smbc_getFunctionRemoveCachedServer(context)(context, 307 srv); 308 return NULL; 309 } 310 311 /* 312 * We don't need to renegotiate encryption 313 * here as the encryption context is not per 314 * tid. 315 */ 316 317 status = cli_tcon_andx(srv->cli, srv->cli->share, "?????", 318 *pp_password, 319 strlen(*pp_password)+1); 320 if (!NT_STATUS_IS_OK(status)) { 321 errno = map_errno_from_nt_status(status); 322 cli_shutdown(srv->cli); 323 srv->cli = NULL; 324 smbc_getFunctionRemoveCachedServer(context)(context, 325 srv); 326 srv = NULL; 327 } 328 329 /* Determine if this share supports case sensitivity */ 330 if (is_ipc) { 331 DEBUG(4, 332 ("IPC$ so ignore case sensitivity\n")); 333 } else if (!cli_get_fs_attr_info(c, &fs_attrs)) { 334 DEBUG(4, ("Could not retrieve " 335 "case sensitivity flag: %s.\n", 336 cli_errstr(c))); 337 338 /* 339 * We can't determine the case sensitivity of 340 * the share. We have no choice but to use the 341 * user-specified case sensitivity setting. 342 */ 343 if (smbc_getOptionCaseSensitive(context)) { 344 cli_set_case_sensitive(c, True); 345 } else { 346 cli_set_case_sensitive(c, False); 347 } 348 } else { 349 DEBUG(4, 350 ("Case sensitive: %s\n", 351 (fs_attrs & FILE_CASE_SENSITIVE_SEARCH 352 ? "True" 353 : "False"))); 354 cli_set_case_sensitive( 355 c, 356 (fs_attrs & FILE_CASE_SENSITIVE_SEARCH 357 ? True 358 : False)); 359 } 360 361 /* 362 * Regenerate the dev value since it's based on both 363 * server and share 364 */ 365 if (srv) { 366 srv->dev = (dev_t)(str_checksum(srv->cli->desthost) ^ 367 str_checksum(srv->cli->share)); 368 } 369 } 370 } 371 372 /* If we have a connection... */ 373 if (srv) { 374 /* ... then we're done here. Give 'em what they came for. */ 375 *in_cache = true; 376 goto done; 377 } 378 379 /* If we're not asked to connect when a connection doesn't exist... */ 380 if (! connect_if_not_found) { 381 /* ... then we're done here. */ 382 return NULL; 383 } 384 385 if (!*pp_workgroup || !*pp_username || !*pp_password) { 386 errno = ENOMEM; 387 return NULL; 388 } 389 390 make_nmb_name(&calling, smbc_getNetbiosName(context), 0x0); 391 make_nmb_name(&called , server, 0x20); 392 393 DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server)); 394 395 DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); 396 397again: 398 399 zero_sockaddr(&ss); 400 401 /* have to open a new connection */ 402 if ((c = cli_initialise()) == NULL) { 403 errno = ENOMEM; 404 return NULL; 405 } 406 407 if (smbc_getOptionUseKerberos(context)) { 408 c->use_kerberos = True; 409 } 410 411 if (smbc_getOptionFallbackAfterKerberos(context)) { 412 c->fallback_after_kerberos = True; 413 } 414 415 if (smbc_getOptionUseCCache(context)) { 416 c->use_ccache = True; 417 } 418 419 c->timeout = smbc_getTimeout(context); 420 421 /* 422 * Force use of port 139 for first try if share is $IPC, empty, or 423 * null, so browse lists can work 424 */ 425 if (share == NULL || *share == '\0' || is_ipc) { 426 port_try_first = 139; 427 port_try_next = 445; 428 } else { 429 port_try_first = 445; 430 port_try_next = 139; 431 } 432 433 c->port = port_try_first; 434 435 status = cli_connect(c, server_n, &ss); 436 if (!NT_STATUS_IS_OK(status)) { 437 438 /* First connection attempt failed. Try alternate port. */ 439 c->port = port_try_next; 440 441 status = cli_connect(c, server_n, &ss); 442 if (!NT_STATUS_IS_OK(status)) { 443 cli_shutdown(c); 444 errno = ETIMEDOUT; 445 return NULL; 446 } 447 } 448 449 if (!cli_session_request(c, &calling, &called)) { 450 cli_shutdown(c); 451 if (strcmp(called.name, "*SMBSERVER")) { 452 make_nmb_name(&called , "*SMBSERVER", 0x20); 453 goto again; 454 } else { /* Try one more time, but ensure we don't loop */ 455 456 /* Only try this if server is an IP address ... */ 457 458 if (is_ipaddress(server) && !tried_reverse) { 459 fstring remote_name; 460 struct sockaddr_storage rem_ss; 461 462 if (!interpret_string_addr(&rem_ss, server, 463 NI_NUMERICHOST)) { 464 DEBUG(4, ("Could not convert IP address " 465 "%s to struct sockaddr_storage\n", 466 server)); 467 errno = ETIMEDOUT; 468 return NULL; 469 } 470 471 tried_reverse++; /* Yuck */ 472 473 if (name_status_find("*", 0, 0, 474 &rem_ss, remote_name)) { 475 make_nmb_name(&called, 476 remote_name, 477 0x20); 478 goto again; 479 } 480 } 481 } 482 errno = ETIMEDOUT; 483 return NULL; 484 } 485 486 DEBUG(4,(" session request ok\n")); 487 488 489 status = cli_negprot(c); 490 491 if (!NT_STATUS_IS_OK(status)) { 492 cli_shutdown(c); 493 errno = ETIMEDOUT; 494 return NULL; 495 } 496 497 username_used = *pp_username; 498 499 if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used, 500 *pp_password, 501 strlen(*pp_password), 502 *pp_password, 503 strlen(*pp_password), 504 *pp_workgroup))) { 505fprintf(stderr, "JerryLin: Libsmb_server.c->SMBC_server_internal: cli_session_setup fail with username=[%s], password=[%s]\n", username_used, *pp_password); 506 /* Failed. Try an anonymous login, if allowed by flags. */ 507 username_used = ""; 508 509 if (smbc_getOptionNoAutoAnonymousLogin(context) || 510 !NT_STATUS_IS_OK(cli_session_setup(c, username_used, 511 *pp_password, 1, 512 *pp_password, 0, 513 *pp_workgroup))) { 514 515 cli_shutdown(c); 516 errno = EPERM; 517 return NULL; 518 } 519 } 520 521 status = cli_init_creds(c, username_used, 522 *pp_workgroup, *pp_password); 523 if (!NT_STATUS_IS_OK(status)) { 524 errno = map_errno_from_nt_status(status); 525 cli_shutdown(c); 526 return NULL; 527 } 528 529 DEBUG(4,(" session setup ok\n")); 530 531 /* here's the fun part....to support 'msdfs proxy' shares 532 (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL 533 here before trying to connect to the original share. 534 cli_check_msdfs_proxy() will fail if it is a normal share. */ 535 536 if ((c->capabilities & CAP_DFS) && 537 cli_check_msdfs_proxy(ctx, c, share, 538 &newserver, &newshare, 539 /* FIXME: cli_check_msdfs_proxy() does 540 not support smbc_smb_encrypt_level type */ 541 context->internal->smb_encryption_level ? 542 true : false, 543 *pp_username, 544 *pp_password, 545 *pp_workgroup)) { 546 cli_shutdown(c); 547 srv = SMBC_server_internal(ctx, context, connect_if_not_found, 548 newserver, newshare, pp_workgroup, 549 pp_username, pp_password, in_cache); 550 TALLOC_FREE(newserver); 551 TALLOC_FREE(newshare); 552 return srv; 553 } 554 555 /* must be a normal share */ 556 status = cli_tcon_andx(c, share, "?????", *pp_password, 557 strlen(*pp_password)+1); 558 if (!NT_STATUS_IS_OK(status)) { 559 errno = map_errno_from_nt_status(status); 560 fprintf(stderr, "JerryLin: Libsmb_server.c->SMBC_server_internal: cli_tcon_andx return %08X, errno=[%d]\n", NT_STATUS_V(status), errno); 561 cli_shutdown(c); 562 return NULL; 563 } 564 565 DEBUG(4,(" tconx ok\n")); 566 567 /* Determine if this share supports case sensitivity */ 568 if (is_ipc) { 569 DEBUG(4, ("IPC$ so ignore case sensitivity\n")); 570 } else if (!cli_get_fs_attr_info(c, &fs_attrs)) { 571 DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n", 572 cli_errstr(c))); 573 574 /* 575 * We can't determine the case sensitivity of the share. We 576 * have no choice but to use the user-specified case 577 * sensitivity setting. 578 */ 579 if (smbc_getOptionCaseSensitive(context)) { 580 cli_set_case_sensitive(c, True); 581 } else { 582 cli_set_case_sensitive(c, False); 583 } 584 } else { 585 DEBUG(4, ("Case sensitive: %s\n", 586 (fs_attrs & FILE_CASE_SENSITIVE_SEARCH 587 ? "True" 588 : "False"))); 589 cli_set_case_sensitive(c, 590 (fs_attrs & FILE_CASE_SENSITIVE_SEARCH 591 ? True 592 : False)); 593 } 594 595 596 if (context->internal->smb_encryption_level) { 597 /* Attempt UNIX smb encryption. */ 598 if (!NT_STATUS_IS_OK(cli_force_encryption(c, 599 username_used, 600 *pp_password, 601 *pp_workgroup))) { 602 603 /* 604 * context->smb_encryption_level == 1 605 * means don't fail if encryption can't be negotiated, 606 * == 2 means fail if encryption can't be negotiated. 607 */ 608 609 DEBUG(4,(" SMB encrypt failed\n")); 610 611 if (context->internal->smb_encryption_level == 2) { 612 cli_shutdown(c); 613 errno = EPERM; 614 return NULL; 615 } 616 } 617 DEBUG(4,(" SMB encrypt ok\n")); 618 } 619 620 /* 621 * Ok, we have got a nice connection 622 * Let's allocate a server structure. 623 */ 624 625 srv = SMB_MALLOC_P(SMBCSRV); 626 if (!srv) { 627 cli_shutdown(c); 628 errno = ENOMEM; 629 return NULL; 630 } 631 632 ZERO_STRUCTP(srv); 633 srv->cli = c; 634 srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share)); 635 srv->no_pathinfo = False; 636 srv->no_pathinfo2 = False; 637 srv->no_nt_session = False; 638 639done: 640 if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) { 641 workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context)); 642 } else { 643 workgroup = *pp_workgroup; 644 } 645 if(!workgroup) { 646 return NULL; 647 } 648 649 /* set the credentials to make DFS work */ 650 smbc_set_credentials_with_fallback(context, 651 workgroup, 652 *pp_username, 653 *pp_password); 654 655 return srv; 656} 657 658SMBCSRV * 659SMBC_server(TALLOC_CTX *ctx, 660 SMBCCTX *context, 661 bool connect_if_not_found, 662 const char *server, 663 const char *share, 664 char **pp_workgroup, 665 char **pp_username, 666 char **pp_password) 667{ 668 SMBCSRV *srv=NULL; 669 bool in_cache = false; 670 671 srv = SMBC_server_internal(ctx, context, connect_if_not_found, 672 server, share, pp_workgroup, 673 pp_username, pp_password, &in_cache); 674 675 if (!srv) { 676 return NULL; 677 } 678 if (in_cache) { 679 return srv; 680 } 681 682 /* Now add it to the cache (internal or external) */ 683 /* Let the cache function set errno if it wants to */ 684 errno = 0; 685 if (smbc_getFunctionAddCachedServer(context)(context, srv, 686 server, share, 687 *pp_workgroup, 688 *pp_username)) { 689 int saved_errno = errno; 690 DEBUG(3, (" Failed to add server to cache\n")); 691 errno = saved_errno; 692 if (errno == 0) { 693 errno = ENOMEM; 694 } 695 SAFE_FREE(srv); 696 return NULL; 697 } 698 699 DEBUG(2, ("Server connect ok: //%s/%s: %p\n", 700 server, share, srv)); 701 702 DLIST_ADD(context->internal->servers, srv); 703 return srv; 704} 705 706/* 707 * Connect to a server for getting/setting attributes, possibly on an existing 708 * connection. This works similarly to SMBC_server(). 709 */ 710SMBCSRV * 711SMBC_attr_server(TALLOC_CTX *ctx, 712 SMBCCTX *context, 713 const char *server, 714 const char *share, 715 char **pp_workgroup, 716 char **pp_username, 717 char **pp_password) 718{ 719 int flags; 720 struct sockaddr_storage ss; 721 struct cli_state *ipc_cli = NULL; 722 struct rpc_pipe_client *pipe_hnd = NULL; 723 NTSTATUS nt_status; 724 SMBCSRV *srv=NULL; 725 SMBCSRV *ipc_srv=NULL; 726 727 /* 728 * Use srv->cli->desthost and srv->cli->share instead of 729 * server and share below to connect to the actual share, 730 * i.e., a normal share or a referred share from 731 * 'msdfs proxy' share. 732 */ 733 srv = SMBC_server(ctx, context, true, server, share, 734 pp_workgroup, pp_username, pp_password); 735 if (!srv) { 736 return NULL; 737 } 738 server = srv->cli->desthost; 739 share = srv->cli->share; 740 741 /* 742 * See if we've already created this special connection. Reference 743 * our "special" share name '*IPC$', which is an impossible real share 744 * name due to the leading asterisk. 745 */ 746 ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$", 747 pp_workgroup, pp_username, pp_password); 748 if (!ipc_srv) { 749 750 /* We didn't find a cached connection. Get the password */ 751 if (!*pp_password || (*pp_password)[0] == '\0') { 752 /* ... then retrieve it now. */ 753 SMBC_call_auth_fn(ctx, context, server, share, 754 pp_workgroup, 755 pp_username, 756 pp_password); 757 if (!*pp_workgroup || !*pp_username || !*pp_password) { 758 errno = ENOMEM; 759 return NULL; 760 } 761 } 762 763 flags = 0; 764 if (smbc_getOptionUseKerberos(context)) { 765 flags |= CLI_FULL_CONNECTION_USE_KERBEROS; 766 } 767 if (smbc_getOptionUseCCache(context)) { 768 flags |= CLI_FULL_CONNECTION_USE_CCACHE; 769 } 770 771 zero_sockaddr(&ss); 772 nt_status = cli_full_connection(&ipc_cli, 773 global_myname(), server, 774 &ss, 0, "IPC$", "?????", 775 *pp_username, 776 *pp_workgroup, 777 *pp_password, 778 flags, 779 Undefined, NULL); 780 if (! NT_STATUS_IS_OK(nt_status)) { 781 DEBUG(1,("cli_full_connection failed! (%s)\n", 782 nt_errstr(nt_status))); 783 errno = ENOTSUP; 784 return NULL; 785 } 786 787 if (context->internal->smb_encryption_level) { 788 /* Attempt UNIX smb encryption. */ 789 if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli, 790 *pp_username, 791 *pp_password, 792 *pp_workgroup))) { 793 794 /* 795 * context->smb_encryption_level == 796 * 1 means don't fail if encryption can't be 797 * negotiated, == 2 means fail if encryption 798 * can't be negotiated. 799 */ 800 801 DEBUG(4,(" SMB encrypt failed on IPC$\n")); 802 803 if (context->internal->smb_encryption_level == 2) { 804 cli_shutdown(ipc_cli); 805 errno = EPERM; 806 return NULL; 807 } 808 } 809 DEBUG(4,(" SMB encrypt ok on IPC$\n")); 810 } 811 812 ipc_srv = SMB_MALLOC_P(SMBCSRV); 813 if (!ipc_srv) { 814 errno = ENOMEM; 815 cli_shutdown(ipc_cli); 816 return NULL; 817 } 818 819 ZERO_STRUCTP(ipc_srv); 820 ipc_srv->cli = ipc_cli; 821 822 nt_status = cli_rpc_pipe_open_noauth( 823 ipc_srv->cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd); 824 if (!NT_STATUS_IS_OK(nt_status)) { 825 DEBUG(1, ("cli_nt_session_open fail!\n")); 826 errno = ENOTSUP; 827 cli_shutdown(ipc_srv->cli); 828 free(ipc_srv); 829 return NULL; 830 } 831 832 /* 833 * Some systems don't support 834 * SEC_FLAG_MAXIMUM_ALLOWED, but NT sends 0x2000000 835 * so we might as well do it too. 836 */ 837 838 nt_status = rpccli_lsa_open_policy( 839 pipe_hnd, 840 talloc_tos(), 841 True, 842 GENERIC_EXECUTE_ACCESS, 843 &ipc_srv->pol); 844 845 if (!NT_STATUS_IS_OK(nt_status)) { 846 errno = SMBC_errno(context, ipc_srv->cli); 847 cli_shutdown(ipc_srv->cli); 848 return NULL; 849 } 850 851 /* now add it to the cache (internal or external) */ 852 853 errno = 0; /* let cache function set errno if it likes */ 854 if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv, 855 server, 856 "*IPC$", 857 *pp_workgroup, 858 *pp_username)) { 859 DEBUG(3, (" Failed to add server to cache\n")); 860 if (errno == 0) { 861 errno = ENOMEM; 862 } 863 cli_shutdown(ipc_srv->cli); 864 free(ipc_srv); 865 return NULL; 866 } 867 868 DLIST_ADD(context->internal->servers, ipc_srv); 869 } 870 871 return ipc_srv; 872} 873