Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/libsmb/clidfs.c

    r919 r988  
    2626#include "trans2.h"
    2727#include "libsmb/nmblib.h"
     28#include "../libcli/smb/smbXcli_base.h"
    2829
    2930/********************************************************************
     
    4849                        const char *sharename)
    4950{
    50         NTSTATUS status = cli_force_encryption(c,
     51        NTSTATUS status;
     52
     53        if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
     54                status = smb2cli_session_encryption_on(c->smb2.session);
     55                if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED)) {
     56                        d_printf("Encryption required and "
     57                                "server doesn't support "
     58                                "SMB3 encryption - failing connect\n");
     59                } else if (!NT_STATUS_IS_OK(status)) {
     60                        d_printf("Encryption required and "
     61                                "setup failed with error %s.\n",
     62                                nt_errstr(status));
     63                }
     64                return status;
     65        }
     66
     67        status = cli_force_encryption(c,
    5168                                        username,
    5269                                        password,
     
    7895********************************************************************/
    7996
    80 static struct cli_state *do_connect(TALLOC_CTX *ctx,
     97static NTSTATUS do_connect(TALLOC_CTX *ctx,
    8198                                        const char *server,
    8299                                        const char *share,
     
    86103                                        int max_protocol,
    87104                                        int port,
    88                                         int name_type)
     105                                        int name_type,
     106                                        struct cli_state **pcli)
    89107{
    90108        struct cli_state *c = NULL;
    91         struct nmb_name called, calling;
    92         const char *called_str;
    93         const char *server_n;
    94         struct sockaddr_storage ss;
    95109        char *servicename;
    96110        char *sharename;
     
    98112        const char *username;
    99113        const char *password;
     114        const char *domain;
    100115        NTSTATUS status;
     116        int flags = 0;
    101117        int signing_state = get_cmdline_auth_info_signing_state(auth_info);
    102118
    103119        if (force_encrypt) {
    104                 signing_state = Required;
     120                signing_state = SMB_SIGNING_REQUIRED;
    105121        }
    106122
     
    108124        servicename = talloc_strdup(ctx,share);
    109125        if (!servicename) {
    110                 return NULL;
     126                return NT_STATUS_NO_MEMORY;
    111127        }
    112128        sharename = servicename;
    113129        if (*sharename == '\\') {
    114130                sharename += 2;
    115                 called_str = sharename;
    116131                if (server == NULL) {
    117132                        server = sharename;
     
    119134                sharename = strchr_m(sharename,'\\');
    120135                if (!sharename) {
    121                         return NULL;
     136                        return NT_STATUS_NO_MEMORY;
    122137                }
    123138                *sharename = 0;
    124139                sharename++;
    125         } else {
    126                 called_str = server;
    127         }
    128 
    129         server_n = server;
    130 
    131         zero_sockaddr(&ss);
    132 
    133         make_nmb_name(&calling, global_myname(), 0x0);
    134         make_nmb_name(&called , called_str, name_type);
    135 
    136  again:
    137         zero_sockaddr(&ss);
    138 
    139         /* have to open a new connection */
    140         c = cli_initialise_ex(signing_state);
    141         if (c == NULL) {
    142                 d_printf("Connection to %s failed\n", server_n);
    143                 return NULL;
    144         }
    145         if (port) {
    146                 cli_set_port(c, port);
    147         }
    148 
    149         status = cli_connect(c, server_n, &ss);
     140        }
     141        if (server == NULL) {
     142                return NT_STATUS_INVALID_PARAMETER;
     143        }
     144
     145        if (get_cmdline_auth_info_use_kerberos(auth_info)) {
     146                flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
     147        }
     148        if (get_cmdline_auth_info_fallback_after_kerberos(auth_info)) {
     149                flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
     150        }
     151        if (get_cmdline_auth_info_use_ccache(auth_info)) {
     152                flags |= CLI_FULL_CONNECTION_USE_CCACHE;
     153        }
     154        if (get_cmdline_auth_info_use_pw_nt_hash(auth_info)) {
     155                flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
     156        }
     157
     158        status = cli_connect_nb(
     159                server, NULL, port, name_type, NULL,
     160                signing_state,
     161                flags, &c);
     162
    150163        if (!NT_STATUS_IS_OK(status)) {
    151164                d_printf("Connection to %s failed (Error %s)\n",
    152                                 server_n,
     165                                server,
    153166                                nt_errstr(status));
    154                 cli_shutdown(c);
    155                 return NULL;
     167                return status;
    156168        }
    157169
     
    159171                max_protocol = PROTOCOL_NT1;
    160172        }
    161         c->protocol = max_protocol;
    162         c->use_kerberos = get_cmdline_auth_info_use_kerberos(auth_info);
    163         c->fallback_after_kerberos =
    164                 get_cmdline_auth_info_fallback_after_kerberos(auth_info);
    165         c->use_ccache = get_cmdline_auth_info_use_ccache(auth_info);
    166 
    167         if (!cli_session_request(c, &calling, &called)) {
    168                 char *p;
    169                 d_printf("session request to %s failed (%s)\n",
    170                          called.name, cli_errstr(c));
    171                 cli_shutdown(c);
    172                 c = NULL;
    173                 if ((p=strchr_m(called.name, '.'))) {
    174                         *p = 0;
    175                         goto again;
    176                 }
    177                 if (strcmp(called.name, "*SMBSERVER")) {
    178                         make_nmb_name(&called , "*SMBSERVER", 0x20);
    179                         goto again;
    180                 }
    181                 return NULL;
    182         }
    183 
    184173        DEBUG(4,(" session request ok\n"));
    185174
    186         status = cli_negprot(c);
     175        status = smbXcli_negprot(c->conn, c->timeout,
     176                                 lp_client_min_protocol(),
     177                                 max_protocol);
    187178
    188179        if (!NT_STATUS_IS_OK(status)) {
     
    190181                         nt_errstr(status));
    191182                cli_shutdown(c);
    192                 return NULL;
     183                return status;
     184        }
     185
     186        if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
     187                /* Ensure we ask for some initial credits. */
     188                smb2cli_conn_set_max_credits(c->conn, DEFAULT_SMB2_MAX_CREDITS);
    193189        }
    194190
    195191        username = get_cmdline_auth_info_username(auth_info);
    196192        password = get_cmdline_auth_info_password(auth_info);
    197 
    198         if (!NT_STATUS_IS_OK(cli_session_setup(c, username,
    199                                                password, strlen(password),
    200                                                password, strlen(password),
    201                                                lp_workgroup()))) {
     193        domain = get_cmdline_auth_info_domain(auth_info);
     194        if ((domain == NULL) || (domain[0] == '\0')) {
     195                domain = lp_workgroup();
     196        }
     197
     198        status = cli_session_setup(c, username,
     199                                   password, strlen(password),
     200                                   password, strlen(password),
     201                                   domain);
     202        if (!NT_STATUS_IS_OK(status)) {
    202203                /* If a password was not supplied then
    203204                 * try again with a null username. */
    204205                if (password[0] || !username[0] ||
    205206                        get_cmdline_auth_info_use_kerberos(auth_info) ||
    206                         !NT_STATUS_IS_OK(cli_session_setup(c, "",
     207                        !NT_STATUS_IS_OK(status = cli_session_setup(c, "",
    207208                                                "", 0,
    208209                                                "", 0,
    209210                                               lp_workgroup()))) {
    210                         d_printf("session setup failed: %s\n", cli_errstr(c));
    211                         if (NT_STATUS_V(cli_nt_error(c)) ==
    212                             NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
     211                        d_printf("session setup failed: %s\n",
     212                                 nt_errstr(status));
     213                        if (NT_STATUS_EQUAL(status,
     214                                            NT_STATUS_MORE_PROCESSING_REQUIRED))
    213215                                d_printf("did you forget to run kinit?\n");
    214216                        cli_shutdown(c);
    215                         return NULL;
     217                        return status;
    216218                }
    217219                d_printf("Anonymous login successful\n");
    218                 status = cli_init_creds(c, "", lp_workgroup(), "");
    219         } else {
    220                 status = cli_init_creds(c, username, lp_workgroup(), password);
    221220        }
    222221
     
    224223                DEBUG(10,("cli_init_creds() failed: %s\n", nt_errstr(status)));
    225224                cli_shutdown(c);
    226                 return NULL;
     225                return status;
    227226        }
    228227
     
    243242           cli_check_msdfs_proxy() will fail if it is a normal share. */
    244243
    245         if ((c->capabilities & CAP_DFS) &&
     244        if (smbXcli_conn_dfs_supported(c->conn) &&
    246245                        cli_check_msdfs_proxy(ctx, c, sharename,
    247246                                &newserver, &newshare,
     
    249248                                username,
    250249                                password,
    251                                 lp_workgroup())) {
     250                                domain)) {
    252251                cli_shutdown(c);
    253252                return do_connect(ctx, newserver,
    254253                                newshare, auth_info, false,
    255254                                force_encrypt, max_protocol,
    256                                 port, name_type);
     255                                port, name_type, pcli);
    257256        }
    258257
    259258        /* must be a normal share */
    260259
    261         status = cli_tcon_andx(c, sharename, "?????",
    262                                password, strlen(password)+1);
     260        status = cli_tree_connect(c, sharename, "?????",
     261                                  password, strlen(password)+1);
    263262        if (!NT_STATUS_IS_OK(status)) {
    264263                d_printf("tree connect failed: %s\n", nt_errstr(status));
    265264                cli_shutdown(c);
    266                 return NULL;
     265                return status;
    267266        }
    268267
     
    271270                                        username,
    272271                                        password,
    273                                         lp_workgroup(),
     272                                        domain,
    274273                                        sharename);
    275274                if (!NT_STATUS_IS_OK(status)) {
    276275                        cli_shutdown(c);
    277                         return NULL;
     276                        return status;
    278277                }
    279278        }
    280279
    281280        DEBUG(4,(" tconx ok\n"));
    282         return c;
     281        *pcli = c;
     282        return NT_STATUS_OK;
    283283}
    284284
     
    288288static void cli_set_mntpoint(struct cli_state *cli, const char *mnt)
    289289{
    290         char *name = clean_name(NULL, mnt);
     290        TALLOC_CTX *frame = talloc_stackframe();
     291        char *name = clean_name(frame, mnt);
    291292        if (!name) {
     293                TALLOC_FREE(frame);
    292294                return;
    293295        }
    294296        TALLOC_FREE(cli->dfs_mountpoint);
    295297        cli->dfs_mountpoint = talloc_strdup(cli, name);
    296         TALLOC_FREE(name);
     298        TALLOC_FREE(frame);
    297299}
    298300
     
    302304********************************************************************/
    303305
    304 static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
    305                                         struct cli_state *referring_cli,
    306                                         const char *server,
    307                                         const char *share,
    308                                         const struct user_auth_info *auth_info,
    309                                         bool show_hdr,
    310                                         bool force_encrypt,
    311                                         int max_protocol,
    312                                         int port,
    313                                         int name_type)
     306static NTSTATUS cli_cm_connect(TALLOC_CTX *ctx,
     307                               struct cli_state *referring_cli,
     308                               const char *server,
     309                               const char *share,
     310                               const struct user_auth_info *auth_info,
     311                               bool show_hdr,
     312                               bool force_encrypt,
     313                               int max_protocol,
     314                               int port,
     315                               int name_type,
     316                               struct cli_state **pcli)
    314317{
    315318        struct cli_state *cli;
    316 
    317         cli = do_connect(ctx, server, share,
     319        NTSTATUS status;
     320
     321        status = do_connect(ctx, server, share,
    318322                                auth_info,
    319323                                show_hdr, force_encrypt, max_protocol,
    320                                 port, name_type);
    321 
    322         if (!cli ) {
    323                 return NULL;
     324                                port, name_type, &cli);
     325
     326        if (!NT_STATUS_IS_OK(status)) {
     327                return status;
    324328        }
    325329
    326330        /* Enter into the list. */
    327331        if (referring_cli) {
    328                 DLIST_ADD_END(referring_cli, cli, struct cli_state *);
     332                DLIST_ADD_END(referring_cli, cli);
    329333        }
    330334
    331335        if (referring_cli && referring_cli->requested_posix_capabilities) {
    332                 uint16 major, minor;
    333                 uint32 caplow, caphigh;
    334                 NTSTATUS status;
     336                uint16_t major, minor;
     337                uint32_t caplow, caphigh;
    335338                status = cli_unix_extensions_version(cli, &major, &minor,
    336339                                                     &caplow, &caphigh);
     
    342345        }
    343346
    344         return cli;
     347        *pcli = cli;
     348        return NT_STATUS_OK;
    345349}
    346350
     
    361365        /* Search to the start of the list. */
    362366        for (p = cli; p; p = DLIST_PREV(p)) {
    363                 if (strequal(server, p->desthost) &&
     367                const char *remote_name =
     368                        smbXcli_conn_remote_name(p->conn);
     369
     370                if (strequal(server, remote_name) &&
    364371                                strequal(share,p->share)) {
    365372                        return p;
     
    369376        /* Search to the end of the list. */
    370377        for (p = cli->next; p; p = p->next) {
    371                 if (strequal(server, p->desthost) &&
     378                const char *remote_name =
     379                        smbXcli_conn_remote_name(p->conn);
     380
     381                if (strequal(server, remote_name) &&
    372382                                strequal(share,p->share)) {
    373383                        return p;
     
    382392****************************************************************************/
    383393
    384 struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
     394NTSTATUS cli_cm_open(TALLOC_CTX *ctx,
    385395                                struct cli_state *referring_cli,
    386396                                const char *server,
     
    391401                                int max_protocol,
    392402                                int port,
    393                                 int name_type)
     403                                int name_type,
     404                                struct cli_state **pcli)
    394405{
    395406        /* Try to reuse an existing connection in this list. */
    396407        struct cli_state *c = cli_cm_find(referring_cli, server, share);
     408        NTSTATUS status;
    397409
    398410        if (c) {
    399                 return c;
     411                *pcli = c;
     412                return NT_STATUS_OK;
    400413        }
    401414
     
    406419                        "without auth info\n",
    407420                        server, share );
    408                 return NULL;
    409         }
    410 
    411         return cli_cm_connect(ctx,
     421                return NT_STATUS_INVALID_PARAMETER;
     422        }
     423
     424        status = cli_cm_connect(ctx,
    412425                                referring_cli,
    413426                                server,
     
    418431                                max_protocol,
    419432                                port,
    420                                 name_type);
     433                                name_type,
     434                                &c);
     435        if (!NT_STATUS_IS_OK(status)) {
     436                return status;
     437        }
     438        *pcli = c;
     439        return NT_STATUS_OK;
    421440}
    422441
     
    424443****************************************************************************/
    425444
    426 void cli_cm_display(const struct cli_state *cli)
     445void cli_cm_display(struct cli_state *cli)
    427446{
    428447        int i;
     
    430449        for (i=0; cli; cli = cli->next,i++ ) {
    431450                d_printf("%d:\tserver=%s, share=%s\n",
    432                         i, cli->desthost, cli->share );
     451                        i, smbXcli_conn_remote_name(cli->conn), cli->share);
    433452        }
    434453}
     
    597616        return talloc_asprintf(ctx, "%c%s%c%s%c%s",
    598617                        path_sep,
    599                         cli->desthost,
     618                        smbXcli_conn_remote_name(cli->conn),
    600619                        path_sep,
    601620                        cli->share,
     
    613632        /* only deal with DS when we negotiated NT_STATUS codes and UNICODE */
    614633
    615         if (!(cli->capabilities & CAP_UNICODE)) {
     634        if (!(smbXcli_conn_use_unicode(cli->conn))) {
    616635                return false;
    617636        }
    618         if (!(cli->capabilities & CAP_STATUS32)) {
     637        if (!(smb1cli_conn_capabilities(cli->conn) & CAP_STATUS32)) {
    619638                return false;
    620639        }
     
    636655                        size_t *consumed)
    637656{
    638         unsigned int data_len = 0;
    639657        unsigned int param_len = 0;
    640         uint16 setup[1];
     658        uint16_t recv_flags2;
    641659        uint8_t *param = NULL;
    642660        uint8_t *rdata = NULL;
    643661        char *p;
    644662        char *endp;
    645         size_t pathlen = 2*(strlen(path)+1);
    646663        smb_ucs2_t *path_ucs;
    647664        char *consumed_path = NULL;
    648665        uint16_t consumed_ucs;
    649         uint16 num_referrals;
     666        uint16_t num_referrals;
    650667        struct client_dfs_referral *referrals = NULL;
    651668        NTSTATUS status;
     669        TALLOC_CTX *frame = talloc_stackframe();
    652670
    653671        *num_refs = 0;
    654672        *refs = NULL;
    655673
    656         SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL);
    657 
    658         param = SMB_MALLOC_ARRAY(uint8_t, 2+pathlen+2);
     674        param = talloc_array(talloc_tos(), uint8_t, 2);
    659675        if (!param) {
    660676                status = NT_STATUS_NO_MEMORY;
     
    662678        }
    663679        SSVAL(param, 0, 0x03);  /* max referral level */
    664         p = (char *)(&param[2]);
    665 
    666         path_ucs = (smb_ucs2_t *)p;
    667         p += clistr_push(cli, p, path, pathlen, STR_TERMINATE);
    668         param_len = PTR_DIFF(p, param);
    669 
    670         status = cli_trans(talloc_tos(), cli, SMBtrans2,
    671                            NULL, 0xffff, 0, 0,
    672                            setup, 1, 0,
    673                            param, param_len, 2,
    674                            NULL, 0, cli->max_xmit,
    675                            NULL,
    676                            NULL, 0, NULL, /* rsetup */
    677                            NULL, 0, NULL,
    678                            &rdata, 4, &data_len);
    679         if (!NT_STATUS_IS_OK(status)) {
     680
     681        param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
     682                                      path, strlen(path)+1,
     683                                      NULL);
     684        if (!param) {
     685                status = NT_STATUS_NO_MEMORY;
    680686                goto out;
    681687        }
    682         if (data_len < 4) {
    683                 goto out;
    684         }
    685 
    686         endp = (char *)rdata + data_len;
     688        param_len = talloc_get_size(param);
     689        path_ucs = (smb_ucs2_t *)&param[2];
     690
     691        if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
     692                DATA_BLOB in_input_buffer;
     693                DATA_BLOB in_output_buffer = data_blob_null;
     694                DATA_BLOB out_input_buffer = data_blob_null;
     695                DATA_BLOB out_output_buffer = data_blob_null;
     696
     697                in_input_buffer.data = param;
     698                in_input_buffer.length = param_len;
     699
     700                status = smb2cli_ioctl(cli->conn,
     701                                       cli->timeout,
     702                                       cli->smb2.session,
     703                                       cli->smb2.tcon,
     704                                       UINT64_MAX, /* in_fid_persistent */
     705                                       UINT64_MAX, /* in_fid_volatile */
     706                                       FSCTL_DFS_GET_REFERRALS,
     707                                       0, /* in_max_input_length */
     708                                       &in_input_buffer,
     709                                       CLI_BUFFER_SIZE, /* in_max_output_length */
     710                                       &in_output_buffer,
     711                                       SMB2_IOCTL_FLAG_IS_FSCTL,
     712                                       talloc_tos(),
     713                                       &out_input_buffer,
     714                                       &out_output_buffer);
     715                if (!NT_STATUS_IS_OK(status)) {
     716                        goto out;
     717                }
     718
     719                if (out_output_buffer.length < 4) {
     720                        status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     721                        goto out;
     722                }
     723
     724                recv_flags2 = FLAGS2_UNICODE_STRINGS;
     725                rdata = out_output_buffer.data;
     726                endp = (char *)rdata + out_output_buffer.length;
     727        } else {
     728                unsigned int data_len = 0;
     729                uint16_t setup[1];
     730
     731                SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL);
     732
     733                status = cli_trans(talloc_tos(), cli, SMBtrans2,
     734                                   NULL, 0xffff, 0, 0,
     735                                   setup, 1, 0,
     736                                   param, param_len, 2,
     737                                   NULL, 0, CLI_BUFFER_SIZE,
     738                                   &recv_flags2,
     739                                   NULL, 0, NULL, /* rsetup */
     740                                   NULL, 0, NULL,
     741                                   &rdata, 4, &data_len);
     742                if (!NT_STATUS_IS_OK(status)) {
     743                        goto out;
     744                }
     745
     746                endp = (char *)rdata + data_len;
     747        }
    687748
    688749        consumed_ucs  = SVAL(rdata, 0);
     
    696757         * the incoming path. */
    697758
     759        errno = 0;
    698760        if (pull_string_talloc(talloc_tos(),
    699761                        NULL,
     
    703765                        consumed_ucs,
    704766                        STR_UNICODE) == 0) {
     767                if (errno != 0) {
     768                        status = map_nt_error_from_unix(errno);
     769                } else {
     770                        status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     771                }
    705772                goto out;
    706773        }
    707774        if (consumed_path == NULL) {
     775                status = map_nt_error_from_unix(errno);
    708776                goto out;
    709777        }
     
    711779
    712780        if (num_referrals != 0) {
    713                 uint16 ref_version;
    714                 uint16 ref_size;
     781                uint16_t ref_version;
     782                uint16_t ref_size;
    715783                int i;
    716                 uint16 node_offset;
     784                uint16_t node_offset;
    717785
    718786                referrals = talloc_array(ctx, struct client_dfs_referral,
     
    720788
    721789                if (!referrals) {
     790                        status = NT_STATUS_NO_MEMORY;
    722791                        goto out;
    723792                }
     
    742811
    743812                        if (p + node_offset > endp) {
     813                                status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    744814                                goto out;
    745815                        }
    746                         clistr_pull_talloc(ctx, cli->inbuf,
    747                                            SVAL(cli->inbuf, smb_flg2),
     816                        clistr_pull_talloc(referrals,
     817                                           (const char *)rdata,
     818                                           recv_flags2,
    748819                                           &referrals[i].dfspath,
    749                                            p+node_offset, -1,
     820                                           p+node_offset,
     821                                           PTR_DIFF(endp, p+node_offset),
    750822                                           STR_TERMINATE|STR_UNICODE);
    751823
    752824                        if (!referrals[i].dfspath) {
     825                                status = map_nt_error_from_unix(errno);
    753826                                goto out;
    754827                        }
     
    756829                }
    757830                if (i < num_referrals) {
     831                        status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    758832                        goto out;
    759833                }
     
    765839  out:
    766840
    767         TALLOC_FREE(consumed_path);
    768         SAFE_FREE(param);
    769         TALLOC_FREE(rdata);
     841        TALLOC_FREE(frame);
    770842        return status;
    771843}
     
    773845/********************************************************************
    774846********************************************************************/
    775 
    776 bool cli_resolve_path(TALLOC_CTX *ctx,
    777                         const char *mountpt,
    778                         const struct user_auth_info *dfs_auth_info,
    779                         struct cli_state *rootcli,
    780                         const char *path,
    781                         struct cli_state **targetcli,
    782                         char **pp_targetpath)
     847struct cli_dfs_path_split {
     848        char *server;
     849        char *share;
     850        char *extrapath;
     851};
     852
     853NTSTATUS cli_resolve_path(TALLOC_CTX *ctx,
     854                          const char *mountpt,
     855                          const struct user_auth_info *dfs_auth_info,
     856                          struct cli_state *rootcli,
     857                          const char *path,
     858                          struct cli_state **targetcli,
     859                          char **pp_targetpath)
    783860{
    784861        struct client_dfs_referral *refs = NULL;
     
    790867        char *extrapath = NULL;
    791868        int pathlen;
    792         char *server = NULL;
    793         char *share = NULL;
    794869        struct cli_state *newcli = NULL;
     870        struct cli_state *ccli = NULL;
     871        int count = 0;
    795872        char *newpath = NULL;
    796873        char *newmount = NULL;
    797874        char *ppath = NULL;
    798875        SMB_STRUCT_STAT sbuf;
    799         uint32 attributes;
     876        uint32_t attributes;
    800877        NTSTATUS status;
     878        struct smbXcli_tcon *root_tcon = NULL;
     879        struct smbXcli_tcon *target_tcon = NULL;
     880        struct cli_dfs_path_split *dfs_refs = NULL;
    801881
    802882        if ( !rootcli || !path || !targetcli ) {
    803                 return false;
     883                return NT_STATUS_INVALID_PARAMETER;
    804884        }
    805885
    806886        /* Don't do anything if this is not a DFS root. */
    807887
    808         if ( !rootcli->dfsroot) {
     888        if (smbXcli_conn_protocol(rootcli->conn) >= PROTOCOL_SMB2_02) {
     889                root_tcon = rootcli->smb2.tcon;
     890        } else {
     891                root_tcon = rootcli->smb1.tcon;
     892        }
     893
     894        if (!smbXcli_tcon_is_dfs_share(root_tcon)) {
    809895                *targetcli = rootcli;
    810896                *pp_targetpath = talloc_strdup(ctx, path);
    811897                if (!*pp_targetpath) {
    812                         return false;
    813                 }
    814                 return true;
     898                        return NT_STATUS_NO_MEMORY;
     899                }
     900                return NT_STATUS_OK;
    815901        }
    816902
     
    821907        cleanpath = clean_path(ctx, path);
    822908        if (!cleanpath) {
    823                 return false;
     909                return NT_STATUS_NO_MEMORY;
    824910        }
    825911
    826912        dfs_path = cli_dfs_make_full_path(ctx, rootcli, cleanpath);
    827913        if (!dfs_path) {
    828                 return false;
     914                return NT_STATUS_NO_MEMORY;
    829915        }
    830916
     
    835921                *pp_targetpath = talloc_strdup(ctx, path);
    836922                if (!*pp_targetpath) {
    837                         return false;
     923                        return NT_STATUS_NO_MEMORY;
    838924                }
    839925                goto done;
     
    847933                *pp_targetpath = talloc_strdup(ctx, path);
    848934                if (!*pp_targetpath) {
    849                         return false;
     935                        return NT_STATUS_NO_MEMORY;
    850936                }
    851937                goto done;
     
    856942        if (!cli_dfs_check_error(rootcli, NT_STATUS_PATH_NOT_COVERED,
    857943                                 status)) {
    858                 return false;
     944                return status;
    859945        }
    860946
    861947        /* Check for the referral. */
    862948
    863         if (!(cli_ipc = cli_cm_open(ctx,
    864                                 rootcli,
    865                                 rootcli->desthost,
    866                                 "IPC$",
     949        status = cli_cm_open(ctx,
     950                             rootcli,
     951                             smbXcli_conn_remote_name(rootcli->conn),
     952                             "IPC$",
     953                             dfs_auth_info,
     954                             false,
     955                             smb1cli_conn_encryption_on(rootcli->conn),
     956                             smbXcli_conn_protocol(rootcli->conn),
     957                             0,
     958                             0x20,
     959                             &cli_ipc);
     960        if (!NT_STATUS_IS_OK(status)) {
     961                return status;
     962        }
     963
     964        status = cli_dfs_get_referral(ctx, cli_ipc, dfs_path, &refs,
     965                                      &num_refs, &consumed);
     966        if (!NT_STATUS_IS_OK(status)) {
     967                return status;
     968        }
     969
     970        if (!num_refs || !refs[0].dfspath) {
     971                return NT_STATUS_NOT_FOUND;
     972        }
     973
     974        /*
     975         * Bug#10123 - DFS referal entries can be provided in a random order,
     976         * so check the connection cache for each item to avoid unnecessary
     977         * reconnections.
     978         */
     979        dfs_refs = talloc_array(ctx, struct cli_dfs_path_split, num_refs);
     980        if (dfs_refs == NULL) {
     981                return NT_STATUS_NO_MEMORY;
     982        }
     983
     984        for (count = 0; count < num_refs; count++) {
     985                if (!split_dfs_path(dfs_refs, refs[count].dfspath,
     986                                    &dfs_refs[count].server,
     987                                    &dfs_refs[count].share,
     988                                    &dfs_refs[count].extrapath)) {
     989                        TALLOC_FREE(dfs_refs);
     990                        return NT_STATUS_NOT_FOUND;
     991                }
     992
     993                ccli = cli_cm_find(rootcli, dfs_refs[count].server,
     994                                   dfs_refs[count].share);
     995                if (ccli != NULL) {
     996                        extrapath = dfs_refs[count].extrapath;
     997                        *targetcli = ccli;
     998                        break;
     999                }
     1000        }
     1001
     1002        /*
     1003         * If no cached connection was found, then connect to the first live
     1004         * referral server in the list.
     1005         */
     1006        for (count = 0; (ccli == NULL) && (count < num_refs); count++) {
     1007                /* Connect to the target server & share */
     1008                status = cli_cm_connect(ctx, rootcli,
     1009                                dfs_refs[count].server,
     1010                                dfs_refs[count].share,
    8671011                                dfs_auth_info,
    8681012                                false,
    869                                 (rootcli->trans_enc_state != NULL),
    870                                 rootcli->protocol,
     1013                                smb1cli_conn_encryption_on(rootcli->conn),
     1014                                smbXcli_conn_protocol(rootcli->conn),
    8711015                                0,
    872                                 0x20))) {
    873                 return false;
    874         }
    875 
    876         status = cli_dfs_get_referral(ctx, cli_ipc, dfs_path, &refs,
    877                                       &num_refs, &consumed);
    878         if (!NT_STATUS_IS_OK(status) || !num_refs) {
    879                 return false;
    880         }
    881 
    882         /* Just store the first referral for now. */
    883 
    884         if (!refs[0].dfspath) {
    885                 return false;
    886         }
    887         if (!split_dfs_path(ctx, refs[0].dfspath, &server, &share,
    888                             &extrapath)) {
    889                 return false;
     1016                                0x20,
     1017                                targetcli);
     1018                if (!NT_STATUS_IS_OK(status)) {
     1019                        d_printf("Unable to follow dfs referral [\\%s\\%s]\n",
     1020                                 dfs_refs[count].server,
     1021                                 dfs_refs[count].share);
     1022                        continue;
     1023                } else {
     1024                        extrapath = dfs_refs[count].extrapath;
     1025                        break;
     1026                }
     1027        }
     1028
     1029        /* No available referral server for the connection */
     1030        if (*targetcli == NULL) {
     1031                TALLOC_FREE(dfs_refs);
     1032                return status;
    8901033        }
    8911034
     
    8941037        dfs_path = cli_dfs_make_full_path(ctx, rootcli, path);
    8951038        if (!dfs_path) {
    896                 return false;
     1039                TALLOC_FREE(dfs_refs);
     1040                return NT_STATUS_NO_MEMORY;
    8971041        }
    8981042        pathlen = strlen(dfs_path);
     
    9001044        *pp_targetpath = talloc_strdup(ctx, &dfs_path[consumed]);
    9011045        if (!*pp_targetpath) {
    902                 return false;
     1046                TALLOC_FREE(dfs_refs);
     1047                return NT_STATUS_NO_MEMORY;
    9031048        }
    9041049        dfs_path[consumed] = '\0';
     
    9091054         * (in \server\share\path format).
    9101055         */
    911 
    912         /* Open the connection to the target server & share */
    913         if ((*targetcli = cli_cm_open(ctx, rootcli,
    914                                         server,
    915                                         share,
    916                                         dfs_auth_info,
    917                                         false,
    918                                         (rootcli->trans_enc_state != NULL),
    919                                         rootcli->protocol,
    920                                         0,
    921                                         0x20)) == NULL) {
    922                 d_printf("Unable to follow dfs referral [\\%s\\%s]\n",
    923                         server, share );
    924                 return false;
    925         }
    9261056
    9271057        if (extrapath && strlen(extrapath) > 0) {
     
    9401070                }
    9411071                if (!*pp_targetpath) {
    942                         return false;
     1072                        TALLOC_FREE(dfs_refs);
     1073                        return NT_STATUS_NO_MEMORY;
    9431074                }
    9441075        }
     
    9531084                        "dfs_path (%s) not in correct format.\n",
    9541085                        dfs_path );
    955                 return false;
     1086                TALLOC_FREE(dfs_refs);
     1087                return NT_STATUS_NOT_FOUND;
    9561088        }
    9571089
     
    9591091
    9601092        if ((ppath = strchr_m( dfs_path, '\\' )) == NULL) {
    961                 return false;
     1093                TALLOC_FREE(dfs_refs);
     1094                return NT_STATUS_NOT_FOUND;
    9621095        }
    9631096
     
    9651098
    9661099        if ((ppath = strchr_m( ppath+1, '\\' )) == NULL) {
    967                 return false;
     1100                TALLOC_FREE(dfs_refs);
     1101                return NT_STATUS_NOT_FOUND;
    9681102        }
    9691103
     
    9721106        newmount = talloc_asprintf(ctx, "%s\\%s", mountpt, ppath );
    9731107        if (!newmount) {
    974                 return false;
     1108                TALLOC_FREE(dfs_refs);
     1109                return NT_STATUS_NOT_FOUND;
    9751110        }
    9761111
     
    9811116
    9821117        if (!strequal(*pp_targetpath, "\\") && !strequal(*pp_targetpath, "/")) {
    983                 if (cli_resolve_path(ctx,
    984                                         newmount,
    985                                         dfs_auth_info,
    986                                         *targetcli,
    987                                         *pp_targetpath,
    988                                         &newcli,
    989                                         &newpath)) {
     1118                status = cli_resolve_path(ctx,
     1119                                          newmount,
     1120                                          dfs_auth_info,
     1121                                          *targetcli,
     1122                                          *pp_targetpath,
     1123                                          &newcli,
     1124                                          &newpath);
     1125                if (NT_STATUS_IS_OK(status)) {
    9901126                        /*
    9911127                         * When cli_resolve_path returns true here it's always
     
    9951131                        *targetcli = newcli;
    9961132                        *pp_targetpath = newpath;
    997                         return true;
     1133                        TALLOC_FREE(dfs_refs);
     1134                        return status;
    9981135                }
    9991136        }
     
    10011138  done:
    10021139
     1140        if (smbXcli_conn_protocol((*targetcli)->conn) >= PROTOCOL_SMB2_02) {
     1141                target_tcon = (*targetcli)->smb2.tcon;
     1142        } else {
     1143                target_tcon = (*targetcli)->smb1.tcon;
     1144        }
     1145
    10031146        /* If returning true ensure we return a dfs root full path. */
    1004         if ((*targetcli)->dfsroot) {
     1147        if (smbXcli_tcon_is_dfs_share(target_tcon)) {
    10051148                dfs_path = talloc_strdup(ctx, *pp_targetpath);
    10061149                if (!dfs_path) {
    1007                         return false;
     1150                        TALLOC_FREE(dfs_refs);
     1151                        return NT_STATUS_NO_MEMORY;
    10081152                }
    10091153                *pp_targetpath = cli_dfs_make_full_path(ctx, *targetcli, dfs_path);
    1010         }
    1011 
    1012         return true;
     1154                if (*pp_targetpath == NULL) {
     1155                        TALLOC_FREE(dfs_refs);
     1156                        return NT_STATUS_NO_MEMORY;
     1157                }
     1158        }
     1159
     1160        TALLOC_FREE(dfs_refs);
     1161        return NT_STATUS_OK;
    10131162}
    10141163
     
    10311180        char *fullpath = NULL;
    10321181        bool res;
    1033         uint16 cnum;
     1182        uint16_t cnum;
    10341183        char *newextrapath = NULL;
    10351184        NTSTATUS status;
     1185        const char *remote_name;
    10361186
    10371187        if (!cli || !sharename) {
     
    10391189        }
    10401190
    1041         cnum = cli->cnum;
     1191        remote_name = smbXcli_conn_remote_name(cli->conn);
     1192        cnum = cli_state_get_tid(cli);
    10421193
    10431194        /* special case.  never check for a referral on the IPC$ share */
     
    10491200        /* send a trans2_query_path_info to check for a referral */
    10501201
    1051         fullpath = talloc_asprintf(ctx, "\\%s\\%s", cli->desthost, sharename );
     1202        fullpath = talloc_asprintf(ctx, "\\%s\\%s", remote_name, sharename);
    10521203        if (!fullpath) {
    10531204                return false;
     
    10561207        /* check for the referral */
    10571208
    1058         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, "IPC$", "IPC", NULL, 0))) {
     1209        if (!NT_STATUS_IS_OK(cli_tree_connect(cli, "IPC$", "IPC", NULL, 0))) {
    10591210                return false;
    10601211        }
     
    10641215                                        username,
    10651216                                        password,
    1066                                         lp_workgroup(),
     1217                                        domain,
    10671218                                        "IPC$");
    10681219                if (!NT_STATUS_IS_OK(status)) {
     
    10801231        }
    10811232
    1082         cli->cnum = cnum;
     1233        cli_state_set_tid(cli, cnum);
    10831234
    10841235        if (!res || !num_refs) {
     
    10971248        /* check that this is not a self-referral */
    10981249
    1099         if (strequal(cli->desthost, *pp_newserver) &&
     1250        if (strequal(remote_name, *pp_newserver) &&
    11001251                        strequal(sharename, *pp_newshare)) {
    11011252                return false;
Note: See TracChangeset for help on using the changeset viewer.