r5503: - add torture test which tests for invalid printernames
[samba.git] / source4 / torture / rpc / spoolss.c
index 34221a14fa0c29efbca8af98e04ccc48835de729..c7a0a1e066aa8e1e0cf92ee0a297c204991296b1 100644 (file)
@@ -20,6 +20,7 @@
 */
 
 #include "includes.h"
+#include "librpc/gen_ndr/ndr_spoolss.h"
 
 static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                     struct policy_handle *handle)
@@ -88,7 +89,8 @@ static BOOL test_ClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static BOOL test_GetForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                 struct policy_handle *handle, char *formname)
+                        struct policy_handle *handle, 
+                        const char *formname)
 {
        NTSTATUS status;
        struct spoolss_GetForm r;
@@ -160,24 +162,16 @@ static BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
                status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
 
-               if (!r.out.buffer) {
+               if (!r.out.info) {
                        printf("No forms returned");
                        return False;
                }
 
-               status = pull_spoolss_FormInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("EnumFormsArray parse failed - %s\n", nt_errstr(status));
-                       return False;
-               }
+               info = *r.out.info;
 
-               for (j=0;j<r.out.count;j++) {
-                       printf("Form %d\n", j);
-                       NDR_PRINT_UNION_DEBUG(spoolss_FormInfo, r.in.level, &info[j]);
+               for (j = 0; j < r.out.count; j++) {
+                       test_GetForm(p, mem_ctx, handle, info[j].info1.formname);
                }
-
-               for (j = 0; j < r.out.count; j++)
-                       test_GetForm(p, mem_ctx, handle, info[j].info1.name);
        }
 
        if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
@@ -190,7 +184,8 @@ static BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                    struct policy_handle *handle, char *formname)
+                           struct policy_handle *handle, 
+                           const char *formname)
 {
        NTSTATUS status;
        struct spoolss_DeleteForm r;
@@ -221,7 +216,7 @@ static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        r.in.handle = handle;
        r.in.level = 1;
        form.flags = 2;         /* User form */
-       form.name = formname;
+       form.formname = formname;
        form.width = 1;
        form.length = 2;
        form.left = 3;
@@ -246,7 +241,7 @@ static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                struct spoolss_SetForm sf;
 
                sf.in.handle = handle;
-               sf.in.form_name = formname;
+               sf.in.formname = formname;
                sf.in.level = 1;
                sf.in.info.info1 = &form;
                form.width = 1234;
@@ -270,6 +265,51 @@ static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
+static BOOL test_EnumPorts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+{
+       NTSTATUS status;
+       struct spoolss_EnumPorts r;
+       uint32_t buf_size;
+
+       r.in.servername = talloc_asprintf(mem_ctx, "\\\\%s", 
+                                         dcerpc_server_name(p));
+       r.in.level = 2;
+       r.in.buffer = NULL;
+       buf_size = 0;
+       r.in.buf_size = &buf_size;
+       r.out.buf_size = &buf_size;
+
+       printf("Testing EnumPorts\n");
+
+       status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("EnumPorts failed -- %s\n", nt_errstr(status));
+               return False;
+       }
+
+       if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
+
+               data_blob_clear(&blob);
+               r.in.buffer = &blob;
+
+               status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("EnumPorts failed -- %s\n", nt_errstr(status));
+                       return False;
+               }
+
+               if (!r.out.info) {
+                       printf("No ports returned");
+                       return False;
+               }
+       }
+
+       return True;
+}
+
 static BOOL test_GetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                  struct policy_handle *handle, uint32_t job_id)
 {
@@ -368,31 +408,16 @@ static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
                status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
 
-               if (!r.out.buffer) {
+               if (!r.out.info) {
                        printf("No jobs returned");
                        return True;
                }
 
-               status = pull_spoolss_JobInfoArray(
-                       r.out.buffer, mem_ctx, r.in.level, r.out.count,
-                       &info);
-
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("EnumJobsArray parse failed - %s\n",
-                              nt_errstr(status));
-                       return False;
-               }
-
-               for (j = 0; j < r.out.count; j++) {
-                       printf("Job %d\n", j);
-                       NDR_PRINT_UNION_DEBUG(
-                               spoolss_JobInfo, r.in.level, &info[j]);
-               }
+               info = *r.out.info;
 
                for (j = 0; j < r.out.count; j++) {
                        test_GetJob(p, mem_ctx, handle, info[j].info1.job_id);
-                       test_SetJob(
-                               p, mem_ctx, handle, info[j].info1.job_id, 1);
+                       test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, 1);
                }
 
        } else if (!W_ERROR_IS_OK(r.out.result)) {
@@ -404,7 +429,8 @@ static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                        struct policy_handle *handle, char *value_name)
+                               struct policy_handle *handle, 
+                               const char *value_name)
 {
        NTSTATUS status;
        struct spoolss_GetPrinterData r;
@@ -439,8 +465,9 @@ static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                          struct policy_handle *handle, char *key_name,
-                          char *value_name)
+                                 struct policy_handle *handle, 
+                                 const char *key_name,
+                                 const char *value_name)
 {
        NTSTATUS status;
        struct spoolss_GetPrinterDataEx r;
@@ -524,7 +551,8 @@ static BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static BOOL test_DeletePrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                           struct policy_handle *handle, char *value_name)
+                                  struct policy_handle *handle, 
+                                  const char *value_name)
 {
        NTSTATUS status;
        struct spoolss_DeletePrinterData r;
@@ -549,8 +577,8 @@ static BOOL test_SetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status;
        struct spoolss_SetPrinterData r;
-       char *value_name = "spottyfoot";
-
+       const char *value_name = "spottyfoot";
+       
        r.in.handle = handle;
        r.in.value_name = value_name;
        r.in.type = 0;
@@ -581,7 +609,7 @@ static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
        BOOL ret = True;
 
        /* only makes sense on SMB */
-       if (p->transport.transport != NCACN_NP) {
+       if (p->conn->transport.transport != NCACN_NP) {
                return True;
        }
 
@@ -612,34 +640,109 @@ 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)
 {
        NTSTATUS status;
        struct spoolss_OpenPrinter r;
        struct policy_handle handle;
-       DATA_BLOB blob;
        BOOL ret = True;
 
-       blob = data_blob(NULL, 0);
+       r.in.printername        = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
+       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.out.handle            = &handle;
 
-       r.in.server = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
-       r.in.printer = NULL;
-       r.in.buffer = &blob;
-       r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;  
-       r.out.handle = &handle;
-
-       printf("\nTesting OpenPrinter(\\\\%s)\n", r.in.server);
+       printf("\nTesting OpenPrinter(%s)\n", r.in.printername);
 
        status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
        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)) {
                ret = False;
        }
