[SCM] Samba Shared Repository - branch v3-6-test updated
Andreas Schneider
asn at samba.org
Mon Mar 7 02:49:42 MST 2011
The branch, v3-6-test has been updated
via 754f980 s3: add two missing vfs disconnect calls
via aadf1e6 s3-printing: fix cups pcap reload with no printers
via b0fe017 s3-printing: remove unneeded local_pcap_copy global
via 2a79186 s3-printing: follow force user/group for driver IO
from b0ad407 s3: Move EXOP definitions to smbldap.h
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test
- Log -----------------------------------------------------------------
commit 754f980e87f8e8902826dea8735ba0addd13ad0c
Author: David Disseldorp <ddiss at suse.de>
Date: Fri Mar 4 14:53:39 2011 +0100
s3: add two missing vfs disconnect calls
The fix for bug 7976 added a vfs connect call to create_conn_struct.
This change adds two further disconnect calls that were missed by the
original change.
commit aadf1e6a8cd90903b23fc1d76d0d51cc400380b3
Author: David Disseldorp <ddiss at suse.de>
Date: Thu Dec 30 15:58:48 2010 +0100
s3-printing: fix cups pcap reload with no printers
cups_async_callback() is called to receive new printcap data from a
child process which requests the information from cupsd.
Newly received printcap information is stored in a temporary printcap
cache (tmp_pcap_cache). Once the child process closes the printcap IPC
file descriptor, the system printcap cache is replaced with the newly
populated tmp_pcap_cache, however this only occurs if tmp_pcap_cache is
non null (has at least one printer).
If the printcap cache is empty, which is the case when cups is not
exporting any printers, the printcap cache is not replaced resulting in
stale data.
https://bugzilla.samba.org/show_bug.cgi?id=7915
commit b0fe017917bf891d401a9f2a61a4f47805f89281
Author: David Disseldorp <ddiss at suse.de>
Date: Thu Dec 30 14:32:29 2010 +0100
s3-printing: remove unneeded local_pcap_copy global
The cups local_pcap_copy global served as a temporary buffer during
asynchronous cups printcap cache updates, as well as indicating when
the printcap cache had not yet been filled and printcap cache update
should block.
As smbd printcap reads are now triggered by the parent smbd following
printcap cache update, the variable and blocking mechanism are no longer
needed.
commit 2a791861462977a82b33ad57a4d5203dc9270aff
Author: David Disseldorp <ddiss at suse.de>
Date: Wed Mar 2 14:34:28 2011 +0100
s3-printing: follow force user/group for driver IO
Configuring force user/group settings for the print$ share currently has
unexpected results, this is explained by how the driver upload/add
process takes place. Consider the following example:
[print$]
path = /print-drv
write list = $DRIVER_UPLOAD_USER
force group = ntadmin
- the client connects to the [print$] share and uploads all driver
files to the /print-drv/W32X86 directory.
- This is permitted, as /print-drv/W32X86 is owned by group ntadmin, and
the "force group = ntadmin" takes effect for the [print$] session.
- Once all files are uploaded, the client connects to the [ipc$]
share and issues an AddPrinterDriverEx spoolss request.
- In handling this request move_driver_to_download_area() is called,
which attempts to create the directory /print-drv/W32X86/3
- The create directory fails, as it is done as the user connected to
the [ipc$] share which does not have permission to write to the driver
directory. The [print$] "force group = ntadmin" has no effect.
This is a regression from previous behaviour prior to the commit:
783ab04 Convert move_driver_to_download_area to use create_conn_struct.
https://bugzilla.samba.org/show_bug.cgi?id=7921
-----------------------------------------------------------------------
Summary of changes:
source3/include/proto.h | 1 +
source3/printing/nt_printing.c | 47 +++++++++++-
source3/printing/print_cups.c | 89 ++++++++++-----------
source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 2 +
source3/smbd/service.c | 127 ++++++++++++++++-------------
5 files changed, 163 insertions(+), 103 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/include/proto.h b/source3/include/proto.h
index e8b8af8..6e17814 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -5326,6 +5326,7 @@ void exit_server_fault(void);
/* The following definitions come from smbd/service.c */
bool set_conn_connectpath(connection_struct *conn, const char *connectpath);
+NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum);
bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir);
void load_registry_shares(void);
int add_home_service(const char *service, const char *username, const char *homedir);
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 5d4c071..090d773 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -625,6 +625,19 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
return -1;
}
+ nt_status = set_conn_force_user_group(conn, printdollar_snum);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0, ("failed set force user / group\n"));
+ *perr = ntstatus_to_werror(nt_status);
+ goto error_free_conn;
+ }
+
+ if (!become_user(conn, get_current_vuid(conn))) {
+ DEBUG(0, ("failed to become user\n"));
+ *perr = WERR_ACCESS_DENIED;
+ goto error_free_conn;
+ }
+
/* Open the driver file (Portable Executable format) and determine the
* deriver the cversion. */
driverpath = talloc_asprintf(talloc_tos(),
@@ -720,6 +733,8 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
*perr = WERR_OK;
error_exit:
+ unbecome_user();
+ error_free_conn:
TALLOC_FREE(smb_fname);
if (fsp != NULL) {
close_file(NULL, fsp, NORMAL_CLOSE);
@@ -993,6 +1008,19 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
return err;
}
+ nt_status = set_conn_force_user_group(conn, printdollar_snum);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0, ("failed set force user / group\n"));
+ err = ntstatus_to_werror(nt_status);
+ goto err_free_conn;
+ }
+
+ if (!become_user(conn, get_current_vuid(conn))) {
+ DEBUG(0, ("failed to become user\n"));
+ err = WERR_ACCESS_DENIED;
+ goto err_free_conn;
+ }
+
new_dir = talloc_asprintf(ctx,
"%s/%d",
short_architecture,
@@ -1126,7 +1154,9 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
}
err = WERR_OK;
- err_exit:
+ err_exit:
+ unbecome_user();
+ err_free_conn:
TALLOC_FREE(smb_dname);
if (conn != NULL) {
@@ -1907,6 +1937,19 @@ bool delete_driver_files(const struct auth_serversupplied_info *server_info,
return false;
}
+ nt_status = set_conn_force_user_group(conn, printdollar_snum);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0, ("failed set force user / group\n"));
+ ret = false;
+ goto err_free_conn;
+ }
+
+ if (!become_user(conn, get_current_vuid(conn))) {
+ DEBUG(0, ("failed to become user\n"));
+ ret = false;
+ goto err_free_conn;
+ }
+
if ( !CAN_WRITE(conn) ) {
DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
ret = false;
@@ -1968,6 +2011,8 @@ bool delete_driver_files(const struct auth_serversupplied_info *server_info,
ret = true;
err_out:
+ unbecome_user();
+ err_free_conn:
if (conn != NULL) {
vfs_ChDir(conn, oldcwd);
SMB_VFS_DISCONNECT(conn);
diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c
index 0e5dac5..3031a88 100644
--- a/source3/printing/print_cups.c
+++ b/source3/printing/print_cups.c
@@ -390,8 +390,7 @@ static bool cups_cache_reload_async(int fd)
return ret;
}
-static struct pcap_cache *local_pcap_copy;
-struct fd_event *cache_fd_event;
+static struct fd_event *cache_fd_event;
static bool cups_pcap_load_async(struct tevent_context *ev,
struct messaging_context *msg_ctx,
@@ -466,6 +465,7 @@ static void cups_async_callback(struct event_context *event_ctx,
struct cups_async_cb_args *cb_args = (struct cups_async_cb_args *)p;
int fd = cb_args->pipe_fd;
struct pcap_cache *tmp_pcap_cache = NULL;
+ bool ret_ok = true;
DEBUG(5,("cups_async_callback: callback received for printer data. "
"fd = %d\n", fd));
@@ -483,6 +483,7 @@ static void cups_async_callback(struct event_context *event_ctx,
if (ret != sizeof(namelen)) {
DEBUG(10,("cups_async_callback: namelen read failed %d %s\n",
errno, strerror(errno)));
+ ret_ok = false;
break;
}
@@ -497,6 +498,7 @@ static void cups_async_callback(struct event_context *event_ctx,
if (ret != sizeof(infolen)) {
DEBUG(10,("cups_async_callback: infolen read failed %s\n",
strerror(errno)));
+ ret_ok = false;
break;
}
@@ -506,6 +508,7 @@ static void cups_async_callback(struct event_context *event_ctx,
if (namelen) {
name = TALLOC_ARRAY(frame, char, namelen);
if (!name) {
+ ret_ok = false;
break;
}
ret = sys_read(fd, name, namelen);
@@ -516,6 +519,7 @@ static void cups_async_callback(struct event_context *event_ctx,
if (ret != namelen) {
DEBUG(10,("cups_async_callback: name read failed %s\n",
strerror(errno)));
+ ret_ok = false;
break;
}
DEBUG(11,("cups_async_callback: read name %s\n",
@@ -526,6 +530,7 @@ static void cups_async_callback(struct event_context *event_ctx,
if (infolen) {
info = TALLOC_ARRAY(frame, char, infolen);
if (!info) {
+ ret_ok = false;
break;
}
ret = sys_read(fd, info, infolen);
@@ -536,6 +541,7 @@ static void cups_async_callback(struct event_context *event_ctx,
if (ret != infolen) {
DEBUG(10,("cups_async_callback: info read failed %s\n",
strerror(errno)));
+ ret_ok = false;
break;
}
DEBUG(11,("cups_async_callback: read info %s\n",
@@ -545,31 +551,35 @@ static void cups_async_callback(struct event_context *event_ctx,
}
/* Add to our local pcap cache. */
- pcap_cache_add_specific(&tmp_pcap_cache, name, info);
+ ret_ok = pcap_cache_add_specific(&tmp_pcap_cache, name, info);
TALLOC_FREE(name);
TALLOC_FREE(info);
+ if (!ret_ok) {
+ DEBUG(0, ("failed to add to tmp pcap cache\n"));
+ break;
+ }
}
TALLOC_FREE(frame);
- if (tmp_pcap_cache) {
- bool ret;
- /* We got a namelist, replace our local cache. */
- pcap_cache_destroy_specific(&local_pcap_copy);
- local_pcap_copy = tmp_pcap_cache;
-
- /* And the systemwide pcap cache. */
- ret = pcap_cache_replace(local_pcap_copy);
- if (!ret)
+ if (!ret_ok) {
+ DEBUG(0, ("failed to read a new printer list\n"));
+ pcap_cache_destroy_specific(&tmp_pcap_cache);
+ } else {
+ /*
+ * replace the system-wide pcap cache with a (possibly empty)
+ * new one.
+ * FIXME The child process does not currently propagate cups
+ * errors back up to the parent, therefore we cannot
+ * differentiate between an empty printer list and a failure.
+ */
+ ret_ok = pcap_cache_replace(tmp_pcap_cache);
+ if (!ret_ok) {
DEBUG(0, ("failed to replace pcap cache\n"));
-
- /* Caller may have requested post cache fill callback */
- if (ret && cb_args->post_cache_fill_fn != NULL) {
+ } else if (cb_args->post_cache_fill_fn != NULL) {
+ /* Caller requested post cache fill callback */
cb_args->post_cache_fill_fn(cb_args->event_ctx,
cb_args->msg_ctx);
}
- } else {
- DEBUG(2,("cups_async_callback: failed to read a new "
- "printer list\n"));
}
close(fd);
TALLOC_FREE(cb_args);
@@ -600,35 +610,22 @@ bool cups_cache_reload(struct tevent_context *ev,
talloc_free(cb_args);
return false;
}
- if (!local_pcap_copy) {
- /* We have no local cache, wait directly for
- * async refresh to complete.
- */
- DEBUG(10,("cups_cache_reload: sync read on fd %d\n",
- *p_pipe_fd ));
-
- cups_async_callback(ev, NULL,
- EVENT_FD_READ,
- (void *)cb_args);
- if (!local_pcap_copy) {
- return false;
- }
- } else {
- DEBUG(10,("cups_cache_reload: async read on fd %d\n",
- *p_pipe_fd ));
-
- /* Trigger an event when the pipe can be read. */
- cache_fd_event = event_add_fd(ev,
- NULL, *p_pipe_fd,
- EVENT_FD_READ,
- cups_async_callback,
- (void *)cb_args);
- if (!cache_fd_event) {
- close(*p_pipe_fd);
- TALLOC_FREE(cb_args);
- return false;
- }
+
+ DEBUG(10,("cups_cache_reload: async read on fd %d\n",
+ *p_pipe_fd ));
+
+ /* Trigger an event when the pipe can be read. */
+ cache_fd_event = event_add_fd(ev,
+ NULL, *p_pipe_fd,
+ EVENT_FD_READ,
+ cups_async_callback,
+ (void *)cb_args);
+ if (!cache_fd_event) {
+ close(*p_pipe_fd);
+ TALLOC_FREE(cb_args);
+ return false;
}
+
return true;
}
diff --git a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
index 9ceb8b3..414274f 100644
--- a/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srvsvc/srv_srvsvc_nt.c
@@ -2216,6 +2216,7 @@ WERROR _srvsvc_NetGetFileSecurity(struct pipes_struct *p,
close_file(NULL, fsp, NORMAL_CLOSE);
vfs_ChDir(conn, oldcwd);
+ SMB_VFS_DISCONNECT(conn);
conn_free(conn);
werr = WERR_OK;
goto done;
@@ -2360,6 +2361,7 @@ WERROR _srvsvc_NetSetFileSecurity(struct pipes_struct *p,
close_file(NULL, fsp, NORMAL_CLOSE);
vfs_ChDir(conn, oldcwd);
+ SMB_VFS_DISCONNECT(conn);
conn_free(conn);
werr = WERR_OK;
goto done;
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index a58f17c..f55534a 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -658,6 +658,72 @@ static NTSTATUS create_connection_server_info(struct smbd_server_connection *sco
return NT_STATUS_ACCESS_DENIED;
}
+/****************************************************************************
+ set relavent user and group settings corresponding to force user/group
+ configuration for the given snum.
+****************************************************************************/
+
+NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
+{
+ NTSTATUS status;
+
+ if (*lp_force_user(snum)) {
+
+ /*
+ * Replace conn->server_info with a completely faked up one
+ * from the username we are forced into :-)
+ */
+
+ char *fuser;
+ struct auth_serversupplied_info *forced_serverinfo;
+
+ fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
+ lp_const_servicename(snum));
+ if (fuser == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = make_serverinfo_from_username(
+ conn, fuser, conn->server_info->guest,
+ &forced_serverinfo);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ TALLOC_FREE(conn->server_info);
+ conn->server_info = forced_serverinfo;
+
+ conn->force_user = true;
+ DEBUG(3,("Forced user %s\n", fuser));
+ }
+
+ /*
+ * If force group is true, then override
+ * any groupid stored for the connecting user.
+ */
+
+ if (*lp_force_group(snum)) {
+
+ status = find_forced_group(
+ conn->force_user, snum, conn->server_info->unix_name,
+ &conn->server_info->ptok->sids[1],
+ &conn->server_info->utok.gid);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /*
+ * We need to cache this gid, to use within
+ * change_to_user() separately from the conn->server_info
+ * struct. We only use conn->server_info directly if
+ * "force_user" was set.
+ */
+ conn->force_group_gid = conn->server_info->utok.gid;
+ }
+
+ return NT_STATUS_OK;
+}
/****************************************************************************
Make a connection, given the snum to connect to, and the vuser of the
@@ -741,62 +807,11 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
conn->read_only = lp_readonly(SNUM(conn));
- if (*lp_force_user(snum)) {
-
- /*
- * Replace conn->server_info with a completely faked up one
- * from the username we are forced into :-)
- */
-
- char *fuser;
- struct auth_serversupplied_info *forced_serverinfo;
-
- fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
- lp_servicename(snum));
- if (fuser == NULL) {
- *pstatus = NT_STATUS_NO_MEMORY;
- goto err_root_exit;
- }
-
- status = make_serverinfo_from_username(
- conn, fuser, conn->server_info->guest,
- &forced_serverinfo);
- if (!NT_STATUS_IS_OK(status)) {
- *pstatus = status;
- goto err_root_exit;
- }
-
- TALLOC_FREE(conn->server_info);
- conn->server_info = forced_serverinfo;
-
- conn->force_user = True;
- DEBUG(3,("Forced user %s\n", fuser));
- }
-
- /*
- * If force group is true, then override
- * any groupid stored for the connecting user.
- */
-
- if (*lp_force_group(snum)) {
-
- status = find_forced_group(
- conn->force_user, snum, conn->server_info->unix_name,
- &conn->server_info->ptok->sids[1],
- &conn->server_info->utok.gid);
-
- if (!NT_STATUS_IS_OK(status)) {
- *pstatus = status;
- goto err_root_exit;
- }
-
- /*
- * We need to cache this gid, to use within
- * change_to_user() separately from the conn->server_info
- * struct. We only use conn->server_info directly if
- * "force_user" was set.
- */
- conn->force_group_gid = conn->server_info->utok.gid;
+ status = set_conn_force_user_group(conn, snum);
+ if (!NT_STATUS_IS_OK(status)) {
+ conn_free(conn);
+ *pstatus = status;
+ return NULL;
}
conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
--
Samba Shared Repository
More information about the samba-cvs
mailing list