smbd: add create_conn_struct_tos[_cwd]() helper functions
authorStefan Metzmacher <metze@samba.org>
Thu, 24 May 2018 13:59:43 +0000 (15:59 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 14 Jun 2018 18:52:20 +0000 (20:52 +0200)
This makes it more obvious that the returned connection_struct
is only temporary (and allocated on talloc_tos()!)
It will never allow async requests on a long term
tevent context! So we create a short term event context.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/msdfs.c
source3/smbd/proto.h

index 3c23d74..d6fbe93 100644 (file)
@@ -448,6 +448,131 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
        return NT_STATUS_OK;
 }
 
+static int conn_struct_tos_destructor(struct conn_struct_tos *c)
+{
+       if (c->oldcwd_fname != NULL) {
+               vfs_ChDir(c->conn, c->oldcwd_fname);
+               TALLOC_FREE(c->oldcwd_fname);
+       }
+       SMB_VFS_DISCONNECT(c->conn);
+       conn_free(c->conn);
+       return 0;
+}
+
+/********************************************************
+ Fake up a connection struct for the VFS layer, for use in
+ applications (such as the python bindings), that do not want the
+ global working directory changed under them.
+
+ SMB_VFS_CONNECT requires root privileges.
+ This temporary uses become_root() and unbecome_root().
+
+ But further impersonation has to be cone by the caller.
+*********************************************************/
+NTSTATUS create_conn_struct_tos(struct messaging_context *msg,
+                               int snum,
+                               const char *path,
+                               const struct auth_session_info *session_info,
+                               struct conn_struct_tos **_c)
+{
+       struct conn_struct_tos *c = NULL;
+       struct tevent_context *ev = NULL;
+       NTSTATUS status;
+
+       *_c = NULL;
+
+       c = talloc_zero(talloc_tos(), struct conn_struct_tos);
+       if (c == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ev = samba_tevent_context_init(c);
+       if (ev == NULL) {
+               TALLOC_FREE(c);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = create_conn_struct(c,
+                                   ev,
+                                   msg,
+                                   &c->conn,
+                                   snum,
+                                   path,
+                                   session_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(c);
+               return status;
+       }
+       talloc_steal(c, c->conn);
+
+       talloc_set_destructor(c, conn_struct_tos_destructor);
+
+       *_c = c;
+       return NT_STATUS_OK;
+}
+
+/********************************************************
+ Fake up a connection struct for the VFS layer.
+ Note: this performs a vfs connect and CHANGES CWD !!!! JRA.
+
+ See also the comment for create_conn_struct_tos() above!
+
+ The CWD change is reverted by the destructor of
+ conn_struct_tos when the current talloc_tos() is destroyed.
+*********************************************************/
+NTSTATUS create_conn_struct_tos_cwd(struct messaging_context *msg,
+                                   int snum,
+                                   const char *path,
+                                   const struct auth_session_info *session_info,
+                                   struct conn_struct_tos **_c)
+{
+       struct conn_struct_tos *c = NULL;
+       struct smb_filename smb_fname_connectpath = {0};
+       NTSTATUS status;
+
+       *_c = NULL;
+
+       status = create_conn_struct_tos(msg,
+                                       snum,
+                                       path,
+                                       session_info,
+                                       &c);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /*
+        * Windows seems to insist on doing trans2getdfsreferral() calls on
+        * the IPC$ share as the anonymous user. If we try to chdir as that
+        * user we will fail.... WTF ? JRA.
+        */
+
+       c->oldcwd_fname = vfs_GetWd(c, c->conn);
+       if (c->oldcwd_fname == NULL) {
+               status = map_nt_error_from_unix(errno);
+               DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno)));
+               TALLOC_FREE(c);
+               return status;
+       }
+
+       smb_fname_connectpath = (struct smb_filename) {
+               .base_name = c->conn->connectpath
+       };
+
+       if (vfs_ChDir(c->conn, &smb_fname_connectpath) != 0) {
+               status = map_nt_error_from_unix(errno);
+               DBG_NOTICE("Can't ChDir to new conn path %s. "
+                          "Error was %s\n",
+                          c->conn->connectpath, strerror(errno));
+               TALLOC_FREE(c->oldcwd_fname);
+               TALLOC_FREE(c);
+               return status;
+       }
+
+       *_c = c;
+       return NT_STATUS_OK;
+}
+
 static void shuffle_strlist(char **list, int count)
 {
        int i;
index 5f72da0..ed12e50 100644 (file)
@@ -514,6 +514,22 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
                                const char *path,
                                const struct auth_session_info *session_info,
                                struct smb_filename **poldcwd_fname);
+struct connection_struct;
+struct smb_filename;
+struct conn_struct_tos {
+       struct connection_struct *conn;
+       struct smb_filename *oldcwd_fname;
+};
+NTSTATUS create_conn_struct_tos(struct messaging_context *msg,
+                               int snum,
+                               const char *path,
+                               const struct auth_session_info *session_info,
+                               struct conn_struct_tos **_c);
+NTSTATUS create_conn_struct_tos_cwd(struct messaging_context *msg,
+                                   int snum,
+                                   const char *path,
+                                   const struct auth_session_info *session_info,
+                                   struct conn_struct_tos **_c);
 
 /* The following definitions come from smbd/negprot.c  */