@@ -651,7 +754,7 @@ static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        if (!test_ClosePrinter(p, mem_ctx, &handle)) {
                ret = False;
        }
-       
+
        return ret;
 }
 
@@ -662,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_required = 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;
@@ -683,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);
 
@@ -790,21 +894,12 @@ static BOOL test_EnumPrinters(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                        continue;
                }
 
-               if (!r.out.buffer) {
+               if (!r.out.info) {
                        printf("No printers returned");
                        continue;
                }
 
-               status = pull_spoolss_PrinterInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("EnumPrintersArray parse failed - %s\n", nt_errstr(status));
-                       continue;
-               }
-
-               for (j=0;j<r.out.count;j++) {
-                       printf("Printer %d\n", j);
-                       NDR_PRINT_UNION_DEBUG(spoolss_PrinterInfo, r.in.level, &info[j]);
-               }
+               info = *r.out.info;
 
                for (j=0;j<r.out.count;j++) {
                        if (r.in.level == 1) {
@@ -826,7 +921,8 @@ static BOOL test_EnumPrinters(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 }
 
 static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                                  struct policy_handle *handle, char *driver_name)
+                                  struct policy_handle *handle, 
+                                  const char *driver_name)
 {
        NTSTATUS status;
        struct spoolss_GetPrinterDriver2 r;
@@ -874,12 +970,10 @@ static BOOL test_EnumPrinterDrivers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
                uint32_t buf_size;
-               char *server;
                union spoolss_DriverInfo *info;
                uint32_t j;
 
-               asprintf(&server, "\\\\%s", dcerpc_server_name(p));
-               r.in.server = server;
+               r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
                r.in.environment = "Windows NT x86";
                r.in.level = levels[i];
                r.in.buffer = NULL;
@@ -897,74 +991,52 @@ static BOOL test_EnumPrinterDrivers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                        ret = False;
                        continue;
                }
