r5503: - add torture test which tests for invalid printernames
authorStefan Metzmacher <metze@samba.org>
Tue, 22 Feb 2005 11:51:18 +0000 (11:51 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:10:52 +0000 (13:10 -0500)
- add OpenPrinter() server code that just calls OpenPrinterEx()

- fix OpenPrinterEx logic, we pass the invalid printer names test now

metze
(This used to be commit 3085d3728eaf76097319f648ab4bc7f9447bbe10)

source4/rpc_server/spoolss/dcesrv_spoolss.c
source4/rpc_server/spoolss/dcesrv_spoolss.h
source4/torture/rpc/spoolss.c

index 470c9e2674d1fb57366876ef0fda5163d48d186d..fa3a16f7e1557fba8545cba194fed6dec75f425c 100644 (file)
@@ -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);
 }
 
 
index aef13dd6d6f22552fb80a3a8c30d03d5e499cbc4..3375ff3d9c61b9a8fe44963e62934ac8df5a8ff6 100644 (file)
@@ -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;
 };
index de8da366b72971f4772fe9b88ef36d4fb2b0ad7e..c7a0a1e066aa8e1e0cf92ee0a297c204991296b1 100644 (file)
@@ -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);