1/* 2 Unix SMB/CIFS implementation. 3 4 Simple LDB NTPTR backend 5 6 Copyright (C) Stefan (metze) Metzmacher 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21/* 22 This implements a NTPTR backend that store 23 all objects (Printers, Ports, Monitors, PrinterDrivers ...) 24 in a ldb database, but doesn't do real printing. 25 26 This is just used for testing how some of 27 the SPOOLSS protocol details should work 28*/ 29 30#include "includes.h" 31#include "ntptr/ntptr.h" 32#include "librpc/gen_ndr/ndr_spoolss.h" 33#include "lib/ldb/include/ldb.h" 34#include "auth/auth.h" 35#include "dsdb/samdb/samdb.h" 36#include "ldb_wrap.h" 37#include "../lib/util/util_ldb.h" 38#include "rpc_server/common/common.h" 39#include "param/param.h" 40 41/* 42 connect to the SPOOLSS database 43 return a ldb_context pointer on success, or NULL on failure 44 */ 45static struct ldb_context *sptr_db_connect(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, struct loadparm_context *lp_ctx) 46{ 47 return ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx, lp_spoolss_url(lp_ctx), system_session(mem_ctx, lp_ctx), 48 NULL, 0, NULL); 49} 50 51static int sptr_db_search(struct ldb_context *ldb, 52 TALLOC_CTX *mem_ctx, 53 struct ldb_dn *basedn, 54 struct ldb_message ***res, 55 const char * const *attrs, 56 const char *format, ...) PRINTF_ATTRIBUTE(6,7); 57 58static int sptr_db_search(struct ldb_context *ldb, 59 TALLOC_CTX *mem_ctx, 60 struct ldb_dn *basedn, 61 struct ldb_message ***res, 62 const char * const *attrs, 63 const char *format, ...) 64{ 65 va_list ap; 66 int count; 67 68 va_start(ap, format); 69 count = gendb_search_v(ldb, mem_ctx, basedn, res, attrs, format, ap); 70 va_end(ap); 71 72 return count; 73} 74 75#define SET_STRING(ldb, mod, attr, value) do { \ 76 if (value == NULL) return WERR_INVALID_PARAM; \ 77 if (samdb_msg_add_string(ldb, (TALLOC_CTX *)mod, mod, attr, value) != 0) { \ 78 return WERR_NOMEM; \ 79 } \ 80} while (0) 81 82#define SET_UINT(ldb, mod, attr, value) do { \ 83 if (samdb_msg_add_uint(ldb, (TALLOC_CTX *)mod, mod, attr, value) != 0) { \ 84 return WERR_NOMEM; \ 85 } \ 86} while (0) 87 88static NTSTATUS sptr_init_context(struct ntptr_context *ntptr) 89{ 90 struct ldb_context *sptr_db = sptr_db_connect(ntptr, ntptr->ev_ctx, ntptr->lp_ctx); 91 NT_STATUS_HAVE_NO_MEMORY(sptr_db); 92 93 ntptr->private_data = sptr_db; 94 95 return NT_STATUS_OK; 96} 97 98/* PrintServer functions */ 99static WERROR sptr_OpenPrintServer(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, 100 struct spoolss_OpenPrinterEx *r, 101 const char *server_name, 102 struct ntptr_GenericHandle **_server) 103{ 104 struct ntptr_GenericHandle *server; 105 106 /* TODO: do access check here! */ 107 108 server = talloc(mem_ctx, struct ntptr_GenericHandle); 109 W_ERROR_HAVE_NO_MEMORY(server); 110 111 server->type = NTPTR_HANDLE_SERVER; 112 server->ntptr = ntptr; 113 server->object_name = talloc_strdup(server, server_name); 114 W_ERROR_HAVE_NO_MEMORY(server->object_name); 115 server->access_mask = 0; 116 server->private_data = NULL; 117 118 *_server = server; 119 return WERR_OK; 120} 121 122/* 123 * PrintServer PrinterData functions 124 */ 125 126static WERROR sptr_PrintServerData(struct ntptr_GenericHandle *server, 127 TALLOC_CTX *mem_ctx, 128 const char *value_name, 129 union spoolss_PrinterData *r, 130 enum winreg_Type *type) 131{ 132 struct dcerpc_server_info *server_info = lp_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx); 133 if (strcmp("W3SvcInstalled", value_name) == 0) { 134 *type = REG_DWORD; 135 r->value = 0; 136 return WERR_OK; 137 } else if (strcmp("BeepEnabled", value_name) == 0) { 138 *type = REG_DWORD; 139 r->value = 0; 140 return WERR_OK; 141 } else if (strcmp("EventLog", value_name) == 0) { 142 *type = REG_DWORD; 143 r->value = 0; 144 return WERR_OK; 145 } else if (strcmp("NetPopup", value_name) == 0) { 146 *type = REG_DWORD; 147 r->value = 0; 148 return WERR_OK; 149 } else if (strcmp("NetPopupToComputer", value_name) == 0) { 150 *type = REG_DWORD; 151 r->value = 0; 152 return WERR_OK; 153 } else if (strcmp("MajorVersion", value_name) == 0) { 154 *type = REG_DWORD; 155 r->value = 3; 156 return WERR_OK; 157 } else if (strcmp("MinorVersion", value_name) == 0) { 158 *type = REG_DWORD; 159 r->value = 0; 160 return WERR_OK; 161 } else if (strcmp("DefaultSpoolDirectory", value_name) == 0) { 162 *type = REG_SZ; 163 r->string = talloc_strdup(mem_ctx, "C:\\PRINTERS"); 164 W_ERROR_HAVE_NO_MEMORY(r->string); 165 return WERR_OK; 166 } else if (strcmp("Architecture", value_name) == 0) { 167 *type = REG_SZ; 168 r->string = talloc_strdup(mem_ctx, SPOOLSS_ARCHITECTURE_NT_X86); 169 W_ERROR_HAVE_NO_MEMORY(r->string); 170 return WERR_OK; 171 } else if (strcmp("DsPresent", value_name) == 0) { 172 *type = REG_DWORD; 173 r->value = 1; 174 return WERR_OK; 175 } else if (strcmp("OSVersion", value_name) == 0) { 176 DATA_BLOB blob; 177 enum ndr_err_code ndr_err; 178 struct spoolss_OSVersion os; 179 180 os.major = server_info->version_major; 181 os.minor = server_info->version_minor; 182 os.build = server_info->version_build; 183 os.extra_string = ""; 184 185 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); 186 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 187 return WERR_GENERAL_FAILURE; 188 } 189 190 *type = REG_BINARY; 191 r->binary = blob; 192 return WERR_OK; 193 } else if (strcmp("OSVersionEx", value_name) == 0) { 194 DATA_BLOB blob; 195 enum ndr_err_code ndr_err; 196 struct spoolss_OSVersionEx os_ex; 197 198 os_ex.major = server_info->version_major; 199 os_ex.minor = server_info->version_minor; 200 os_ex.build = server_info->version_build; 201 os_ex.extra_string = ""; 202 os_ex.service_pack_major= 0; 203 os_ex.service_pack_minor= 0; 204 os_ex.suite_mask = 0; 205 os_ex.product_type = 0; 206 os_ex.reserved = 0; 207 208 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); 209 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 210 return WERR_GENERAL_FAILURE; 211 } 212 213 *type = REG_BINARY; 214 r->binary = blob; 215 return WERR_OK; 216 } else if (strcmp("DNSMachineName", value_name) == 0) { 217 if (!lp_realm(server->ntptr->lp_ctx)) return WERR_INVALID_PARAM; 218 219 *type = REG_SZ; 220 r->string = talloc_asprintf(mem_ctx, "%s.%s", 221 lp_netbios_name(server->ntptr->lp_ctx), 222 lp_realm(server->ntptr->lp_ctx)); 223 W_ERROR_HAVE_NO_MEMORY(r->string); 224 return WERR_OK; 225 } 226 227 return WERR_INVALID_PARAM; 228} 229 230static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, 231 struct spoolss_GetPrinterData *r) 232{ 233 WERROR result; 234 union spoolss_PrinterData data; 235 DATA_BLOB blob; 236 enum ndr_err_code ndr_err; 237 238 result = sptr_PrintServerData(server, mem_ctx, r->in.value_name, &data, r->out.type); 239 if (!W_ERROR_IS_OK(result)) { 240 return result; 241 } 242 243 ndr_err = ndr_push_union_blob(&blob, mem_ctx, lp_iconv_convenience(server->ntptr->lp_ctx), 244 &data, *r->out.type, (ndr_push_flags_fn_t)ndr_push_spoolss_PrinterData); 245 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 246 return WERR_GENERAL_FAILURE; 247 } 248 249 *r->out.needed = blob.length; 250 251 if (r->in.offered >= *r->out.needed) { 252 memcpy(r->out.data, blob.data, blob.length); 253 } 254 255 return WERR_OK; 256} 257 258/* PrintServer Form functions */ 259static WERROR sptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, 260 struct spoolss_EnumForms *r) 261{ 262 struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); 263 struct ldb_message **msgs; 264 int count; 265 int i; 266 union spoolss_FormInfo *info; 267 268 count = sptr_db_search(sptr_db, mem_ctx, 269 ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"), 270 &msgs, NULL, "(&(objectClass=form))"); 271 272 if (count == 0) return WERR_OK; 273 if (count < 0) return WERR_GENERAL_FAILURE; 274 275 info = talloc_array(mem_ctx, union spoolss_FormInfo, count); 276 W_ERROR_HAVE_NO_MEMORY(info); 277 278 switch (r->in.level) { 279 case 1: 280 for (i=0; i < count; i++) { 281 info[i].info1.flags = samdb_result_uint(msgs[i], "flags", SPOOLSS_FORM_BUILTIN); 282 283 info[i].info1.form_name = samdb_result_string(msgs[i], "form-name", NULL); 284 W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name); 285 286 info[i].info1.size.width = samdb_result_uint(msgs[i], "size-width", 0); 287 info[i].info1.size.height = samdb_result_uint(msgs[i], "size-height", 0); 288 289 info[i].info1.area.left = samdb_result_uint(msgs[i], "area-left", 0); 290 info[i].info1.area.top = samdb_result_uint(msgs[i], "area-top", 0); 291 info[i].info1.area.right = samdb_result_uint(msgs[i], "area-right", 0); 292 info[i].info1.area.bottom = samdb_result_uint(msgs[i], "area-bottom", 0); 293 } 294 break; 295 default: 296 return WERR_UNKNOWN_LEVEL; 297 } 298 299 *r->out.info = info; 300 *r->out.count = count; 301 return WERR_OK; 302} 303 304static WERROR sptr_AddPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, 305 struct spoolss_AddForm *r) 306{ 307 struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); 308 struct ldb_message *msg,**msgs; 309 const char * const attrs[] = {"flags", NULL }; 310 int count, ret; 311 312 /* TODO: do checks access here 313 * if (!(server->access_mask & desired_access)) { 314 * return WERR_FOOBAR; 315 * } 316 */ 317 318 switch (r->in.level) { 319 case 1: 320 if (!r->in.info.info1) { 321 return WERR_FOOBAR; 322 } 323 count = sptr_db_search(sptr_db, mem_ctx, 324 ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"), 325 &msgs, attrs, "(&(form-name=%s)(objectClass=form))", 326 r->in.info.info1->form_name); 327 328 if (count == 1) return WERR_FOOBAR; 329 if (count > 1) return WERR_FOOBAR; 330 if (count < 0) return WERR_GENERAL_FAILURE; 331 332 if (r->in.info.info1->flags != SPOOLSS_FORM_USER) { 333 return WERR_FOOBAR; 334 } 335 336 msg = ldb_msg_new(mem_ctx); 337 W_ERROR_HAVE_NO_MEMORY(msg); 338 339 /* add core elements to the ldb_message for the Form */ 340 msg->dn = ldb_dn_new_fmt(msg, sptr_db, "form-name=%s,CN=Forms,CN=PrintServer", r->in.info.info1->form_name); 341 SET_STRING(sptr_db, msg, "objectClass", "form"); 342 343 SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags); 344 345 SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name); 346 347 SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width); 348 SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height); 349 350 SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left); 351 SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top); 352 SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right); 353 SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom); 354 break; 355 default: 356 return WERR_UNKNOWN_LEVEL; 357 } 358 359 ret = ldb_add(sptr_db, msg); 360 if (ret != 0) { 361 return WERR_FOOBAR; 362 } 363 364 return WERR_OK; 365} 366 367static WERROR sptr_SetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, 368 struct spoolss_SetForm *r) 369{ 370 struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); 371 struct ldb_message *msg,**msgs; 372 const char * const attrs[] = { "flags", NULL}; 373 int count, ret; 374 enum spoolss_FormFlags flags; 375 376 /* TODO: do checks access here 377 * if (!(server->access_mask & desired_access)) { 378 * return WERR_FOOBAR; 379 * } 380 */ 381 382 switch (r->in.level) { 383 case 1: 384 if (!r->in.info.info1) { 385 return WERR_FOOBAR; 386 } 387 388 count = sptr_db_search(sptr_db, mem_ctx, 389 ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"), 390 &msgs, attrs, "(&(form-name=%s)(objectClass=form))", 391 r->in.info.info1->form_name); 392 393 if (count == 0) return WERR_FOOBAR; 394 if (count > 1) return WERR_FOOBAR; 395 if (count < 0) return WERR_GENERAL_FAILURE; 396 397 flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN); 398 if (flags != SPOOLSS_FORM_USER) { 399 return WERR_FOOBAR; 400 } 401 402 msg = ldb_msg_new(mem_ctx); 403 W_ERROR_HAVE_NO_MEMORY(msg); 404 405 /* add core elements to the ldb_message for the user */ 406 msg->dn = msgs[0]->dn; 407 408 SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags); 409 410 SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name); 411 412 SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width); 413 SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height); 414 415 SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left); 416 SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top); 417 SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right); 418 SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom); 419 break; 420 default: 421 return WERR_UNKNOWN_LEVEL; 422 } 423 424 ret = samdb_replace(sptr_db, mem_ctx, msg); 425 if (ret != 0) { 426 return WERR_FOOBAR; 427 } 428 429 return WERR_OK; 430} 431 432static WERROR sptr_DeletePrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx, 433 struct spoolss_DeleteForm *r) 434{ 435 struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context); 436 struct ldb_message **msgs; 437 const char * const attrs[] = { "flags", NULL}; 438 int count, ret; 439 enum spoolss_FormFlags flags; 440 441 /* TODO: do checks access here 442 * if (!(server->access_mask & desired_access)) { 443 * return WERR_FOOBAR; 444 * } 445 */ 446 447 if (!r->in.form_name) { 448 return WERR_FOOBAR; 449 } 450 451 count = sptr_db_search(sptr_db, mem_ctx, 452 ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"), 453 &msgs, attrs, "(&(form-name=%s)(objectclass=form))", 454 r->in.form_name); 455 456 if (count == 0) return WERR_FOOBAR; 457 if (count > 1) return WERR_FOOBAR; 458 if (count < 0) return WERR_GENERAL_FAILURE; 459 460 flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN); 461 if (flags != SPOOLSS_FORM_USER) { 462 return WERR_FOOBAR; 463 } 464 465 ret = ldb_delete(sptr_db, msgs[0]->dn); 466 if (ret != 0) { 467 return WERR_FOOBAR; 468 } 469 470 return WERR_OK; 471} 472 473/* PrintServer Driver functions */ 474static WERROR sptr_EnumPrinterDrivers(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, 475 struct spoolss_EnumPrinterDrivers *r) 476{ 477 return WERR_OK; 478} 479 480static WERROR sptr_GetPrinterDriverDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, 481 struct spoolss_GetPrinterDriverDirectory *r) 482{ 483 union spoolss_DriverDirectoryInfo *info; 484 const char *prefix; 485 const char *postfix; 486 487 /* 488 * NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a 489 * are ignoring the r->in.level completely, so we do :-) 490 */ 491 492 /* 493 * TODO: check the server name is ours 494 * - if it's a invalid UNC then return WERR_INVALID_NAME 495 * - if it's the wrong host name return WERR_INVALID_PARAM 496 * - if it's "" then we need to return a local WINDOWS path 497 */ 498 if (!r->in.server || !r->in.server[0]) { 499 prefix = "C:\\DRIVERS"; 500 } else { 501 prefix = talloc_asprintf(mem_ctx, "%s\\print$", r->in.server); 502 W_ERROR_HAVE_NO_MEMORY(prefix); 503 } 504 505 if (r->in.environment && strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) { 506 postfix = "W32X86"; 507 } else { 508 return WERR_INVALID_ENVIRONMENT; 509 } 510 511 info = talloc(mem_ctx, union spoolss_DriverDirectoryInfo); 512 W_ERROR_HAVE_NO_MEMORY(info); 513 514 info->info1.directory_name = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix); 515 W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name); 516 517 r->out.info = info; 518 return WERR_OK; 519} 520 521/* Printer functions */ 522static WERROR sptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, 523 struct spoolss_EnumPrinters *r) 524{ 525 struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context); 526 struct ldb_message **msgs; 527 int count; 528 int i; 529 union spoolss_PrinterInfo *info; 530 531 count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL, 532 "(&(objectclass=printer))"); 533 534 if (count == 0) return WERR_OK; 535 if (count < 0) return WERR_GENERAL_FAILURE; 536 537 info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count); 538 W_ERROR_HAVE_NO_MEMORY(info); 539 540 switch(r->in.level) { 541 case 1: 542 for (i = 0; i < count; i++) { 543 info[i].info1.flags = samdb_result_uint(msgs[i], "flags", 0); 544 545 info[i].info1.name = samdb_result_string(msgs[i], "name", ""); 546 W_ERROR_HAVE_NO_MEMORY(info[i].info1.name); 547 548 info[i].info1.description = samdb_result_string(msgs[i], "description", ""); 549 W_ERROR_HAVE_NO_MEMORY(info[i].info1.description); 550 551 info[i].info1.comment = samdb_result_string(msgs[i], "comment", NULL); 552 } 553 break; 554 case 2: 555 for (i = 0; i < count; i++) { 556 info[i].info2.servername = samdb_result_string(msgs[i], "servername", ""); 557 W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername); 558 559 info[i].info2.printername = samdb_result_string(msgs[i], "printername", ""); 560 W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername); 561 562 info[i].info2.sharename = samdb_result_string(msgs[i], "sharename", ""); 563 W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename); 564 565 info[i].info2.portname = samdb_result_string(msgs[i], "portname", ""); 566 W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname); 567 568 info[i].info2.drivername = samdb_result_string(msgs[i], "drivername", ""); 569 W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername); 570 571 info[i].info2.comment = samdb_result_string(msgs[i], "comment", NULL); 572 573 info[i].info2.location = samdb_result_string(msgs[i], "location", NULL); 574 575 info[i].info2.devmode = NULL; 576 577 info[i].info2.sepfile = samdb_result_string(msgs[i], "sepfile", NULL); 578 579 info[i].info2.printprocessor = samdb_result_string(msgs[i], "printprocessor", ""); 580 W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor); 581 582 info[i].info2.datatype = samdb_result_string(msgs[i], "datatype", ""); 583 W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype); 584 585 info[i].info2.parameters = samdb_result_string(msgs[i], "parameters", NULL); 586 587 info[i].info2.secdesc = NULL; 588 589 info[i].info2.attributes = samdb_result_uint(msgs[i], "attributes", 0); 590 info[i].info2.priority = samdb_result_uint(msgs[i], "priority", 0); 591 info[i].info2.defaultpriority = samdb_result_uint(msgs[i], "defaultpriority", 0); 592 info[i].info2.starttime = samdb_result_uint(msgs[i], "starttime", 0); 593 info[i].info2.untiltime = samdb_result_uint(msgs[i], "untiltime", 0); 594 info[i].info2.status = samdb_result_uint(msgs[i], "status", 0); 595 info[i].info2.cjobs = samdb_result_uint(msgs[i], "cjobs", 0); 596 info[i].info2.averageppm = samdb_result_uint(msgs[i], "averageppm", 0); 597 } 598 break; 599 case 4: 600 for (i = 0; i < count; i++) { 601 info[i].info4.printername = samdb_result_string(msgs[i], "printername", ""); 602 W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername); 603 604 info[i].info4.servername = samdb_result_string(msgs[i], "servername", ""); 605 W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername); 606 607 info[i].info4.attributes = samdb_result_uint(msgs[i], "attributes", 0); 608 } 609 break; 610 case 5: 611 for (i = 0; i < count; i++) { 612 info[i].info5.printername = samdb_result_string(msgs[i], "name", ""); 613 W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername); 614 615 info[i].info5.portname = samdb_result_string(msgs[i], "port", ""); 616 W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname); 617 618 info[i].info5.attributes = samdb_result_uint(msgs[i], "attributes", 0); 619 info[i].info5.device_not_selected_timeout = samdb_result_uint(msgs[i], "device_not_selected_timeout", 0); 620 info[i].info5.transmission_retry_timeout = samdb_result_uint(msgs[i], "transmission_retry_timeout", 0); 621 } 622 break; 623 default: 624 return WERR_UNKNOWN_LEVEL; 625 } 626 627 *r->out.info = info; 628 *r->out.count = count; 629 return WERR_OK; 630} 631 632static WERROR sptr_OpenPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, 633 struct spoolss_OpenPrinterEx *r, 634 const char *printer_name, 635 struct ntptr_GenericHandle **printer) 636{ 637 return WERR_INVALID_PRINTER_NAME; 638} 639 640/* port functions */ 641static WERROR sptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, 642 struct spoolss_EnumPorts *r) 643{ 644 struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context); 645 struct ldb_message **msgs; 646 int count; 647 int i; 648 union spoolss_PortInfo *info; 649 650 count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL, 651 "(&(objectclass=port))"); 652 653 if (count == 0) return WERR_OK; 654 if (count < 0) return WERR_GENERAL_FAILURE; 655 656 info = talloc_array(mem_ctx, union spoolss_PortInfo, count); 657 W_ERROR_HAVE_NO_MEMORY(info); 658 659 switch (r->in.level) { 660 case 1: 661 for (i = 0; i < count; i++) { 662 info[i].info1.port_name = samdb_result_string(msgs[i], "port-name", ""); 663 W_ERROR_HAVE_NO_MEMORY(info[i].info1.port_name); 664 } 665 break; 666 case 2: 667 for (i=0; i < count; i++) { 668 info[i].info2.port_name = samdb_result_string(msgs[i], "port-name", ""); 669 W_ERROR_HAVE_NO_MEMORY(info[i].info2.port_name); 670 671 info[i].info2.monitor_name = samdb_result_string(msgs[i], "monitor-name", ""); 672 W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name); 673 674 info[i].info2.description = samdb_result_string(msgs[i], "description", ""); 675 W_ERROR_HAVE_NO_MEMORY(info[i].info2.description); 676 677 info[i].info2.port_type = samdb_result_uint(msgs[i], "port-type", SPOOLSS_PORT_TYPE_WRITE); 678 info[i].info2.reserved = samdb_result_uint(msgs[i], "reserved", 0); 679 } 680 break; 681 default: 682 return WERR_UNKNOWN_LEVEL; 683 } 684 685 *r->out.info = info; 686 *r->out.count = count; 687 return WERR_OK; 688} 689 690/* monitor functions */ 691static WERROR sptr_EnumMonitors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, 692 struct spoolss_EnumMonitors *r) 693{ 694 struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context); 695 struct ldb_message **msgs; 696 int count; 697 int i; 698 union spoolss_MonitorInfo *info; 699 700 count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL, 701 "(&(objectclass=monitor))"); 702 703 if (count == 0) return WERR_OK; 704 if (count < 0) return WERR_GENERAL_FAILURE; 705 706 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, count); 707 W_ERROR_HAVE_NO_MEMORY(info); 708 709 switch (r->in.level) { 710 case 1: 711 for (i = 0; i < count; i++) { 712 info[i].info1.monitor_name = samdb_result_string(msgs[i], "monitor-name", ""); 713 W_ERROR_HAVE_NO_MEMORY(info[i].info1.monitor_name); 714 } 715 break; 716 case 2: 717 for (i=0; i < count; i++) { 718 info[i].info2.monitor_name = samdb_result_string(msgs[i], "monitor-name", ""); 719 W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name); 720 721 info[i].info2.environment = samdb_result_string(msgs[i], "environment", ""); 722 W_ERROR_HAVE_NO_MEMORY(info[i].info2.environment); 723 724 info[i].info2.dll_name = samdb_result_string(msgs[i], "dll-name", ""); 725 W_ERROR_HAVE_NO_MEMORY(info[i].info2.dll_name); 726 } 727 break; 728 default: 729 return WERR_UNKNOWN_LEVEL; 730 } 731 732 *r->out.info = info; 733 *r->out.count = count; 734 return WERR_OK; 735} 736 737/* Printer Form functions */ 738static WERROR sptr_GetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx, 739 struct spoolss_GetForm *r) 740{ 741 struct ldb_context *sptr_db = talloc_get_type(printer->ntptr->private_data, struct ldb_context); 742 struct ldb_message **msgs; 743 struct ldb_dn *base_dn; 744 int count; 745 union spoolss_FormInfo *info; 746 747 /* TODO: do checks access here 748 * if (!(printer->access_mask & desired_access)) { 749 * return WERR_FOOBAR; 750 * } 751 */ 752 753 base_dn = ldb_dn_new_fmt(mem_ctx, sptr_db, "CN=Forms,CN=%s,CN=Printers", printer->object_name); 754 W_ERROR_HAVE_NO_MEMORY(base_dn); 755 756 count = sptr_db_search(sptr_db, mem_ctx, base_dn, &msgs, NULL, 757 "(&(form-name=%s)(objectClass=form))", 758 r->in.form_name); 759 760 if (count == 0) return WERR_FOOBAR; 761 if (count > 1) return WERR_FOOBAR; 762 if (count < 0) return WERR_GENERAL_FAILURE; 763 764 info = talloc(mem_ctx, union spoolss_FormInfo); 765 W_ERROR_HAVE_NO_MEMORY(info); 766 767 switch (r->in.level) { 768 case 1: 769 info->info1.flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN); 770 771 info->info1.form_name = samdb_result_string(msgs[0], "form-name", NULL); 772 W_ERROR_HAVE_NO_MEMORY(info->info1.form_name); 773 774 info->info1.size.width = samdb_result_uint(msgs[0], "size-width", 0); 775 info->info1.size.height = samdb_result_uint(msgs[0], "size-height", 0); 776 777 info->info1.area.left = samdb_result_uint(msgs[0], "area-left", 0); 778 info->info1.area.top = samdb_result_uint(msgs[0], "area-top", 0); 779 info->info1.area.right = samdb_result_uint(msgs[0], "area-right", 0); 780 info->info1.area.bottom = samdb_result_uint(msgs[0], "area-bottom", 0); 781 break; 782 default: 783 return WERR_UNKNOWN_LEVEL; 784 } 785 786 r->out.info = info; 787 return WERR_OK; 788} 789 790static WERROR sptr_GetPrintProcessorDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, 791 struct spoolss_GetPrintProcessorDirectory *r) 792{ 793 union spoolss_PrintProcessorDirectoryInfo *info; 794 const char *prefix; 795 const char *postfix; 796 797 /* 798 * NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a 799 * are ignoring the r->in.level completely, so we do :-) 800 */ 801 802 /* 803 * TODO: check the server name is ours 804 * - if it's a invalid UNC then return WERR_INVALID_NAME 805 * - if it's the wrong host name return WERR_INVALID_PARAM 806 * - if it's "" then we need to return a local WINDOWS path 807 */ 808 if (!r->in.server || !r->in.server[0]) { 809 prefix = "C:\\PRTPROCS"; 810 } else { 811 prefix = talloc_asprintf(mem_ctx, "%s\\prnproc$", r->in.server); 812 W_ERROR_HAVE_NO_MEMORY(prefix); 813 } 814 815 if (r->in.environment && strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) { 816 postfix = "W32X86"; 817 } else { 818 return WERR_INVALID_ENVIRONMENT; 819 } 820 821 info = talloc(mem_ctx, union spoolss_PrintProcessorDirectoryInfo); 822 W_ERROR_HAVE_NO_MEMORY(info); 823 824 info->info1.directory_name = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix); 825 W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name); 826 827 r->out.info = info; 828 return WERR_OK; 829} 830 831 832/* 833 initialialise the simble ldb backend, registering ourselves with the ntptr subsystem 834 */ 835static const struct ntptr_ops ntptr_simple_ldb_ops = { 836 .name = "simple_ldb", 837 .init_context = sptr_init_context, 838 839 /* PrintServer functions */ 840 .OpenPrintServer = sptr_OpenPrintServer, 841/* .XcvDataPrintServer = sptr_XcvDataPrintServer, 842*/ 843 /* PrintServer PrinterData functions */ 844/* .EnumPrintServerData = sptr_EnumPrintServerData, 845*/ .GetPrintServerData = sptr_GetPrintServerData, 846/* .SetPrintServerData = sptr_SetPrintServerData, 847 .DeletePrintServerData = sptr_DeletePrintServerData, 848*/ 849 /* PrintServer Form functions */ 850 .EnumPrintServerForms = sptr_EnumPrintServerForms, 851 .AddPrintServerForm = sptr_AddPrintServerForm, 852 .SetPrintServerForm = sptr_SetPrintServerForm, 853 .DeletePrintServerForm = sptr_DeletePrintServerForm, 854 855 /* PrintServer Driver functions */ 856 .EnumPrinterDrivers = sptr_EnumPrinterDrivers, 857/* .AddPrinterDriver = sptr_AddPrinterDriver, 858 .DeletePrinterDriver = sptr_DeletePrinterDriver, 859*/ .GetPrinterDriverDirectory = sptr_GetPrinterDriverDirectory, 860 861 /* Port functions */ 862 .EnumPorts = sptr_EnumPorts, 863/* .OpenPort = sptr_OpenPort, 864 .XcvDataPort = sptr_XcvDataPort, 865*/ 866 /* Monitor functions */ 867 .EnumMonitors = sptr_EnumMonitors, 868/* .OpenMonitor = sptr_OpenMonitor, 869 .XcvDataMonitor = sptr_XcvDataMonitor, 870*/ 871 /* PrintProcessor functions */ 872/* .EnumPrintProcessors = sptr_EnumPrintProcessors, 873*/ 874 .GetPrintProcessorDirectory = sptr_GetPrintProcessorDirectory, 875 876 /* Printer functions */ 877 .EnumPrinters = sptr_EnumPrinters, 878 .OpenPrinter = sptr_OpenPrinter, 879/* .AddPrinter = sptr_AddPrinter, 880 .GetPrinter = sptr_GetPrinter, 881 .SetPrinter = sptr_SetPrinter, 882 .DeletePrinter = sptr_DeletePrinter, 883 .XcvDataPrinter = sptr_XcvDataPrinter, 884*/ 885 /* Printer Driver functions */ 886/* .GetPrinterDriver = sptr_GetPrinterDriver, 887*/ 888 /* Printer PrinterData functions */ 889/* .EnumPrinterData = sptr_EnumPrinterData, 890 .GetPrinterData = sptr_GetPrinterData, 891 .SetPrinterData = sptr_SetPrinterData, 892 .DeletePrinterData = sptr_DeletePrinterData, 893*/ 894 /* Printer Form functions */ 895/* .EnumPrinterForms = sptr_EnumPrinterForms, 896 .AddPrinterForm = sptr_AddPrinterForm, 897*/ .GetPrinterForm = sptr_GetPrinterForm, 898/* .SetPrinterForm = sptr_SetPrinterForm, 899 .DeletePrinterForm = sptr_DeletePrinterForm, 900*/ 901 /* Printer Job functions */ 902/* .EnumJobs = sptr_EnumJobs, 903 .AddJob = sptr_AddJob, 904 .ScheduleJob = sptr_ScheduleJob, 905 .GetJob = sptr_GetJob, 906 .SetJob = sptr_SetJob, 907*/ 908 /* Printer Printing functions */ 909/* .StartDocPrinter = sptr_StartDocPrinter, 910 .EndDocPrinter = sptr_EndDocPrinter, 911 .StartPagePrinter = sptr_StartPagePrinter, 912 .EndPagePrinter = sptr_EndPagePrinter, 913 .WritePrinter = sptr_WritePrinter, 914 .ReadPrinter = sptr_ReadPrinter, 915*/}; 916 917NTSTATUS ntptr_simple_ldb_init(void) 918{ 919 NTSTATUS ret; 920 921 ret = ntptr_register(&ntptr_simple_ldb_ops); 922 if (!NT_STATUS_IS_OK(ret)) { 923 DEBUG(0,("Failed to register NTPTR '%s' backend!\n", 924 ntptr_simple_ldb_ops.name)); 925 } 926 927 return ret; 928} 929