[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