s3-libsmb: update libsmb to use new DLIST macros
[abartlet/samba.git/.git] / source3 / libsmb / clidfs.c
index 8544d5520eac5825d95f1ca069ca8705b0171949..d9e2b87d10c39898cd310ab2c5566c5c5c53cbe7 100644 (file)
    as a separator when looking at the pathname part.... JRA.
 ********************************************************************/
 
-static struct cm_cred_struct {
-       char *username;
-       char *password;
-       bool got_pass;
-       bool use_kerberos;
-       bool fallback_after_kerberos;
-       int signing_state;
-} cm_creds;
-
-static void cm_set_password(const char *newpass);
-
-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.
 ********************************************************************/
@@ -96,6 +75,7 @@ NTSTATUS cli_cm_force_encryption(struct cli_state *c,
 static struct cli_state *do_connect(TALLOC_CTX *ctx,
                                        const char *server,
                                        const char *share,
+                                       const struct user_auth_info *auth_info,
                                        bool show_sessetup,
                                        bool force_encrypt,
                                        int max_protocol,
@@ -104,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;
@@ -121,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;
                }
@@ -130,6 +112,8 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
                }
                *sharename = 0;
                sharename++;
+       } else {
+               called_str = server;
        }
 
        server_n = server;
@@ -137,13 +121,13 @@ 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);
 
        /* have to open a new connection */
