📄 ntptr_simple_ldb.c
字号:
/* 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 3 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, see <http://www.gnu.org/licenses/>.*//* 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 "auth/auth.h"#include "dsdb/samdb/samdb.h"#include "ldb_wrap.h"#include "util/util_ldb.h"#include "rpc_server/common/common.h"#include "param/param.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, struct event_context *ev_ctx, struct loadparm_context *lp_ctx){ return ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx, lp_spoolss_url(lp_ctx), system_session(mem_ctx, lp_ctx), NULL, 0, NULL);}static int sptr_db_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *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, struct ldb_dn *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;}#define SET_STRING(ldb, mod, attr, value) do { \ if (value == NULL) return WERR_INVALID_PARAM; \ if (samdb_msg_add_string(ldb, (TALLOC_CTX *)mod, mod, attr, value) != 0) { \ return WERR_NOMEM; \ } \} while (0)#define SET_UINT(ldb, mod, attr, value) do { \ if (samdb_msg_add_uint(ldb, (TALLOC_CTX *)mod, mod, attr, value) != 0) { \ return WERR_NOMEM; \ } \} while (0)static NTSTATUS sptr_init_context(struct ntptr_context *ntptr){ struct ldb_context *sptr_db = sptr_db_connect(ntptr, ntptr->ev_ctx, ntptr->lp_ctx); 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->object_name = talloc_strdup(server, server_name); W_ERROR_HAVE_NO_MEMORY(server->object_name); server->access_mask = 0; 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; } else if (strcmp("OSVersion", r->in.value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersion os; os.major = dcesrv_common_get_version_major(mem_ctx, server->ntptr->lp_ctx); os.minor = dcesrv_common_get_version_minor(mem_ctx, server->ntptr->lp_ctx); os.build = dcesrv_common_get_version_build(mem_ctx, server->ntptr->lp_ctx); os.extra_string = ""; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(server->ntptr->lp_ctx), &os, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } r->out.type = SPOOLSS_PRINTER_DATA_TYPE_BINARY; r->out.data.binary = blob; return WERR_OK; } else if (strcmp("OSVersionEx", r->in.value_name) == 0) { DATA_BLOB blob; enum ndr_err_code ndr_err; struct spoolss_OSVersionEx os_ex; os_ex.major = dcesrv_common_get_version_major(mem_ctx, server->ntptr->lp_ctx); os_ex.minor = dcesrv_common_get_version_minor(mem_ctx, server->ntptr->lp_ctx); os_ex.build = dcesrv_common_get_version_build(mem_ctx, server->ntptr->lp_ctx); os_ex.extra_string = ""; os_ex.unknown2 = 0; os_ex.unknown3 = 0; ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(server->ntptr->lp_ctx), &os_ex, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersionEx); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return WERR_GENERAL_FAILURE; } r->out.type = SPOOLSS_PRINTER_DATA_TYPE_BINARY; r->out.data.binary = blob; return WERR_OK; } else if (strcmp("DNSMachineName", r->in.value_name) == 0) { if (!lp_realm(server->ntptr->lp_ctx)) return WERR_INVALID_PARAM; r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; r->out.data.string = talloc_asprintf(mem_ctx, "%s.%s", lp_netbios_name(server->ntptr->lp_ctx), lp_realm(server->ntptr->lp_ctx)); W_ERROR_HAVE_NO_MEMORY(r->out.data.string); 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, ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,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_BUILTIN); info[i].info1.form_name = samdb_result_string(msgs[i], "form-name", NULL); W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name); info[i].info1.size.width = samdb_result_uint(msgs[i], "size-width", 0); info[i].info1.size.height = samdb_result_uint(msgs[i], "size-height", 0); 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], "area-right", 0); info[i].info1.area.bottom = samdb_result_uint(msgs[i], "area-bottom", 0); } break; default: return WERR_UNKNOWN_LEVEL; } r->out.info = info; r->out.count = count; return WERR_OK;}static WERROR sptr_AddPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, struct spoolss_AddForm *r){ struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); struct ldb_message *msg,**msgs; const char * const attrs[] = {"flags", NULL }; int count, ret; /* TODO: do checks access here * if (!(server->access_mask & desired_access)) { * return WERR_FOOBAR; * } */ switch (r->in.level) { case 1: if (!r->in.info.info1) { return WERR_FOOBAR; } count = sptr_db_search(sptr_db, mem_ctx, ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"), &msgs, attrs, "(&(form-name=%s)(objectClass=form))", r->in.info.info1->form_name); if (count == 1) return WERR_FOOBAR; if (count > 1) return WERR_FOOBAR; if (count < 0) return WERR_GENERAL_FAILURE; if (r->in.info.info1->flags != SPOOLSS_FORM_USER) { return WERR_FOOBAR; } msg = ldb_msg_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(msg); /* add core elements to the ldb_message for the Form */ msg->dn = ldb_dn_new_fmt(msg, sptr_db, "form-name=%s,CN=Forms,CN=PrintServer", r->in.info.info1->form_name); SET_STRING(sptr_db, msg, "objectClass", "form"); SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags); SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name); SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width); SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height); SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left); SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top); SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right); SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom); break; default: return WERR_UNKNOWN_LEVEL; } ret = ldb_add(sptr_db, msg); if (ret != 0) { return WERR_FOOBAR; } return WERR_OK;}static WERROR sptr_SetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, struct spoolss_SetForm *r){ struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); struct ldb_message *msg,**msgs; const char * const attrs[] = { "flags", NULL}; int count, ret; enum spoolss_FormFlags flags; /* TODO: do checks access here * if (!(server->access_mask & desired_access)) { * return WERR_FOOBAR; * } */ switch (r->in.level) { case 1: if (!r->in.info.info1) { return WERR_FOOBAR; } count = sptr_db_search(sptr_db, mem_ctx, ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"), &msgs, attrs, "(&(form-name=%s)(objectClass=form))", r->in.info.info1->form_name); if (count == 0) return WERR_FOOBAR; if (count > 1) return WERR_FOOBAR; if (count < 0) return WERR_GENERAL_FAILURE; flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN); if (flags != SPOOLSS_FORM_USER) { return WERR_FOOBAR; } msg = ldb_msg_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(msg); /* add core elements to the ldb_message for the user */ msg->dn = msgs[0]->dn; SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags); SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name); SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width); SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height); SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left); SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top); SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right); SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom); break; default: return WERR_UNKNOWN_LEVEL; } ret = samdb_replace(sptr_db, mem_ctx, msg); if (ret != 0) { return WERR_FOOBAR; } return WERR_OK;}static WERROR sptr_DeletePrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, struct spoolss_DeleteForm *r){ struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); struct ldb_message **msgs; const char * const attrs[] = { "flags", NULL}; int count, ret; enum spoolss_FormFlags flags; /* TODO: do checks access here * if (!(server->access_mask & desired_access)) { * return WERR_FOOBAR; * } */ if (!r->in.form_name) { return WERR_FOOBAR; } count = sptr_db_search(sptr_db, mem_ctx, ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"), &msgs, attrs, "(&(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; flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN); if (flags != SPOOLSS_FORM_USER) { return WERR_FOOBAR; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -