From 8f85427d6d8fa7e6bfd76ed5335c8dbe7dd14afe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 16 Jun 2005 17:27:57 +0000 Subject: r7643: This patch adds a new NTPTR subsystem: - this is an abstraction layer for print services, like out NTVFS subsystem for file services - all protocol specific details are still in rpc_server/spoolss/ - like the stupid in and out Buffer handling - checking of the r->in.server_name - ... - this subsystem can have multiple implementation selected by the "ntptr providor" global-section parameter - I currently added a "simple_ldb" backend, that stores Printers, Forms, Ports, Monitors, ... in the spoolss.db, and does no real printing this backend is basicly for testing, how the spoolss protocol works - the interface is just a prototype and will be changed a bit the next days or weeks, till the simple_ldb backend can handle all calls that are used by normal w2k3/xp clients - I'll also make the api async, as the ntvfs api this will make things like the RemoteFindFirstPrinterChangeNotifyEx(), that opens a connection back to the client, easier to implement, as we should not block the whole smbd for that - the idea is to later implement a "unix" backend that works like the current samba3 code - and maybe some embedded print server vendors can write there own backend that can directly talk to a printer without having cups or something like this - the default settings are (it currently makes no sense to change them :-): ntptr providor = simple_ldb spoolss database = $private_dir/spoolss.db metze (This used to be commit 455b5536d41bc31ebef8290812f45d4a38afa8e9) --- source4/config.list | 1 + source4/include/structs.h | 35 ++ source4/librpc/idl/spoolss.idl | 2 +- source4/ntptr/config.mk | 24 + source4/ntptr/ntptr.h | 189 +++++++ source4/ntptr/ntptr_base.c | 134 +++++ source4/ntptr/ntptr_interface.c | 561 +++++++++++++++++++ source4/ntptr/simple_ldb/ntptr_simple_ldb.c | 596 +++++++++++++++++++++ source4/param/loadparm.c | 4 + source4/rpc_server/config.mk | 8 +- source4/rpc_server/spoolss/dcesrv_spoolss.c | 803 ++++++++++------------------ source4/rpc_server/spoolss/dcesrv_spoolss.h | 38 -- source4/rpc_server/spoolss/spoolssdb.c | 113 ---- 13 files changed, 1839 insertions(+), 669 deletions(-) create mode 100644 source4/ntptr/config.mk create mode 100644 source4/ntptr/ntptr.h create mode 100644 source4/ntptr/ntptr_base.c create mode 100644 source4/ntptr/ntptr_interface.c create mode 100644 source4/ntptr/simple_ldb/ntptr_simple_ldb.c delete mode 100644 source4/rpc_server/spoolss/dcesrv_spoolss.h delete mode 100644 source4/rpc_server/spoolss/spoolssdb.c diff --git a/source4/config.list b/source4/config.list index cc8262314c..69b79c11b0 100644 --- a/source4/config.list +++ b/source4/config.list @@ -38,6 +38,7 @@ utils/config.mk ntvfs/posix/config.mk ntvfs/config.mk ntvfs/unixuid/config.mk +ntptr/config.mk torture/config.mk librpc/config.mk client/config.mk diff --git a/source4/include/structs.h b/source4/include/structs.h index 944f79225b..2c8003e791 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -37,8 +37,43 @@ union spoolss_FormInfo; union spoolss_PortInfo; union spoolss_MonitorInfo; union spoolss_PrintProcessorInfo; + struct spoolss_GetPrinterData; struct spoolss_SetPrinterData; +struct spoolss_OpenPrinterEx; +struct spoolss_EnumPrinterData; +struct spoolss_DeletePrinterData; +struct spoolss_AddForm; +struct spoolss_GetForm; +struct spoolss_SetForm; +struct spoolss_DeleteForm; +struct spoolss_AddPrinterDriver; +struct spoolss_DeletePrinterDriver; +struct spoolss_GetPrinterDriverDirectory; +struct spoolss_AddPrinter; +struct spoolss_GetPrinter; +struct spoolss_SetPrinter; +struct spoolss_DeletePrinter; +struct spoolss_GetPrinterDriver; +struct spoolss_EnumPrinterData; +struct spoolss_DeletePrinterData; +struct spoolss_AddForm; +struct spoolss_GetForm; +struct spoolss_SetForm; +struct spoolss_DeleteForm; +struct spoolss_AddJob; +struct spoolss_ScheduleJob; +struct spoolss_GetJob; +struct spoolss_SetJob; +struct spoolss_StartDocPrinter; +struct spoolss_EndDocPrinter; +struct spoolss_StartPagePrinter; +struct spoolss_EndPagePrinter; +struct spoolss_WritePrinter; +struct spoolss_ReadPrinter; + +struct ntptr_context; +struct ntptr_GenericHandle; struct drsuapi_DsReplicaObjectListItem; struct drsuapi_DsReplicaObjectListItemEx; diff --git a/source4/librpc/idl/spoolss.idl b/source4/librpc/idl/spoolss.idl index 0321ad16cb..33ae96caf5 100644 --- a/source4/librpc/idl/spoolss.idl +++ b/source4/librpc/idl/spoolss.idl @@ -878,7 +878,7 @@ [in,switch_is(level)] spoolss_SetFormInfo info ); - typedef [nodiscriminant,relative_base,public] union { + typedef [nodiscriminant,relative_base,public,gensize] union { [case(1)] spoolss_FormInfo1 info1; [default]; } spoolss_FormInfo; diff --git a/source4/ntptr/config.mk b/source4/ntptr/config.mk new file mode 100644 index 0000000000..ab36d75343 --- /dev/null +++ b/source4/ntptr/config.mk @@ -0,0 +1,24 @@ +# NTPTR Server subsystem + +################################################ +# Start MODULE ntptr_simple_ldb +[MODULE::ntptr_simple_ldb] +INIT_FUNCTION = ntptr_simple_ldb_init +SUBSYSTEM = NTPTR +INIT_OBJ_FILES = \ + ntptr/simple_ldb/ntptr_simple_ldb.o +REQUIRED_SUBSYSTEMS = \ + LIBLDB +# End MODULE ntptr_simple_ldb +################################################ + +################################################ +# Start SUBSYSTEM NTPTR +[SUBSYSTEM::NTPTR] +INIT_OBJ_FILES = \ + ntptr/ntptr_base.o +ADD_OBJ_FILES = \ + ntptr/ntptr_interface.o +# +# End SUBSYSTEM NTPTR +################################################ diff --git a/source4/ntptr/ntptr.h b/source4/ntptr/ntptr.h new file mode 100644 index 0000000000..847cef97c3 --- /dev/null +++ b/source4/ntptr/ntptr.h @@ -0,0 +1,189 @@ +/* + Unix SMB/CIFS implementation. + + NTPTR structures and defines + + Copyright (C) Stefan (metze) Metzmacher 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* modules can use the following to determine if the interface has changed */ +#define NTPTR_INTERFACE_VERSION 0 + +struct ntptr_context; + +enum ntptr_HandleType { + NTPTR_HANDLE_SERVER, + NTPTR_HANDLE_PRINTER, + NTPTR_HANDLE_PORT, + NTPTR_HANDLE_MONITOR +}; + +struct ntptr_GenericHandle { + enum ntptr_HandleType type; + struct ntptr_context *ntptr; + uint32_t access_mask; + void *private_data; +}; + +/* the ntptr operations structure - contains function pointers to + the backend implementations of each operation */ +struct ntptr_ops { + const char *name; + + /* initial setup */ + NTSTATUS (*init_context)(struct ntptr_context *ntptr); + + /* PrintServer functions */ + WERROR (*OpenPrintServer)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *printer_name, + struct ntptr_GenericHandle **server); + + /* PrintServer PrinterData functions */ + WERROR (*EnumPrintServerData)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinterData *r); + WERROR (*GetPrintServerData)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterData *r); + WERROR (*SetPrintServerData)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_SetPrinterData *r); + WERROR (*DeletePrintServerData)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_DeletePrinterData *r); + + /* PrintServer Form functions */ + WERROR (*EnumPrintServerForms)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_EnumForms *r); + WERROR (*AddPrintServerForm)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_AddForm *r); + WERROR (*GetPrintServerForm)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_GetForm *r); + WERROR (*SetPrintServerForm)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_SetForm *r); + WERROR (*DeletePrintServerForm)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_DeleteForm *r); + + /* PrintServer Driver functions */ + WERROR (*EnumPrinterDrivers)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinterDrivers *r); + WERROR (*AddPrinterDriver)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_AddPrinterDriver *r); + WERROR (*DeletePrinterDriver)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_DeletePrinterDriver *r); + WERROR (*GetPrinterDriverDirectory)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterDriverDirectory *r); + + /* Port functions */ + WERROR (*EnumPorts)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPorts *r); + WERROR (*OpenPort)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *port_name, + struct ntptr_GenericHandle **prt); + + /* Monitor functions */ + WERROR (*EnumMonitors)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumMonitors *r); + WERROR (*OpenMonitor)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *monitor_name, + struct ntptr_GenericHandle **monitor); + + /* PrintProcessor functions */ + WERROR (*EnumPrintProcessors)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrintProcessors *r); + + /* Printer functions */ + WERROR (*EnumPrinters)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinters *r); + WERROR (*OpenPrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *printer_name, + struct ntptr_GenericHandle **printer); + WERROR (*AddPrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_AddPrinter *r, + struct ntptr_GenericHandle **printer); + WERROR (*GetPrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinter *r); + WERROR (*SetPrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_SetPrinter *r); + WERROR (*DeletePrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_DeletePrinter *r); + + /* Printer Driver functions */ + WERROR (*GetPrinterDriver)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterDriver *r); + + /* Printer PrinterData functions */ + WERROR (*EnumPrinterData)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinterData *r); + WERROR (*GetPrinterData)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterData *r); + WERROR (*SetPrinterData)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_SetPrinterData *r); + WERROR (*DeletePrinterData)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_DeletePrinterData *r); + + /* Printer Form functions */ + WERROR (*EnumPrinterForms)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EnumForms *r); + WERROR (*AddPrinterForm)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_AddForm *r); + WERROR (*GetPrinterForm)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_GetForm *r); + WERROR (*SetPrinterForm)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_SetForm *r); + WERROR (*DeletePrinterForm)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_DeleteForm *r); + + /* Printer Job functions */ + WERROR (*EnumJobs)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EnumJobs *r); + WERROR (*AddJob)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_AddJob *r); + WERROR (*ScheduleJob)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_ScheduleJob *r); + WERROR (*GetJob)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_GetJob *r); + WERROR (*SetJob)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_SetJob *r); + + /* Printer Printing functions */ + WERROR (*StartDocPrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_StartDocPrinter *r); + WERROR (*EndDocPrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EndDocPrinter *r); + WERROR (*StartPagePrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_StartPagePrinter *r); + WERROR (*EndPagePrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EndPagePrinter *r); + WERROR (*WritePrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_WritePrinter *r); + WERROR (*ReadPrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_ReadPrinter *r); +}; + +struct ntptr_context { + const struct ntptr_ops *ops; + void *private_data; +}; + +/* this structure is used by backends to determine the size of some critical types */ +struct ntptr_critical_sizes { + int interface_version; + int sizeof_ntptr_critical_sizes; + int sizeof_ntptr_context; + int sizeof_ntptr_ops; +}; diff --git a/source4/ntptr/ntptr_base.c b/source4/ntptr/ntptr_base.c new file mode 100644 index 0000000000..f12a58cb4e --- /dev/null +++ b/source4/ntptr/ntptr_base.c @@ -0,0 +1,134 @@ +/* + Unix SMB/CIFS implementation. + + NTPTR base code + + Copyright (C) Stefan (metze) Metzmacher 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + this implements the core code for all NTPTR modules. Backends register themselves here. +*/ + +#include "includes.h" +#include "ntptr/ntptr.h" +#include "dlinklist.h" + +/* the list of currently registered NTPTR backends */ +static struct ntptr_backend { + const struct ntptr_ops *ops; +} *backends = NULL; +static int num_backends; + +/* + register a NTPTR backend. + + The 'name' can be later used by other backends to find the operations + structure for this backend. +*/ +NTSTATUS ntptr_register(const void *_ops) +{ + const struct ntptr_ops *ops = _ops; + struct ntptr_ops *new_ops; + + if (ntptr_backend_byname(ops->name) != NULL) { + /* its already registered! */ + DEBUG(0,("NTPTR backend '%s' already registered\n", + ops->name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + backends = realloc_p(backends, struct ntptr_backend, num_backends+1); + if (!backends) { + smb_panic("out of memory in ntptr_register"); + } + + new_ops = smb_xmemdup(ops, sizeof(*ops)); + new_ops->name = smb_xstrdup(ops->name); + + backends[num_backends].ops = new_ops; + + num_backends++; + + DEBUG(3,("NTPTR backend '%s'\n", + ops->name)); + + return NT_STATUS_OK; +} + + +/* + return the operations structure for a named backend +*/ +const struct ntptr_ops *ntptr_backend_byname(const char *name) +{ + int i; + + for (i=0;iname, name) == 0) { + return backends[i].ops; + } + } + + return NULL; +} + + +/* + return the NTPTR interface version, and the size of some critical types + This can be used by backends to either detect compilation errors, or provide + multiple implementations for different smbd compilation options in one module +*/ +static const struct ntptr_critical_sizes critical_sizes = { + .interface_version = NTPTR_INTERFACE_VERSION, + .sizeof_ntptr_critical_sizes = sizeof(struct ntptr_critical_sizes), + .sizeof_ntptr_context = sizeof(struct ntptr_context), + .sizeof_ntptr_ops = sizeof(struct ntptr_ops), +}; +const struct ntptr_critical_sizes *ntptr_interface_version(void) +{ + return &critical_sizes; +} + +/* + create a ntptr_context with a specified NTPTR backend +*/ +NTSTATUS ntptr_init_context(TALLOC_CTX *mem_ctx, const char *providor, struct ntptr_context **_ntptr) +{ + NTSTATUS status; + struct ntptr_context *ntptr; + + if (!providor) { + return NT_STATUS_INTERNAL_ERROR; + } + + ntptr = talloc(mem_ctx, struct ntptr_context); + NT_STATUS_HAVE_NO_MEMORY(ntptr); + ntptr->private_data = NULL; + ntptr->ops = ntptr_backend_byname(providor); + + if (!ntptr->ops) { + DEBUG(1,("ntptr_init_context: failed to find NTPTR providor='%s'\n", + providor)); + return NT_STATUS_INTERNAL_ERROR; + } + + status = ntptr->ops->init_context(ntptr); + NT_STATUS_NOT_OK_RETURN(status); + + *_ntptr = ntptr; + return NT_STATUS_OK; +} diff --git a/source4/ntptr/ntptr_interface.c b/source4/ntptr/ntptr_interface.c new file mode 100644 index 0000000000..b389a5b894 --- /dev/null +++ b/source4/ntptr/ntptr_interface.c @@ -0,0 +1,561 @@ +/* + Unix SMB/CIFS implementation. + + NTPTR interface functions + + Copyright (C) Stefan (metze) Metzmacher 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "ntptr/ntptr.h" + + +/* PrintServer functions */ +WERROR ntptr_OpenPrintServer(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *printer_name, + struct ntptr_GenericHandle **server) +{ + if (!ntptr->ops->OpenPrintServer) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->OpenPrintServer(ntptr, mem_ctx, r, printer_name, server); +} + + +/* PrintServer PrinterData functions */ +WERROR ntptr_EnumPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinterData *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->EnumPrintServerData) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->EnumPrintServerData(server, mem_ctx, r); +} + +WERROR ntptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterData *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->GetPrintServerData) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->GetPrintServerData(server, mem_ctx, r); +} + +WERROR ntptr_SetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_SetPrinterData *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->SetPrintServerData) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->SetPrintServerData(server, mem_ctx, r); +} + +WERROR ntptr_DeletePrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_DeletePrinterData *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->DeletePrintServerData) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->DeletePrintServerData(server, mem_ctx, r); +} + + +/* PrintServer Form functions */ +WERROR ntptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_EnumForms *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->EnumPrintServerForms) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->EnumPrintServerForms(server, mem_ctx, r); +} + +WERROR ntptr_AddPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_AddForm *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->AddPrintServerForm) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->AddPrintServerForm(server, mem_ctx, r); +} + +WERROR ntptr_GetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_GetForm *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->GetPrintServerForm) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->GetPrintServerForm(server, mem_ctx, r); +} + +WERROR ntptr_SetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_SetForm *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->SetPrintServerForm) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->SetPrintServerForm(server, mem_ctx, r); +} + +WERROR ntptr_DeletePrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_DeleteForm *r) +{ + if (server->type != NTPTR_HANDLE_SERVER) { + return WERR_FOOBAR; + } + if (!server->ntptr->ops->DeletePrintServerForm) { + return WERR_NOT_SUPPORTED; + } + return server->ntptr->ops->DeletePrintServerForm(server, mem_ctx, r); +} + + +/* PrintServer Driver functions */ +WERROR ntptr_EnumPrinterDrivers(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinterDrivers *r) +{ + if (!ntptr->ops->EnumPrinterDrivers) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->EnumPrinterDrivers(ntptr, mem_ctx, r); +} + +WERROR ntptr_AddPrinterDriver(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_AddPrinterDriver *r) +{ + if (!ntptr->ops->AddPrinterDriver) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->AddPrinterDriver(ntptr, mem_ctx, r); +} + +WERROR ntptr_DeletePrinterDriver(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_DeletePrinterDriver *r) +{ + if (!ntptr->ops->DeletePrinterDriver) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->DeletePrinterDriver(ntptr, mem_ctx, r); +} + +WERROR ntptr_GetPrinterDriverDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterDriverDirectory *r) +{ + if (!ntptr->ops->GetPrinterDriverDirectory) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->GetPrinterDriverDirectory(ntptr, mem_ctx, r); +} + + +/* Port functions */ +WERROR ntptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPorts *r) +{ + if (!ntptr->ops->EnumPorts) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->EnumPorts(ntptr, mem_ctx, r); +} + +WERROR ntptr_OpenPort(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *port_name, + struct ntptr_GenericHandle **prt) +{ + if (!ntptr->ops->OpenPort) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->OpenPort(ntptr, mem_ctx, r, port_name, prt); +} + + +/* Monitor functions */ +WERROR ntptr_EnumMonitors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumMonitors *r) +{ + if (!ntptr->ops->EnumMonitors) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->EnumMonitors(ntptr, mem_ctx, r); +} + +WERROR ntptr_OpenMonitor(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *monitor_name, + struct ntptr_GenericHandle **monitor) +{ + if (!ntptr->ops->OpenMonitor) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->OpenMonitor(ntptr, mem_ctx, r, monitor_name, monitor); +} + + +/* PrintProcessor functions */ +WERROR ntptr_EnumPrintProcessors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrintProcessors *r) +{ + if (!ntptr->ops->EnumPrintProcessors) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->EnumPrintProcessors(ntptr, mem_ctx, r); +} + + +/* Printer functions */ +WERROR ntptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinters *r) +{ + if (!ntptr->ops->EnumPrinters) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->EnumPrinters(ntptr, mem_ctx, r); +} + +WERROR ntptr_OpenPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *printer_name, + struct ntptr_GenericHandle **printer) +{ + if (!ntptr->ops->OpenPrinter) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->OpenPrinter(ntptr, mem_ctx, r, printer_name, printer); +} + +WERROR ntptr_AddPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_AddPrinter *r, + struct ntptr_GenericHandle **printer) +{ + if (!ntptr->ops->AddPrinter) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->AddPrinter(ntptr, mem_ctx, r, printer); +} + +WERROR ntptr_GetPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinter *r) +{ + if (!ntptr->ops->GetPrinter) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->GetPrinter(ntptr, mem_ctx, r); +} + +WERROR ntptr_SetPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_SetPrinter *r) +{ + if (!ntptr->ops->SetPrinter) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->SetPrinter(ntptr, mem_ctx, r); +} + +WERROR ntptr_DeletePrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_DeletePrinter *r) +{ + if (!ntptr->ops->DeletePrinter) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->DeletePrinter(ntptr, mem_ctx, r); +} + + +/* Printer Driver functions */ +WERROR ntptr_GetPrinterDriver(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterDriver *r) +{ + if (!ntptr->ops->GetPrinterDriver) { + return WERR_NOT_SUPPORTED; + } + return ntptr->ops->GetPrinterDriver(ntptr, mem_ctx, r); +} + + +/* Printer PrinterData functions */ +WERROR ntptr_EnumPrinterData(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinterData *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->EnumPrinterData) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->EnumPrinterData(printer, mem_ctx, r); +} + +WERROR ntptr_GetPrinterData(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterData *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->GetPrinterData) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->GetPrinterData(printer, mem_ctx, r); +} + +WERROR ntptr_SetPrinterData(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_SetPrinterData *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->SetPrinterData) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->SetPrinterData(printer, mem_ctx, r); +} + +WERROR ntptr_DeletePrinterData(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_DeletePrinterData *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->DeletePrinterData) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->DeletePrinterData(printer, mem_ctx, r); +} + + +/* Printer Form functions */ +WERROR ntptr_EnumPrinterForms(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EnumForms *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->EnumPrinterForms) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->EnumPrinterForms(printer, mem_ctx, r); +} + +WERROR ntptr_AddPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_AddForm *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->AddPrinterForm) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->AddPrinterForm(printer, mem_ctx, r); +} + +WERROR ntptr_GetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_GetForm *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->GetPrinterForm) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->GetPrinterForm(printer, mem_ctx, r); +} + +WERROR ntptr_SetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_SetForm *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->SetPrinterForm) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->SetPrinterForm(printer, mem_ctx, r); +} + +WERROR ntptr_DeletePrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_DeleteForm *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->DeletePrinterForm) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->DeletePrinterForm(printer, mem_ctx, r); +} + + +/* Printer Job functions */ +WERROR ntptr_EnumJobs(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EnumJobs *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->EnumJobs) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->EnumJobs(printer, mem_ctx, r); +} + +WERROR ntptr_AddJob(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_AddJob *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->AddJob) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->AddJob(printer, mem_ctx, r); +} + +WERROR ntptr_ScheduleJob(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_ScheduleJob *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->ScheduleJob) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->ScheduleJob(printer, mem_ctx, r); +} + +WERROR ntptr_GetJob(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_GetJob *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->GetJob) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->GetJob(printer, mem_ctx, r); +} + +WERROR ntptr_SetJob(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_SetJob *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->SetJob) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->SetJob(printer, mem_ctx, r); +} + + +/* Printer Printing functions */ +WERROR ntptr_StartDocPrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_StartDocPrinter *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->StartDocPrinter) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->StartDocPrinter(printer, mem_ctx, r); +} + +WERROR ntptr_EndDocPrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EndDocPrinter *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->EndDocPrinter) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->EndDocPrinter(printer, mem_ctx, r); +} + +WERROR ntptr_StartPagePrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_StartPagePrinter *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->StartPagePrinter) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->StartPagePrinter(printer, mem_ctx, r); +} + +WERROR ntptr_EndPagePrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_EndPagePrinter *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->EndPagePrinter) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->EndPagePrinter(printer, mem_ctx, r); +} + +WERROR ntptr_WritePrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_WritePrinter *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->WritePrinter) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->WritePrinter(printer, mem_ctx, r); +} + +WERROR ntptr_ReadPrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, + struct spoolss_ReadPrinter *r) +{ + if (printer->type != NTPTR_HANDLE_PRINTER) { + return WERR_FOOBAR; + } + if (!printer->ntptr->ops->ReadPrinter) { + return WERR_NOT_SUPPORTED; + } + return printer->ntptr->ops->ReadPrinter(printer, mem_ctx, r); +} + diff --git a/source4/ntptr/simple_ldb/ntptr_simple_ldb.c b/source4/ntptr/simple_ldb/ntptr_simple_ldb.c new file mode 100644 index 0000000000..4c8113365e --- /dev/null +++ b/source4/ntptr/simple_ldb/ntptr_simple_ldb.c @@ -0,0 +1,596 @@ +/* + Unix SMB/CIFS implementation. + + Simple LDB NTPTR backend + + Copyright (C) Stefan (metze) Metzmacher 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + This implements a NTPTR backend that store + all objects (Printers, Ports, Monitors, PrinterDrivers ...) + in a ldb database, but doesn't do real printing. + + This is just used for testing how some of + the SPOOLSS protocol details should work +*/ + +#include "includes.h" +#include "ntptr/ntptr.h" +#include "librpc/gen_ndr/ndr_spoolss.h" +#include "lib/ldb/include/ldb.h" +#include "db_wrap.h" + +/* + connect to the SPOOLSS database + return a ldb_context pointer on success, or NULL on failure + */ +static struct ldb_context *sptr_db_connect(TALLOC_CTX *mem_ctx) +{ + return ldb_wrap_connect(mem_ctx, lp_spoolss_url(), 0, NULL); +} + +static int sptr_db_search(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *basedn, + struct ldb_message ***res, + const char * const *attrs, + const char *format, ...) PRINTF_ATTRIBUTE(6,7); + +static int sptr_db_search(struct ldb_context *ldb, + TALLOC_CTX *mem_ctx, + const char *basedn, + struct ldb_message ***res, + const char * const *attrs, + const char *format, ...) +{ + va_list ap; + int count; + + va_start(ap, format); + count = gendb_search_v(ldb, mem_ctx, basedn, res, attrs, format, ap); + va_end(ap); + + return count; +} + +static NTSTATUS sptr_init_context(struct ntptr_context *ntptr) +{ + struct ldb_context *sptr_db = sptr_db_connect(ntptr); + NT_STATUS_HAVE_NO_MEMORY(sptr_db); + + ntptr->private_data = sptr_db; + + return NT_STATUS_OK; +} + +/* PrintServer functions */ +static WERROR sptr_OpenPrintServer(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *server_name, + struct ntptr_GenericHandle **_server) +{ + struct ntptr_GenericHandle *server; + + /* TODO: do access check here! */ + + server = talloc(mem_ctx, struct ntptr_GenericHandle); + W_ERROR_HAVE_NO_MEMORY(server); + + server->type = NTPTR_HANDLE_SERVER; + server->ntptr = ntptr; + server->access_mask = r->in.access_mask; + server->private_data = NULL; + + *_server = server; + return WERR_OK; +} + +/* + * PrintServer PrinterData functions + */ +static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterData *r) +{ + if (strcmp("W3SvcInstalled", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + r->out.data.value = 0; + return WERR_OK; + } else if (strcmp("BeepEnabled", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + r->out.data.value = 0; + return WERR_OK; + } else if (strcmp("EventLog", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + r->out.data.value = 0; + return WERR_OK; + } else if (strcmp("NetPopup", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + r->out.data.value = 0; + return WERR_OK; + } else if (strcmp("NetPopupToComputer", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + r->out.data.value = 0; + return WERR_OK; + } else if (strcmp("MajorVersion", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + r->out.data.value = 3; + return WERR_OK; + } else if (strcmp("MinorVersion", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + r->out.data.value = 0; + return WERR_OK; + } else if (strcmp("DefaultSpoolDirectory", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; + r->out.data.string = "C:\\PRINTERS"; + return WERR_OK; + } else if (strcmp("Architecture", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; + r->out.data.string = SPOOLSS_ARCHITECTURE_NT_X86; + return WERR_OK; + } else if (strcmp("DsPresent", r->in.value_name) == 0) { + r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + r->out.data.value = 1; + return WERR_OK; + } + + return WERR_INVALID_PARAM; +} + +/* PrintServer Form functions */ +static WERROR sptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_EnumForms *r) +{ + struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); + struct ldb_message **msgs; + int count; + int i; + union spoolss_FormInfo *info; + + count = sptr_db_search(sptr_db, mem_ctx, "CN=PrintServer", &msgs, NULL, + "(&(objectclass=form))"); + + if (count == 0) return WERR_OK; + if (count < 0) return WERR_GENERAL_FAILURE; + + info = talloc_array(mem_ctx, union spoolss_FormInfo, count); + W_ERROR_HAVE_NO_MEMORY(info); + + switch (r->in.level) { + case 1: + for (i=0; i < count; i++) { + info[i].info1.flags = samdb_result_uint(msgs[i], "flags", SPOOLSS_FORM_PRINTER); + + info[i].info1.form_name = samdb_result_string(msgs[i], "form_name", "Letter"); + W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name); + + info[i].info1.size.width = samdb_result_uint(msgs[i], "size_widgth", 0x34b5c); + info[i].info1.size.height = samdb_result_uint(msgs[i], "size_height", 0x44368); + + info[i].info1.area.left = samdb_result_uint(msgs[i], "area_left", 0); + info[i].info1.area.top = samdb_result_uint(msgs[i], "area_top", 0); + info[i].info1.area.right = samdb_result_uint(msgs[i], "are_right", 0x34b5c); + info[i].info1.area.bottom = samdb_result_uint(msgs[i], "area_bottom", 0x44368); + } + break; + default: + return WERR_UNKNOWN_LEVEL; + } + + r->out.info = info; + r->out.count = count; + return WERR_OK; +} + +static WERROR sptr_GetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, + struct spoolss_GetForm *r) +{ + struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); + struct ldb_message **msgs; + int count; + union spoolss_FormInfo *info; + + count = sptr_db_search(sptr_db, mem_ctx, "CN=PrintServer", &msgs, NULL, + "(&(form_name=%s)(objectclass=form))", + r->in.form_name); + + if (count == 0) return WERR_FOOBAR; + if (count > 1) return WERR_FOOBAR; + if (count < 0) return WERR_GENERAL_FAILURE; + + info = talloc(mem_ctx, union spoolss_FormInfo); + W_ERROR_HAVE_NO_MEMORY(info); + + switch (r->in.level) { + case 1: + info->info1.flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_PRINTER); + + info->info1.form_name = samdb_result_string(msgs[0], "form_name", "Letter"); + W_ERROR_HAVE_NO_MEMORY(info->info1.form_name); + + info->info1.size.width = samdb_result_uint(msgs[0], "size_widgth", 0x34b5c); + info->info1.size.height = samdb_result_uint(msgs[0], "size_height", 0x44368); + + info->info1.area.left = samdb_result_uint(msgs[0], "area_left", 0); + info->info1.area.top = samdb_result_uint(msgs[0], "area_top", 0); + info->info1.area.right = samdb_result_uint(msgs[0], "are_right", 0x34b5c); + info->info1.area.bottom = samdb_result_uint(msgs[0], "area_bottom", 0x44368); + break; + default: + return WERR_UNKNOWN_LEVEL; + } + + r->out.info = info; + return WERR_OK; +} + +/* PrintServer Driver functions */ +static WERROR sptr_EnumPrinterDrivers(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinterDrivers *r) +{ + return WERR_OK; +} + +static WERROR sptr_GetPrinterDriverDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_GetPrinterDriverDirectory *r) +{ + union spoolss_DriverDirectoryInfo *info; + const char *prefix; + const char *postfix; + + /* + * NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a + * are ignoring the r->in.level completely, so we do :-) + */ + + /* + * TODO: check the server name is ours + * - if it's a invalid UNC then return WERR_INVALID_NAME + * - if it's the wrong host name return WERR_INVALID_PARAM + * - if it's "" then we need to return a local WINDOWS path + */ + if (!r->in.server || !r->in.server[0]) { + prefix = "C:\\DRIVERS"; + } else { + prefix = talloc_asprintf(mem_ctx, "%s\\print$", r->in.server); + W_ERROR_HAVE_NO_MEMORY(prefix); + } + + if (r->in.environment && strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) { + postfix = "W32X86"; + } else { + return WERR_INVALID_ENVIRONMENT; + } + + info = talloc(mem_ctx, union spoolss_DriverDirectoryInfo); + W_ERROR_HAVE_NO_MEMORY(info); + + info->info1.directory_name = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix); + W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name); + + r->out.info = info; + return WERR_OK; +} + +/* Printer functions */ +static WERROR sptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinters *r) +{ + struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context); + struct ldb_message **msgs; + int count; + int i; + union spoolss_PrinterInfo *info; + + count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL, + "(&(objectclass=printer))"); + + if (count == 0) return WERR_OK; + if (count < 0) return WERR_GENERAL_FAILURE; + + info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count); + W_ERROR_HAVE_NO_MEMORY(info); + + switch(r->in.level) { + case 1: + for (i = 0; i < count; i++) { + info[i].info1.flags = samdb_result_uint(msgs[i], "flags", 0); + + info[i].info1.name = samdb_result_string(msgs[i], "name", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info1.name); + + info[i].info1.description = samdb_result_string(msgs[i], "description", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info1.description); + + info[i].info1.comment = samdb_result_string(msgs[i], "comment", NULL); + } + break; + case 2: + for (i = 0; i < count; i++) { + info[i].info2.servername = samdb_result_string(msgs[i], "servername", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername); + + info[i].info2.printername = samdb_result_string(msgs[i], "printername", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername); + + info[i].info2.sharename = samdb_result_string(msgs[i], "sharename", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename); + + info[i].info2.portname = samdb_result_string(msgs[i], "portname", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname); + + info[i].info2.drivername = samdb_result_string(msgs[i], "drivername", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername); + + info[i].info2.comment = samdb_result_string(msgs[i], "comment", NULL); + + info[i].info2.location = samdb_result_string(msgs[i], "location", NULL); + + info[i].info2.devmode = NULL; + + info[i].info2.sepfile = samdb_result_string(msgs[i], "sepfile", NULL); + + info[i].info2.printprocessor = samdb_result_string(msgs[i], "printprocessor", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor); + + info[i].info2.datatype = samdb_result_string(msgs[i], "datatype", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype); + + info[i].info2.parameters = samdb_result_string(msgs[i], "parameters", NULL); + + info[i].info2.secdesc = NULL; + + info[i].info2.attributes = samdb_result_uint(msgs[i], "attributes", 0); + info[i].info2.priority = samdb_result_uint(msgs[i], "priority", 0); + info[i].info2.defaultpriority = samdb_result_uint(msgs[i], "defaultpriority", 0); + info[i].info2.starttime = samdb_result_uint(msgs[i], "starttime", 0); + info[i].info2.untiltime = samdb_result_uint(msgs[i], "untiltime", 0); + info[i].info2.status = samdb_result_uint(msgs[i], "status", 0); + info[i].info2.cjobs = samdb_result_uint(msgs[i], "cjobs", 0); + info[i].info2.averageppm = samdb_result_uint(msgs[i], "averageppm", 0); + } + break; + case 4: + for (i = 0; i < count; i++) { + info[i].info4.printername = samdb_result_string(msgs[i], "printername", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername); + + info[i].info4.servername = samdb_result_string(msgs[i], "servername", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername); + + info[i].info4.attributes = samdb_result_uint(msgs[i], "attributes", 0); + } + break; + case 5: + for (i = 0; i < count; i++) { + info[i].info5.printername = samdb_result_string(msgs[i], "name", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername); + + info[i].info5.portname = samdb_result_string(msgs[i], "port", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname); + + info[i].info5.attributes = samdb_result_uint(msgs[i], "attributes", 0); + info[i].info5.device_not_selected_timeout = samdb_result_uint(msgs[i], "device_not_selected_timeout", 0); + info[i].info5.transmission_retry_timeout = samdb_result_uint(msgs[i], "transmission_retry_timeout", 0); + } + break; + default: + return WERR_UNKNOWN_LEVEL; + } + + r->out.info = info; + r->out.count = count; + return WERR_OK; +} + +static WERROR sptr_OpenPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_OpenPrinterEx *r, + const char *printer_name, + struct ntptr_GenericHandle **printer) +{ + return WERR_INVALID_PRINTER_NAME; +} + +/* port functions */ +static WERROR sptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPorts *r) +{ + struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context); + struct ldb_message **msgs; + int count; + int i; + union spoolss_PortInfo *info; + + count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL, + "(&(objectclass=port))"); + + if (count == 0) return WERR_OK; + if (count < 0) return WERR_GENERAL_FAILURE; + + info = talloc_array(mem_ctx, union spoolss_PortInfo, count); + W_ERROR_HAVE_NO_MEMORY(info); + + switch (r->in.level) { + case 1: + for (i = 0; i < count; i++) { + info[i].info1.port_name = samdb_result_string(msgs[i], "port_name", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info1.port_name); + } + break; + case 2: + for (i=0; i < count; i++) { + info[i].info2.port_name = samdb_result_string(msgs[i], "port_name", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.port_name); + + info[i].info2.monitor_name = samdb_result_string(msgs[i], "monitor_name", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name); + + info[i].info2.description = samdb_result_string(msgs[i], "description", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.description); + + info[i].info2.port_type = samdb_result_uint(msgs[i], "port_type", SPOOLSS_PORT_TYPE_WRITE); + info[i].info2.reserved = samdb_result_uint(msgs[i], "reserved", 0); + } + break; + default: + return WERR_UNKNOWN_LEVEL; + } + + r->out.info = info; + r->out.count = count; + return WERR_OK; +} + +/* monitor functions */ +static WERROR sptr_EnumMonitors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, + struct spoolss_EnumMonitors *r) +{ + struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context); + struct ldb_message **msgs; + int count; + int i; + union spoolss_MonitorInfo *info; + + count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL, + "(&(objectclass=monitor))"); + + if (count == 0) return WERR_OK; + if (count < 0) return WERR_GENERAL_FAILURE; + + info = talloc_array(mem_ctx, union spoolss_MonitorInfo, count); + W_ERROR_HAVE_NO_MEMORY(info); + + switch (r->in.level) { + case 1: + for (i = 0; i < count; i++) { + info[i].info1.monitor_name = samdb_result_string(msgs[i], "monitor_name", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info1.monitor_name); + } + break; + case 2: + for (i=0; i < count; i++) { + info[i].info2.monitor_name = samdb_result_string(msgs[i], "monitor_name", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name); + + info[i].info2.environment = samdb_result_string(msgs[i], "environment", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.environment); + + info[i].info2.dll_name = samdb_result_string(msgs[i], "dll_name", ""); + W_ERROR_HAVE_NO_MEMORY(info[i].info2.dll_name); + } + break; + default: + return WERR_UNKNOWN_LEVEL; + } + + r->out.info = info; + r->out.count = count; + return WERR_OK; + return WERR_OK; +} + +/* + initialialise the simble ldb backend, registering ourselves with the ntptr subsystem + */ +static const struct ntptr_ops ntptr_simple_ldb_ops = { + .name = "simple_ldb", + .init_context = sptr_init_context, + + /* PrintServer functions */ + .OpenPrintServer = sptr_OpenPrintServer, + + /* PrintServer PrinterData functions */ +/* .EnumPrintServerData = sptr_EnumPrintServerData, +*/ .GetPrintServerData = sptr_GetPrintServerData, +/* .SetPrintServerData = sptr_SetPrintServerData, + .DeletePrintServerData = sptr_DeletePrintServerData, +*/ + /* PrintServer Form functions */ + .EnumPrintServerForms = sptr_EnumPrintServerForms, +/* .AddPrintServerForm = sptr_AddPrintServerForm, +*/ .GetPrintServerForm = sptr_GetPrintServerForm, +/* .SetPrintServerForm = sptr_SetPrintServerForm, + .DeletePrintServerForm = sptr_DeletePrintServerForm, +*/ + /* PrintServer Driver functions */ + .EnumPrinterDrivers = sptr_EnumPrinterDrivers, +/* .AddPrinterDriver = sptr_AddPrinterDriver, + .DeletePrinterDriver = sptr_DeletePrinterDriver, +*/ .GetPrinterDriverDirectory = sptr_GetPrinterDriverDirectory, + + /* Port functions */ + .EnumPorts = sptr_EnumPorts, +/* .OpenPort = sptr_OpenPort, +*/ + /* Monitor functions */ + .EnumMonitors = sptr_EnumMonitors, +/* .OpenMonitor = sptr_OpenMonitor, +*/ + /* PrintProcessor functions */ +/* .EnumPrintProcessors = sptr_EnumPrintProcessors, +*/ + /* Printer functions */ + .EnumPrinters = sptr_EnumPrinters, + .OpenPrinter = sptr_OpenPrinter, +/* .AddPrinter = sptr_AddPrinter, + .GetPrinter = sptr_GetPrinter, + .SetPrinter = sptr_SetPrinter, + .DeletePrinter = sptr_DeletePrinter, +*/ + /* Printer Driver functions */ +/* .GetPrinterDriver = sptr_GetPrinterDriver, +*/ + /* Printer PrinterData functions */ +/* .EnumPrinterData = sptr_EnumPrinterData, + .GetPrinterData = sptr_GetPrinterData, + .SetPrinterData = sptr_SetPrinterData, + .DeletePrinterData = sptr_DeletePrinterData, +*/ + /* Printer Form functions */ +/* .EnumPrinterForms = sptr_EnumPrinterForms, + .AddPrinterForm = sptr_AddPrinterForm, + .GetPrinterForm = sptr_GetPrinterForm, + .SetPrinterForm = sptr_SetPrinterForm, + .DeletePrinterForm = sptr_DeletePrinterForm, +*/ + /* Printer Job functions */ +/* .EnumJobs = sptr_EnumJobs, + .AddJob = sptr_AddJob, + .ScheduleJob = sptr_ScheduleJob, + .GetJob = sptr_GetJob, + .SetJob = sptr_SetJob, +*/ + /* Printer Printing functions */ +/* .StartDocPrinter = sptr_StartDocPrinter, + .EndDocPrinter = sptr_EndDocPrinter, + .StartPagePrinter = sptr_StartPagePrinter, + .EndPagePrinter = sptr_EndPagePrinter, + .WritePrinter = sptr_WritePrinter, + .ReadPrinter = sptr_ReadPrinter, +*/}; + +NTSTATUS ntptr_simple_ldb_init(void) +{ + NTSTATUS ret; + + ret = ntptr_register(&ntptr_simple_ldb_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register NTPTR '%s' backend!\n", + ntptr_simple_ldb_ops.name)); + } + + return ret; +} diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index deb7d2284f..92e98dcf7d 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -167,6 +167,7 @@ typedef struct char *szWINSPartners; char **dcerpc_ep_servers; char **server_services; + char *ntptr_providor; char *szWinbindUID; char *szWinbindGID; char *szNonUnixAccountRange; @@ -528,6 +529,7 @@ static struct parm_struct parm_table[] = { {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED}, + {"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED}, {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED}, {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED}, @@ -921,6 +923,7 @@ static void init_globals(void) do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup"); do_parameter("server services", "smb rpc nbt ldap cldap web"); + do_parameter("ntptr providor", "simple_ldb"); do_parameter("auth methods", "anonymous sam_ignoredomain"); do_parameter("smb passwd file", dyn_SMB_PASSWD_FILE); do_parameter("private dir", dyn_PRIVATE_DIR); @@ -1175,6 +1178,7 @@ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir) FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir) FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers) FN_GLOBAL_LIST(lp_server_services, &Globals.server_services) +FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor) FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir) FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService) FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv) diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk index c6407e3e53..af3c61cb2e 100644 --- a/source4/rpc_server/config.mk +++ b/source4/rpc_server/config.mk @@ -161,12 +161,12 @@ REQUIRED_SUBSYSTEMS = \ INIT_FUNCTION = dcerpc_server_spoolss_init SUBSYSTEM = DCERPC INIT_OBJ_FILES = \ - rpc_server/spoolss/dcesrv_spoolss.o \ - rpc_server/spoolss/spoolssdb.o + rpc_server/spoolss/dcesrv_spoolss.o REQUIRED_SUBSYSTEMS = \ DCERPC_COMMON \ - NDR_SPOOLSS -# End MODULE dcerpc_lsa + NDR_SPOOLSS \ + NTPTR +# End MODULE dcerpc_spoolss ################################################ ################################################ diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.c b/source4/rpc_server/spoolss/dcesrv_spoolss.c index 5c6506b7c2..7689f084a9 100644 --- a/source4/rpc_server/spoolss/dcesrv_spoolss.c +++ b/source4/rpc_server/spoolss/dcesrv_spoolss.c @@ -25,138 +25,186 @@ #include "rpc_server/dcerpc_server.h" #include "librpc/gen_ndr/ndr_spoolss.h" #include "rpc_server/common/common.h" -#include "rpc_server/spoolss/dcesrv_spoolss.h" +#include "ntptr/ntptr.h" #include "lib/socket/socket.h" #include "smbd/service_stream.h" -#define SPOOLSS_BUFFER_SIZE(fn,level,count,info) \ - ndr_size_##fn##_info(dce_call, level, count, info) +#define SPOOLSS_BUFFER_UNION(fn,info,level) \ + ((info)?ndr_size_##fn(info, level, 0):0) + +#define SPOOLSS_BUFFER_UNION_ARRAY(fn,info,level,count) \ + ((info)?ndr_size_##fn##_info(dce_call, level, count, info):0) #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= r->out.needed)?val_true:val_false) -/* - spoolss_EnumPrinters -*/ -static WERROR spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct spoolss_EnumPrinters *r) +static WERROR spoolss_parse_printer_name(TALLOC_CTX *mem_ctx, const char *name, + const char **_server_name, + const char **_object_name, + enum ntptr_HandleType *_object_type) { - void *spoolss_ctx; - struct ldb_message **msgs; - int count; - int i; - union spoolss_PrinterInfo *info; + char *p; + char *server = NULL; + char *server_unc = NULL; + const char *object = name; - spoolss_ctx = spoolssdb_connect(); - W_ERROR_HAVE_NO_MEMORY(spoolss_ctx); + /* no printername is there it's like open server */ + if (!name) { + *_server_name = NULL; + *_object_name = NULL; + *_object_type = NTPTR_HANDLE_SERVER; + return WERR_OK; + } - count = spoolssdb_search(spoolss_ctx, mem_ctx, NULL, &msgs, NULL, - "(&(objectclass=printer))"); - spoolssdb_close(spoolss_ctx); + /* just "\\" is invalid */ + if (strequal("\\\\", name)) { + return WERR_INVALID_PRINTER_NAME; + } - if (count == 0) return WERR_OK; - if (count < 0) return WERR_GENERAL_FAILURE; + if (strncmp("\\\\", name, 2) == 0) { + server_unc = talloc_strdup(mem_ctx, name); + W_ERROR_HAVE_NO_MEMORY(server_unc); + server = server_unc + 2; - info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count); - W_ERROR_HAVE_NO_MEMORY(info); + /* here we know we have "\\" in front not followed + * by '\0', now see if we have another "\" in the string + */ + p = strchr_m(server, '\\'); + if (!p) { + /* there's no other "\", so it's ("\\%s",server) + */ + *_server_name = server_unc; + *_object_name = NULL; + *_object_type = NTPTR_HANDLE_SERVER; + return WERR_OK; + } + /* 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[0] = '\0'; + /* everything that follows is the printer name */ + p++; + object = p; - switch(r->in.level) { - case 1: - for (i = 0; i < count; i++) { - info[i].info1.flags = samdb_result_uint(msgs[i], "flags", 0); + /* just "" as server is invalid */ + if (strequal(server, "")) { + return WERR_INVALID_PRINTER_NAME; + } + } - info[i].info1.name = samdb_result_string(msgs[i], "name", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info1.name); + /* just "" is invalid */ + if (strequal(object, "")) { + return WERR_INVALID_PRINTER_NAME; + } - info[i].info1.description = samdb_result_string(msgs[i], "description", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info1.description); +#define XCV_PORT ",XcvPort " +#define XCV_MONITOR ",XcvMonitor " + if (strncmp(object, XCV_PORT, strlen(XCV_PORT)) == 0) { + object += strlen(XCV_PORT); - info[i].info1.comment = samdb_result_string(msgs[i], "comment", NULL); + /* just "" is invalid */ + if (strequal(object, "")) { + return WERR_INVALID_PRINTER_NAME; } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinters, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 2: - for (i = 0; i < count; i++) { - info[i].info2.servername = samdb_result_string(msgs[i], "servername", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername); - info[i].info2.printername = samdb_result_string(msgs[i], "printername", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername); + *_server_name = server_unc; + *_object_name = object; + *_object_type = NTPTR_HANDLE_PORT; + return WERR_OK; + } else if (strncmp(object, XCV_MONITOR, strlen(XCV_MONITOR)) == 0) { + object += strlen(XCV_MONITOR); - info[i].info2.sharename = samdb_result_string(msgs[i], "sharename", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename); + /* just "" is invalid */ + if (strequal(object, "")) { + return WERR_INVALID_PRINTER_NAME; + } - info[i].info2.portname = samdb_result_string(msgs[i], "portname", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname); + *_server_name = server_unc; + *_object_name = object; + *_object_type = NTPTR_HANDLE_MONITOR; + return WERR_OK; + } - info[i].info2.drivername = samdb_result_string(msgs[i], "drivername", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername); + *_server_name = server_unc; + *_object_name = object; + *_object_type = NTPTR_HANDLE_PRINTER; + return WERR_OK; +} - info[i].info2.comment = samdb_result_string(msgs[i], "comment", NULL); +/* + * Check server_name is: + * - "" , functions that don't allow "", + * should check that on their own, before calling this function + * - our name (only netbios yet, TODO: need to test dns name!) + * - our ip address of the current use socket + * otherwise return WERR_INVALID_PRINTER_NAME + */ +static WERROR spoolss_check_server_name(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + const char *server_name) +{ + BOOL ret; + const char *ip_str; - info[i].info2.location = samdb_result_string(msgs[i], "location", NULL); + if (!server_name) return WERR_OK; - info[i].info2.devmode = NULL; + ret = strequal("",server_name); + if (ret) return WERR_OK; - info[i].info2.sepfile = samdb_result_string(msgs[i], "sepfile", NULL); + if (strncmp("\\\\", server_name, 2) != 0) { + return WERR_INVALID_PRINTER_NAME; + } - info[i].info2.printprocessor = samdb_result_string(msgs[i], "printprocessor", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor); + server_name += 2; - info[i].info2.datatype = samdb_result_string(msgs[i], "datatype", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype); + ret = strequal(lp_netbios_name(), server_name); + if (ret) return WERR_OK; - info[i].info2.parameters = samdb_result_string(msgs[i], "parameters", NULL); + /* TODO: check dns name here ? */ - info[i].info2.secdesc = NULL; + ip_str = socket_get_my_addr(dce_call->conn->srv_conn->socket, mem_ctx); + W_ERROR_HAVE_NO_MEMORY(ip_str); - info[i].info2.attributes = samdb_result_uint(msgs[i], "attributes", 0); - info[i].info2.priority = samdb_result_uint(msgs[i], "priority", 0); - info[i].info2.defaultpriority = samdb_result_uint(msgs[i], "defaultpriority", 0); - info[i].info2.starttime = samdb_result_uint(msgs[i], "starttime", 0); - info[i].info2.untiltime = samdb_result_uint(msgs[i], "untiltime", 0); - info[i].info2.status = samdb_result_uint(msgs[i], "status", 0); - info[i].info2.cjobs = samdb_result_uint(msgs[i], "cjobs", 0); - info[i].info2.averageppm = samdb_result_uint(msgs[i], "averageppm", 0); - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinters, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 4: - for (i = 0; i < count; i++) { - info[i].info4.printername = samdb_result_string(msgs[i], "printername", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername); - - info[i].info4.servername = samdb_result_string(msgs[i], "servername", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername); - - info[i].info4.attributes = samdb_result_uint(msgs[i], "attributes", 0); - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinters, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 5: - for (i = 0; i < count; i++) { - info[i].info5.printername = samdb_result_string(msgs[i], "name", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername); - - info[i].info5.portname = samdb_result_string(msgs[i], "port", ""); - W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname); - - info[i].info5.attributes = samdb_result_uint(msgs[i], "attributes", 0); - info[i].info5.device_not_selected_timeout = samdb_result_uint(msgs[i], "device_not_selected_timeout", 0); - info[i].info5.transmission_retry_timeout = samdb_result_uint(msgs[i], "transmission_retry_timeout", 0); - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinters, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - } + ret = strequal(ip_str, server_name); + if (ret) return WERR_OK; + + return WERR_INVALID_PRINTER_NAME; +} + +static NTSTATUS dcerpc_spoolss_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface) +{ + NTSTATUS status; + struct ntptr_context *ntptr; + + status = ntptr_init_context(dce_call->context, lp_ntptr_providor(), &ntptr); + NT_STATUS_NOT_OK_RETURN(status); + + dce_call->context->private = ntptr; + + return NT_STATUS_OK; +} + +#define DCESRV_INTERFACE_SPOOLSS_BIND dcerpc_spoolss_bind + +/* + spoolss_EnumPrinters +*/ +static WERROR spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct spoolss_EnumPrinters *r) +{ + struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context); + WERROR status; - return WERR_UNKNOWN_LEVEL; + status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server); + W_ERROR_NOT_OK_RETURN(status); + + status = ntptr_EnumPrinters(ntptr, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); + + r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinters, r->out.info, r->in.level, r->out.count); + r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0); + return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, @@ -279,64 +327,19 @@ static WERROR spoolss_AddPrinterDriver(struct dcesrv_call_state *dce_call, TALLO static WERROR spoolss_EnumPrinterDrivers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_EnumPrinterDrivers *r) { - union spoolss_DriverInfo *info; - int count; - int i; - - count = 0; - - if (count == 0) return WERR_OK; - if (count < 0) return WERR_GENERAL_FAILURE; + struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context); + WERROR status; - info = talloc_array(mem_ctx, union spoolss_DriverInfo, count); - W_ERROR_HAVE_NO_MEMORY(info); + status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server); + W_ERROR_NOT_OK_RETURN(status); - switch (r->in.level) { - case 1: - for (i=0; i < count; i++) { - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 2: - for (i=0; i < count; i++) { - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 3: - for (i=0; i < count; i++) { - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 4: - for (i=0; i < count; i++) { - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 5: - for (i=0; i < count; i++) { - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 6: - for (i=0; i < count; i++) { - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - } + status = ntptr_EnumPrinterDrivers(ntptr, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); - return WERR_UNKNOWN_LEVEL; + r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinterDrivers, r->out.info, r->in.level, r->out.count); + r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0); + return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -356,42 +359,17 @@ static WERROR spoolss_GetPrinterDriver(struct dcesrv_call_state *dce_call, TALLO static WERROR spoolss_GetPrinterDriverDirectory(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_GetPrinterDriverDirectory *r) { - union spoolss_DriverDirectoryInfo *info; - const char *prefix; - const char *postfix; - - /* - * NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a - * are ignoring the r->in.level completely, so we do :-) - */ - - /* - * TODO: check the server name is ours - * - if it's a invalid UNC then return WERR_INVALID_NAME - * - if it's the wrong host name return WERR_INVALID_PARAM - * - if it's "" then we need to return a local WINDOWS path - */ - if (strcmp("", r->in.server) == 0) { - prefix = "C:\\DRIVERS"; - } else { - prefix = talloc_asprintf(mem_ctx, "%s\\print$", r->in.server); - W_ERROR_HAVE_NO_MEMORY(prefix); - } - - if (strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) { - postfix = "W32X86"; - } else { - return WERR_INVALID_ENVIRONMENT; - } + struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context); + WERROR status; - info = talloc(mem_ctx, union spoolss_DriverDirectoryInfo); - W_ERROR_HAVE_NO_MEMORY(info); + status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server); + W_ERROR_NOT_OK_RETURN(status); - info->info1.directory_name = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix); - W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name); + status = ntptr_GetPrinterDriverDirectory(ntptr, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); - r->out.needed = ndr_size_spoolss_DriverDirectoryInfo(info, r->in.level, 0); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); + r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, r->out.info, r->in.level); + r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -532,67 +510,28 @@ static WERROR spoolss_ScheduleJob(struct dcesrv_call_state *dce_call, TALLOC_CTX static WERROR spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_GetPrinterData *r) { + struct ntptr_GenericHandle *handle; struct dcesrv_handle *h; - WERROR status = WERR_INVALID_PARAM; - enum spoolss_PrinterDataType type = SPOOLSS_PRINTER_DATA_TYPE_NULL; - union spoolss_PrinterData data; + WERROR status; DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); - - if (h->wire_handle.handle_type == SPOOLSS_HANDLE_SERVER) { - /* TODO: do access check here */ - - if (strcmp("W3SvcInstalled", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - data.value = 0; - status = WERR_OK; - } else if (strcmp("BeepEnabled", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - data.value = 0; - status = WERR_OK; - } else if (strcmp("EventLog", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - data.value = 0; - status = WERR_OK; - } else if (strcmp("NetPopup", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - data.value = 0; - status = WERR_OK; - } else if (strcmp("NetPopupToComputer", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - data.value = 0; - status = WERR_OK; - } else if (strcmp("MajorVersion", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - data.value = 3; - status = WERR_OK; - } else if (strcmp("MinorVersion", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - data.value = 0; - status = WERR_OK; - } else if (strcmp("DefaultSpoolDirectory", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_STRING; - data.string = "C:\\PRINTERS"; - status = WERR_OK; - } else if (strcmp("Architecture", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_STRING; - data.string = SPOOLSS_ARCHITECTURE_NT_X86; - status = WERR_OK; - } else if (strcmp("DsPresent", r->in.value_name) == 0) { - type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - data.value = 1; - status = WERR_OK; - } + handle = talloc_get_type(h->data, struct ntptr_GenericHandle); + + switch (handle->type) { + case NTPTR_HANDLE_SERVER: + status = ntptr_GetPrintServerData(handle, mem_ctx, r); + break; + default: + status = WERR_FOOBAR; + break; } - if (W_ERROR_IS_OK(status)) { - r->out.needed = ndr_size_spoolss_PrinterData(&data, type, 0); - r->out.type = SPOOLSS_BUFFER_OK(type, SPOOLSS_PRINTER_DATA_TYPE_NULL); - r->out.data = SPOOLSS_BUFFER_OK(data, data); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA); - } + W_ERROR_NOT_OK_RETURN(status); - return status; + r->out.needed = ndr_size_spoolss_PrinterData(&r->out.data, r->out.type, 0); + r->out.type = SPOOLSS_BUFFER_OK(r->out.type, SPOOLSS_PRINTER_DATA_TYPE_NULL); + r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data); + return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA); } @@ -662,7 +601,29 @@ static WERROR spoolss_DeleteForm(struct dcesrv_call_state *dce_call, TALLOC_CTX static WERROR spoolss_GetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_GetForm *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + struct ntptr_GenericHandle *handle; + struct dcesrv_handle *h; + WERROR status; + + DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); + handle = talloc_get_type(h->data, struct ntptr_GenericHandle); + + switch (handle->type) { + case NTPTR_HANDLE_SERVER: + status = ntptr_GetPrintServerForm(handle, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); + break; + case NTPTR_HANDLE_PRINTER: + status = ntptr_GetPrinterForm(handle, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); + break; + default: + return WERR_FOOBAR; + } + + r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, r->out.info, r->in.level); + r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -682,44 +643,30 @@ static WERROR spoolss_SetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *me static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_EnumForms *r) { - union spoolss_FormInfo *info; - int count; - int i; + struct ntptr_GenericHandle *handle; struct dcesrv_handle *h; + WERROR status; DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); - - count = 1; - - if (count == 0) return WERR_OK; - if (count < 0) return WERR_GENERAL_FAILURE; - - info = talloc_array(mem_ctx, union spoolss_FormInfo, count); - W_ERROR_HAVE_NO_MEMORY(info); - - switch (r->in.level) { - case 1: - for (i=0; i < count; i++) { - info[i].info1.flags = SPOOLSS_FORM_PRINTER; - - info[i].info1.form_name = talloc_strdup(mem_ctx, "Letter"); - W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name); - - info[i].info1.size.width = 0x34b5c; - info[i].info1.size.height = 0x44368; - - info[i].info1.area.left = 0; - info[i].info1.area.top = 0; - info[i].info1.area.right = 0x34b5c; - info[i].info1.area.bottom = 0x44368; - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumForms, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); + handle = talloc_get_type(h->data, struct ntptr_GenericHandle); + + switch (handle->type) { + case NTPTR_HANDLE_SERVER: + status = ntptr_EnumPrintServerForms(handle, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); + break; + case NTPTR_HANDLE_PRINTER: + status = ntptr_EnumPrinterForms(handle, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); + break; + default: + return WERR_FOOBAR; } - return WERR_UNKNOWN_LEVEL; + r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, r->out.info, r->in.level, r->out.count); + r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0); + return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -729,49 +676,19 @@ static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX * static WERROR spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_EnumPorts *r) { - union spoolss_PortInfo *info; - int count; - int i; - - count = 1; + struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context); + WERROR status; - if (count == 0) return WERR_OK; - if (count < 0) return WERR_GENERAL_FAILURE; + status = spoolss_check_server_name(dce_call, mem_ctx, r->in.servername); + W_ERROR_NOT_OK_RETURN(status); - info = talloc_array(mem_ctx, union spoolss_PortInfo, count); - W_ERROR_HAVE_NO_MEMORY(info); + status = ntptr_EnumPorts(ntptr, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); - switch (r->in.level) { - case 1: - for (i=0; i < count; i++) { - info[i].info1.port_name = talloc_strdup(mem_ctx, "Samba Printer Port"); - W_ERROR_HAVE_NO_MEMORY(info[i].info1.port_name); - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPorts, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 2: - for (i=0; i < count; i++) { - info[i].info2.port_name = talloc_strdup(mem_ctx, "Samba Printer Port"); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.port_name); - - info[i].info2.monitor_name = talloc_strdup(mem_ctx, "Local Monitor"); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name); - - info[i].info2.description = talloc_strdup(mem_ctx, "Local Port"); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.description); - - info[i].info2.port_type = SPOOLSS_PORT_TYPE_WRITE; - info[i].info2.reserved = 0; - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPorts, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - } - - return WERR_UNKNOWN_LEVEL; + r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPorts, r->out.info, r->in.level, r->out.count); + r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0); + return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -781,46 +698,19 @@ static WERROR spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLOC_CTX * static WERROR spoolss_EnumMonitors(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_EnumMonitors *r) { - union spoolss_MonitorInfo *info; - int count; - int i; - - count = 1; - - if (count == 0) return WERR_OK; - if (count < 0) return WERR_GENERAL_FAILURE; + struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context); + WERROR status; - info = talloc_array(mem_ctx, union spoolss_MonitorInfo, count); - W_ERROR_HAVE_NO_MEMORY(info); + status = spoolss_check_server_name(dce_call, mem_ctx, r->in.servername); + W_ERROR_NOT_OK_RETURN(status); - switch (r->in.level) { - case 1: - for (i=0; i < count; i++) { - info[i].info1.monitor_name = talloc_strdup(mem_ctx, "Standard TCP/IP Port"); - W_ERROR_HAVE_NO_MEMORY(info[i].info1.monitor_name); - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumMonitors, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - case 2: - for (i=0; i < count; i++) { - info[i].info2.monitor_name = talloc_strdup(mem_ctx, "Standard TCP/IP Port"); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name); - - info[i].info2.environment = talloc_strdup(mem_ctx, SPOOLSS_ARCHITECTURE_NT_X86); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.environment); - - info[i].info2.dll_name = talloc_strdup(mem_ctx, "tcpmon.dll"); - W_ERROR_HAVE_NO_MEMORY(info[i].info2.dll_name); - } - r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumMonitors, r->in.level, count, info); - r->out.info = SPOOLSS_BUFFER_OK(info, NULL); - r->out.count = SPOOLSS_BUFFER_OK(count, 0); - return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); - } + status = ntptr_EnumMonitors(ntptr, mem_ctx, r); + W_ERROR_NOT_OK_RETURN(status); - return WERR_UNKNOWN_LEVEL; + r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumMonitors, r->out.info, r->in.level, r->out.count); + r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0); + return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -1110,7 +1000,12 @@ static WERROR spoolss_ResetPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_ static WERROR spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r) { - return WERR_NOT_SUPPORTED; + /* + * TODO: for now just return ok, + * to keep the w2k3 PrintServer + * happy to allow to open the Add Printer GUI + */ + return WERR_OK; } @@ -1143,175 +1038,57 @@ static WERROR spoolss_44(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } - -static WERROR spoolss_OpenPrinterEx_server(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct spoolss_OpenPrinterEx *r, - const char *server_name) -{ - struct spoolss_handle_server *state; - struct dcesrv_handle *handle; - BOOL ret; - - /* Check printername is our name or our ip address - */ - ret = strequal(server_name, lp_netbios_name()); - if (!ret) { - const char *ip = socket_get_my_addr(dce_call->conn->srv_conn->socket, mem_ctx); - W_ERROR_HAVE_NO_MEMORY(ip); - - ret = strequal(server_name, ip); - if (!ret) { - return WERR_INVALID_PRINTER_NAME; - } - } - - /* TODO: do access check here */ - - handle = dcesrv_handle_new(dce_call->context, SPOOLSS_HANDLE_SERVER); - W_ERROR_HAVE_NO_MEMORY(handle); - - 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; - - return WERR_OK; -} - -static WERROR spoolss_OpenPrinterEx_port(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct spoolss_OpenPrinterEx *r, - const char *server_name, - const char *port_name) -{ - DEBUG(1, ("looking for port [%s] (server[%s])\n", port_name, server_name)); - - return WERR_INVALID_PRINTER_NAME; -} - -static WERROR spoolss_OpenPrinterEx_monitor(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct spoolss_OpenPrinterEx *r, - const char *server_name, - const char *monitor_name) -{ - if (strequal("Standard TCP/IP Port", monitor_name)) { - struct dcesrv_handle *handle; - - handle = dcesrv_handle_new(dce_call->context, SPOOLSS_HANDLE_MONITOR); - W_ERROR_HAVE_NO_MEMORY(handle); - - handle->data = NULL; - - *r->out.handle = handle->wire_handle; - - return WERR_OK; - } - - DEBUG(1, ("looking for monitor [%s] (server[%s])\n", monitor_name, server_name)); - - return WERR_INVALID_PRINTER_NAME; -} - -static WERROR spoolss_OpenPrinterEx_printer(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - struct spoolss_OpenPrinterEx *r, - const char *server_name, - const char *printer_name) -{ - DEBUG(3, ("looking for printer [%s] (server[%s])\n", printer_name, server_name)); - - return WERR_INVALID_PRINTER_NAME; -} - /* spoolss_OpenPrinterEx */ static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_OpenPrinterEx *r) { - char *p; - char *server = NULL; - const char *object = r->in.printername; - ZERO_STRUCTP(r->out.handle); - - /* no printername is there it's like open server */ - if (!r->in.printername) { - return spoolss_OpenPrinterEx_server(dce_call, mem_ctx, r, NULL); - } - - /* just "\\" is invalid */ - if (strequal(r->in.printername, "\\\\")) { - return WERR_INVALID_PRINTER_NAME; - } - - if (strncmp(r->in.printername, "\\\\", 2) == 0) { - server = talloc_strdup(mem_ctx, r->in.printername + 2); - W_ERROR_HAVE_NO_MEMORY(server); - - /* here we know we have "\\" in front not followed - * by '\0', now see if we have another "\" in the string - */ - p = strchr_m(server, '\\'); - if (!p) { - /* there's no other "\", so it's ("\\%s",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[0] = '\0'; - /* everything that follows is the printer name */ - p++; - object = p; + struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context); + struct ntptr_GenericHandle *handle; + struct dcesrv_handle *h; + const char *server; + const char *object; + enum ntptr_HandleType type; + WERROR status; - /* just "" as server is invalid */ - if (strequal(server, "")) { - DEBUG(2,("OpenPrinterEx invalid print server: [%s][%s][%s]\n", r->in.printername, server, object)); - return WERR_INVALID_PRINTER_NAME; - } - } + ZERO_STRUCTP(r->out.handle); - /* just "" is invalid */ - if (strequal(object, "")) { - DEBUG(2,("OpenPrinterEx invalid object: [%s][%s][%s]\n", r->in.printername, server, object)); - return WERR_INVALID_PRINTER_NAME; + status = spoolss_parse_printer_name(mem_ctx, r->in.printername, &server, &object, &type); + W_ERROR_NOT_OK_RETURN(status); + + status = spoolss_check_server_name(dce_call, mem_ctx, server); + W_ERROR_NOT_OK_RETURN(status); + + switch (type) { + case NTPTR_HANDLE_SERVER: + status = ntptr_OpenPrintServer(ntptr, mem_ctx, r, server, &handle); + W_ERROR_NOT_OK_RETURN(status); + break; + case NTPTR_HANDLE_PORT: + status = ntptr_OpenPort(ntptr, mem_ctx, r, object, &handle); + W_ERROR_NOT_OK_RETURN(status); + break; + case NTPTR_HANDLE_MONITOR: + status = ntptr_OpenMonitor(ntptr, mem_ctx, r, object, &handle); + W_ERROR_NOT_OK_RETURN(status); + break; + case NTPTR_HANDLE_PRINTER: + status = ntptr_OpenPrinter(ntptr, mem_ctx, r, object, &handle); + W_ERROR_NOT_OK_RETURN(status); + break; + default: + return WERR_FOOBAR; } - DEBUG(3,("OpenPrinterEx object: [%s][%s][%s]\n", r->in.printername, server, object)); - -#define XCV_PORT ",XcvPort " -#define XCV_MONITOR ",XcvMonitor " - if (strncmp(object, XCV_PORT, strlen(XCV_PORT)) == 0) { - object += strlen(XCV_PORT); - - /* just "" is invalid */ - if (strequal(object, "")) { - DEBUG(2,("OpenPrinterEx invalid port: [%s][%s][%s]\n", r->in.printername, server, object)); - return WERR_INVALID_PRINTER_NAME; - } + h = dcesrv_handle_new(dce_call->context, handle->type); + W_ERROR_HAVE_NO_MEMORY(h); - return spoolss_OpenPrinterEx_port(dce_call, mem_ctx, r, server, object); - } else if (strncmp(object, XCV_MONITOR, strlen(XCV_MONITOR)) == 0) { - object += strlen(XCV_MONITOR); + h->data = talloc_steal(h, handle); - /* just "" is invalid */ - if (strequal(object, "")) { - DEBUG(2,("OpenPrinterEx invalid monitor: [%s][%s][%s]\n", r->in.printername, server, object)); - return WERR_INVALID_PRINTER_NAME; - } + *r->out.handle = h->wire_handle; - return spoolss_OpenPrinterEx_monitor(dce_call, mem_ctx, r, server, object); - } - - return spoolss_OpenPrinterEx_printer(dce_call, mem_ctx, r, server, object); + return WERR_OK; } /* diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.h b/source4/rpc_server/spoolss/dcesrv_spoolss.h deleted file mode 100644 index 0b3f69ca2a..0000000000 --- a/source4/rpc_server/spoolss/dcesrv_spoolss.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - endpoint server for the spoolss pipe - definitions - - Copyright (C) Tim Potter 2004 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - this type allows us to distinguish handle types -*/ -enum spoolss_handle_type { - SPOOLSS_HANDLE_SERVER, - SPOOLSS_HANDLE_PRINTER, - SPOOLSS_HANDLE_PORT, - SPOOLSS_HANDLE_MONITOR -}; - -/* - state asscoiated with a spoolss_OpenPrinter{,Ex}() operation -*/ -struct spoolss_handle_server { - uint32_t access_mask; -}; diff --git a/source4/rpc_server/spoolss/spoolssdb.c b/source4/rpc_server/spoolss/spoolssdb.c deleted file mode 100644 index cec9ade0d4..0000000000 --- a/source4/rpc_server/spoolss/spoolssdb.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - interface functions for the spoolss database - - Copyright (C) Andrew Tridgell 2004 - Copyright (C) Tim Potter 2004 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "lib/ldb/include/ldb.h" - -struct spoolssdb_context { - struct ldb_context *ldb; -}; - -/* - this is used to catch debug messages from ldb -*/ -static void spoolssdb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0); -static void spoolssdb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) -{ - char *s = NULL; - if (DEBUGLEVEL < 4 && level > LDB_DEBUG_WARNING) { - return; - } - vasprintf(&s, fmt, ap); - if (!s) return; - DEBUG(level, ("spoolssdb: %s\n", s)); - free(s); -} - -/* - connect to the spoolss database - return an opaque context pointer on success, or NULL on failure - */ -void *spoolssdb_connect(void) -{ - struct spoolssdb_context *ctx; - /* - the way that unix fcntl locking works forces us to have a - static ldb handle here rather than a much more sensible - approach of having the ldb handle as part of the - spoolss_OpenPrinter() pipe state. Otherwise we would try to open - the ldb more than once, and tdb would rightly refuse the - second open due to the broken nature of unix locking. - */ - static struct ldb_context *static_spoolss_db; - - if (static_spoolss_db == NULL) { - static_spoolss_db = ldb_connect(lp_spoolss_url(), 0, NULL); - if (static_spoolss_db == NULL) { - return NULL; - } - } - - ldb_set_debug(static_spoolss_db, spoolssdb_debug, NULL); - - ctx = malloc_p(struct spoolssdb_context); - if (!ctx) { - errno = ENOMEM; - return NULL; - } - - ctx->ldb = static_spoolss_db; - - return ctx; -} - -/* close a connection to the spoolss db */ -void spoolssdb_close(void *ctx) -{ - struct spoolssdb_context *spoolss_ctx = ctx; - /* we don't actually close due to broken posix locking semantics */ - spoolss_ctx->ldb = NULL; - free(spoolss_ctx); -} - -/* - search the db for the specified attributes - varargs variant -*/ -int spoolssdb_search(void *ctx, - TALLOC_CTX *mem_ctx, - const char *basedn, - struct ldb_message ***res, - const char * const *attrs, - const char *format, ...) _PRINTF_ATTRIBUTE(6,7) -{ - struct spoolssdb_context *spoolss_ctx = ctx; - va_list ap; - int count; - - va_start(ap, format); - count = gendb_search_v(spoolss_ctx->ldb, mem_ctx, basedn, res, attrs, format, ap); - va_end(ap); - - return count; -} - -- cgit