-       if (!(c=cli_initialise_ex(cm_creds.signing_state))) {
+       if (!(c=cli_initialise_ex(get_cmdline_auth_info_signing_state(auth_info)))) {
                d_printf("Connection to %s failed\n", server_n);
                if (c) {
                        cli_shutdown(c);
@@ -167,8 +151,10 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
                max_protocol = PROTOCOL_NT1;
        }
        c->protocol = max_protocol;
-       c->use_kerberos = cm_creds.use_kerberos;
-       c->fallback_after_kerberos = cm_creds.fallback_after_kerberos;
+       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;
@@ -198,20 +184,8 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
                return NULL;
        }
 
-       if (!cm_creds.got_pass && !cm_creds.use_kerberos) {
-               char *label = NULL;
-               char *pass;
-               label = talloc_asprintf(ctx, "Enter %s's password: ",
-                       cm_creds.username);
-               pass = getpass(label);
-               if (pass) {
-                       cm_set_password(pass);
-               }
-               TALLOC_FREE(label);
-       }
-
-       username = cm_creds.username ? cm_creds.username : "";
-       password = cm_creds.password ? cm_creds.password : "";
+       username = get_cmdline_auth_info_username(auth_info);
+       password = get_cmdline_auth_info_password(auth_info);
 
        if (!NT_STATUS_IS_OK(cli_session_setup(c, username,
                                               password, strlen(password),
@@ -219,8 +193,9 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
                                               lp_workgroup()))) {
                /* If a password was not supplied then
                 * try again with a null username. */
-               if (password[0] || !username[0] || cm_creds.use_kerberos ||
-                   !NT_STATUS_IS_OK(cli_session_setup(c, "",
+               if (password[0] || !username[0] ||
+                       get_cmdline_auth_info_use_kerberos(auth_info) ||
+                       !NT_STATUS_IS_OK(cli_session_setup(c, "",
                                                "", 0,
                                                "", 0,
                                               lp_workgroup()))) {
@@ -232,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 ) {
@@ -248,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,
@@ -259,7 +243,7 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
                                lp_workgroup())) {
                cli_shutdown(c);
                return do_connect(ctx, newserver,
-                               newshare, false,
+                               newshare, auth_info, false,
                                force_encrypt, max_protocol,
                                port, name_type);
        }
@@ -313,6 +297,7 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
                                        struct cli_state *referring_cli,
                                        const char *server,
                                        const char *share,
+                                       const struct user_auth_info *auth_info,
                                        bool show_hdr,
                                        bool force_encrypt,
                                        int max_protocol,
@@ -322,6 +307,7 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx,
        struct cli_state *cli;
 
        cli = do_connect(ctx, server, share,
+                               auth_info,
                                show_hdr, force_encrypt, max_protocol,
                                port, name_type);
 
@@ -337,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);
@@ -363,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;
@@ -389,6 +377,7 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
                                struct cli_state *referring_cli,
                                const char *server,
                                const char *share,
+                               const struct user_auth_info *auth_info,
                                bool show_hdr,
                                bool force_encrypt,
                                int max_protocol,
@@ -402,9 +391,25 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx,
                return c;
        }
 
-       return cli_cm_connect(ctx, referring_cli,
-                               server, share, show_hdr, force_encrypt,
-                               max_protocol, port, name_type);
+       if (auth_info == NULL) {
+               /* Can't do a new connection
+                * without auth info. */
+               d_printf("cli_cm_open() Unable to open connection [\\%s\\%s] "
+                       "without auth info\n",
+                       server, share );
+               return NULL;
+       }
+
+       return cli_cm_connect(ctx,
+                               referring_cli,
+                               server,
+                               share,
+                               auth_info,
+                               show_hdr,
+                               force_encrypt,
+                               max_protocol,
+                               port,
+                               name_type);
 }
 
 /****************************************************************************
@@ -423,18 +428,10 @@ void cli_cm_display(const struct cli_state *cli)
 /****************************************************************************
 ****************************************************************************/
 
-static void cm_set_password(const char *newpass)
-{
-       SAFE_FREE(cm_creds.password);
-       cm_creds.password = SMB_STRDUP(newpass);
-       if (cm_creds.password) {
-               cm_creds.got_pass = true;
-       }
-}
-
 /****************************************************************************
 ****************************************************************************/
 
+#if 0
 void cli_cm_set_credentials(struct user_auth_info *auth_info)
 {
        SAFE_FREE(cm_creds.username);
@@ -449,51 +446,7 @@ void cli_cm_set_credentials(struct user_auth_info *auth_info)
        cm_creds.fallback_after_kerberos = false;
        cm_creds.signing_state = get_cmdline_auth_info_signing_state(auth_info);
 }
-
-/****************************************************************************
-****************************************************************************/
-
-void cli_cm_set_signing_state(int state)
-{
-       cm_creds.signing_state = state;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-void cli_cm_set_username(const char *username)
-{
-       SAFE_FREE(cm_creds.username);
-       cm_creds.username = SMB_STRDUP(username);
-}
-
-/****************************************************************************
-****************************************************************************/
-
-void cli_cm_set_password(const char *newpass)
-{
-       SAFE_FREE(cm_creds.password);
-       cm_creds.password = SMB_STRDUP(newpass);
-       if (cm_creds.password) {
-               cm_creds.got_pass = true;
-       }
-}
-
-/****************************************************************************
-****************************************************************************/
-
-void cli_cm_set_use_kerberos(void)
-{
-       cm_creds.use_kerberos = true;
-}
-
-/****************************************************************************
-****************************************************************************/
-
-void cli_cm_set_fallback_after_kerberos(void)
-{
-       cm_creds.fallback_after_kerberos = true;
-}
+#endif
 
 /**********************************************************************
  split a dfs path into the server, share name, and extrapath components
@@ -604,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);
 }
 
 /********************************************************************
@@ -640,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;
@@ -661,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);
 
@@ -676,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) {
@@ -694,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;
@@ -753,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;
@@ -763,14 +750,15 @@ bool cli_dfs_get_referral(TALLOC_CTX *ctx,
 
 bool cli_resolve_path(TALLOC_CTX *ctx,
                        const char *mountpt,
+                       const struct user_auth_info *dfs_auth_info,
                        struct cli_state *rootcli,
                        const char *path,
                        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;
@@ -843,13 +831,16 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
 
        /* Check for the referral. */
 
-       if (!(cli_ipc = cli_cm_open(ctx, rootcli,
-                                       rootcli->desthost,
-                                       "IPC$", false,
-                                       (rootcli->trans_enc_state != NULL),
-                                       rootcli->protocol,
-                                       0,
-                                       0x20))) {
+       if (!(cli_ipc = cli_cm_open(ctx,
+                               rootcli,
+                               rootcli->desthost,
+                               "IPC$",
+                               dfs_auth_info,
+                               false,
+                               (rootcli->trans_enc_state != NULL),
+                               rootcli->protocol,
+                               0,
+                               0x20))) {
                return false;
        }
 
@@ -875,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.
@@ -893,6 +884,7 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
        if ((*targetcli = cli_cm_open(ctx, rootcli,
                                        server,
                                        share,
+                                       dfs_auth_info,
                                        false,
                                        (rootcli->trans_enc_state != NULL),
                                        rootcli->protocol,
@@ -952,6 +944,7 @@ bool cli_resolve_path(TALLOC_CTX *ctx,
        if (!strequal(*pp_targetpath, "\\") && !strequal(*pp_targetpath, "/")) {
                if (cli_resolve_path(ctx,
                                        newmount,
+                                       dfs_auth_info,
                                        *targetcli,
                                        *pp_targetpath,
                                        &newcli,
@@ -984,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,
@@ -994,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;
@@ -1028,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(),
@@ -1040,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;
        }