From: Stefan Metzmacher Date: Thu, 24 May 2018 13:59:43 +0000 (+0200) Subject: smbd: add create_conn_struct_tos[_cwd]() helper functions X-Git-Tag: tevent-0.9.37~371 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=66bc2c4332f475d9b614c442223749a499b39c60;p=thirdparty%2Fsamba.git smbd: add create_conn_struct_tos[_cwd]() helper functions 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 Reviewed-by: Jeremy Allison --- diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 3c23d745eee..d6fbe93fcbb 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -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; diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 5f72da0f996..ed12e504bf8 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -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 */