s3-libsmb: update libsmb to use new DLIST macros
[abartlet/samba.git/.git] / source3 / libsmb / clidfs.c
index 18e7ab1dec732084dc105c15041a1dc119038316..d9e2b87d10c39898cd310ab2c5566c5c5c53cbe7 100644 (file)
    as a separator when looking at the pathname part.... JRA.
 ********************************************************************/
 
-static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
-                               struct cli_state *cli,
-                               const char *sharename,
-                               char **pp_newserver,
-                               char **pp_newshare,
-                               bool force_encrypt,
-                               const char *username,
-                               const char *password,
-                               const char *domain);
-
 /********************************************************************
  Ensure a connection is encrypted.
 ********************************************************************/
@@ -94,6 +84,7 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
 {
        struct cli_state *c = NULL;
        struct nmb_name called, calling;
+       const char *called_str;
        const char *server_n;
        struct sockaddr_storage ss;
        char *servicename;
@@ -111,6 +102,7 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
        sharename = servicename;
        if (*sharename == '\\') {
                sharename += 2;
+               called_str = sharename;
                if (server == NULL) {
                        server = sharename;
                }
@@ -120,6 +112,8 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
                }
                *sharename = 0;
                sharename++;
+       } else {
+               called_str = server;
        }
 
        server_n = server;
@@ -127,7 +121,7 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
        zero_sockaddr(&ss);
 
        make_nmb_name(&calling, global_myname(), 0x0);
-       make_nmb_name(&called , server, name_type);
+       make_nmb_name(&called , called_str, name_type);
 
  again:
        zero_sockaddr(&ss);
@@ -160,6 +154,7 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
        c->use_kerberos = get_cmdline_auth_info_use_kerberos(auth_info);
        c->fallback_after_kerberos =
                get_cmdline_auth_info_fallback_after_kerberos(auth_info);
+       c->use_ccache = get_cmdline_auth_info_use_ccache(auth_info);
 
        if (!cli_session_request(c, &calling, &called)) {
                char *p;
@@ -212,6 +207,15 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
                        return NULL;
                }
                d_printf("Anonymous login successful\n");