-               
+
                if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
                        DATA_BLOB blob = data_blob_talloc(
                                mem_ctx, NULL, buf_size);
 
                        data_blob_clear(&blob);
                        r.in.buffer = &blob;
-                       status = dcerpc_spoolss_EnumPrinterDrivers(
-                               p, mem_ctx, &r);
+                       status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
                }
                
                if (!NT_STATUS_IS_OK(status) ||
                    !W_ERROR_IS_OK(r.out.result)) {
                        printf("EnumPrinterDrivers failed - %s/%s\n", 
                               nt_errstr(status), win_errstr(r.out.result));
-                       goto done;
+                       break;
                }
 
-               if (!r.out.buffer) {
+               if (!r.out.info) {
                        printf("No printer drivers returned");
-                       goto done;
+                       break;
                }
 
-               status = pull_spoolss_DriverInfoArray(
-                       r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
+               info = *r.out.info;
 
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("EnumPrinterDriverArray parse failed - %s\n", 
-                              nt_errstr(status));
-                       continue;
-               }
+               if (r.in.level != 1) continue;
 
                for (j=0;j<r.out.count;j++) {
-                       printf("Printer driver %d\n", j);
-                       NDR_PRINT_UNION_DEBUG(
-                               spoolss_DriverInfo, r.in.level, 
-                               &info[j]);
+                       struct policy_handle handle;
 
-                       if (r.in.level == 1) {
-                               struct policy_handle handle;
-
-                               if (!call_OpenPrinterEx(
-                                           p, mem_ctx, "",
-                                           &handle))
-                                       continue;
-
-                               test_GetPrinterDriver2(
-                                       p, mem_ctx, &handle, 
-                                       info[j].info1.driver_name);
+                       if (!call_OpenPrinterEx(p, mem_ctx, "",&handle)) {
+                               continue;
                        }
+                       ret &=test_GetPrinterDriver2(p, mem_ctx, &handle, info[j].info1.driver_name);
                }
-
-       done:
-               free(server);
        }
-       
+
        return ret;
 }
 
-BOOL torture_rpc_spoolss(int dummy)
+BOOL torture_rpc_spoolss(void)
 {
         NTSTATUS status;
         struct dcerpc_pipe *p;
        TALLOC_CTX *mem_ctx;
        BOOL ret = True;
 
-       mem_ctx = talloc_init("torture_rpc_spoolss");
-
        status = torture_rpc_connection(&p, 
                                        DCERPC_SPOOLSS_NAME,
                                        DCERPC_SPOOLSS_UUID,
@@ -973,15 +1045,17 @@ BOOL torture_rpc_spoolss(int dummy)
                return False;
        }
 
-       if (!test_EnumPrinters(p, mem_ctx)) {
-               ret = False;
-       }
+       mem_ctx = talloc_init("torture_rpc_spoolss");
 
-       if (!test_EnumPrinterDrivers(p, mem_ctx)) {
-               ret = False;
-       }
+       ret &= test_OpenPrinter_badnames(p, mem_ctx);
+
+       ret &= test_EnumPorts(p, mem_ctx);
+
+       ret &= test_EnumPrinters(p, mem_ctx);
+
+       ret &= test_EnumPrinterDrivers(p, mem_ctx);
 
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
 
         torture_rpc_close(p);