[PATCH 4/6] s3-spoolss: Hookup port creation basing name on parsed CUPS URIs

Justin Chevrier jchevrier at gmail.com
Wed Aug 31 13:03:12 MDT 2011


Signed-off-by: Justin Chevrier <jchevrier at gmail.com>
---
 source3/rpc_client/cli_winreg_spoolss.c       |    5 +-
 source3/rpc_client/cli_winreg_spoolss.h       |    3 +-
 source3/rpc_server/spoolss/srv_spoolss_nt.c   |  169 +++++++++++++++++++++----
 source3/rpc_server/spoolss/srv_spoolss_util.c |    6 +-
 source3/rpc_server/spoolss/srv_spoolss_util.h |    3 +-
 5 files changed, 154 insertions(+), 32 deletions(-)

diff --git a/source3/rpc_client/cli_winreg_spoolss.c b/source3/rpc_client/cli_winreg_spoolss.c
index 3159e0b..0d04a1a 100644
--- a/source3/rpc_client/cli_winreg_spoolss.c
+++ b/source3/rpc_client/cli_winreg_spoolss.c
@@ -589,7 +589,8 @@ static WERROR winreg_printer_ver_to_dword(const char *str, uint64_t *data)
 
 WERROR winreg_create_printer(TALLOC_CTX *mem_ctx,
 			     struct dcerpc_binding_handle *winreg_handle,
-			     const char *sharename)
+			     const char *sharename,
+			     const char *portname)
 {
 	uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
 	struct policy_handle hive_hnd, key_hnd;
@@ -865,7 +866,7 @@ WERROR winreg_create_printer(TALLOC_CTX *mem_ctx,
 	info2->sharename = sharename;
 	info2_mask |= SPOOLSS_PRINTER_INFO_SHARENAME;
 
-	info2->portname = SAMBA_PRINTER_PORT_NAME;
+	info2->portname = portname;
 	info2_mask |= SPOOLSS_PRINTER_INFO_PORTNAME;
 
 	info2->printprocessor = "winprint";
diff --git a/source3/rpc_client/cli_winreg_spoolss.h b/source3/rpc_client/cli_winreg_spoolss.h
index 6cd6863..93bfb65 100644
--- a/source3/rpc_client/cli_winreg_spoolss.h
+++ b/source3/rpc_client/cli_winreg_spoolss.h
@@ -102,7 +102,8 @@ enum spoolss_PrinterInfo2Mask {
 
 WERROR winreg_create_printer(TALLOC_CTX *mem_ctx,
 			     struct dcerpc_binding_handle *b,
-			     const char *sharename);
+			     const char *sharename,
+			     const char *portname);
 
 /**
  * @internal
diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
index 6403805..3619e6c 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
+++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
@@ -1697,6 +1697,76 @@ static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
 	return WERR_OK;
 }
 
+/********************************************************************
+********************************************************************/
+
+static bool get_printer_port(TALLOC_CTX *mem_ctx,
+				 const char *printername,
+				 const char **portname,
+				 const char **ipaddress)
+{
+	const char *uri = NULL;
+	char *p, *tmpuri;
+	NTSTATUS nt_status;
+
+	nt_status = printer_list_get_printer(mem_ctx,
+					     printername,
+					     NULL,
+					     NULL,
+					     &uri,
+					     NULL);
+
+	if (NT_STATUS_IS_OK(nt_status)) {
+		if (uri != NULL) {
+			/* We only care about network URIs */
+			if (uri == strstr(uri, "ipp://") || uri == strstr(uri, "http://") ||
+			    uri == strstr(uri, "lpd://") || uri == strstr(uri, "https://") ||
+			    uri == strstr(uri, "socket://")) {
+			    	uri = strchr(uri, ':');
+				uri += 3;
+
+				p = talloc_strdup(mem_ctx, uri);
+				if (p == NULL) {
+					return false;
+				}
+
+				if ((tmpuri = strchr(p, ':')) != NULL) {
+					*tmpuri = '\0';
+				}
+				if ((tmpuri = strchr(p, '/')) != NULL) {
+					*tmpuri = '\0';
+				}
+
+				/* If what's left after stripping extra characters isn't a valid
+				 * IP address, give up. Should we do a DNS lookup on the string? */
+				if (inet_addr(p) == -1) {
+					goto done;
+				}
+
+				if (portname) {
+					*portname = talloc_asprintf(mem_ctx, "IP_%s", p);
+					if(*portname == NULL) {
+						return false;
+					}
+				}
+				if (ipaddress) {
+					*ipaddress = talloc_strdup(mem_ctx, p);
+					if(*ipaddress == NULL) {
+						return false;
+					}
+				}
+
+				talloc_free(p);
+				return true;
+			}
+		}
+	}
+
+done:
+	DEBUGADD(2,("Printer URI references a local printer or is not recognized.\n"));
+	return false;
+}
+
 /****************************************************************
  _spoolss_OpenPrinterEx
 ****************************************************************/
@@ -1707,6 +1777,7 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 	int snum;
 	char *raddr;
 	char *rhost;
+	const char *portname, *ipaddress;
 	struct printer_handle *Printer=NULL;
 	WERROR result;
 	int rc;
@@ -1923,11 +1994,23 @@ WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
 
 		DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
 			? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
+		
+		if (get_printer_port(p->mem_ctx, lp_const_servicename(snum), &portname, &ipaddress)) {
+			winreg_create_port_internal(p->mem_ctx,
+					      get_session_info_system(),
+					      p->msg_ctx,
+					      portname,
+					      ipaddress);
+		} else {
+                	portname = talloc_strdup(p->mem_ctx, SAMBA_PRINTER_PORT_NAME);
+                	W_ERROR_HAVE_NO_MEMORY(portname);
+		}
 
 		winreg_create_printer_internal(p->mem_ctx,
 				      get_session_info_system(),
 				      p->msg_ctx,
-				      lp_const_servicename(snum));
+				      lp_const_servicename(snum),
+				      portname);
 
 		break;
 
@@ -4307,6 +4390,7 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
 
 	for (snum = 0; snum < n_services; snum++) {
 
+		const char *portname;
 		const char *printer;
 		struct spoolss_PrinterInfo2 *info2;
 
@@ -4329,8 +4413,14 @@ static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
 			}
 		}
 