+               status = cli_init_creds(c, "", lp_workgroup(), "");
+       } else {
+               status = cli_init_creds(c, username, lp_workgroup(), password);
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10,("cli_init_creds() failed: %s\n", nt_errstr(status)));
+               cli_shutdown(c);
+               return NULL;
        }
 
        if ( show_sessetup ) {
@@ -228,7 +232,7 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
        /* here's the fun part....to support 'msdfs proxy' shares
           (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL
           here before trying to connect to the original share.
-          check_dfs_proxy() will fail if it is a normal share. */
+          cli_check_msdfs_proxy() will fail if it is a normal share. */
 
        if ((c->capabilities & CAP_DFS) &&
                        cli_check_msdfs_proxy(ctx, c, sharename,
@@ -319,8 +323,10 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
        if (referring_cli && referring_cli->posix_capabilities) {
                uint16 major, minor;
                uint32 caplow, caphigh;
-               if (cli_unix_extensions_version(cli, &major,
-                                       &minor, &caplow, &caphigh)) {
+               NTSTATUS status;
+               status = cli_unix_extensions_version(cli, &major, &minor,
+                                                    &caplow, &caphigh);
+               if (NT_STATUS_IS_OK(status)) {
                        cli_set_unix_extensions_capabilities(cli,
                                        major, minor,
                                        caplow, caphigh);
@@ -345,7 +351,7 @@ static struct cli_state *cli_cm_find(struct cli_state *cli,
        }
 
        /* Search to the start of the list. */
-       for (p = cli; p; p = p->prev) {
+       for (p = cli; p; p = DLIST_PREV(p)) {
                if (strequal(server, p->desthost) &&
                                strequal(share,p->share)) {
                        return p;
@@ -551,13 +557,23 @@ static char *cli_dfs_make_full_path(TALLOC_CTX *ctx,
                                        struct cli_state *cli,
                                        const char *dir)
 {
+       char path_sep = '\\';
+
        /* Ensure the extrapath doesn't start with a separator. */
        while (IS_DIRECTORY_SEP(*dir)) {
                dir++;
        }
 
-       return talloc_asprintf(ctx, "\\%s\\%s\\%s",
-                       cli->desthost, cli->share, dir);
+       if (cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+               path_sep = '/';
+       }
+       return talloc_asprintf(ctx, "%c%s%c%s%c%s",
+                       path_sep,
+                       cli->desthost,
+                       path_sep,
+                       cli->share,
+                       path_sep,
+                       dir);
 }
 
 /********************************************************************
@@ -587,20 +603,23 @@ static bool cli_dfs_check_error( struct cli_state *cli, NTSTATUS status )
 bool cli_dfs_get_referral(TALLOC_CTX *ctx,
                        struct cli_state *cli,
                        const char *path,
-                       CLIENT_DFS_REFERRAL**refs,
+                       struct client_dfs_referral **refs,
                        size_t *num_refs,
-                       uint16 *consumed)
+                       size_t *consumed)
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
        uint16 setup = TRANSACT2_GET_DFS_REFERRAL;
-       char *param;
+       char *param = NULL;
        char *rparam=NULL, *rdata=NULL;
        char *p;
        char *endp;
        size_t pathlen = 2*(strlen(path)+1);
+       smb_ucs2_t *path_ucs;
+       char *consumed_path = NULL;
+       uint16_t consumed_ucs;
        uint16 num_referrals;
-       CLIENT_DFS_REFERRAL *referrals = NULL;
+       struct client_dfs_referral *referrals = NULL;
        bool ret = false;
 
        *num_refs = 0;
@@ -608,11 +627,12 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
 
        param = SMB_MALLOC_ARRAY(char, 2+pathlen+2);
        if (!param) {
-               return false;
+               goto out;
        }
        SSVAL(param, 0, 0x03);  /* max referral level */
        p = &param[2];
 
+       path_ucs = (smb_ucs2_t *)p;
        p += clistr_push(cli, p, path, pathlen, STR_TERMINATE);
        param_len = PTR_DIFF(p, param);
 
@@ -623,16 +643,13 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
                        param, param_len, 2,            /* param, length, max */
                        NULL, 0, cli->max_xmit /* data, length, max */
                        )) {
-               SAFE_FREE(param);
-               return false;
+               goto out;
        }
 
-       SAFE_FREE(param);
-
        if (!cli_receive_trans(cli, SMBtrans2,
                &rparam, &param_len,
                &rdata, &data_len)) {
-                       return false;
+               goto out;
        }
 
        if (data_len < 4) {
@@ -641,17 +658,38 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
 
        endp = rdata + data_len;
 
-       *consumed     = SVAL(rdata, 0);
+       consumed_ucs  = SVAL(rdata, 0);
        num_referrals = SVAL(rdata, 2);
 
+       /* consumed_ucs is the number of bytes
+        * of the UCS2 path consumed not counting any
+        * terminating null. We need to convert
+        * back to unix charset and count again
+        * to get the number of bytes consumed from
+        * the incoming path. */
+
+       if (pull_string_talloc(talloc_tos(),
+                       NULL,
+                       0,
+                       &consumed_path,
+                       path_ucs,
+                       consumed_ucs,
+                       STR_UNICODE) == 0) {
+               goto out;
+       }
+       if (consumed_path == NULL) {
+               goto out;
+       }
+       *consumed = strlen(consumed_path);
+
        if (num_referrals != 0) {
                uint16 ref_version;
                uint16 ref_size;
                int i;
                uint16 node_offset;
 
-               referrals = TALLOC_ARRAY(ctx, CLIENT_DFS_REFERRAL,
-                               num_referrals);
+               referrals = talloc_array(ctx, struct client_dfs_referral,
+                                        num_referrals);
 
                if (!referrals) {
                        goto out;
@@ -700,6 +738,8 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
 
   out:
 
+       TALLOC_FREE(consumed_path);
+       SAFE_FREE(param);
        SAFE_FREE(rdata);
        SAFE_FREE(rparam);
        return ret;
@@ -716,9 +756,9 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
                        struct cli_state **targetcli,
                        char **pp_targetpath)
 {
-       CLIENT_DFS_REFERRAL *refs = NULL;
+       struct client_dfs_referral *refs = NULL;
        size_t num_refs = 0;
-       uint16 consumed;
+       size_t consumed = 0;
        struct cli_state *cli_ipc = NULL;
        char *dfs_path = NULL;
        char *cleanpath = NULL;
@@ -826,13 +866,13 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
        if (!dfs_path) {
                return false;
        }
-       pathlen = strlen(dfs_path)*2;
+       pathlen = strlen(dfs_path);
        consumed = MIN(pathlen, consumed);
-       *pp_targetpath = talloc_strdup(ctx, &dfs_path[consumed/2]);
+       *pp_targetpath = talloc_strdup(ctx, &dfs_path[consumed]);
        if (!*pp_targetpath) {
                return false;
        }
-       dfs_path[consumed/2] = '\0';
+       dfs_path[consumed] = '\0';
 
        /*
         * *pp_targetpath is now the unconsumed part of the path.
@@ -937,7 +977,7 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
 /********************************************************************
 ********************************************************************/
 
-static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
+bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
                                struct cli_state *cli,
                                const char *sharename,
                                char **pp_newserver,
@@ -947,13 +987,14 @@ static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
                                const char *password,
                                const char *domain)
 {
-       CLIENT_DFS_REFERRAL *refs = NULL;
+       struct client_dfs_referral *refs = NULL;
        size_t num_refs = 0;
-       uint16 consumed;
+       size_t consumed = 0;
        char *fullpath = NULL;
        bool res;
        uint16 cnum;
        char *newextrapath = NULL;
+       NTSTATUS status;
 
        if (!cli || !sharename) {
                return false;
@@ -981,7 +1022,7 @@ static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
        }
 
        if (force_encrypt) {
-               NTSTATUS status = cli_cm_force_encryption(cli,
+               status = cli_cm_force_encryption(cli,
                                        username,
                                        password,
                                        lp_workgroup(),
@@ -993,7 +1034,8 @@ static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 
        res = cli_dfs_get_referral(ctx, cli, fullpath, &refs, &num_refs, &consumed);
 
-       if (!cli_tdis(cli)) {
+       status = cli_tdis(cli);
+       if (!NT_STATUS_IS_OK(status)) {
                return false;
        }