summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2006-07-23 16:54:16 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:10:18 -0500
commit2dc38416b65177aca94b4de3c9cfcb5c8edb0df2 (patch)
tree41a53a753d102f1bbf67cf822bcde219ac93aca5
parentba07fa43d0b0090f5e686d8c1822468049f52416 (diff)
downloadsamba-2dc38416b65177aca94b4de3c9cfcb5c8edb0df2.tar.gz
samba-2dc38416b65177aca94b4de3c9cfcb5c8edb0df2.tar.bz2
samba-2dc38416b65177aca94b4de3c9cfcb5c8edb0df2.zip
r17205: Even if this makes me look foolish, at least start to scratch on the surface
of spoolss. If snum is to be removed, then we should make at least the attempt to walk parts of the code before and after the changes. This walks GetPrinterInfo level 0-7. Volker (This used to be commit 0c05f571a0eda2412896f340b7c751cf7cbdbd2a)
-rw-r--r--source4/torture/rpc/rpc.c1
-rw-r--r--source4/torture/rpc/samba3rpc.c331
2 files changed, 308 insertions, 24 deletions
diff --git a/source4/torture/rpc/rpc.c b/source4/torture/rpc/rpc.c
index 67ad1f1ae5..879fa7aa8e 100644
--- a/source4/torture/rpc/rpc.c
+++ b/source4/torture/rpc/rpc.c
@@ -135,6 +135,7 @@ NTSTATUS torture_rpc_init(void)
register_torture_op("RPC-SAMBA3-GETUSERNAME",
torture_samba3_rpc_getusername);
register_torture_op("RPC-SAMBA3-LSA", torture_samba3_rpc_lsa);
+ register_torture_op("RPC-SAMBA3-SPOOLSS", torture_samba3_rpc_spoolss);
register_torture_op("RPC-DRSUAPI", torture_rpc_drsuapi);
register_torture_op("RPC-CRACKNAMES", torture_rpc_drsuapi_cracknames);
register_torture_op("RPC-ROT", torture_rpc_rot);
diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c
index cd7eb7c581..94613185dc 100644
--- a/source4/torture/rpc/samba3rpc.c
+++ b/source4/torture/rpc/samba3rpc.c
@@ -32,6 +32,8 @@
#include "librpc/gen_ndr/ndr_netlogon_c.h"
#include "librpc/gen_ndr/ndr_srvsvc.h"
#include "librpc/gen_ndr/ndr_srvsvc_c.h"
+#include "librpc/gen_ndr/ndr_spoolss.h"
+#include "librpc/gen_ndr/ndr_spoolss_c.h"
#include "lib/cmdline/popt_common.h"
#include "librpc/rpc/dcerpc.h"
#include "torture/rpc/rpc.h"
@@ -1355,17 +1357,18 @@ BOOL torture_samba3_sessionkey(struct torture_context *torture)
* open pipe and bind, given an IPC$ context
*/
-static struct dcerpc_pipe *pipe_bind_smb(TALLOC_CTX *mem_ctx,
- struct smbcli_tree *tree,
- const char *pipe_name,
- const struct dcerpc_interface_table *iface)
+static NTSTATUS pipe_bind_smb(TALLOC_CTX *mem_ctx,
+ struct smbcli_tree *tree,
+ const char *pipe_name,
+ const struct dcerpc_interface_table *iface,
+ struct dcerpc_pipe **p)
{
struct dcerpc_pipe *result;
NTSTATUS status;
if (!(result = dcerpc_pipe_init(
mem_ctx, tree->session->transport->socket->event.ctx))) {
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
status = dcerpc_pipe_open_smb(result->conn, tree, pipe_name);
@@ -1373,17 +1376,18 @@ static struct dcerpc_pipe *pipe_bind_smb(TALLOC_CTX *mem_ctx,
d_printf("dcerpc_pipe_open_smb failed: %s\n",
nt_errstr(status));
talloc_free(result);
- return NULL;
+ return status;
}
status = dcerpc_bind_auth_none(result, iface);
if (!NT_STATUS_IS_OK(status)) {
d_printf("schannel bind failed: %s\n", nt_errstr(status));
talloc_free(result);
- return NULL;
+ return status;
}
- return result;
+ *p = result;
+ return NT_STATUS_OK;
}
/*
@@ -1486,9 +1490,11 @@ static struct dom_sid *whoami(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree)
struct lsa_StringPointer authority_name_p;
struct dom_sid *result;
- if (!(lsa = pipe_bind_smb(mem_ctx, tree, "\\pipe\\lsarpc",
- &dcerpc_table_lsarpc))) {
- d_printf("Could not bind to LSA\n");
+ status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\lsarpc",
+ &dcerpc_table_lsarpc, &lsa);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) Could not bind to LSA: %s\n",
+ __location__, nt_errstr(status));
return NULL;
}
@@ -1800,6 +1806,7 @@ BOOL torture_samba3_rpc_srvsvc(struct torture_context *torture)
BOOL ret = True;
const char *sharename = NULL;
struct smbcli_state *cli;
+ NTSTATUS status;
if (!(mem_ctx = talloc_new(torture))) {
return False;
@@ -1812,9 +1819,11 @@ BOOL torture_samba3_rpc_srvsvc(struct torture_context *torture)
return False;
}
- if (!(p = pipe_bind_smb(mem_ctx, cli->tree, "\\pipe\\srvsvc",
- &dcerpc_table_srvsvc))) {
- d_printf("could not bind to srvsvc pipe\n");
+ status = pipe_bind_smb(mem_ctx, cli->tree, "\\pipe\\srvsvc",
+ &dcerpc_table_srvsvc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) could not bind to srvsvc pipe: %s\n",
+ __location__, nt_errstr(status));
ret = False;
goto done;
}
@@ -1853,9 +1862,11 @@ static struct security_descriptor *get_sharesec(TALLOC_CTX *mem_ctx,
return NULL;
}
- if (!(p = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
- &dcerpc_table_srvsvc))) {
- d_printf("could not bind to srvsvc pipe\n");
+ status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
+ &dcerpc_table_srvsvc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) could not bind to srvsvc pipe: %s\n",
+ __location__, nt_errstr(status));
talloc_free(tmp_ctx);
return NULL;
}
@@ -1906,9 +1917,11 @@ static NTSTATUS set_sharesec(TALLOC_CTX *mem_ctx,
return NT_STATUS_UNSUCCESSFUL;
}
- if (!(p = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
- &dcerpc_table_srvsvc))) {
- d_printf("could not bind to srvsvc pipe\n");
+ status = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
+ &dcerpc_table_srvsvc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) could not bind to srvsvc pipe: %s\n",
+ __location__, nt_errstr(status));
talloc_free(tmp_ctx);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2094,10 +2107,11 @@ BOOL torture_samba3_rpc_lsa(struct torture_context *torture)
return False;
}
- p = pipe_bind_smb(mem_ctx, cli->tree, "\\lsarpc",
- &dcerpc_table_lsarpc);
- if (p == NULL) {
- d_printf("(%s) pipe_bind_smb failed\n", __location__);
+ status = pipe_bind_smb(mem_ctx, cli->tree, "\\lsarpc",
+ &dcerpc_table_lsarpc, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
+ nt_errstr(status));
talloc_free(mem_ctx);
return False;
}
@@ -2148,3 +2162,272 @@ BOOL torture_samba3_rpc_lsa(struct torture_context *torture)
return ret;
}
+
+static NTSTATUS find_printers(TALLOC_CTX *ctx, struct smbcli_tree *tree,
+ const char ***printers, int *num_printers)
+{
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+ struct dcerpc_pipe *p;
+ struct srvsvc_NetShareEnum r;
+ struct srvsvc_NetShareCtr1 c1_in;
+ struct srvsvc_NetShareCtr1 *c1;
+ int i;
+
+ mem_ctx = talloc_new(ctx);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = pipe_bind_smb(mem_ctx, tree, "\\srvsvc", &dcerpc_table_srvsvc,
+ &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("could not bind to srvsvc pipe\n");
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ r.in.server_unc = talloc_asprintf(
+ mem_ctx, "\\\\%s", dcerpc_server_name(p));
+ r.in.level = 1;
+ ZERO_STRUCT(c1_in);
+ r.in.ctr.ctr1 = &c1_in;
+ r.in.max_buffer = (uint32_t)-1;
+ r.in.resume_handle = NULL;
+
+ status = dcerpc_srvsvc_NetShareEnum(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("NetShareEnum level %u failed - %s\n",
+ r.in.level, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ *printers = NULL;
+ *num_printers = 0;
+ c1 = r.out.ctr.ctr1;
+ for (i=0; i<c1->count; i++) {
+ if (c1->array[i].type != STYPE_PRINTQ) {
+ continue;
+ }
+ if (!add_string_to_array(ctx, c1->array[i].name,
+ printers, num_printers)) {
+ talloc_free(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ talloc_free(mem_ctx);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS getprinterinfo(TALLOC_CTX *ctx, struct dcerpc_pipe *pipe,
+ struct policy_handle *handle, int level,
+ union spoolss_PrinterInfo **res)
+{
+ TALLOC_CTX *mem_ctx;
+ struct spoolss_GetPrinter r;
+ DATA_BLOB blob;
+ NTSTATUS status;
+
+ mem_ctx = talloc_new(ctx);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ r.in.handle = handle;
+ r.in.level = level;
+ r.in.buffer = NULL;
+ r.in.offered = 0;
+
+ status = dcerpc_spoolss_GetPrinter(pipe, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s\n",
+ __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+ printf("GetPrinter unexpected return code %s, should "
+ "be WERR_INSUFFICIENT_BUFFER\n",
+ win_errstr(r.out.result));
+ talloc_free(mem_ctx);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ r.in.handle = handle;
+ r.in.level = level;
+ blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
+ if (blob.data == NULL) {
+ talloc_free(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ memset(blob.data, 0, blob.length);
+ r.in.buffer = &blob;
+ r.in.offered = r.out.needed;
+
+ status = dcerpc_spoolss_GetPrinter(pipe, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
+ d_printf("(%s) dcerpc_spoolss_GetPrinter failed: %s, "
+ "%s\n", __location__, nt_errstr(status),
+ win_errstr(r.out.result));
+ talloc_free(mem_ctx);
+ return NT_STATUS_IS_OK(status) ?
+ NT_STATUS_UNSUCCESSFUL : status;
+ }
+
+ if (res != NULL) {
+ *res = talloc_steal(ctx, r.out.info);
+ }
+
+ talloc_free(mem_ctx);
+ return NT_STATUS_OK;
+}
+
+
+BOOL torture_samba3_rpc_spoolss(struct torture_context *torture)
+{
+ TALLOC_CTX *mem_ctx;
+ BOOL ret = True;
+ struct smbcli_state *cli;
+ struct dcerpc_pipe *p;
+ NTSTATUS status;
+ struct policy_handle server_handle, printer_handle;
+ const char **printers;
+ int num_printers;
+ struct spoolss_UserLevel1 userlevel1;
+
+ if (!(mem_ctx = talloc_new(torture))) {
+ return False;
+ }
+
+ if (!(torture_open_connection_share(
+ mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+ "IPC$", NULL))) {
+ d_printf("IPC$ connection failed\n");
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (!NT_STATUS_IS_OK(find_printers(mem_ctx, cli->tree,
+ &printers, &num_printers))) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ if (num_printers == 0) {
+ d_printf("Did not find printers\n");
+ talloc_free(mem_ctx);
+ return True;
+ }
+
+ status = pipe_bind_smb(mem_ctx, cli->tree, "\\spoolss",
+ &dcerpc_table_spoolss, &p);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) pipe_bind_smb failed: %s\n", __location__,
+ nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ ZERO_STRUCT(userlevel1);
+ userlevel1.client = talloc_asprintf(
+ mem_ctx, "\\\\%s", lp_netbios_name());
+ userlevel1.user = cli_credentials_get_username(cmdline_credentials);
+ userlevel1.build = 2600;
+ userlevel1.major = 3;
+ userlevel1.minor = 0;
+ userlevel1.processor = 0;
+
+ {
+ struct spoolss_OpenPrinterEx r;
+
+ ZERO_STRUCT(r);
+ r.in.printername = talloc_asprintf(
+ mem_ctx, "\\\\%s", dcerpc_server_name(p));
+ r.in.datatype = NULL;
+ r.in.access_mask = 0;
+ r.in.level = 1;
+ r.in.userlevel.level1 = &userlevel1;
+ r.out.handle = &server_handle;
+
+ status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
+ "%s\n", __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ {
+ struct spoolss_ClosePrinter r;
+
+ r.in.handle = &server_handle;
+ r.out.handle = &server_handle;
+
+ status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
+ "%s\n", __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ {
+ struct spoolss_OpenPrinterEx r;
+
+ ZERO_STRUCT(r);
+ r.in.printername = talloc_asprintf(
+ mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p),
+ printers[0]);
+ r.in.datatype = NULL;
+ r.in.access_mask = 0;
+ r.in.level = 1;
+ r.in.userlevel.level1 = &userlevel1;
+ r.out.handle = &printer_handle;
+
+ status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_spoolss_OpenPrinterEx failed: "
+ "%s\n", __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ {
+ int i;
+
+ for (i=0; i<8; i++) {
+ status = getprinterinfo(mem_ctx, p, &printer_handle,
+ i, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) getprinterinfo %d failed: %s\n",
+ __location__, i, nt_errstr(status));
+ ret = False;
+ }
+ }
+ }
+
+ {
+ struct spoolss_ClosePrinter r;
+
+ r.in.handle = &printer_handle;
+ r.out.handle = &printer_handle;
+
+ status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("(%s) dcerpc_spoolss_ClosePrinter failed: "
+ "%s\n", __location__, nt_errstr(status));
+ talloc_free(mem_ctx);
+ return False;
+ }
+ }
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}