Ensure all callers to the rpc_client/cli_pipe functions correctly
[kamenim/samba.git] / source3 / libsmb / libsmb_dir.c
index 612a8772c0efdb6a93882bb4c890a1450b1cbb2d..73bbf82861e342692a930c478d99807dc845ee08 100644 (file)
@@ -267,14 +267,15 @@ net_share_enum_rpc(struct cli_state *cli,
        struct srvsvc_NetShareCtr1 ctr1;
        fstring name = "";
         fstring comment = "";
-       struct rpc_pipe_client *pipe_hnd;
+       struct rpc_pipe_client *pipe_hnd = NULL;
         NTSTATUS nt_status;
        uint32_t resume_handle = 0;
        uint32_t total_entries = 0;
 
         /* Open the server service pipe */
-        pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status);
-        if (!pipe_hnd) {
+        nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
+                                            &pipe_hnd);
+        if (!NT_STATUS_IS_OK(nt_status)) {
                 DEBUG(1, ("net_share_enum_rpc pipe open fail!\n"));
                 return -1;
         }
@@ -319,7 +320,7 @@ net_share_enum_rpc(struct cli_state *cli,
 
 done:
         /* Close the server service pipe */
-        cli_rpc_pipe_close(pipe_hnd);
+        TALLOC_FREE(pipe_hnd);
 
         /* Tell 'em if it worked */
         return W_ERROR_IS_OK(result) ? 0 : -1;
@@ -614,9 +615,13 @@ SMBC_opendir_ctx(SMBCCTX *context,
                          */
                        if (!srv &&
                             !is_ipaddress(server) &&
-                           (resolve_name(server, &rem_ss, 0x1d) ||   /* LMB */
-                             resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */
-
+                           (resolve_name(server, &rem_ss, 0x1d, false) ||   /* LMB */
+                             resolve_name(server, &rem_ss, 0x1b, false) )) { /* DMB */
+                               /*
+                                * "server" is actually a workgroup name,
+                                * not a server. Make this clear.
+                                */
+                               char *wgroup = server;
                                fstring buserver;
 
                                dir->dir_type = SMBC_SERVER;
@@ -624,12 +629,17 @@ SMBC_opendir_ctx(SMBCCTX *context,
                                /*
                                 * Get the backup list ...
                                 */
-                               if (!name_status_find(server, 0, 0,
+                               if (!name_status_find(wgroup, 0, 0,
                                                       &rem_ss, buserver)) {
+                                       char addr[INET6_ADDRSTRLEN];
 
+                                       print_sockaddr(addr, sizeof(addr), &rem_ss);
                                         DEBUG(0,("Could not get name of "
-                                                 "local/domain master browser "
-                                                 "for server %s\n", server));
+                                                "local/domain master browser "
+                                                "for workgroup %s from "
+                                               "address %s\n",
+                                               wgroup,
+                                               addr));
                                        if (dir) {
                                                SAFE_FREE(dir->fname);
                                                SAFE_FREE(dir);
@@ -662,7 +672,7 @@ SMBC_opendir_ctx(SMBCCTX *context,
                                dir->srv = srv;
 
                                /* Now, list the servers ... */
-                               if (!cli_NetServerEnum(srv->cli, server,
+                               if (!cli_NetServerEnum(srv->cli, wgroup,
                                                        0x0000FFFE, list_fn,
                                                       (void *)dir)) {
 
@@ -674,7 +684,7 @@ SMBC_opendir_ctx(SMBCCTX *context,
                                        return NULL;
                                }
                        } else if (srv ||
-                                   (resolve_name(server, &rem_ss, 0x20))) {
+                                   (resolve_name(server, &rem_ss, 0x20, false))) {
 
                                 /*
                                  * If we hadn't found the server, get one now
@@ -769,8 +779,9 @@ SMBC_opendir_ctx(SMBCCTX *context,
                                return NULL;
                        }
 
-                       if (!cli_resolve_path(frame, "", srv->cli, path,
-                                              &targetcli, &targetpath)) {
+                       if (!cli_resolve_path(frame, "", context->internal->auth_info,
+                                               srv->cli, path,
+                                               &targetcli, &targetpath)) {
                                d_printf("Could not resolve %s\n", path);
                                if (dir) {
                                        SAFE_FREE(dir->fname);
@@ -894,7 +905,7 @@ smbc_readdir_internal(SMBCCTX * context,
 
                 /* url-encode the name.  get back remaining buffer space */
                 max_namebuf_len =
-                        SMBC_urlencode(dest->name, src->name, max_namebuf_len);
+                        smbc_urlencode(dest->name, src->name, max_namebuf_len);
 
                 /* We now know the name length */
                 dest->namelen = strlen(dest->name);
@@ -975,9 +986,8 @@ SMBC_readdir_ctx(SMBCCTX *context,
 
         }
 
-        dirp = (struct smbc_dirent *)context->internal->dirent;
-        maxlen = (sizeof(context->internal->dirent) -
-                  sizeof(struct smbc_dirent));
+        dirp = &context->internal->dirent;
+        maxlen = sizeof(context->internal->_dirent_name);
 
         smbc_readdir_internal(context, dirp, dirent, maxlen);
 
@@ -1048,9 +1058,8 @@ SMBC_getdents_ctx(SMBCCTX *context,
                }
 
                 /* Do urlencoding of next entry, if so selected */
-                dirent = (struct smbc_dirent *)context->internal->dirent;
-                maxlen = (sizeof(context->internal->dirent) -
-                          sizeof(struct smbc_dirent));
+                dirent = &context->internal->dirent;
+                maxlen = sizeof(context->internal->_dirent_name);
                 smbc_readdir_internal(context, dirent,
                                       dirlist->dirent, maxlen);
 
@@ -1167,16 +1176,17 @@ SMBC_mkdir_ctx(SMBCCTX *context,
        }
 
        /*d_printf(">>>mkdir: resolving %s\n", path);*/
-       if (!cli_resolve_path(frame, "", srv->cli, path,
-                              &targetcli, &targetpath)) {
+       if (!cli_resolve_path(frame, "", context->internal->auth_info,
+                               srv->cli, path,
+                               &targetcli, &targetpath)) {
                d_printf("Could not resolve %s\n", path);
-               TALLOC_FREE(frame);
+                errno = ENOENT;
+                TALLOC_FREE(frame);
                return -1;
        }
        /*d_printf(">>>mkdir: resolved path as %s\n", targetpath);*/
 
-       if (!cli_mkdir(targetcli, targetpath)) {
-
+       if (!NT_STATUS_IS_OK(cli_mkdir(targetcli, targetpath))) {
                errno = SMBC_errno(context, targetcli);
                TALLOC_FREE(frame);
                return -1;
@@ -1192,8 +1202,6 @@ SMBC_mkdir_ctx(SMBCCTX *context,
  * Our list function simply checks to see if a directory is not empty
  */
 
-static int smbc_rmdir_dirempty = True;
-
 static void
 rmdir_list_fn(const char *mnt,
               file_info *finfo,
@@ -1202,7 +1210,8 @@ rmdir_list_fn(const char *mnt,
 {
        if (strncmp(finfo->name, ".", 1) != 0 &&
             strncmp(finfo->name, "..", 2) != 0) {
-               smbc_rmdir_dirempty = False;
+               bool *smbc_rmdir_dirempty = (bool *)state;
+               *smbc_rmdir_dirempty = false;
         }
 }
 
@@ -1274,16 +1283,17 @@ SMBC_rmdir_ctx(SMBCCTX *context,
        }
 
        /*d_printf(">>>rmdir: resolving %s\n", path);*/
-       if (!cli_resolve_path(frame, "", srv->cli, path,
-                              &targetcli, &targetpath)) {
+       if (!cli_resolve_path(frame, "", context->internal->auth_info,
+                               srv->cli, path,
+                               &targetcli, &targetpath)) {
                d_printf("Could not resolve %s\n", path);
+                errno = ENOENT;
                TALLOC_FREE(frame);
                return -1;
        }
        /*d_printf(">>>rmdir: resolved path as %s\n", targetpath);*/
 
-
-       if (!cli_rmdir(targetcli, targetpath)) {
+       if (!NT_STATUS_IS_OK(cli_rmdir(targetcli, targetpath))) {
 
                errno = SMBC_errno(context, targetcli);
 
@@ -1291,8 +1301,7 @@ SMBC_rmdir_ctx(SMBCCTX *context,
 
                         /* Local storage to avoid buffer overflows */
                        char *lpath;
-
-                       smbc_rmdir_dirempty = True;  /* Make this so ... */
+                       bool smbc_rmdir_dirempty = true;
 
                        lpath = talloc_asprintf(frame, "%s\\*",
                                                targetpath);
@@ -1304,7 +1313,8 @@ SMBC_rmdir_ctx(SMBCCTX *context,
 
                        if (cli_list(targetcli, lpath,
                                      aDIR | aSYSTEM | aHIDDEN,
-                                     rmdir_list_fn, NULL) < 0) {
+                                     rmdir_list_fn,
+                                    &smbc_rmdir_dirempty) < 0) {
 
                                /* Fix errno to ignore latest error ... */
                                DEBUG(5, ("smbc_rmdir: "
@@ -1502,6 +1512,8 @@ SMBC_chmod_ctx(SMBCCTX *context,
         char *user = NULL;
         char *password = NULL;
         char *workgroup = NULL;
+       char *targetpath = NULL;
+       struct cli_state *targetcli = NULL;
        char *path = NULL;
        uint16 mode;
        TALLOC_CTX *frame = talloc_stackframe();
@@ -1519,7 +1531,7 @@ SMBC_chmod_ctx(SMBCCTX *context,
                return -1;
        }
 
-       DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, newmode));
+       DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, (unsigned int)newmode));
 
        if (SMBC_parse_path(frame,
                             context,
@@ -1552,6 +1564,16 @@ SMBC_chmod_ctx(SMBCCTX *context,
                TALLOC_FREE(frame);
                return -1;  /* errno set by SMBC_server */
        }
+       
+       /*d_printf(">>>unlink: resolving %s\n", path);*/
+       if (!cli_resolve_path(frame, "", context->internal->auth_info,
+                               srv->cli, path,
+                               &targetcli, &targetpath)) {
+               d_printf("Could not resolve %s\n", path);
+                errno = ENOENT;
+               TALLOC_FREE(frame);
+               return -1;
+       }
 
        mode = 0;
 
@@ -1560,8 +1582,8 @@ SMBC_chmod_ctx(SMBCCTX *context,
        if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
        if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
 
-       if (!cli_setatr(srv->cli, path, mode, 0)) {
-               errno = SMBC_errno(context, srv->cli);
+       if (!NT_STATUS_IS_OK(cli_setatr(targetcli, targetpath, mode, 0))) {
+               errno = SMBC_errno(context, targetcli);
                TALLOC_FREE(frame);
                return -1;
        }
@@ -1737,15 +1759,17 @@ SMBC_unlink_ctx(SMBCCTX *context,
        }
 
        /*d_printf(">>>unlink: resolving %s\n", path);*/
-       if (!cli_resolve_path(frame, "", srv->cli, path,
-                              &targetcli, &targetpath)) {
+       if (!cli_resolve_path(frame, "", context->internal->auth_info,
+                               srv->cli, path,
+                               &targetcli, &targetpath)) {
                d_printf("Could not resolve %s\n", path);
+                errno = ENOENT;
                TALLOC_FREE(frame);
                return -1;
        }
        /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/
 
-       if (!cli_unlink(targetcli, targetpath)) {
+       if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetpath, aSYSTEM | aHIDDEN))) {
 
                errno = SMBC_errno(context, targetcli);
 
@@ -1902,18 +1926,37 @@ SMBC_rename_ctx(SMBCCTX *ocontext,
 
        }
 
+       /* set the credentials to make DFS work */
+       smbc_set_credentials_with_fallback(ocontext,
+                                          workgroup,
+                                          user1,
+                                          password1);
+
        /*d_printf(">>>rename: resolving %s\n", path1);*/
-       if (!cli_resolve_path(frame, "", srv->cli, path1,
-                              &targetcli1, &targetpath1)) {
+       if (!cli_resolve_path(frame, "", ocontext->internal->auth_info,
+                               srv->cli,
+                               path1,
+                               &targetcli1, &targetpath1)) {
                d_printf("Could not resolve %s\n", path1);
+                errno = ENOENT;
                TALLOC_FREE(frame);
                return -1;
        }
+       
+       /* set the credentials to make DFS work */
+       smbc_set_credentials_with_fallback(ncontext,
+                                          workgroup,
+                                          user2,
+                                          password2);
+       
        /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/
        /*d_printf(">>>rename: resolving %s\n", path2);*/
-       if (!cli_resolve_path(frame, "", srv->cli, path2,
-                              &targetcli2, &targetpath2)) {
+       if (!cli_resolve_path(frame, "", ncontext->internal->auth_info,
+                               srv->cli, 
+                               path2,
+                               &targetcli2, &targetpath2)) {
                d_printf("Could not resolve %s\n", path2);
+                errno = ENOENT;
                TALLOC_FREE(frame);
                return -1;
        }
@@ -1928,12 +1971,12 @@ SMBC_rename_ctx(SMBCCTX *ocontext,
                return -1;
        }
 
-       if (!cli_rename(targetcli1, targetpath1, targetpath2)) {
+       if (!NT_STATUS_IS_OK(cli_rename(targetcli1, targetpath1, targetpath2))) {
                int eno = SMBC_errno(ocontext, targetcli1);
 
                if (eno != EEXIST ||
-                   !cli_unlink(targetcli1, targetpath2) ||
-                   !cli_rename(targetcli1, targetpath1, targetpath2)) {
+                   !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2, aSYSTEM | aHIDDEN)) ||
+                   !NT_STATUS_IS_OK(cli_rename(targetcli1, targetpath1, targetpath2))) {
 
                        errno = eno;
                        TALLOC_FREE(frame);