+		if(!get_printer_port(tmp_ctx, printer, &portname, NULL)) {
+                        portname = talloc_strdup(tmp_ctx, SAMBA_PRINTER_PORT_NAME);
+                        W_ERROR_HAVE_NO_MEMORY(portname);
+                }
+
 		result = winreg_create_printer(tmp_ctx, b,
-					       printer);
+					       printer,
+					       portname);
 		if (!W_ERROR_IS_OK(result)) {
 			goto out;
 		}
@@ -7755,49 +7845,61 @@ static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
 ****************************************************************************/
 
 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
+				const struct auth_session_info *session_info,
+				struct messaging_context *msg_ctx,
 				union spoolss_PortInfo **info_p,
 				uint32_t *count)
 {
+	uint32_t num_keys;
 	union spoolss_PortInfo *info = NULL;
 	int i=0;
 	WERROR result = WERR_OK;
-	char **qlines = NULL;
-	int numlines = 0;
+	const char **array = NULL;
+	DATA_BLOB blob;
 
-	result = enumports_hook(talloc_tos(), &numlines, &qlines );
+	result = winreg_enum_ports_key_internal(mem_ctx,
+					 session_info,
+					 msg_ctx,
+					 &num_keys,
+					 &array);
 	if (!W_ERROR_IS_OK(result)) {
 		goto out;
 	}
 
-	if (numlines) {
-		info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
+	if (!push_reg_multi_sz(mem_ctx, &blob, array)) {
+		result = WERR_NOMEM;
+		goto out;
+	}
+
+	if (num_keys) {
+		info = talloc_array(mem_ctx, union spoolss_PortInfo, num_keys);
 		if (!info) {
 			DEBUG(10,("Returning WERR_NOMEM\n"));
 			result = WERR_NOMEM;
 			goto out;
 		}
 
-		for (i=0; i<numlines; i++) {
-			DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
-			result = fill_port_1(info, &info[i].info1, qlines[i]);
+		for (i=0; i<num_keys; i++) {
+			DEBUG(6,("Filling port number [%d] with port [%s]\n", i, array[i]));
+			result = fill_port_1(info, &info[i].info1, array[i]);
 			if (!W_ERROR_IS_OK(result)) {
 				goto out;
 			}
 		}
 	}
-	TALLOC_FREE(qlines);
+	TALLOC_FREE(array);
 
 out:
 	if (!W_ERROR_IS_OK(result)) {
 		TALLOC_FREE(info);
-		TALLOC_FREE(qlines);
+		TALLOC_FREE(array);
 		*count = 0;
 		*info_p = NULL;
 		return result;
 	}
 
 	*info_p = info;
-	*count = numlines;
+	*count = num_keys;
 
 	return WERR_OK;
 }
@@ -7807,49 +7909,61 @@ out:
 ****************************************************************************/
 
 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
+				const struct auth_session_info *session_info,
+				struct messaging_context *msg_ctx,
 				union spoolss_PortInfo **info_p,
 				uint32_t *count)
 {
+	uint32_t num_keys;
 	union spoolss_PortInfo *info = NULL;
 	int i=0;
 	WERROR result = WERR_OK;
-	char **qlines = NULL;
-	int numlines = 0;
+	const char **array = NULL;
+	DATA_BLOB blob;
 
-	result = enumports_hook(talloc_tos(), &numlines, &qlines );
+	result = winreg_enum_ports_key_internal(mem_ctx,
+					 session_info,
+					 msg_ctx,
+					 &num_keys,
+					 &array);
 	if (!W_ERROR_IS_OK(result)) {
 		goto out;
 	}
 
-	if (numlines) {
-		info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
+	if (!push_reg_multi_sz(mem_ctx, &blob, array)) {
+		result = WERR_NOMEM;
+		goto out;
+	}
+
+	if (num_keys) {
+		info = talloc_array(mem_ctx, union spoolss_PortInfo, num_keys);
 		if (!info) {
 			DEBUG(10,("Returning WERR_NOMEM\n"));
 			result = WERR_NOMEM;
 			goto out;
 		}
 
-		for (i=0; i<numlines; i++) {
-			DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
-			result = fill_port_2(info, &info[i].info2, qlines[i]);
+		for (i=0; i<num_keys; i++) {
+			DEBUG(6,("Filling port number [%d] with port [%s]\n", i, array[i]));
+			result = fill_port_2(info, &info[i].info2, array[i]);
 			if (!W_ERROR_IS_OK(result)) {
 				goto out;
 			}
 		}
 	}
-	TALLOC_FREE(qlines);
+	TALLOC_FREE(array);
 
 out:
 	if (!W_ERROR_IS_OK(result)) {
 		TALLOC_FREE(info);
-		TALLOC_FREE(qlines);
+		TALLOC_FREE(array);
 		*count = 0;
 		*info_p = NULL;
 		return result;
 	}
 
 	*info_p = info;
-	*count = numlines;
+	*count = num_keys;
 
 	return WERR_OK;
 }
@@ -7861,6 +7975,7 @@ out:
 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
 			  struct spoolss_EnumPorts *r)
 {
+	const struct auth_session_info *session_info = get_session_info_system();
 	WERROR result;
 
 	/* that's an [in out] buffer */
@@ -7877,11 +7992,13 @@ WERROR _spoolss_EnumPorts(struct pipes_struct *p,
 
 	switch (r->in.level) {
 	case 1:
-		result = enumports_level_1(p->mem_ctx, r->out.info,
+		result = enumports_level_1(p->mem_ctx, session_info,
+					   p->msg_ctx, r->out.info,
 					   r->out.count);
 		break;
 	case 2:
-		result = enumports_level_2(p->mem_ctx, r->out.info,
+		result = enumports_level_2(p->mem_ctx, session_info,
+					   p->msg_ctx, r->out.info,
 					   r->out.count);
 		break;
 	default:
diff --git a/source3/rpc_server/spoolss/srv_spoolss_util.c b/source3/rpc_server/spoolss/srv_spoolss_util.c
index ed7bfa1..4bb370a 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_util.c
+++ b/source3/rpc_server/spoolss/srv_spoolss_util.c
@@ -182,7 +182,8 @@ WERROR winreg_get_printer_internal(TALLOC_CTX *mem_ctx,
 WERROR winreg_create_printer_internal(TALLOC_CTX *mem_ctx,
 				      const struct auth_session_info *session_info,
 				      struct messaging_context *msg_ctx,
-				      const char *sharename)
+				      const char *sharename,
+				      const char *portname)
 {
 	WERROR result;
 	struct dcerpc_binding_handle *b;
@@ -201,7 +202,8 @@ WERROR winreg_create_printer_internal(TALLOC_CTX *mem_ctx,
 
 	result = winreg_create_printer(mem_ctx,
 				       b,
-				       sharename);
+				       sharename,
+				       portname);
 
 	talloc_free(tmp_ctx);
 	return result;
diff --git a/source3/rpc_server/spoolss/srv_spoolss_util.h b/source3/rpc_server/spoolss/srv_spoolss_util.h
index a43c133..ac0107b 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_util.h
+++ b/source3/rpc_server/spoolss/srv_spoolss_util.h
@@ -52,7 +52,8 @@ WERROR winreg_get_printer_internal(TALLOC_CTX *mem_ctx,
 WERROR winreg_create_printer_internal(TALLOC_CTX *mem_ctx,
 				      const struct auth_session_info *session_info,
 				      struct messaging_context *msg_ctx,
-				      const char *sharename);
+				      const char *sharename,
+				      const char *portname);
 WERROR winreg_update_printer_internal(TALLOC_CTX *mem_ctx,
 				      const struct auth_session_info *session_info,
 				      struct messaging_context *msg_ctx,
-- 
1.7.3.4



More information about the samba-technical mailing list