diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/rpc_server/spoolss/dcesrv_spoolss.c | 119 | ||||
-rw-r--r-- | source4/rpc_server/spoolss/dcesrv_spoolss.h | 6 | ||||
-rw-r--r-- | source4/torture/rpc/spoolss.c | 115 |
3 files changed, 179 insertions, 61 deletions
diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.c b/source4/rpc_server/spoolss/dcesrv_spoolss.c index 470c9e2674..fa3a16f7e1 100644 --- a/source4/rpc_server/spoolss/dcesrv_spoolss.c +++ b/source4/rpc_server/spoolss/dcesrv_spoolss.c @@ -143,14 +143,37 @@ static WERROR spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TALLOC_CT return WERR_UNKNOWN_LEVEL; } - +static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r); /* spoolss_OpenPrinter */ static WERROR spoolss_OpenPrinter(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_OpenPrinter *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + WERROR status; + struct spoolss_OpenPrinterEx *r2; + + r2 = talloc(mem_ctx, struct spoolss_OpenPrinterEx); + W_ERROR_HAVE_NO_MEMORY(r2); + + r2->in.printername = r->in.printername; + r2->in.datatype = r->in.datatype; + r2->in.devmode_ctr = r->in.devmode_ctr; + r2->in.access_mask = r->in.access_mask; + r2->in.level = 1; + r2->in.userlevel.level1 = NULL; + + r2->out.handle = r->out.handle; + + /* TODO: we should take care about async replies here, + if spoolss_OpenPrinterEx() would be async! + */ + status = spoolss_OpenPrinterEx(dce_call, mem_ctx, r2); + + r->out.handle = r2->out.handle; + + return status; } @@ -836,49 +859,46 @@ static WERROR spoolss_44(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx static WERROR spoolss_OpenPrinterEx_server(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct spoolss_OpenPrinterEx *r) + struct spoolss_OpenPrinterEx *r, + const char *server_name) { - struct spoolss_openprinter_state *state; + struct spoolss_handle_server *state; struct dcesrv_handle *handle; - - /* Check printername is our name */ - - if (!strequal(r->in.printername + 2, lp_netbios_name())) - return WERR_INVALID_PRINTER_NAME; + BOOL ret; + + /* Check printername is our name or our ip address + */ + ret = strequal(server_name, lp_netbios_name()); + if (!ret) { + /* TODO: + ret = strequal(server_name, ...our_ip...);*/ + if (!ret) { + return WERR_INVALID_PRINTER_NAME; + } + } handle = dcesrv_handle_new(dce_call->context, SPOOLSS_HANDLE_SERVER); - if (!handle) { - return WERR_NOMEM; - } + W_ERROR_HAVE_NO_MEMORY(handle); - state = talloc(handle, struct spoolss_openprinter_state); - if (!state) { - return WERR_OK; - } + state = talloc(handle, struct spoolss_handle_server); + W_ERROR_HAVE_NO_MEMORY(state); handle->data = state; - state->access_mask = r->in.access_mask; - *r->out.handle = handle->wire_handle; + state->handle_type = SPOOLSS_HANDLE_SERVER; + state->access_mask = r->in.access_mask; + + *r->out.handle = handle->wire_handle; return WERR_OK; } static WERROR spoolss_OpenPrinterEx_printer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct spoolss_OpenPrinterEx *r) + struct spoolss_OpenPrinterEx *r, + const char *printer_name) { - char *server = talloc_strdup(mem_ctx, r->in.printername + 2); - char *pos, *printer; - - pos = strchr(server, '\\'); - *pos = 0; - printer = talloc_strdup(mem_ctx, pos + 1); - - if (!strequal(server, lp_netbios_name())) - return WERR_INVALID_PRINTER_NAME; - - DEBUG(0, ("looking for server %s, printer %s\n", server, printer)); + DEBUG(0, ("looking for printer %s\n", printer_name)); return WERR_INVALID_PRINTER_NAME; } @@ -889,17 +909,40 @@ static WERROR spoolss_OpenPrinterEx_printer(struct dcesrv_call_state *dce_call, static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_OpenPrinterEx *r) { + const char *p; + const char *printer = r->in.printername; ZERO_STRUCTP(r->out.handle); - - /* Printername must start with \\ */ - if (strncmp(r->in.printername, "\\\\", 2) == 0) - return WERR_INVALID_PARAM; + /* just "\\" is invalid */ + if (strequal(r->in.printername, "\\\\")) { + return WERR_INVALID_PRINTER_NAME; + } - if (strchr_m(r->in.printername + 2, '\\')) - return spoolss_OpenPrinterEx_server(dce_call, mem_ctx, r); - - return spoolss_OpenPrinterEx_printer(dce_call, mem_ctx, r); + if (strncmp(r->in.printername, "\\\\", 2) == 0) { + /* here we know we have "\\" in front not followed + * by '\0', now see if we have another "\" in the string + */ + p = strchr_m(r->in.printername + 2, '\\'); + if (!p) { + /* there's no other "\", so it's ("\\%s",server) + */ + const char *server = r->in.printername + 2; + DEBUG(0,("print server: [%s][%s]\n", r->in.printername, server)); + return spoolss_OpenPrinterEx_server(dce_call, mem_ctx, r, server); + } + /* here we know that we have ("\\%s\",server), + * if we have '\0' as next then it's an invalid name + * otherwise the printer_name + */ + p++; + if (p[0] == '\0') { + return WERR_INVALID_PRINTER_NAME; + } + printer = p; + } + + DEBUG(0,("printer: [%s][%s]\n", r->in.printername, printer)); + return spoolss_OpenPrinterEx_printer(dce_call, mem_ctx, r, printer); } diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.h b/source4/rpc_server/spoolss/dcesrv_spoolss.h index aef13dd6d6..3375ff3d9c 100644 --- a/source4/rpc_server/spoolss/dcesrv_spoolss.h +++ b/source4/rpc_server/spoolss/dcesrv_spoolss.h @@ -23,7 +23,7 @@ /* this type allows us to distinguish handle types */ -enum spoolss_handle { +enum spoolss_handle_type { SPOOLSS_HANDLE_SERVER, SPOOLSS_HANDLE_PRINTER }; @@ -31,7 +31,7 @@ enum spoolss_handle { /* state asscoiated with a spoolss_OpenPrinter{,Ex}() operation */ -struct spoolss_openprinter_state { - void *openprinter_ctx; +struct spoolss_handle_server { + enum spoolss_handle_type handle_type; uint32_t access_mask; }; diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index de8da366b7..c7a0a1e066 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -640,6 +640,85 @@ static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct return ret; } +static BOOL test_OpenPrinter_badname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *name) +{ + NTSTATUS status; + struct spoolss_OpenPrinter op; + struct spoolss_OpenPrinterEx opEx; + struct policy_handle handle; + BOOL ret = True; + + op.in.printername = name; + op.in.datatype = NULL; + op.in.devmode_ctr.size = 0; + op.in.devmode_ctr.devmode= NULL; + op.in.access_mask = 0; + op.out.handle = &handle; + + printf("\nTesting OpenPrinter(%s) with bad name\n", op.in.printername); + + status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &op); + if (!NT_STATUS_IS_OK(status)) { + printf("OpenPrinter failed - %s\n", nt_errstr(status)); + ret = False; + } + if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) { + printf("OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n", + name, win_errstr(op.out.result)); + } + + if (W_ERROR_IS_OK(op.out.result)) { + ret &=test_ClosePrinter(p, mem_ctx, &handle); + } + + opEx.in.printername = name; + opEx.in.datatype = NULL; + opEx.in.devmode_ctr.size = 0; + opEx.in.devmode_ctr.devmode = NULL; + opEx.in.access_mask = 0; + opEx.in.level = 1; + opEx.in.userlevel.level1 = NULL; + opEx.out.handle = &handle; + + printf("\nTesting OpenPrinter(%s) with bad name\n", opEx.in.printername); + + status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &opEx); + if (!NT_STATUS_IS_OK(status)) { + printf("OpenPrinter failed - %s\n", nt_errstr(status)); + ret = False; + } + if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,opEx.out.result)) { + printf("OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n", + name, win_errstr(opEx.out.result)); + } + + if (W_ERROR_IS_OK(opEx.out.result)) { + ret &=test_ClosePrinter(p, mem_ctx, &handle); + } + + return ret; +} + +static BOOL test_OpenPrinter_badnames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) +{ + BOOL ret = True; + char *name; + + ret &= test_OpenPrinter_badname(p, mem_ctx, "__INVALID_PRINTER__"); + ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\127.0.0.1"); + ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\localhost"); + + name = talloc_asprintf(mem_ctx, "\\\\%s\\", dcerpc_server_name(p)); + ret &= test_OpenPrinter_badname(p, mem_ctx, name); + talloc_free(name); + + name = talloc_asprintf(mem_ctx, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)); + ret &= test_OpenPrinter_badname(p, mem_ctx, name); + talloc_free(name); + + return ret; +} + static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *name) { @@ -661,8 +740,7 @@ static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) { printf("OpenPrinter failed - %s/%s\n", nt_errstr(status), win_errstr(r.out.result)); - /* don't consider failing this an error until we understand it */ - return True; + return False; } if (!test_GetPrinter(p, mem_ctx, &handle)) { @@ -687,18 +765,20 @@ static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct spoolss_UserLevel1 userlevel1; NTSTATUS status; - if (name && name[0]) + if (name && name[0]) { r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name); - else + } else { r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p)); + } - r.in.datatype = NULL; - r.in.devmode_ctr.size = 0; - r.in.devmode_ctr.devmode = NULL; - r.in.access_mask = 0x02000000; - r.in.level = 1; + r.in.datatype = NULL; + r.in.devmode_ctr.size = 0; + r.in.devmode_ctr.devmode= NULL; + r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + r.in.level = 1; + r.in.userlevel.level1 = &userlevel1; r.out.handle = handle; userlevel1.size = 1234; @@ -708,7 +788,6 @@ static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, userlevel1.major = 2; userlevel1.minor = 3; userlevel1.processor = 4; - r.in.userlevel.level1 = &userlevel1; printf("Testing OpenPrinterEx(%s)\n", r.in.printername); @@ -968,18 +1047,14 @@ BOOL torture_rpc_spoolss(void) mem_ctx = talloc_init("torture_rpc_spoolss"); - if (!test_EnumPorts(p, mem_ctx)) { - ret = False; - } + ret &= test_OpenPrinter_badnames(p, mem_ctx); - if (!test_EnumPrinters(p, mem_ctx)) { - ret = False; - } + ret &= test_EnumPorts(p, mem_ctx); + + ret &= test_EnumPrinters(p, mem_ctx); + + ret &= test_EnumPrinterDrivers(p, mem_ctx); - if (!test_EnumPrinterDrivers(p, mem_ctx)) { - ret = False; - } -printf("blub\n"); talloc_free(mem_ctx); torture_rpc_close(p); |