Changeset 745 for trunk/server/source4/lib
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 53 deleted
- 122 edited
- 57 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/lib/cmdline/popt_common.c
r414 r745 67 67 68 68 if (reason == POPT_CALLBACK_REASON_POST) { 69 if (lp _configfile(cmdline_lp_ctx) == NULL) {70 lp_load_default(cmdline_lp_ctx);69 if (lpcfg_configfile(cmdline_lp_ctx) == NULL) { 70 lpcfg_load_default(cmdline_lp_ctx); 71 71 } 72 72 /* Hook any 'every Samba program must do this, after … … 84 84 85 85 if (reason == POPT_CALLBACK_REASON_PRE) { 86 cmdline_lp_ctx = loadparm_init (talloc_autofree_context());86 cmdline_lp_ctx = loadparm_init_global(false); 87 87 88 88 /* Hook for 'almost the first thing to do in a samba program' here */ … … 109 109 110 110 case OPT_OPTION: 111 if (!lp _set_option(cmdline_lp_ctx, arg)) {111 if (!lpcfg_set_option(cmdline_lp_ctx, arg)) { 112 112 fprintf(stderr, "Error setting option '%s'\n", arg); 113 113 exit(1); … … 116 116 117 117 case 'd': 118 lp _set_cmdline(cmdline_lp_ctx, "log level", arg);118 lpcfg_set_cmdline(cmdline_lp_ctx, "log level", arg); 119 119 break; 120 120 … … 125 125 case 's': 126 126 if (arg) { 127 lp _load(cmdline_lp_ctx, arg);127 lpcfg_load(cmdline_lp_ctx, arg); 128 128 } 129 129 break; … … 132 132 if (arg) { 133 133 char *new_logfile = talloc_asprintf(NULL, "%s/log.%s", arg, pname); 134 lp _set_cmdline(cmdline_lp_ctx, "log file", new_logfile);134 lpcfg_set_cmdline(cmdline_lp_ctx, "log file", new_logfile); 135 135 talloc_free(new_logfile); 136 136 } … … 153 153 case 'O': 154 154 if (arg) { 155 lp _set_cmdline(lp_ctx, "socket options", arg);155 lpcfg_set_cmdline(lp_ctx, "socket options", arg); 156 156 } 157 157 break; 158 158 159 159 case 'W': 160 lp _set_cmdline(lp_ctx, "workgroup", arg);160 lpcfg_set_cmdline(lp_ctx, "workgroup", arg); 161 161 break; 162 162 163 163 case 'r': 164 lp _set_cmdline(lp_ctx, "realm", arg);164 lpcfg_set_cmdline(lp_ctx, "realm", arg); 165 165 break; 166 166 167 167 case 'n': 168 lp _set_cmdline(lp_ctx, "netbios name", arg);168 lpcfg_set_cmdline(lp_ctx, "netbios name", arg); 169 169 break; 170 170 171 171 case 'i': 172 lp _set_cmdline(lp_ctx, "netbios scope", arg);172 lpcfg_set_cmdline(lp_ctx, "netbios scope", arg); 173 173 break; 174 174 175 175 case 'm': 176 lp _set_cmdline(lp_ctx, "client max protocol", arg);176 lpcfg_set_cmdline(lp_ctx, "client max protocol", arg); 177 177 break; 178 178 179 179 case 'R': 180 lp _set_cmdline(lp_ctx, "name resolve order", arg);180 lpcfg_set_cmdline(lp_ctx, "name resolve order", arg); 181 181 break; 182 182 183 183 case 'S': 184 lp _set_cmdline(lp_ctx, "client signing", arg);184 lpcfg_set_cmdline(lp_ctx, "client signing", arg); 185 185 break; 186 186 -
trunk/server/source4/lib/cmdline/popt_credentials.c
r414 r745 32 32 * -N,--no-pass 33 33 * -S,--signing 34 * -P--machine-pass35 * 36 * 34 * -P,--machine-pass 35 * --simple-bind-dn 36 * --password 37 37 */ 38 38 39 static bool dont_ask; 40 static bool machine_account_pending; 39 41 40 static bool dont_ask; 41 42 enum opt { OPT_SIMPLE_BIND_DN, OPT_PASSWORD, OPT_KERBEROS }; 42 enum opt { OPT_SIMPLE_BIND_DN, OPT_PASSWORD, OPT_KERBEROS, OPT_SIGN, OPT_ENCRYPT }; 43 43 44 44 /* … … 66 66 cli_credentials_set_cmdline_callbacks(cmdline_credentials); 67 67 } 68 69 if (machine_account_pending) { 70 cli_credentials_set_machine_account(cmdline_credentials, cmdline_lp_ctx); 71 } 72 68 73 return; 74 69 75 } 70 76 … … 97 103 case 'P': 98 104 /* Later, after this is all over, get the machine account details from the secrets.ldb */ 99 cli_credentials_set_machine_account_pending(cmdline_credentials, cmdline_lp_ctx);105 machine_account_pending = true; 100 106 break; 101 107 … … 106 112 if (arg) { 107 113 if (!set_boolean(arg, &use_kerberos)) { 108 fprintf(stderr, "Error parsing -k %s\n", arg); 114 fprintf(stderr, "Error parsing -k %s. Should be " 115 "-k [yes|no]\n", arg); 109 116 exit(1); 110 117 break; … … 120 127 121 128 case OPT_SIMPLE_BIND_DN: 129 { 122 130 cli_credentials_set_bind_dn(cmdline_credentials, arg); 123 131 break; 132 } 133 case OPT_SIGN: 134 { 135 uint32_t gensec_features; 136 137 gensec_features = cli_credentials_get_gensec_features(cmdline_credentials); 138 139 gensec_features |= GENSEC_FEATURE_SIGN; 140 cli_credentials_set_gensec_features(cmdline_credentials, 141 gensec_features); 142 break; 143 } 144 case OPT_ENCRYPT: 145 { 146 uint32_t gensec_features; 147 148 gensec_features = cli_credentials_get_gensec_features(cmdline_credentials); 149 150 gensec_features |= GENSEC_FEATURE_SEAL; 151 cli_credentials_set_gensec_features(cmdline_credentials, 152 gensec_features); 153 break; 154 } 124 155 } 125 156 } … … 135 166 { "machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password (implies -k)" }, 136 167 { "simple-bind-dn", 0, POPT_ARG_STRING, NULL, OPT_SIMPLE_BIND_DN, "DN to use for a simple bind" }, 137 { "kerberos", 'k', POPT_ARG_STRING, NULL, OPT_KERBEROS, "Use Kerberos" }, 168 { "kerberos", 'k', POPT_ARG_STRING, NULL, OPT_KERBEROS, "Use Kerberos, -k [yes|no]" }, 169 { "sign", 'S', POPT_ARG_NONE, NULL, OPT_SIGN, "Sign connection to prevent modification in transit" }, 170 { "encrypt", 'e', POPT_ARG_NONE, NULL, OPT_ENCRYPT, "Encrypt connection for privacy" }, 138 171 { NULL } 139 172 }; -
trunk/server/source4/lib/com/dcom/main.c
r414 r745 172 172 return dcerpc_pipe_connect(ctx->event_ctx, p, "ncalrpc", 173 173 &ndr_table_IRemoteActivation, 174 174 dcom_get_server_credentials(ctx, NULL), ctx->event_ctx, ctx->lp_ctx); 175 175 } 176 176 loc_ctx = talloc_new(ctx); … … 183 183 status = dcerpc_pipe_connect_b(ctx->event_ctx, p, bd, 184 184 &ndr_table_IRemoteActivation, 185 185 dcom_get_server_credentials(ctx, bd->host), ctx->event_ctx, ctx->lp_ctx); 186 186 goto end; 187 187 } … … 705 705 return; 706 706 } 707 707 /*TODO: FIXME - for now this unused anyway */ 708 708 req = dcerpc_ndr_request_send(p, &s->d->obj.u_objref.u_standard.std.ipid, s->table, s->opnum, s, s->r); 709 709 composite_continue_rpc(c, req, s->continuation, c); -
trunk/server/source4/lib/com/main.c
r414 r745 53 53 54 54 /* Run IClassFactory::CreateInstance() */ 55 error = IClassFactory_CreateInstance(factory, ctx, NULL, &classfact_iid, &iunk);55 error = IClassFactory_CreateInstance(factory, ctx, NULL, &classfact_iid, (struct MInterfacePointer *) &iunk); 56 56 if (!W_ERROR_IS_OK(error)) { 57 57 DEBUG(3, ("Error while calling IClassFactory::CreateInstance : %s\n", win_errstr(error))); -
trunk/server/source4/lib/com/pycom.c
r414 r745 18 18 */ 19 19 20 #include <Python.h> 20 21 #include "includes.h" 21 #include <Python.h>22 22 #include "lib/com/com.h" 23 23 #include "librpc/ndr/libndr.h" 24 24 #include "libcli/util/pyerrors.h" 25 26 #ifndef Py_RETURN_NONE27 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None28 #endif29 25 30 26 static struct com_context *py_com_ctx = NULL; /* FIXME: evil global */ -
trunk/server/source4/lib/events/events.h
r414 r745 2 2 #define __LIB_EVENTS_H__ 3 3 #define TEVENT_COMPAT_DEFINES 1 4 #include < ../lib/tevent/tevent.h>4 #include <tevent.h> 5 5 struct tevent_context *s4_event_context_init(TALLOC_CTX *mem_ctx); 6 6 struct tevent_context *event_context_find(TALLOC_CTX *mem_ctx) _DEPRECATED_; 7 void s4_event_context_set_default(struct tevent_context *ev); 7 8 #endif /* __LIB_EVENTS_H__ */ -
trunk/server/source4/lib/events/tevent_s4.c
r414 r745 72 72 } 73 73 74 /*75 find an event context that is a parent of the given memory context,76 or create a new event context as a child of the given context if77 none is found78 79 This should be used in preference to event_context_init() in places80 where you would prefer to use the existing event context if possible81 (which is most situations)82 */83 struct tevent_context *event_context_find(TALLOC_CTX *mem_ctx)84 {85 struct tevent_context *ev = talloc_find_parent_bytype(mem_ctx, struct tevent_context);86 if (ev == NULL) {87 ev = tevent_context_init(mem_ctx);88 }89 return ev;90 } -
trunk/server/source4/lib/ldb-samba/ldif_handlers.c
r414 r745 3 3 4 4 Copyright (C) Andrew Tridgell 2005 5 Copyright (C) Andrew Bartlett 2006-200 75 Copyright (C) Andrew Bartlett 2006-2009 6 6 Copyright (C) Matthias Dieter Wallnöfer 2009 7 7 ** NOTE! The following LGPL license applies to the ldb … … 24 24 25 25 #include "includes.h" 26 #include "lib/ldb/include/ldb.h"27 #include "lib/ldb/include/ldb_module.h"26 #include <ldb.h> 27 #include <ldb_module.h> 28 28 #include "ldb_handlers.h" 29 29 #include "dsdb/samdb/samdb.h" … … 31 31 #include "librpc/gen_ndr/ndr_misc.h" 32 32 #include "librpc/gen_ndr/ndr_drsblobs.h" 33 #include "librpc/gen_ndr/ndr_dnsp.h" 33 34 #include "librpc/ndr/libndr.h" 34 35 #include "libcli/security/security.h" 35 36 #include "param/param.h" 37 #include "../lib/util/asn1.h" 36 38 37 39 /* 38 40 use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob 41 42 If mask_errors is true, then function succeeds but out data 43 is set to "<Unable to decode binary data>" message 44 45 \return 0 on success; -1 on error 39 46 */ 40 47 static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx, … … 42 49 size_t struct_size, 43 50 ndr_pull_flags_fn_t pull_fn, 44 ndr_print_fn_t print_fn) 51 ndr_print_fn_t print_fn, 52 bool mask_errors) 45 53 { 46 54 uint8_t *p; … … 51 59 p = talloc_size(mem_ctx, struct_size); 52 60 err = ndr_pull_struct_blob(in, mem_ctx, 53 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),54 61 p, pull_fn); 55 62 if (err != NDR_ERR_SUCCESS) { 63 /* fail in not in mask_error mode */ 64 if (!mask_errors) { 65 return -1; 66 } 56 67 talloc_free(p); 57 68 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>"); … … 80 91 return -1; 81 92 } 82 ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL,sid,93 ndr_err = ndr_push_struct_blob(out, mem_ctx, sid, 83 94 (ndr_push_flags_fn_t)ndr_push_dom_sid); 84 95 talloc_free(sid); … … 92 103 convert a NDR formatted blob to a ldif formatted objectSid 93 104 */ 94 staticint ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,105 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx, 95 106 const struct ldb_val *in, struct ldb_val *out) 96 107 { … … 102 113 return -1; 103 114 } 104 ndr_err = ndr_pull_struct_blob_all(in, sid, NULL,sid,115 ndr_err = ndr_pull_struct_blob_all(in, sid, sid, 105 116 (ndr_pull_flags_fn_t)ndr_pull_dom_sid); 106 117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 116 127 } 117 128 118 staticbool ldif_comparision_objectSid_isString(const struct ldb_val *v)129 bool ldif_comparision_objectSid_isString(const struct ldb_val *v) 119 130 { 120 131 if (v->length < 3) { … … 199 210 200 211 /* Check it looks like a SID */ 201 ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, NULL,&sid,212 ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, &sid, 202 213 (ndr_pull_flags_fn_t)ndr_pull_dom_sid); 203 214 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 215 226 struct GUID guid; 216 227 NTSTATUS status; 217 enum ndr_err_code ndr_err;218 228 219 229 status = GUID_from_data_blob(in, &guid); … … 222 232 } 223 233 224 ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, &guid, 225 (ndr_push_flags_fn_t)ndr_push_GUID); 226 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 234 status = GUID_to_ndr_blob(&guid, mem_ctx, out); 235 if (!NT_STATUS_IS_OK(status)) { 227 236 return -1; 228 237 } … … 237 246 { 238 247 struct GUID guid; 239 enum ndr_err_code ndr_err;240 ndr_err = ndr_pull_struct_blob_all(in, mem_ctx, NULL, &guid, 241 (ndr_pull_flags_fn_t)ndr_pull_GUID);242 if (!N DR_ERR_CODE_IS_SUCCESS(ndr_err)) {248 NTSTATUS status; 249 250 status = GUID_from_ndr_blob(in, &guid); 251 if (!NT_STATUS_IS_OK(status)) { 243 252 return -1; 244 253 } … … 263 272 { 264 273 struct GUID guid; 265 enum ndr_err_code ndr_err; 274 NTSTATUS status; 275 266 276 if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) { 267 277 return 0; … … 283 293 284 294 /* Check it looks like a GUID */ 285 ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, NULL, &guid,286 (ndr_pull_flags_fn_t)ndr_pull_GUID);287 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {295 status = GUID_from_ndr_blob(out, &guid); 296 if (!NT_STATUS_IS_OK(status)) { 297 data_blob_free(out); 288 298 return -1; 289 299 } … … 356 366 } 357 367 358 ndr_err = ndr_pull_struct_blob(in, sd, NULL,sd,368 ndr_err = ndr_pull_struct_blob(in, sd, sd, 359 369 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); 360 370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 361 371 /* If this does not parse, then it is probably SDDL, and we should try it that way */ 362 372 363 373 const struct dom_sid *sid = samdb_domain_sid(ldb); 364 374 talloc_free(sd); … … 369 379 } 370 380 371 ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL,sd,381 ndr_err = ndr_push_struct_blob(out, mem_ctx, sd, 372 382 (ndr_push_flags_fn_t)ndr_push_security_descriptor); 373 383 talloc_free(sd); … … 392 402 sizeof(struct security_descriptor), 393 403 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor, 394 (ndr_print_fn_t)ndr_print_security_descriptor); 404 (ndr_print_fn_t)ndr_print_security_descriptor, 405 true); 395 406 396 407 } … … 401 412 } 402 413 /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */ 403 ndr_err = ndr_pull_struct_blob(in, sd, NULL,sd,414 ndr_err = ndr_pull_struct_blob(in, sd, sd, 404 415 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); 405 416 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 407 418 return -1; 408 419 } 409 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, NULL);420 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb)); 410 421 talloc_free(sd); 411 422 if (out->data == NULL) { … … 417 428 418 429 /* 419 canonicalise an objectCategory. We use the short form as the can noical form:430 canonicalise an objectCategory. We use the short form as the canonical form: 420 431 cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person' 421 432 */ … … 425 436 { 426 437 struct ldb_dn *dn1 = NULL; 427 const struct dsdb_schema *schema = dsdb_get_schema(ldb );438 const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL); 428 439 const struct dsdb_class *sclass; 429 440 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); … … 477 488 const struct ldb_val *v2) 478 489 { 479 480 int ret, ret1, ret2; 481 struct ldb_val v1_canon, v2_canon; 482 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 483 484 /* I could try and bail if tmp_ctx was NULL, but what return 485 * value would I use? 486 * 487 * It seems easier to continue on the NULL context 488 */ 489 ret1 = ldif_canonicalise_objectCategory(ldb, tmp_ctx, v1, &v1_canon); 490 ret2 = ldif_canonicalise_objectCategory(ldb, tmp_ctx, v2, &v2_canon); 491 492 if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) { 493 ret = data_blob_cmp(&v1_canon, &v2_canon); 494 } else { 495 ret = data_blob_cmp(v1, v2); 496 } 497 talloc_free(tmp_ctx); 498 return ret; 490 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory, 491 v1, v2); 492 } 493 494 /* 495 convert a NDR formatted blob to a ldif formatted schemaInfo 496 */ 497 static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx, 498 const struct ldb_val *in, struct ldb_val *out) 499 { 500 return ldif_write_NDR(ldb, mem_ctx, in, out, 501 sizeof(struct repsFromToBlob), 502 (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob, 503 (ndr_print_fn_t)ndr_print_schemaInfoBlob, 504 true); 499 505 } 500 506 … … 508 514 enum ndr_err_code ndr_err; 509 515 char *string, *line, *p, *oid; 516 DATA_BLOB oid_blob; 510 517 511 518 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); … … 517 524 blob = talloc_zero(tmp_ctx, struct prefixMapBlob); 518 525 if (blob == NULL) { 519 talloc_free(blob); 520 return -1; 521 } 522 526 talloc_free(tmp_ctx); 527 return -1; 528 } 529 530 /* use the switch value to detect if this is in the binary 531 * format 532 */ 533 if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) { 534 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob, 535 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob); 536 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 537 ndr_err = ndr_push_struct_blob(out, mem_ctx, 538 blob, 539 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob); 540 talloc_free(tmp_ctx); 541 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 542 return -1; 543 } 544 return 0; 545 } 546 } 547 548 /* If this does not parse, then it is probably the text version, and we should try it that way */ 523 549 blob->version = PREFIX_MAP_VERSION_DSDB; 524 550 … … 540 566 } 541 567 } 542 /* allow a tra ling seperator */568 /* allow a trailing separator */ 543 569 if (line == p) { 544 570 break; … … 564 590 oid++; 565 591 566 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.oid 567 = talloc_strdup(blob->ctr.dsdb.mappings, oid); 592 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) { 593 talloc_free(tmp_ctx); 594 return -1; 595 } 596 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length; 597 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data; 568 598 569 599 blob->ctr.dsdb.num_mappings++; … … 578 608 579 609 ndr_err = ndr_push_struct_blob(out, mem_ctx, 580 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),581 610 blob, 582 611 (ndr_push_flags_fn_t)ndr_push_prefixMapBlob); … … 600 629 601 630 if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) { 602 return ldif_write_NDR(ldb, mem_ctx, in, out, 603 sizeof(struct prefixMapBlob), 604 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob, 605 (ndr_print_fn_t)ndr_print_prefixMapBlob); 606 631 int err; 632 /* try to decode the blob as S4 prefixMap */ 633 err = ldif_write_NDR(ldb, mem_ctx, in, out, 634 sizeof(struct prefixMapBlob), 635 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob, 636 (ndr_print_fn_t)ndr_print_prefixMapBlob, 637 false); 638 if (0 == err) { 639 return err; 640 } 641 /* try parsing it as Windows PrefixMap value */ 642 return ldif_write_NDR(ldb, mem_ctx, in, out, 643 sizeof(struct drsuapi_MSPrefixMap_Ctr), 644 (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr, 645 (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr, 646 true); 607 647 } 608 648 … … 612 652 } 613 653 ndr_err = ndr_pull_struct_blob_all(in, blob, 614 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),615 654 blob, 616 655 (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob); 617 656 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 618 talloc_free(blob); 619 return -1; 657 goto failed; 620 658 } 621 659 if (blob->version != PREFIX_MAP_VERSION_DSDB) { 622 return -1;660 goto failed; 623 661 } 624 662 string = talloc_strdup(mem_ctx, ""); 625 663 if (string == NULL) { 626 return -1;664 goto failed; 627 665 } 628 666 629 667 for (i=0; i < blob->ctr.dsdb.num_mappings; i++) { 668 DATA_BLOB oid_blob; 669 char *partial_oid = NULL; 670 630 671 if (i > 0) { 631 672 string = talloc_asprintf_append(string, ";"); 632 673 } 674 675 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid, 676 blob->ctr.dsdb.mappings[i].oid.length); 677 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) { 678 DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X", 679 blob->ctr.dsdb.mappings[i].id_prefix)); 680 goto failed; 681 } 633 682 string = talloc_asprintf_append(string, "%u:%s", 634 683 blob->ctr.dsdb.mappings[i].id_prefix, 635 blob->ctr.dsdb.mappings[i].oid.oid); 684 partial_oid); 685 talloc_free(discard_const(partial_oid)); 636 686 if (string == NULL) { 637 return -1;687 goto failed; 638 688 } 639 689 } … … 642 692 *out = data_blob_string_const(string); 643 693 return 0; 694 695 failed: 696 talloc_free(blob); 697 return -1; 644 698 } 645 699 … … 673 727 const struct ldb_val *v2) 674 728 { 675 676 int ret, ret1, ret2; 677 struct ldb_val v1_canon, v2_canon; 678 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 679 680 /* I could try and bail if tmp_ctx was NULL, but what return 681 * value would I use? 682 * 683 * It seems easier to continue on the NULL context 684 */ 685 ret1 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v1, &v1_canon); 686 ret2 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v2, &v2_canon); 687 688 if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) { 689 ret = data_blob_cmp(&v1_canon, &v2_canon); 690 } else { 691 ret = data_blob_cmp(v1, v2); 692 } 693 talloc_free(tmp_ctx); 694 return ret; 729 return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap, 730 v1, v2); 731 } 732 733 /* length limited conversion of a ldb_val to a int32_t */ 734 static int val_to_int32(const struct ldb_val *in, int32_t *v) 735 { 736 char *end; 737 char buf[64]; 738 739 /* make sure we don't read past the end of the data */ 740 if (in->length > sizeof(buf)-1) { 741 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 742 } 743 strncpy(buf, (char *)in->data, in->length); 744 buf[in->length] = 0; 745 746 /* We've to use "strtoll" here to have the intended overflows. 747 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */ 748 *v = (int32_t) strtoll(buf, &end, 0); 749 if (*end != 0) { 750 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 751 } 752 return LDB_SUCCESS; 753 } 754 755 /* length limited conversion of a ldb_val to a int64_t */ 756 static int val_to_int64(const struct ldb_val *in, int64_t *v) 757 { 758 char *end; 759 char buf[64]; 760 761 /* make sure we don't read past the end of the data */ 762 if (in->length > sizeof(buf)-1) { 763 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 764 } 765 strncpy(buf, (char *)in->data, in->length); 766 buf[in->length] = 0; 767 768 *v = (int64_t) strtoll(buf, &end, 0); 769 if (*end != 0) { 770 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 771 } 772 return LDB_SUCCESS; 695 773 } 696 774 … … 699 777 const struct ldb_val *in, struct ldb_val *out) 700 778 { 701 char *end;702 /* We've to use "strtoll" here to have the intended overflows.703 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */ 704 int32_t i = (int32_t) strtoll((char *)in->data, &end, 0);705 if ( *end != 0) {706 return -1;779 int32_t i; 780 int ret; 781 782 ret = val_to_int32(in, &i); 783 if (ret != LDB_SUCCESS) { 784 return ret; 707 785 } 708 786 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i); 709 787 if (out->data == NULL) { 710 return -1; 788 ldb_oom(ldb); 789 return LDB_ERR_OPERATIONS_ERROR; 711 790 } 712 791 out->length = strlen((char *)out->data); … … 716 795 /* Comparison of two 32-bit integers */ 717 796 static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx, 718 const struct ldb_val *v1, const struct ldb_val *v2) 719 { 720 /* We've to use "strtoll" here to have the intended overflows. 721 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */ 722 return (int32_t) strtoll((char *)v1->data, NULL, 0) 723 - (int32_t) strtoll((char *)v2->data, NULL, 0); 797 const struct ldb_val *v1, const struct ldb_val *v2) 798 { 799 int32_t i1=0, i2=0; 800 val_to_int32(v1, &i1); 801 val_to_int32(v2, &i2); 802 if (i1 == i2) return 0; 803 return i1 > i2? 1 : -1; 804 } 805 806 /* Canonicalisation of two 64-bit integers */ 807 static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx, 808 const struct ldb_val *in, struct ldb_val *out) 809 { 810 int64_t i; 811 int ret; 812 813 ret = val_to_int64(in, &i); 814 if (ret != LDB_SUCCESS) { 815 return ret; 816 } 817 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i); 818 if (out->data == NULL) { 819 ldb_oom(ldb); 820 return LDB_ERR_OPERATIONS_ERROR; 821 } 822 out->length = strlen((char *)out->data); 823 return 0; 824 } 825 826 /* Comparison of two 64-bit integers */ 827 static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx, 828 const struct ldb_val *v1, const struct ldb_val *v2) 829 { 830 int64_t i1=0, i2=0; 831 val_to_int64(v1, &i1); 832 val_to_int64(v2, &i2); 833 if (i1 == i2) return 0; 834 return i1 > i2? 1 : -1; 724 835 } 725 836 … … 733 844 sizeof(struct repsFromToBlob), 734 845 (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob, 735 (ndr_print_fn_t)ndr_print_repsFromToBlob); 846 (ndr_print_fn_t)ndr_print_repsFromToBlob, 847 true); 736 848 } 737 849 … … 745 857 sizeof(struct replPropertyMetaDataBlob), 746 858 (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob, 747 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob); 859 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob, 860 true); 748 861 } 749 862 … … 757 870 sizeof(struct replUpToDateVectorBlob), 758 871 (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob, 759 (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob); 872 (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob, 873 true); 874 } 875 876 877 /* 878 convert a NDR formatted blob to a ldif formatted dnsRecord 879 */ 880 static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx, 881 const struct ldb_val *in, struct ldb_val *out) 882 { 883 return ldif_write_NDR(ldb, mem_ctx, in, out, 884 sizeof(struct dnsp_DnssrvRpcRecord), 885 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord, 886 (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord, 887 true); 888 } 889 890 /* 891 convert a NDR formatted blob of a supplementalCredentials into text 892 */ 893 static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx, 894 const struct ldb_val *in, struct ldb_val *out) 895 { 896 return ldif_write_NDR(ldb, mem_ctx, in, out, 897 sizeof(struct supplementalCredentialsBlob), 898 (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob, 899 (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob, 900 true); 760 901 } 761 902 … … 764 905 const struct ldb_val *in, struct ldb_val *out) 765 906 { 766 *out = data_blob_string_const(data_blob_hex_string (mem_ctx, in));907 *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in)); 767 908 if (!out->data) { 768 909 return -1; … … 770 911 return 0; 771 912 } 913 914 /* 915 compare two dns 916 */ 917 static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx, 918 const struct ldb_val *v1, const struct ldb_val *v2) 919 { 920 struct ldb_dn *dn1 = NULL, *dn2 = NULL; 921 int ret; 922 923 if (dsdb_dn_is_deleted_val(v1)) { 924 /* If the DN is deleted, then we can't search for it */ 925 return -1; 926 } 927 928 if (dsdb_dn_is_deleted_val(v2)) { 929 /* If the DN is deleted, then we can't search for it */ 930 return -1; 931 } 932 933 dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1); 934 if ( ! ldb_dn_validate(dn1)) return -1; 935 936 dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2); 937 if ( ! ldb_dn_validate(dn2)) { 938 talloc_free(dn1); 939 return -1; 940 } 941 942 ret = ldb_dn_compare(dn1, dn2); 943 944 talloc_free(dn1); 945 talloc_free(dn2); 946 return ret; 947 } 948 949 static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx, 950 const struct ldb_val *in, struct ldb_val *out) 951 { 952 struct ldb_dn *dn; 953 int ret = -1; 954 955 out->length = 0; 956 out->data = NULL; 957 958 dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in); 959 if ( ! ldb_dn_validate(dn)) { 960 return LDB_ERR_INVALID_DN_SYNTAX; 961 } 962 963 /* By including the RMD_FLAGS of a deleted DN, we ensure it 964 * does not casually match a not deleted DN */ 965 if (dsdb_dn_is_deleted_val(in)) { 966 out->data = (uint8_t *)talloc_asprintf(mem_ctx, 967 "<RMD_FLAGS=%u>%s", 968 dsdb_dn_val_rmd_flags(in), 969 ldb_dn_get_casefold(dn)); 970 } else { 971 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn); 972 } 973 974 if (out->data == NULL) { 975 goto done; 976 } 977 out->length = strlen((char *)out->data); 978 979 ret = 0; 980 981 done: 982 talloc_free(dn); 983 984 return ret; 985 } 986 987 988 /* 989 write a 64 bit 2-part range 990 */ 991 static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx, 992 const struct ldb_val *in, struct ldb_val *out) 993 { 994 int64_t v; 995 int ret; 996 ret = val_to_int64(in, &v); 997 if (ret != LDB_SUCCESS) { 998 return ret; 999 } 1000 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu", 1001 (unsigned long)(v&0xFFFFFFFF), 1002 (unsigned long)(v>>32)); 1003 if (out->data == NULL) { 1004 ldb_oom(ldb); 1005 return LDB_ERR_OPERATIONS_ERROR; 1006 } 1007 out->length = strlen((char *)out->data); 1008 return LDB_SUCCESS; 1009 } 1010 1011 /* 1012 read a 64 bit 2-part range 1013 */ 1014 static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx, 1015 const struct ldb_val *in, struct ldb_val *out) 1016 { 1017 unsigned long high, low; 1018 char buf[64]; 1019 1020 if (memchr(in->data, '-', in->length) == NULL) { 1021 return ldb_handler_copy(ldb, mem_ctx, in, out); 1022 } 1023 1024 if (in->length > sizeof(buf)-1) { 1025 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 1026 } 1027 strncpy(buf, (const char *)in->data, in->length); 1028 buf[in->length] = 0; 1029 1030 if (sscanf(buf, "%lu-%lu", &low, &high) != 2) { 1031 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 1032 } 1033 1034 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu", 1035 (unsigned long long)(((uint64_t)high)<<32) | (low)); 1036 1037 if (out->data == NULL) { 1038 ldb_oom(ldb); 1039 return LDB_ERR_OPERATIONS_ERROR; 1040 } 1041 out->length = strlen((char *)out->data); 1042 return LDB_SUCCESS; 1043 } 1044 1045 /* 1046 when this operator_fn is set for a syntax, the backend calls is in 1047 preference to the comparison function. We are told the exact 1048 comparison operation that is needed, and we can return errors 1049 */ 1050 static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation, 1051 const struct ldb_schema_attribute *a, 1052 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched) 1053 { 1054 switch (operation) { 1055 case LDB_OP_AND: 1056 case LDB_OP_OR: 1057 case LDB_OP_NOT: 1058 case LDB_OP_SUBSTRING: 1059 case LDB_OP_APPROX: 1060 case LDB_OP_EXTENDED: 1061 /* handled in the backends */ 1062 return LDB_ERR_INAPPROPRIATE_MATCHING; 1063 1064 case LDB_OP_GREATER: 1065 case LDB_OP_LESS: 1066 case LDB_OP_EQUALITY: 1067 { 1068 TALLOC_CTX *tmp_ctx = talloc_new(ldb); 1069 int ret; 1070 if (tmp_ctx == NULL) { 1071 return ldb_oom(ldb); 1072 } 1073 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2); 1074 talloc_free(tmp_ctx); 1075 if (operation == LDB_OP_GREATER) { 1076 *matched = (ret > 0); 1077 } else if (operation == LDB_OP_LESS) { 1078 *matched = (ret < 0); 1079 } else { 1080 *matched = (ret == 0); 1081 } 1082 return LDB_SUCCESS; 1083 } 1084 1085 case LDB_OP_PRESENT: 1086 *matched = true; 1087 return LDB_SUCCESS; 1088 } 1089 1090 /* we shouldn't get here */ 1091 return LDB_ERR_INAPPROPRIATE_MATCHING; 1092 } 1093 1094 /* 1095 special operation for DNs, to take account of the RMD_FLAGS deleted bit 1096 */ 1097 static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation, 1098 const struct ldb_schema_attribute *a, 1099 const struct ldb_val *v1, const struct ldb_val *v2, bool *matched) 1100 { 1101 if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) { 1102 /* If the DN is deleted, then we can't search for it */ 1103 *matched = false; 1104 return LDB_SUCCESS; 1105 } 1106 return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched); 1107 } 1108 772 1109 773 1110 static const struct ldb_schema_syntax samba_syntaxes[] = { … … 777 1114 .ldif_write_fn = ldif_write_objectSid, 778 1115 .canonicalise_fn = ldif_canonicalise_objectSid, 779 .comparison_fn = ldif_comparison_objectSid 1116 .comparison_fn = ldif_comparison_objectSid, 1117 .operator_fn = samba_syntax_operator_fn 780 1118 },{ 781 1119 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR, … … 783 1121 .ldif_write_fn = ldif_write_ntSecurityDescriptor, 784 1122 .canonicalise_fn = ldb_handler_copy, 785 .comparison_fn = ldb_comparison_binary 1123 .comparison_fn = ldb_comparison_binary, 1124 .operator_fn = samba_syntax_operator_fn 786 1125 },{ 787 1126 .name = LDB_SYNTAX_SAMBA_GUID, … … 789 1128 .ldif_write_fn = ldif_write_objectGUID, 790 1129 .canonicalise_fn = ldif_canonicalise_objectGUID, 791 .comparison_fn = ldif_comparison_objectGUID 1130 .comparison_fn = ldif_comparison_objectGUID, 1131 .operator_fn = samba_syntax_operator_fn 792 1132 },{ 793 1133 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY, … … 795 1135 .ldif_write_fn = ldb_handler_copy, 796 1136 .canonicalise_fn = ldif_canonicalise_objectCategory, 797 .comparison_fn = ldif_comparison_objectCategory 1137 .comparison_fn = ldif_comparison_objectCategory, 1138 .operator_fn = samba_syntax_operator_fn 1139 },{ 1140 .name = LDB_SYNTAX_SAMBA_SCHEMAINFO, 1141 .ldif_read_fn = ldb_handler_copy, 1142 .ldif_write_fn = ldif_write_schemaInfo, 1143 .canonicalise_fn = ldb_handler_copy, 1144 .comparison_fn = ldb_comparison_binary, 1145 .operator_fn = samba_syntax_operator_fn 798 1146 },{ 799 1147 .name = LDB_SYNTAX_SAMBA_PREFIX_MAP, … … 801 1149 .ldif_write_fn = ldif_write_prefixMap, 802 1150 .canonicalise_fn = ldif_canonicalise_prefixMap, 803 .comparison_fn = ldif_comparison_prefixMap 1151 .comparison_fn = ldif_comparison_prefixMap, 1152 .operator_fn = samba_syntax_operator_fn 804 1153 },{ 805 1154 .name = LDB_SYNTAX_SAMBA_INT32, … … 807 1156 .ldif_write_fn = ldb_handler_copy, 808 1157 .canonicalise_fn = ldif_canonicalise_int32, 809 .comparison_fn = ldif_comparison_int32 1158 .comparison_fn = ldif_comparison_int32, 1159 .operator_fn = samba_syntax_operator_fn 810 1160 },{ 811 1161 .name = LDB_SYNTAX_SAMBA_REPSFROMTO, … … 813 1163 .ldif_write_fn = ldif_write_repsFromTo, 814 1164 .canonicalise_fn = ldb_handler_copy, 815 .comparison_fn = ldb_comparison_binary 1165 .comparison_fn = ldb_comparison_binary, 1166 .operator_fn = samba_syntax_operator_fn 816 1167 },{ 817 1168 .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA, … … 819 1170 .ldif_write_fn = ldif_write_replPropertyMetaData, 820 1171 .canonicalise_fn = ldb_handler_copy, 821 .comparison_fn = ldb_comparison_binary 1172 .comparison_fn = ldb_comparison_binary, 1173 .operator_fn = samba_syntax_operator_fn 822 1174 },{ 823 1175 .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR, … … 825 1177 .ldif_write_fn = ldif_write_replUpToDateVector, 826 1178 .canonicalise_fn = ldb_handler_copy, 827 .comparison_fn = ldb_comparison_binary 828 }, 1179 .comparison_fn = ldb_comparison_binary, 1180 .operator_fn = samba_syntax_operator_fn 1181 },{ 1182 .name = DSDB_SYNTAX_BINARY_DN, 1183 .ldif_read_fn = ldb_handler_copy, 1184 .ldif_write_fn = ldb_handler_copy, 1185 .canonicalise_fn = dsdb_dn_binary_canonicalise, 1186 .comparison_fn = dsdb_dn_binary_comparison, 1187 .operator_fn = samba_syntax_operator_fn 1188 },{ 1189 .name = DSDB_SYNTAX_STRING_DN, 1190 .ldif_read_fn = ldb_handler_copy, 1191 .ldif_write_fn = ldb_handler_copy, 1192 .canonicalise_fn = dsdb_dn_string_canonicalise, 1193 .comparison_fn = dsdb_dn_string_comparison, 1194 .operator_fn = samba_syntax_operator_fn 1195 },{ 1196 .name = LDB_SYNTAX_DN, 1197 .ldif_read_fn = ldb_handler_copy, 1198 .ldif_write_fn = ldb_handler_copy, 1199 .canonicalise_fn = samba_ldb_dn_link_canonicalise, 1200 .comparison_fn = samba_ldb_dn_link_comparison, 1201 .operator_fn = samba_syntax_operator_dn 1202 },{ 1203 .name = LDB_SYNTAX_SAMBA_RANGE64, 1204 .ldif_read_fn = ldif_read_range64, 1205 .ldif_write_fn = ldif_write_range64, 1206 .canonicalise_fn = ldif_canonicalise_int64, 1207 .comparison_fn = ldif_comparison_int64, 1208 .operator_fn = samba_syntax_operator_fn 1209 },{ 1210 .name = LDB_SYNTAX_SAMBA_DNSRECORD, 1211 .ldif_read_fn = ldb_handler_copy, 1212 .ldif_write_fn = ldif_write_dnsRecord, 1213 .canonicalise_fn = ldb_handler_copy, 1214 .comparison_fn = ldb_comparison_binary, 1215 .operator_fn = samba_syntax_operator_fn 1216 },{ 1217 .name = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS, 1218 .ldif_read_fn = ldb_handler_copy, 1219 .ldif_write_fn = ldif_write_supplementalCredentialsBlob, 1220 .canonicalise_fn = ldb_handler_copy, 1221 .comparison_fn = ldb_comparison_binary, 1222 .operator_fn = samba_syntax_operator_fn 1223 } 829 1224 }; 830 1225 … … 842 1237 },{ 843 1238 .name = "WKGUID", 1239 .read_fn = ldb_handler_copy, 1240 .write_clear_fn = ldb_handler_copy, 1241 .write_hex_fn = ldb_handler_copy 1242 },{ 1243 .name = "RMD_INVOCID", 1244 .read_fn = extended_dn_read_GUID, 1245 .write_clear_fn = ldif_write_objectGUID, 1246 .write_hex_fn = extended_dn_write_hex 1247 },{ 1248 .name = "RMD_FLAGS", 1249 .read_fn = ldb_handler_copy, 1250 .write_clear_fn = ldb_handler_copy, 1251 .write_hex_fn = ldb_handler_copy 1252 },{ 1253 .name = "RMD_ADDTIME", 1254 .read_fn = ldb_handler_copy, 1255 .write_clear_fn = ldb_handler_copy, 1256 .write_hex_fn = ldb_handler_copy 1257 },{ 1258 .name = "RMD_CHANGETIME", 1259 .read_fn = ldb_handler_copy, 1260 .write_clear_fn = ldb_handler_copy, 1261 .write_hex_fn = ldb_handler_copy 1262 },{ 1263 .name = "RMD_LOCAL_USN", 1264 .read_fn = ldb_handler_copy, 1265 .write_clear_fn = ldb_handler_copy, 1266 .write_hex_fn = ldb_handler_copy 1267 },{ 1268 .name = "RMD_ORIGINATING_USN", 1269 .read_fn = ldb_handler_copy, 1270 .write_clear_fn = ldb_handler_copy, 1271 .write_hex_fn = ldb_handler_copy 1272 },{ 1273 .name = "RMD_VERSION", 844 1274 .read_fn = ldb_handler_copy, 845 1275 .write_clear_fn = ldb_handler_copy, … … 855 1285 { "objectSid", LDB_SYNTAX_SAMBA_SID }, 856 1286 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID }, 1287 { "tokenGroups", LDB_SYNTAX_SAMBA_SID }, 857 1288 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR }, 858 { "objectGUID", LDB_SYNTAX_SAMBA_GUID }, 859 { "invocationId", LDB_SYNTAX_SAMBA_GUID }, 860 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID }, 861 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID }, 862 { "parentGUID", LDB_SYNTAX_SAMBA_GUID }, 863 { "siteGUID", LDB_SYNTAX_SAMBA_GUID }, 864 { "pKTGUID", LDB_SYNTAX_SAMBA_GUID }, 865 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID }, 866 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID }, 867 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID }, 1289 { "oMSyntax", LDB_SYNTAX_SAMBA_INT32 }, 868 1290 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY }, 1291 { "schemaInfo", LDB_SYNTAX_SAMBA_SCHEMAINFO }, 869 1292 { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP }, 870 1293 { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO }, … … 872 1295 { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA }, 873 1296 { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR }, 1297 { "rIDAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 }, 1298 { "rIDPreviousAllocationPool", LDB_SYNTAX_SAMBA_RANGE64 }, 1299 { "rIDAvailablePool", LDB_SYNTAX_SAMBA_RANGE64 }, 1300 1301 /* 1302 * these are extracted by searching 1303 * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4)) 1304 */ 1305 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID }, 1306 { "categoryId", LDB_SYNTAX_SAMBA_GUID }, 1307 { "controlAccessRights", LDB_SYNTAX_SAMBA_GUID }, 1308 { "currMachineId", LDB_SYNTAX_SAMBA_GUID }, 1309 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID }, 1310 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID }, 1311 { "implementedCategories", LDB_SYNTAX_SAMBA_GUID }, 1312 { "msDS-AzObjectGuid", LDB_SYNTAX_SAMBA_GUID }, 1313 { "msDFSR-ContentSetGuid", LDB_SYNTAX_SAMBA_GUID }, 1314 { "msDFSR-ReplicationGroupGuid", LDB_SYNTAX_SAMBA_GUID }, 1315 { "mSMQDigests", LDB_SYNTAX_SAMBA_GUID }, 1316 { "mSMQOwnerID", LDB_SYNTAX_SAMBA_GUID }, 1317 { "mSMQQMID", LDB_SYNTAX_SAMBA_GUID }, 1318 { "mSMQQueueType", LDB_SYNTAX_SAMBA_GUID }, 1319 { "mSMQSites", LDB_SYNTAX_SAMBA_GUID }, 1320 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID }, 1321 { "objectGUID", LDB_SYNTAX_SAMBA_GUID }, 1322 { "pKTGuid", LDB_SYNTAX_SAMBA_GUID }, 1323 { "requiredCategories", LDB_SYNTAX_SAMBA_GUID }, 1324 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID }, 1325 { "siteGUID", LDB_SYNTAX_SAMBA_GUID }, 1326 { "msDFS-GenerationGUIDv2", LDB_SYNTAX_SAMBA_GUID }, 1327 { "msDFS-LinkIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID }, 1328 { "msDFS-NamespaceIdentityGUIDv2", LDB_SYNTAX_SAMBA_GUID }, 1329 1330 /* 1331 * these are known to be GUIDs 1332 */ 1333 { "invocationId", LDB_SYNTAX_SAMBA_GUID }, 1334 { "parentGUID", LDB_SYNTAX_SAMBA_GUID }, 1335 { "msDS-OptionalFeatureGUID", LDB_SYNTAX_SAMBA_GUID }, 1336 1337 /* These NDR encoded things we want to be able to read with --show-binary */ 1338 { "dnsRecord", LDB_SYNTAX_SAMBA_DNSRECORD }, 1339 { "supplementalCredentials", LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS} 874 1340 }; 875 1341 876 1342 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name) 877 1343 { 878 u int32_t j;1344 unsigned int j; 879 1345 const struct ldb_schema_syntax *s = NULL; 880 1346 … … 890 1356 const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name) 891 1357 { 892 u int32_t j;1358 unsigned int j; 893 1359 const struct ldb_schema_syntax *s = NULL; 894 1360 … … 908 1374 int ldb_register_samba_handlers(struct ldb_context *ldb) 909 1375 { 910 uint32_t i; 1376 unsigned int i; 1377 int ret; 1378 1379 if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) { 1380 return LDB_SUCCESS; 1381 } 911 1382 912 1383 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) { 913 int ret;914 1384 const struct ldb_schema_syntax *s = NULL; 915 1385 … … 921 1391 922 1392 if (!s) { 923 return -1;1393 return LDB_ERR_OPERATIONS_ERROR; 924 1394 } 925 1395 … … 931 1401 932 1402 for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) { 933 int ret;934 1403 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]); 935 1404 if (ret != LDB_SUCCESS) { … … 937 1406 } 938 1407 939 1408 } 1409 1410 ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1); 1411 if (ret != LDB_SUCCESS) { 1412 return ret; 940 1413 } 941 1414 -
trunk/server/source4/lib/ldb-samba/ldif_handlers.h
r414 r745 6 6 #define LDB_SYNTAX_SAMBA_GUID "LDB_SYNTAX_SAMBA_GUID" 7 7 #define LDB_SYNTAX_SAMBA_OBJECT_CATEGORY "LDB_SYNTAX_SAMBA_OBJECT_CATEGORY" 8 #define LDB_SYNTAX_SAMBA_SCHEMAINFO "LDB_SYNTAX_SAMBA_SCHEMAINFO" 8 9 #define LDB_SYNTAX_SAMBA_PREFIX_MAP "LDB_SYNTAX_SAMBA_PREFIX_MAP" 9 10 #define LDB_SYNTAX_SAMBA_INT32 "LDB_SYNTAX_SAMBA_INT32" … … 11 12 #define LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA "LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA" 12 13 #define LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR "LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR" 13 14 #define LDB_SYNTAX_SAMBA_RANGE64 "LDB_SYNTAX_SAMBA_RANGE64" 15 #define LDB_SYNTAX_SAMBA_DNSRECORD "LDB_SYNTAX_SAMBA_DNSRECORD" 16 #define LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS "LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS" 14 17 #include "lib/ldb-samba/ldif_handlers_proto.h" 15 18 -
trunk/server/source4/lib/ldb/common/attrib_handlers.c
r414 r745 3 3 4 4 Copyright (C) Andrew Tridgell 2005 5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2009 5 6 6 7 ** NOTE! The following LGPL license applies to the ldb … … 55 56 { 56 57 char *s, *t; 57 int l;58 size_t l; 58 59 59 60 if (!in || !out || !(in->data)) { … … 100 101 } 101 102 103 /* length limited conversion of a ldb_val to a int32_t */ 104 static int val_to_int64(const struct ldb_val *in, int64_t *v) 105 { 106 char *end; 107 char buf[64]; 108 109 /* make sure we don't read past the end of the data */ 110 if (in->length > sizeof(buf)-1) { 111 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 112 } 113 strncpy(buf, (char *)in->data, in->length); 114 buf[in->length] = 0; 115 116 /* We've to use "strtoll" here to have the intended overflows. 117 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */ 118 *v = (int64_t) strtoll(buf, &end, 0); 119 if (*end != 0) { 120 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 121 } 122 return LDB_SUCCESS; 123 } 102 124 103 125 … … 109 131 const struct ldb_val *in, struct ldb_val *out) 110 132 { 111 char *end; 112 long long i = strtoll((char *)in->data, &end, 0); 113 if (*end != 0) { 114 return -1; 115 } 116 out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lld", i); 133 int64_t i; 134 int ret; 135 136 ret = val_to_int64(in, &i); 137 if (ret != LDB_SUCCESS) { 138 return ret; 139 } 140 out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i); 117 141 if (out->data == NULL) { 118 return -1; 142 ldb_oom(ldb); 143 return LDB_ERR_OPERATIONS_ERROR; 119 144 } 120 145 out->length = strlen((char *)out->data); … … 128 153 const struct ldb_val *v1, const struct ldb_val *v2) 129 154 { 130 return strtoll((char *)v1->data, NULL, 0) - strtoll((char *)v2->data, NULL, 0); 155 int64_t i1=0, i2=0; 156 val_to_int64(v1, &i1); 157 val_to_int64(v2, &i2); 158 if (i1 == i2) return 0; 159 return i1 > i2? 1 : -1; 131 160 } 132 161 … … 241 270 talloc_free(b1); 242 271 talloc_free(b2); 243 if (memcmp(s1, s2, MIN(n1, n2)) == 0) { 272 ret = memcmp(s1, s2, MIN(n1, n2)); 273 if (ret == 0) { 244 274 if (n1 == n2) return 0; 245 275 if (n1 > n2) { … … 249 279 } 250 280 } 281 return ret; 251 282 } 252 283 … … 338 369 const struct ldb_val *v1, const struct ldb_val *v2) 339 370 { 340 time_t t1, t2; 341 t1 = ldb_string_to_time((char *)v1->data); 342 t2 = ldb_string_to_time((char *)v2->data); 343 return (int)t2 - (int)t1; 371 time_t t1=0, t2=0; 372 ldb_val_to_time(v1, &t1); 373 ldb_val_to_time(v2, &t2); 374 if (t1 == t2) return 0; 375 return t1 > t2? 1 : -1; 344 376 } 345 377 … … 350 382 const struct ldb_val *in, struct ldb_val *out) 351 383 { 352 time_t t = ldb_string_to_time((char *)in->data); 384 time_t t; 385 int ret; 386 ret = ldb_val_to_time(in, &t); 387 if (ret != LDB_SUCCESS) { 388 return ret; 389 } 353 390 out->data = (uint8_t *)ldb_timestring(mem_ctx, t); 354 391 if (out->data == NULL) { 355 return -1; 392 ldb_oom(ldb); 393 return LDB_ERR_OPERATIONS_ERROR; 356 394 } 357 395 out->length = strlen((char *)out->data); … … 421 459 const char *syntax) 422 460 { 423 int i;461 unsigned int i; 424 462 unsigned num_handlers = sizeof(ldb_standard_syntaxes)/sizeof(ldb_standard_syntaxes[0]); 425 463 /* TODO: should be replaced with a binary search */ … … 431 469 return NULL; 432 470 } 471 472 int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx, 473 ldb_attr_handler_t canonicalise_fn, 474 const struct ldb_val *v1, 475 const struct ldb_val *v2) 476 { 477 int ret, ret1, ret2; 478 struct ldb_val v1_canon, v2_canon; 479 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 480 481 /* I could try and bail if tmp_ctx was NULL, but what return 482 * value would I use? 483 * 484 * It seems easier to continue on the NULL context 485 */ 486 ret1 = canonicalise_fn(ldb, tmp_ctx, v1, &v1_canon); 487 ret2 = canonicalise_fn(ldb, tmp_ctx, v2, &v2_canon); 488 489 if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) { 490 ret = ldb_comparison_binary(ldb, mem_ctx, &v1_canon, &v2_canon); 491 } else { 492 ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2); 493 } 494 talloc_free(tmp_ctx); 495 return ret; 496 } -
trunk/server/source4/lib/ldb/common/ldb.c
r414 r745 35 35 #define TEVENT_DEPRECATED 1 36 36 #include "ldb_private.h" 37 #include "ldb.h" 37 38 38 39 static int ldb_context_destructor(void *ptr) … … 92 93 struct ldb_context *ldb; 93 94 int ret; 95 const char *modules_path = getenv("LDB_MODULES_PATH"); 96 97 if (modules_path == NULL) { 98 modules_path = LDB_MODULESDIR; 99 } 100 101 ret = ldb_modules_load(modules_path, LDB_VERSION); 102 if (ret != LDB_SUCCESS) { 103 return NULL; 104 } 94 105 95 106 ldb = talloc_zero(mem_ctx, struct ldb_context); 96 /* FIXME: Hack a new event context so that CMD line utilities work 97 * until we have them all converted */ 107 /* A new event context so that callers who don't want ldb 108 * operating on thier global event context can work without 109 * having to provide their own private one explicitly */ 98 110 if (ev_ctx == NULL) { 99 ev_ctx = tevent_context_init( talloc_autofree_context());111 ev_ctx = tevent_context_init(ldb); 100 112 tevent_set_debug(ev_ctx, ldb_tevent_debug, ldb); 101 113 tevent_loop_allow_nesting(ev_ctx); … … 103 115 104 116 ret = ldb_setup_wellknown_attributes(ldb); 105 if (ret != 0) {117 if (ret != LDB_SUCCESS) { 106 118 talloc_free(ldb); 107 119 return NULL; … … 218 230 { 219 231 int ret; 220 c onst char *url2;232 char *url2; 221 233 /* We seem to need to do this here, or else some utilities don't 222 234 * get ldb backends */ … … 229 241 return LDB_ERR_OPERATIONS_ERROR; 230 242 } 231 ret = ldb_set_opaque(ldb, "ldb_url", talloc_strdup(ldb, url2));243 ret = ldb_set_opaque(ldb, "ldb_url", url2); 232 244 if (ret != LDB_SUCCESS) { 233 245 return ret; 234 246 } 235 247 236 ret = ldb_ connect_backend(ldb, url, options, &ldb->modules);248 ret = ldb_module_connect_backend(ldb, url, options, &ldb->modules); 237 249 if (ret != LDB_SUCCESS) { 238 250 return ret; … … 286 298 } 287 299 300 301 302 /* 303 set an ldb error based on file:line 304 */ 305 int ldb_error_at(struct ldb_context *ldb, int ecode, 306 const char *reason, const char *file, int line) 307 { 308 if (reason == NULL) { 309 reason = ldb_strerror(ecode); 310 } 311 ldb_asprintf_errstring(ldb, "%s at %s:%d", reason, file, line); 312 return ecode; 313 } 314 315 288 316 #define FIRST_OP_NOERR(ldb, op) do { \ 289 317 module = ldb->modules; \ 290 318 while (module && module->ops->op == NULL) module = module->next; \ 319 if ((ldb->flags & LDB_FLG_ENABLE_TRACING) && module) { \ 320 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_trace_request: (%s)->" #op, \ 321 module->ops->name); \ 322 } \ 291 323 } while (0) 292 324 … … 336 368 } 337 369 } 370 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { 371 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "start ldb transaction error: %s", 372 ldb_errstring(module->ldb)); 373 } 338 374 return status; 339 375 } … … 375 411 /* if a module fails the prepare then we need 376 412 to call the end transaction for everyone */ 377 FIRST_OP(ldb, end_transaction);378 module->ops-> end_transaction(module);413 FIRST_OP(ldb, del_transaction); 414 module->ops->del_transaction(module); 379 415 if (ldb->err_string == NULL) { 380 416 /* no error string was setup by the backend */ … … 383 419 ldb_strerror(status), 384 420 status); 421 } 422 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { 423 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "prepare commit transaction error: %s", 424 ldb_errstring(module->ldb)); 385 425 } 386 426 } … … 433 473 status); 434 474 } 475 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { 476 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "commit ldb transaction error: %s", 477 ldb_errstring(module->ldb)); 478 } 435 479 /* cancel the transaction */ 436 480 FIRST_OP(ldb, del_transaction); … … 478 522 status); 479 523 } 524 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { 525 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "cancel ldb transaction error: %s", 526 ldb_errstring(module->ldb)); 527 } 480 528 } 481 529 return status; 482 530 } 531 532 /* 533 cancel a transaction with no error if no transaction is pending 534 used when we fork() to clear any parent transactions 535 */ 536 int ldb_transaction_cancel_noerr(struct ldb_context *ldb) 537 { 538 if (ldb->transaction_active > 0) { 539 return ldb_transaction_cancel(ldb); 540 } 541 return LDB_SUCCESS; 542 } 543 483 544 484 545 /* autostarts a transacion if none active */ … … 633 694 { 634 695 TALLOC_CTX *tmp_ctx = talloc_new(req); 635 int i;696 unsigned int i; 636 697 637 698 switch (req->operation) { … … 706 767 } else { 707 768 for (i=0; req->controls && req->controls[i]; i++) { 708 ldb_debug_add(ldb, " control: %s crit:%u data:%s\n", 709 req->controls[i]->oid, 710 req->controls[i]->critical, 711 req->controls[i]->data?"yes":"no"); 769 if (req->controls[i]->oid) { 770 ldb_debug_add(ldb, " control: %s crit:%u data:%s\n", 771 req->controls[i]->oid, 772 req->controls[i]->critical, 773 req->controls[i]->data?"yes":"no"); 774 } 712 775 } 713 776 } … … 716 779 717 780 talloc_free(tmp_ctx); 781 } 782 783 /* 784 check that the element flags don't have any internal bits set 785 */ 786 static int ldb_msg_check_element_flags(struct ldb_context *ldb, 787 const struct ldb_message *message) 788 { 789 unsigned i; 790 for (i=0; i<message->num_elements; i++) { 791 if (message->elements[i].flags & LDB_FLAG_INTERNAL_MASK) { 792 ldb_asprintf_errstring(ldb, "Invalid element flags 0x%08x on element %s in %s\n", 793 message->elements[i].flags, message->elements[i].name, 794 ldb_dn_get_linearized(message->dn)); 795 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; 796 } 797 } 798 return LDB_SUCCESS; 718 799 } 719 800 … … 743 824 switch (req->operation) { 744 825 case LDB_SEARCH: 826 /* due to "ldb_build_search_req" base DN always != NULL */ 827 if (!ldb_dn_validate(req->op.search.base)) { 828 ldb_asprintf_errstring(ldb, "ldb_search: invalid basedn '%s'", 829 ldb_dn_get_linearized(req->op.search.base)); 830 return LDB_ERR_INVALID_DN_SYNTAX; 831 } 745 832 FIRST_OP(ldb, search); 746 833 ret = module->ops->search(module, req); 747 834 break; 748 835 case LDB_ADD: 836 if (!ldb_dn_validate(req->op.add.message->dn)) { 837 ldb_asprintf_errstring(ldb, "ldb_add: invalid dn '%s'", 838 ldb_dn_get_linearized(req->op.add.message->dn)); 839 return LDB_ERR_INVALID_DN_SYNTAX; 840 } 841 /* 842 * we have to normalize here, as so many places 843 * in modules and backends assume we don't have two 844 * elements with the same name 845 */ 846 ret = ldb_msg_normalize(ldb, req, req->op.add.message, 847 discard_const(&req->op.add.message)); 848 if (ret != LDB_SUCCESS) { 849 ldb_oom(ldb); 850 return LDB_ERR_OPERATIONS_ERROR; 851 } 749 852 FIRST_OP(ldb, add); 853 ret = ldb_msg_check_element_flags(ldb, req->op.add.message); 854 if (ret != LDB_SUCCESS) { 855 return ret; 856 } 750 857 ret = module->ops->add(module, req); 751 858 break; 752 859 case LDB_MODIFY: 860 if (!ldb_dn_validate(req->op.mod.message->dn)) { 861 ldb_asprintf_errstring(ldb, "ldb_modify: invalid dn '%s'", 862 ldb_dn_get_linearized(req->op.mod.message->dn)); 863 return LDB_ERR_INVALID_DN_SYNTAX; 864 } 753 865 FIRST_OP(ldb, modify); 866 ret = ldb_msg_check_element_flags(ldb, req->op.mod.message); 867 if (ret != LDB_SUCCESS) { 868 return ret; 869 } 754 870 ret = module->ops->modify(module, req); 755 871 break; 756 872 case LDB_DELETE: 873 if (!ldb_dn_validate(req->op.del.dn)) { 874 ldb_asprintf_errstring(ldb, "ldb_delete: invalid dn '%s'", 875 ldb_dn_get_linearized(req->op.del.dn)); 876 return LDB_ERR_INVALID_DN_SYNTAX; 877 } 757 878 FIRST_OP(ldb, del); 758 879 ret = module->ops->del(module, req); 759 880 break; 760 881 case LDB_RENAME: 882 if (!ldb_dn_validate(req->op.rename.olddn)) { 883 ldb_asprintf_errstring(ldb, "ldb_rename: invalid olddn '%s'", 884 ldb_dn_get_linearized(req->op.rename.olddn)); 885 return LDB_ERR_INVALID_DN_SYNTAX; 886 } 887 if (!ldb_dn_validate(req->op.rename.newdn)) { 888 ldb_asprintf_errstring(ldb, "ldb_rename: invalid newdn '%s'", 889 ldb_dn_get_linearized(req->op.rename.newdn)); 890 return LDB_ERR_INVALID_DN_SYNTAX; 891 } 761 892 FIRST_OP(ldb, rename); 762 893 ret = module->ops->rename(module, req); … … 794 925 { 795 926 struct ldb_result *res; 796 int n;927 unsigned int n; 797 928 798 929 res = talloc_get_type(req->context, struct ldb_result); … … 852 983 } 853 984 854 int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares) 855 { 985 int ldb_modify_default_callback(struct ldb_request *req, struct ldb_reply *ares) 986 { 987 struct ldb_result *res; 988 unsigned int n; 856 989 int ret; 990 991 res = talloc_get_type(req->context, struct ldb_result); 857 992 858 993 if (!ares) { … … 866 1001 } 867 1002 1003 switch (ares->type) { 1004 case LDB_REPLY_REFERRAL: 1005 if (res->refs) { 1006 for (n = 0; res->refs[n]; n++) /*noop*/ ; 1007 } else { 1008 n = 0; 1009 } 1010 1011 res->refs = talloc_realloc(res, res->refs, char *, n + 2); 1012 if (! res->refs) { 1013 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 1014 } 1015 1016 res->refs[n] = talloc_move(res->refs, &ares->referral); 1017 res->refs[n + 1] = NULL; 1018 break; 1019 1020 case LDB_REPLY_DONE: 1021 talloc_free(ares); 1022 return ldb_request_done(req, LDB_SUCCESS); 1023 default: 1024 talloc_free(ares); 1025 ldb_set_errstring(req->handle->ldb, "Invalid reply type!"); 1026 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 1027 } 1028 1029 talloc_free(ares); 1030 return ldb_request_done(req, LDB_SUCCESS); 1031 } 1032 1033 int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares) 1034 { 1035 int ret; 1036 1037 if (!ares) { 1038 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 1039 } 1040 1041 if (ares->error != LDB_SUCCESS) { 1042 ret = ares->error; 1043 talloc_free(ares); 1044 return ldb_request_done(req, ret); 1045 } 1046 868 1047 if (ares->type != LDB_REPLY_DONE) { 869 1048 talloc_free(ares); … … 878 1057 int ldb_build_search_req_ex(struct ldb_request **ret_req, 879 1058 struct ldb_context *ldb, 880 void*mem_ctx,1059 TALLOC_CTX *mem_ctx, 881 1060 struct ldb_dn *base, 882 1061 enum ldb_scope scope, … … 928 1107 if (parent) { 929 1108 req->handle->nesting++; 1109 req->handle->parent = parent; 1110 req->handle->flags = parent->handle->flags; 930 1111 } 931 1112 … … 936 1117 int ldb_build_search_req(struct ldb_request **ret_req, 937 1118 struct ldb_context *ldb, 938 void*mem_ctx,1119 TALLOC_CTX *mem_ctx, 939 1120 struct ldb_dn *base, 940 1121 enum ldb_scope scope, … … 966 1147 int ldb_build_add_req(struct ldb_request **ret_req, 967 1148 struct ldb_context *ldb, 968 void*mem_ctx,1149 TALLOC_CTX *mem_ctx, 969 1150 const struct ldb_message *message, 970 1151 struct ldb_control **controls, … … 999 1180 if (parent) { 1000 1181 req->handle->nesting++; 1182 req->handle->parent = parent; 1183 req->handle->flags = parent->handle->flags; 1001 1184 } 1002 1185 … … 1008 1191 int ldb_build_mod_req(struct ldb_request **ret_req, 1009 1192 struct ldb_context *ldb, 1010 void*mem_ctx,1193 TALLOC_CTX *mem_ctx, 1011 1194 const struct ldb_message *message, 1012 1195 struct ldb_control **controls, … … 1041 1224 if (parent) { 1042 1225 req->handle->nesting++; 1226 req->handle->parent = parent; 1227 req->handle->flags = parent->handle->flags; 1043 1228 } 1044 1229 … … 1050 1235 int ldb_build_del_req(struct ldb_request **ret_req, 1051 1236 struct ldb_context *ldb, 1052 void*mem_ctx,1237 TALLOC_CTX *mem_ctx, 1053 1238 struct ldb_dn *dn, 1054 1239 struct ldb_control **controls, … … 1083 1268 if (parent) { 1084 1269 req->handle->nesting++; 1270 req->handle->parent = parent; 1271 req->handle->flags = parent->handle->flags; 1085 1272 } 1086 1273 … … 1092 1279 int ldb_build_rename_req(struct ldb_request **ret_req, 1093 1280 struct ldb_context *ldb, 1094 void*mem_ctx,1281 TALLOC_CTX *mem_ctx, 1095 1282 struct ldb_dn *olddn, 1096 1283 struct ldb_dn *newdn, … … 1127 1314 if (parent) { 1128 1315 req->handle->nesting++; 1316 req->handle->parent = parent; 1317 req->handle->flags = parent->handle->flags; 1129 1318 } 1130 1319 … … 1165 1354 int ldb_build_extended_req(struct ldb_request **ret_req, 1166 1355 struct ldb_context *ldb, 1167 void*mem_ctx,1356 TALLOC_CTX *mem_ctx, 1168 1357 const char *oid, 1169 1358 void *data, … … 1200 1389 if (parent) { 1201 1390 req->handle->nesting++; 1391 req->handle->parent = parent; 1392 req->handle->flags = parent->handle->flags; 1202 1393 } 1203 1394 … … 1292 1483 ldb_search_default_callback, 1293 1484 NULL); 1485 ldb_req_set_location(req, "ldb_search"); 1294 1486 1295 1487 if (ret != LDB_SUCCESS) goto done; … … 1335 1527 ldb_op_default_callback, 1336 1528 NULL); 1529 ldb_req_set_location(req, "ldb_add"); 1337 1530 1338 1531 if (ret != LDB_SUCCESS) return ret; … … 1365 1558 ldb_op_default_callback, 1366 1559 NULL); 1560 ldb_req_set_location(req, "ldb_modify"); 1367 1561 1368 1562 if (ret != LDB_SUCCESS) return ret; … … 1390 1584 ldb_op_default_callback, 1391 1585 NULL); 1586 ldb_req_set_location(req, "ldb_delete"); 1392 1587 1393 1588 if (ret != LDB_SUCCESS) return ret; … … 1416 1611 ldb_op_default_callback, 1417 1612 NULL); 1613 ldb_req_set_location(req, "ldb_rename"); 1418 1614 1419 1615 if (ret != LDB_SUCCESS) return ret; … … 1640 1836 ldb->flags = flags; 1641 1837 } 1838 1839 1840 /* 1841 set the location in a ldb request. Used for debugging 1842 */ 1843 void ldb_req_set_location(struct ldb_request *req, const char *location) 1844 { 1845 if (req && req->handle) { 1846 req->handle->location = location; 1847 } 1848 } 1849 1850 /* 1851 return the location set with dsdb_req_set_location 1852 */ 1853 const char *ldb_req_location(struct ldb_request *req) 1854 { 1855 return req->handle->location; 1856 } 1857 1858 /** 1859 mark a request as untrusted. This tells the rootdse module to remove 1860 unregistered controls 1861 */ 1862 void ldb_req_mark_untrusted(struct ldb_request *req) 1863 { 1864 req->handle->flags |= LDB_HANDLE_FLAG_UNTRUSTED; 1865 } 1866 1867 /** 1868 mark a request as trusted. 1869 */ 1870 void ldb_req_mark_trusted(struct ldb_request *req) 1871 { 1872 req->handle->flags &= ~LDB_HANDLE_FLAG_UNTRUSTED; 1873 } 1874 1875 /** 1876 return true is a request is untrusted 1877 */ 1878 bool ldb_req_is_untrusted(struct ldb_request *req) 1879 { 1880 return (req->handle->flags & LDB_HANDLE_FLAG_UNTRUSTED) != 0; 1881 } -
trunk/server/source4/lib/ldb/common/ldb_attributes.c
r414 r745 50 50 const struct ldb_schema_syntax *syntax) 51 51 { 52 int i, n;52 unsigned int i, n; 53 53 struct ldb_schema_attribute *a; 54 54 … … 123 123 const char *name) 124 124 { 125 int i, e, b = 0, r; 125 /* for binary search we need signed variables */ 126 unsigned int i, e, b = 0; 127 int r; 126 128 const struct ldb_schema_attribute *def = &ldb_attribute_default; 127 129 … … 135 137 e = ldb->schema.num_attributes - 1; 136 138 137 while (b <= e) { 138 139 while ((b <= e) && (e != (unsigned int) -1)) { 139 140 i = (b + e) / 2; 140 141 … … 148 149 b = i + 1; 149 150 } 150 151 151 } 152 152 … … 180 180 { 181 181 const struct ldb_schema_attribute *a; 182 int i;182 ptrdiff_t i; 183 183 184 184 a = ldb_schema_attribute_by_name_internal(ldb, name); … … 233 233 { "objectClass", LDB_SYNTAX_OBJECTCLASS } 234 234 }; 235 int i;235 unsigned int i; 236 236 int ret; 237 237 … … 255 255 const struct ldb_dn_extended_syntax *syntax) 256 256 { 257 int n;257 unsigned int n; 258 258 struct ldb_dn_extended_syntax *a; 259 259 … … 285 285 const char *name) 286 286 { 287 int i;287 unsigned int i; 288 288 for (i=0; i < ldb->schema.num_dn_extended_syntax; i++) { 289 289 if (ldb_attr_cmp(ldb->schema.dn_extended_syntax[i].name, name) == 0) { -
trunk/server/source4/lib/ldb/common/ldb_controls.c
r414 r745 38 38 struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid) 39 39 { 40 int i;40 unsigned int i; 41 41 42 42 if (req->controls != NULL) { 43 43 for (i = 0; req->controls[i]; i++) { 44 if ( strcmp(oid, req->controls[i]->oid) == 0) {44 if (req->controls[i]->oid && strcmp(oid, req->controls[i]->oid) == 0) { 45 45 break; 46 46 } … … 57 57 struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid) 58 58 { 59 int i;59 unsigned int i; 60 60 61 61 if (rep->controls != NULL) { 62 62 for (i = 0; rep->controls[i]; i++) { 63 if ( strcmp(oid, rep->controls[i]->oid) == 0) {63 if (rep->controls[i]->oid && strcmp(oid, rep->controls[i]->oid) == 0) { 64 64 break; 65 65 } … … 72 72 } 73 73 74 /* saves the current controls list into the "saver" and replace the one in req with a new one excluding 75 the "exclude" control */ 76 /* returns 0 on error */ 77 int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver) 74 /* 75 * Saves the current controls list into the "saver" (can also be NULL) and 76 * replace the one in "req" with a new one excluding the "exclude" control 77 * (if it is NULL then the list remains the same) 78 * 79 * Returns 0 on error. 80 */ 81 int ldb_save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver) 78 82 { 79 struct ldb_control **lcs; 80 int i, j; 81 82 *saver = req->controls; 83 for (i = 0; req->controls[i]; i++); 84 if (i == 1) { 83 struct ldb_control **lcs, **lcs_old; 84 unsigned int i, j; 85 86 lcs_old = req->controls; 87 if (saver != NULL) { 88 *saver = lcs_old; 89 } 90 91 for (i = 0; req->controls && req->controls[i]; i++); 92 if (i == 0) { 85 93 req->controls = NULL; 86 94 return 1; 87 95 } 88 96 89 lcs = talloc_array(req, struct ldb_control *, i );97 lcs = talloc_array(req, struct ldb_control *, i + 1); 90 98 if (!lcs) { 91 99 return 0; 92 100 } 93 101 94 for (i = 0, j = 0; (*saver)[i]; i++) {95 if (exclude == (*saver)[i]) continue;96 lcs[j] = (*saver)[i];102 for (i = 0, j = 0; lcs_old[i]; i++) { 103 if (exclude == lcs_old[i]) continue; 104 lcs[j] = lcs_old[i]; 97 105 j++; 98 106 } 99 107 lcs[j] = NULL; 100 108 101 req->controls = lcs; 109 req->controls = talloc_realloc(req, lcs, struct ldb_control *, j + 1); 110 if (req->controls == NULL) { 111 return 0; 112 } 102 113 return 1; 103 114 } 104 115 116 /* 117 * Returns a list of controls, except the one specified with "exclude" (can 118 * also be NULL). Included controls become a child of returned list if they 119 * were children of "controls_in". 120 * 121 * Returns NULL on error (OOM) or an empty control list. 122 */ 123 struct ldb_control **ldb_controls_except_specified(struct ldb_control **controls_in, 124 TALLOC_CTX *mem_ctx, 125 struct ldb_control *exclude) 126 { 127 struct ldb_control **lcs = NULL; 128 unsigned int i, j, n; 129 130 for (i = 0; controls_in && controls_in[i]; i++); 131 if (i == 0) { 132 return NULL; 133 } 134 n = i; 135 136 for (i = 0, j = 0; controls_in && controls_in[i]; i++) { 137 if (exclude == controls_in[i]) continue; 138 139 if (!lcs) { 140 /* Allocate here so if we remove the only 141 * control, or there were no controls, we 142 * don't allocate at all, and just return 143 * NULL */ 144 lcs = talloc_array(mem_ctx, struct ldb_control *, 145 n + 1); 146 if (!lcs) { 147 return NULL; 148 } 149 } 150 151 lcs[j] = controls_in[i]; 152 talloc_reparent(controls_in, lcs, lcs[j]); 153 j++; 154 } 155 if (lcs) { 156 lcs[j] = NULL; 157 158 lcs = talloc_realloc(mem_ctx, lcs, struct ldb_control *, j + 1); 159 } 160 161 return lcs; 162 } 163 105 164 /* check if there's any control marked as critical in the list */ 106 165 /* return True if any, False if none */ 107 int check_critical_controls(struct ldb_control **controls)166 int ldb_check_critical_controls(struct ldb_control **controls) 108 167 { 109 int i;168 unsigned int i; 110 169 111 170 if (controls == NULL) { … … 123 182 124 183 int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data) 184 { 185 unsigned int i, n; 186 struct ldb_control **ctrls; 187 struct ldb_control *ctrl; 188 189 for (n=0; req->controls && req->controls[n];n++) { 190 /* having two controls of the same OID makes no sense */ 191 if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) { 192 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 193 } 194 } 195 196 ctrls = talloc_array(req, 197 struct ldb_control *, 198 n + 2); 199 if (!ctrls) return LDB_ERR_OPERATIONS_ERROR; 200 201 for (i=0; i<n; i++) { 202 ctrls[i] = req->controls[i]; 203 } 204 205 req->controls = ctrls; 206 ctrls[n] = NULL; 207 ctrls[n+1] = NULL; 208 209 ctrl = talloc(ctrls, struct ldb_control); 210 if (!ctrl) return LDB_ERR_OPERATIONS_ERROR; 211 212 ctrl->oid = talloc_strdup(ctrl, oid); 213 if (!ctrl->oid) return LDB_ERR_OPERATIONS_ERROR; 214 ctrl->critical = critical; 215 ctrl->data = data; 216 217 ctrls[n] = ctrl; 218 return LDB_SUCCESS; 219 } 220 221 int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data) 125 222 { 126 223 unsigned n; … … 128 225 struct ldb_control *ctrl; 129 226 130 for (n=0; req->controls && req->controls[n];) {227 for (n=0; ares->controls && ares->controls[n];) { 131 228 /* having two controls of the same OID makes no sense */ 132 if ( strcmp(oid, req->controls[n]->oid) == 0) {229 if (ares->controls[n]->oid && strcmp(oid, ares->controls[n]->oid) == 0) { 133 230 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 134 231 } … … 136 233 } 137 234 138 ctrls = talloc_realloc( req, req->controls,235 ctrls = talloc_realloc(ares, ares->controls, 139 236 struct ldb_control *, 140 237 n + 2); 141 238 if (!ctrls) return LDB_ERR_OPERATIONS_ERROR; 142 req->controls = ctrls;239 ares->controls = ctrls; 143 240 ctrls[n] = NULL; 144 241 ctrls[n+1] = NULL; … … 156 253 } 157 254 158 /* Parse controls from the format used on the command line and in ejs */ 159 160 struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings) 255 /* Add a control to the request, replacing the old one if it is already in the request */ 256 int ldb_request_replace_control(struct ldb_request *req, const char *oid, bool critical, void *data) 161 257 { 162 int i; 163 struct ldb_control **ctrl; 164 258 unsigned int n; 259 int ret; 260 261 ret = ldb_request_add_control(req, oid, critical, data); 262 if (ret != LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) { 263 return ret; 264 } 265 266 for (n=0; req->controls[n];n++) { 267 if (req->controls[n]->oid && strcmp(oid, req->controls[n]->oid) == 0) { 268 req->controls[n]->critical = critical; 269 req->controls[n]->data = data; 270 return LDB_SUCCESS; 271 } 272 } 273 274 return LDB_ERR_OPERATIONS_ERROR; 275 } 276 277 /* 278 * Return a control as string 279 * the project (ie. name:value1:value2:...:valuen 280 * The string didn't include the criticity of the critical flag 281 */ 282 char *ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *control) 283 { 284 char *res = NULL; 285 286 if (strcmp(control->oid, LDB_CONTROL_PAGED_RESULTS_OID) == 0) { 287 struct ldb_paged_control *rep_control = talloc_get_type(control->data, struct ldb_paged_control); 288 char *cookie; 289 290 cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, rep_control->cookie_len); 291 if (cookie == NULL) { 292 return NULL; 293 } 294 if (cookie[0] != '\0') { 295 res = talloc_asprintf(mem_ctx, "%s:%d:%s", 296 LDB_CONTROL_PAGED_RESULTS_NAME, 297 control->critical, 298 cookie); 299 300 talloc_free(cookie); 301 } else { 302 res = talloc_asprintf(mem_ctx, "%s:%d", 303 LDB_CONTROL_PAGED_RESULTS_NAME, 304 control->critical); 305 } 306 return res; 307 } 308 309 if (strcmp(control->oid, LDB_CONTROL_VLV_RESP_OID) == 0) { 310 struct ldb_vlv_resp_control *rep_control = talloc_get_type(control->data, 311 struct ldb_vlv_resp_control); 312 313 res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%d:%d:%s", 314 LDB_CONTROL_VLV_RESP_NAME, 315 control->critical, 316 rep_control->targetPosition, 317 rep_control->contentCount, 318 rep_control->vlv_result, 319 rep_control->ctxid_len, 320 rep_control->contextId); 321 322 return res; 323 } 324 325 if (strcmp(control->oid, LDB_CONTROL_SORT_RESP_OID) == 0) { 326 struct ldb_sort_resp_control *rep_control = talloc_get_type(control->data, 327 struct ldb_sort_resp_control); 328 329 res = talloc_asprintf(mem_ctx, "%s:%d:%d:%s", 330 LDB_CONTROL_SORT_RESP_NAME, 331 control->critical, 332 rep_control->result, 333 rep_control->attr_desc); 334 335 return res; 336 } 337 338 if (strcmp(control->oid, LDB_CONTROL_ASQ_OID) == 0) { 339 struct ldb_asq_control *rep_control = talloc_get_type(control->data, 340 struct ldb_asq_control); 341 342 res = talloc_asprintf(mem_ctx, "%s:%d:%d", 343 LDB_CONTROL_SORT_RESP_NAME, 344 control->critical, 345 rep_control->result); 346 347 return res; 348 } 349 350 if (strcmp(control->oid, LDB_CONTROL_DIRSYNC_OID) == 0) { 351 char *cookie; 352 struct ldb_dirsync_control *rep_control = talloc_get_type(control->data, 353 struct ldb_dirsync_control); 354 355 cookie = ldb_base64_encode(mem_ctx, rep_control->cookie, 356 rep_control->cookie_len); 357 if (cookie == NULL) { 358 return NULL; 359 } 360 res = talloc_asprintf(mem_ctx, "%s:%d:%d:%d:%s", 361 LDB_CONTROL_DIRSYNC_NAME, 362 control->critical, 363 rep_control->flags, 364 rep_control->max_attributes, 365 cookie); 366 367 talloc_free(cookie); 368 return res; 369 } 370 371 /* 372 * From here we don't know the control 373 */ 374 if (control->data == NULL) { 375 /* 376 * We don't know the control but there is no real data attached to it 377 * so we can represent it with local_oid:oid:criticity 378 */ 379 res = talloc_asprintf(mem_ctx, "local_oid:%s:%d", 380 control->oid, 381 control->critical); 382 return res; 383 } 384 385 res = talloc_asprintf(mem_ctx, "unknown oid:%s", 386 control->oid); 387 return res; 388 } 389 390 391 /* 392 * A little trick to allow to use constants defined in headers rather than 393 * hardwritten in the file hardwritten in the file 394 * sizeof will return the \0 char as well so it will take the place of ":" in the 395 * length of the string 396 */ 397 #define LDB_CONTROL_CMP(control, NAME) strncmp(control, NAME ":", sizeof(NAME)) 398 399 /* Parse one string and return associated control if parsing is successful*/ 400 struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings) 401 { 402 struct ldb_control *ctrl; 165 403 char *error_string = NULL; 166 404 167 if (control_strings == NULL || control_strings[0] == NULL) 405 if (!(ctrl = talloc(mem_ctx, struct ldb_control))) { 406 ldb_oom(ldb); 168 407 return NULL; 169 170 for (i = 0; control_strings[i]; i++); 171 172 ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1); 173 174 for (i = 0; control_strings[i]; i++) { 175 if (strncmp(control_strings[i], "vlv:", 4) == 0) { 176 struct ldb_vlv_req_control *control; 177 const char *p; 178 char attr[1024]; 179 char ctxid[1024]; 180 int crit, bc, ac, os, cc, ret; 181 182 attr[0] = '\0'; 183 ctxid[0] = '\0'; 184 p = &(control_strings[i][4]); 185 ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid); 186 if (ret < 5) { 187 ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid); 188 } 189 190 if ((ret < 4) || (crit < 0) || (crit > 1)) { 191 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n"); 192 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n"); 193 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, s = string, o = b64 binary blob"); 408 } 409 410 if (LDB_CONTROL_CMP(control_strings, 411 LDB_CONTROL_VLV_REQ_NAME) == 0) { 412 struct ldb_vlv_req_control *control; 413 const char *p; 414 char attr[1024]; 415 char ctxid[1024]; 416 int crit, bc, ac, os, cc, ret; 417 418 attr[0] = '\0'; 419 ctxid[0] = '\0'; 420 p = &(control_strings[sizeof(LDB_CONTROL_VLV_REQ_NAME)]); 421 ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid); 422 if (ret < 5) { 423 ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid); 424 } 425 426 if ((ret < 4) || (crit < 0) || (crit > 1)) { 427 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n"); 428 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n"); 429 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, s = string, o = b64 binary blob"); 430 ldb_set_errstring(ldb, error_string); 431 talloc_free(error_string); 432 return NULL; 433 } 434 ctrl->oid = LDB_CONTROL_VLV_REQ_OID; 435 ctrl->critical = crit; 436 if (!(control = talloc(ctrl, 437 struct ldb_vlv_req_control))) { 438 ldb_oom(ldb); 439 return NULL; 440 } 441 control->beforeCount = bc; 442 control->afterCount = ac; 443 if (attr[0]) { 444 control->type = 1; 445 control->match.gtOrEq.value = talloc_strdup(control, attr); 446 control->match.gtOrEq.value_len = strlen(attr); 447 } else { 448 control->type = 0; 449 control->match.byOffset.offset = os; 450 control->match.byOffset.contentCount = cc; 451 } 452 if (ctxid[0]) { 453 control->ctxid_len = ldb_base64_decode(ctxid); 454 control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len); 455 } else { 456 control->ctxid_len = 0; 457 control->contextId = NULL; 458 } 459 ctrl->data = control; 460 461 return ctrl; 462 } 463 464 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DIRSYNC_NAME) == 0) { 465 struct ldb_dirsync_control *control; 466 const char *p; 467 char cookie[1024]; 468 int crit, flags, max_attrs, ret; 469 470 cookie[0] = '\0'; 471 p = &(control_strings[sizeof(LDB_CONTROL_DIRSYNC_NAME)]); 472 ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie); 473 474 if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) { 475 error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n"); 476 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"); 477 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, o = b64 binary blob"); 478 ldb_set_errstring(ldb, error_string); 479 talloc_free(error_string); 480 return NULL; 481 } 482 483 /* w2k3 seems to ignore the parameter, 484 * but w2k sends a wrong cookie when this value is to small 485 * this would cause looping forever, while getting 486 * the same data and same cookie forever 487 */ 488 if (max_attrs == 0) max_attrs = 0x0FFFFFFF; 489 490 ctrl->oid = LDB_CONTROL_DIRSYNC_OID; 491 ctrl->critical = crit; 492 control = talloc(ctrl, struct ldb_dirsync_control); 493 control->flags = flags; 494 control->max_attributes = max_attrs; 495 if (*cookie) { 496 control->cookie_len = ldb_base64_decode(cookie); 497 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len); 498 } else { 499 control->cookie = NULL; 500 control->cookie_len = 0; 501 } 502 ctrl->data = control; 503 504 return ctrl; 505 } 506 507 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_ASQ_NAME) == 0) { 508 struct ldb_asq_control *control; 509 const char *p; 510 char attr[256]; 511 int crit, ret; 512 513 attr[0] = '\0'; 514 p = &(control_strings[sizeof(LDB_CONTROL_ASQ_NAME)]); 515 ret = sscanf(p, "%d:%255[^$]", &crit, attr); 516 if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) { 517 error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n"); 518 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n"); 519 error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string"); 520 ldb_set_errstring(ldb, error_string); 521 talloc_free(error_string); 522 return NULL; 523 } 524 525 ctrl->oid = LDB_CONTROL_ASQ_OID; 526 ctrl->critical = crit; 527 control = talloc(ctrl, struct ldb_asq_control); 528 control->request = 1; 529 control->source_attribute = talloc_strdup(control, attr); 530 control->src_attr_len = strlen(attr); 531 ctrl->data = control; 532 533 return ctrl; 534 } 535 536 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_EXTENDED_DN_NAME) == 0) { 537 struct ldb_extended_dn_control *control; 538 const char *p; 539 int crit, type, ret; 540 541 p = &(control_strings[sizeof(LDB_CONTROL_EXTENDED_DN_NAME)]); 542 ret = sscanf(p, "%d:%d", &crit, &type); 543 if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) { 544 ret = sscanf(p, "%d", &crit); 545 if ((ret != 1) || (crit < 0) || (crit > 1)) { 546 error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n"); 547 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n"); 548 error_string = talloc_asprintf_append(error_string, " note: b = boolean\n"); 549 error_string = talloc_asprintf_append(error_string, " i = integer\n"); 550 error_string = talloc_asprintf_append(error_string, " valid values are: 0 - hexadecimal representation\n"); 551 error_string = talloc_asprintf_append(error_string, " 1 - normal string representation"); 194 552 ldb_set_errstring(ldb, error_string); 195 553 talloc_free(error_string); 196 554 return NULL; 197 555 } 198 if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) { 199 ldb_oom(ldb); 200 return NULL; 556 control = NULL; 557 } else { 558 control = talloc(ctrl, struct ldb_extended_dn_control); 559 control->type = type; 560 } 561 562 ctrl->oid = LDB_CONTROL_EXTENDED_DN_OID; 563 ctrl->critical = crit; 564 ctrl->data = talloc_steal(ctrl, control); 565 566 return ctrl; 567 } 568 569 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SD_FLAGS_NAME) == 0) { 570 struct ldb_sd_flags_control *control; 571 const char *p; 572 int crit, ret; 573 unsigned secinfo_flags; 574 575 p = &(control_strings[sizeof(LDB_CONTROL_SD_FLAGS_NAME)]); 576 ret = sscanf(p, "%d:%u", &crit, &secinfo_flags); 577 if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) { 578 error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n"); 579 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n"); 580 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number"); 581 ldb_set_errstring(ldb, error_string); 582 talloc_free(error_string); 583 return NULL; 584 } 585 586 ctrl->oid = LDB_CONTROL_SD_FLAGS_OID; 587 ctrl->critical = crit; 588 control = talloc(ctrl, struct ldb_sd_flags_control); 589 control->secinfo_flags = secinfo_flags; 590 ctrl->data = control; 591 592 return ctrl; 593 } 594 595 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SEARCH_OPTIONS_NAME) == 0) { 596 struct ldb_search_options_control *control; 597 const char *p; 598 int crit, ret; 599 unsigned search_options; 600 601 p = &(control_strings[sizeof(LDB_CONTROL_SEARCH_OPTIONS_NAME)]); 602 ret = sscanf(p, "%d:%u", &crit, &search_options); 603 if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) { 604 error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n"); 605 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n"); 606 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number"); 607 ldb_set_errstring(ldb, error_string); 608 talloc_free(error_string); 609 return NULL; 610 } 611 612 ctrl->oid = LDB_CONTROL_SEARCH_OPTIONS_OID; 613 ctrl->critical = crit; 614 control = talloc(ctrl, struct ldb_search_options_control); 615 control->search_options = search_options; 616 ctrl->data = control; 617 618 return ctrl; 619 } 620 621 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_BYPASS_OPERATIONAL_NAME) == 0) { 622 const char *p; 623 int crit, ret; 624 625 p = &(control_strings[sizeof(LDB_CONTROL_BYPASS_OPERATIONAL_NAME)]); 626 ret = sscanf(p, "%d", &crit); 627 if ((ret != 1) || (crit < 0) || (crit > 1)) { 628 error_string = talloc_asprintf(mem_ctx, "invalid bypassopreational control syntax\n"); 629 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 630 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 631 ldb_set_errstring(ldb, error_string); 632 talloc_free(error_string); 633 return NULL; 634 } 635 636 ctrl->oid = LDB_CONTROL_BYPASS_OPERATIONAL_OID; 637 ctrl->critical = crit; 638 ctrl->data = NULL; 639 640 return ctrl; 641 } 642 643 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RELAX_NAME) == 0) { 644 const char *p; 645 int crit, ret; 646 647 p = &(control_strings[sizeof(LDB_CONTROL_RELAX_NAME)]); 648 ret = sscanf(p, "%d", &crit); 649 if ((ret != 1) || (crit < 0) || (crit > 1)) { 650 error_string = talloc_asprintf(mem_ctx, "invalid relax control syntax\n"); 651 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 652 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 653 ldb_set_errstring(ldb, error_string); 654 talloc_free(error_string); 655 return NULL; 656 } 657 658 ctrl->oid = LDB_CONTROL_RELAX_OID; 659 ctrl->critical = crit; 660 ctrl->data = NULL; 661 662 return ctrl; 663 } 664 665 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RECALCULATE_SD_NAME) == 0) { 666 const char *p; 667 int crit, ret; 668 669 p = &(control_strings[sizeof(LDB_CONTROL_RECALCULATE_SD_NAME)]); 670 ret = sscanf(p, "%d", &crit); 671 if ((ret != 1) || (crit < 0) || (crit > 1)) { 672 error_string = talloc_asprintf(mem_ctx, "invalid recalculate_sd control syntax\n"); 673 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 674 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 675 ldb_set_errstring(ldb, error_string); 676 talloc_free(error_string); 677 return NULL; 678 } 679 680 ctrl->oid = LDB_CONTROL_RECALCULATE_SD_OID; 681 ctrl->critical = crit; 682 ctrl->data = NULL; 683 684 return ctrl; 685 } 686 687 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_DOMAIN_SCOPE_NAME) == 0) { 688 const char *p; 689 int crit, ret; 690 691 p = &(control_strings[sizeof(LDB_CONTROL_DOMAIN_SCOPE_NAME)]); 692 ret = sscanf(p, "%d", &crit); 693 if ((ret != 1) || (crit < 0) || (crit > 1)) { 694 error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n"); 695 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 696 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 697 ldb_set_errstring(ldb, error_string); 698 talloc_free(error_string); 699 return NULL; 700 } 701 702 ctrl->oid = LDB_CONTROL_DOMAIN_SCOPE_OID; 703 ctrl->critical = crit; 704 ctrl->data = NULL; 705 706 return ctrl; 707 } 708 709 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PAGED_RESULTS_NAME) == 0) { 710 struct ldb_paged_control *control; 711 const char *p; 712 int crit, size, ret; 713 714 p = &(control_strings[sizeof(LDB_CONTROL_PAGED_RESULTS_NAME)]); 715 ret = sscanf(p, "%d:%d", &crit, &size); 716 if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) { 717 error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n"); 718 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n"); 719 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number"); 720 ldb_set_errstring(ldb, error_string); 721 talloc_free(error_string); 722 return NULL; 723 } 724 725 ctrl->oid = LDB_CONTROL_PAGED_RESULTS_OID; 726 ctrl->critical = crit; 727 control = talloc(ctrl, struct ldb_paged_control); 728 control->size = size; 729 control->cookie = NULL; 730 control->cookie_len = 0; 731 ctrl->data = control; 732 733 return ctrl; 734 } 735 736 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SERVER_SORT_NAME) == 0) { 737 struct ldb_server_sort_control **control; 738 const char *p; 739 char attr[256]; 740 char rule[128]; 741 int crit, rev, ret; 742 743 attr[0] = '\0'; 744 rule[0] = '\0'; 745 p = &(control_strings[sizeof(LDB_CONTROL_SERVER_SORT_NAME)]); 746 ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule); 747 if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') { 748 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n"); 749 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n"); 750 error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string"); 751 ldb_set_errstring(ldb, error_string); 752 talloc_free(error_string); 753 return NULL; 754 } 755 ctrl->oid = LDB_CONTROL_SERVER_SORT_OID; 756 ctrl->critical = crit; 757 control = talloc_array(ctrl, struct ldb_server_sort_control *, 2); 758 control[0] = talloc(control, struct ldb_server_sort_control); 759 control[0]->attributeName = talloc_strdup(control, attr); 760 if (rule[0]) 761 control[0]->orderingRule = talloc_strdup(control, rule); 762 else 763 control[0]->orderingRule = NULL; 764 control[0]->reverse = rev; 765 control[1] = NULL; 766 ctrl->data = control; 767 768 return ctrl; 769 } 770 771 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_NOTIFICATION_NAME) == 0) { 772 const char *p; 773 int crit, ret; 774 775 p = &(control_strings[sizeof(LDB_CONTROL_NOTIFICATION_NAME)]); 776 ret = sscanf(p, "%d", &crit); 777 if ((ret != 1) || (crit < 0) || (crit > 1)) { 778 error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n"); 779 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 780 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 781 ldb_set_errstring(ldb, error_string); 782 talloc_free(error_string); 783 return NULL; 784 } 785 786 ctrl->oid = LDB_CONTROL_NOTIFICATION_OID; 787 ctrl->critical = crit; 788 ctrl->data = NULL; 789 790 return ctrl; 791 } 792 793 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_TREE_DELETE_NAME) == 0) { 794 const char *p; 795 int crit, ret; 796 797 p = &(control_strings[sizeof(LDB_CONTROL_TREE_DELETE_NAME)]); 798 ret = sscanf(p, "%d", &crit); 799 if ((ret != 1) || (crit < 0) || (crit > 1)) { 800 error_string = talloc_asprintf(mem_ctx, "invalid tree_delete control syntax\n"); 801 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 802 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 803 ldb_set_errstring(ldb, error_string); 804 talloc_free(error_string); 805 return NULL; 806 } 807 808 ctrl->oid = LDB_CONTROL_TREE_DELETE_OID; 809 ctrl->critical = crit; 810 ctrl->data = NULL; 811 812 return ctrl; 813 } 814 815 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DELETED_NAME) == 0) { 816 const char *p; 817 int crit, ret; 818 819 p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DELETED_NAME)]); 820 ret = sscanf(p, "%d", &crit); 821 if ((ret != 1) || (crit < 0) || (crit > 1)) { 822 error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n"); 823 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 824 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 825 ldb_set_errstring(ldb, error_string); 826 talloc_free(error_string); 827 return NULL; 828 } 829 830 ctrl->oid = LDB_CONTROL_SHOW_DELETED_OID; 831 ctrl->critical = crit; 832 ctrl->data = NULL; 833 834 return ctrl; 835 } 836 837 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME) == 0) { 838 const char *p; 839 int crit, ret; 840 841 p = &(control_strings[sizeof(LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME)]); 842 ret = sscanf(p, "%d", &crit); 843 if ((ret != 1) || (crit < 0) || (crit > 1)) { 844 error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link control syntax\n"); 845 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 846 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 847 ldb_set_errstring(ldb, error_string); 848 talloc_free(error_string); 849 return NULL; 850 } 851 852 ctrl->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID; 853 ctrl->critical = crit; 854 ctrl->data = NULL; 855 856 return ctrl; 857 } 858 859 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_SHOW_RECYCLED_NAME) == 0) { 860 const char *p; 861 int crit, ret; 862 863 p = &(control_strings[sizeof(LDB_CONTROL_SHOW_RECYCLED_NAME)]); 864 ret = sscanf(p, "%d", &crit); 865 if ((ret != 1) || (crit < 0) || (crit > 1)) { 866 error_string = talloc_asprintf(mem_ctx, "invalid show_recycled control syntax\n"); 867 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 868 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 869 ldb_set_errstring(ldb, error_string); 870 talloc_free(error_string); 871 return NULL; 872 } 873 874 ctrl->oid = LDB_CONTROL_SHOW_RECYCLED_OID; 875 ctrl->critical = crit; 876 ctrl->data = NULL; 877 878 return ctrl; 879 } 880 881 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PERMISSIVE_MODIFY_NAME) == 0) { 882 const char *p; 883 int crit, ret; 884 885 p = &(control_strings[sizeof(LDB_CONTROL_PERMISSIVE_MODIFY_NAME)]); 886 ret = sscanf(p, "%d", &crit); 887 if ((ret != 1) || (crit < 0) || (crit > 1)) { 888 error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n"); 889 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 890 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 891 ldb_set_errstring(ldb, error_string); 892 talloc_free(error_string); 893 return NULL; 894 } 895 896 ctrl->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID; 897 ctrl->critical = crit; 898 ctrl->data = NULL; 899 900 return ctrl; 901 } 902 903 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_REVEAL_INTERNALS_NAME) == 0) { 904 const char *p; 905 int crit, ret; 906 907 p = &(control_strings[sizeof(LDB_CONTROL_REVEAL_INTERNALS_NAME)]); 908 ret = sscanf(p, "%d", &crit); 909 if ((ret != 1) || (crit < 0) || (crit > 1)) { 910 error_string = talloc_asprintf(mem_ctx, "invalid reveal_internals control syntax\n"); 911 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 912 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 913 ldb_set_errstring(ldb, error_string); 914 talloc_free(error_string); 915 return NULL; 916 } 917 918 ctrl->oid = LDB_CONTROL_REVEAL_INTERNALS; 919 ctrl->critical = crit; 920 ctrl->data = NULL; 921 922 return ctrl; 923 } 924 925 if (strncmp(control_strings, "local_oid:", 10) == 0) { 926 const char *p; 927 int crit = 0, ret = 0; 928 char oid[256]; 929 930 oid[0] = '\0'; 931 p = &(control_strings[10]); 932 ret = sscanf(p, "%64[^:]:%d", oid, &crit); 933 934 if ((ret != 2) || strlen(oid) == 0 || (crit < 0) || (crit > 1)) { 935 error_string = talloc_asprintf(mem_ctx, "invalid local_oid control syntax\n"); 936 error_string = talloc_asprintf_append(error_string, " syntax: oid(s):crit(b)\n"); 937 error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string"); 938 ldb_set_errstring(ldb, error_string); 939 talloc_free(error_string); 940 return NULL; 941 } 942 943 ctrl->oid = talloc_strdup(ctrl, oid); 944 if (!ctrl->oid) { 945 ldb_oom(ldb); 946 return NULL; 947 } 948 ctrl->critical = crit; 949 ctrl->data = NULL; 950 951 return ctrl; 952 } 953 954 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_RODC_DCPROMO_NAME) == 0) { 955 const char *p; 956 int crit, ret; 957 958 p = &(control_strings[sizeof(LDB_CONTROL_RODC_DCPROMO_NAME)]); 959 ret = sscanf(p, "%d", &crit); 960 if ((ret != 1) || (crit < 0) || (crit > 1)) { 961 error_string = talloc_asprintf(mem_ctx, "invalid rodc_join control syntax\n"); 962 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 963 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 964 ldb_set_errstring(ldb, error_string); 965 talloc_free(error_string); 966 return NULL; 967 } 968 969 ctrl->oid = LDB_CONTROL_RODC_DCPROMO_OID; 970 ctrl->critical = crit; 971 ctrl->data = NULL; 972 973 return ctrl; 974 } 975 976 if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_PROVISION_NAME) == 0) { 977 const char *p; 978 int crit, ret; 979 980 p = &(control_strings[sizeof(LDB_CONTROL_PROVISION_NAME)]); 981 ret = sscanf(p, "%d", &crit); 982 if ((ret != 1) || (crit < 0) || (crit > 1)) { 983 error_string = talloc_asprintf(mem_ctx, "invalid provision control syntax\n"); 984 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 985 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 986 ldb_set_errstring(ldb, error_string); 987 talloc_free(error_string); 988 return NULL; 989 } 990 991 ctrl->oid = LDB_CONTROL_PROVISION_OID; 992 ctrl->critical = crit; 993 ctrl->data = NULL; 994 995 return ctrl; 996 } 997 /* 998 * When no matching control has been found. 999 */ 1000 return NULL; 1001 } 1002 1003 /* 1004 * A little trick to allow to use constants defined in headers rather than 1005 * hardwritten in the file hardwritten in the file 1006 * sizeof will return the \0 char as well so it will take the place of ":" in the 1007 * length of the string 1008 */ 1009 #define LDB_CONTROL_CMP(control, NAME) strncmp(control, NAME ":", sizeof(NAME)) 1010 1011 /* Parse controls from the format used on the command line and in ejs */ 1012 struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char **control_strings) 1013 { 1014 unsigned int i; 1015 struct ldb_control **ctrl; 1016 1017 if (control_strings == NULL || control_strings[0] == NULL) 1018 return NULL; 1019 1020 for (i = 0; control_strings[i]; i++); 1021 1022 ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1); 1023 1024 ldb_reset_err_string(ldb); 1025 for (i = 0; control_strings[i]; i++) { 1026 ctrl[i] = ldb_parse_control_from_string(ldb, ctrl, control_strings[i]); 1027 if (ctrl[i] == NULL) { 1028 if( ldb_errstring == NULL ) { 1029 /* no controls matched, throw an error */ 1030 ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]); 201 1031 } 202 ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID; 203 ctrl[i]->critical = crit; 204 if (!(control = talloc(ctrl[i], 205 struct ldb_vlv_req_control))) { 206 ldb_oom(ldb); 207 return NULL; 208 } 209 control->beforeCount = bc; 210 control->afterCount = ac; 211 if (attr[0]) { 212 control->type = 1; 213 control->match.gtOrEq.value = talloc_strdup(control, attr); 214 control->match.gtOrEq.value_len = strlen(attr); 215 } else { 216 control->type = 0; 217 control->match.byOffset.offset = os; 218 control->match.byOffset.contentCount = cc; 219 } 220 if (ctxid[0]) { 221 control->ctxid_len = ldb_base64_decode(ctxid); 222 control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len); 223 } else { 224 control->ctxid_len = 0; 225 control->contextId = NULL; 226 } 227 ctrl[i]->data = control; 228 229 continue; 230 } 231 232 if (strncmp(control_strings[i], "dirsync:", 8) == 0) { 233 struct ldb_dirsync_control *control; 234 const char *p; 235 char cookie[1024]; 236 int crit, flags, max_attrs, ret; 237 238 cookie[0] = '\0'; 239 p = &(control_strings[i][8]); 240 ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie); 241 242 if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) { 243 error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n"); 244 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n"); 245 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, o = b64 binary blob"); 246 ldb_set_errstring(ldb, error_string); 247 talloc_free(error_string); 248 return NULL; 249 } 250 251 /* w2k3 seems to ignore the parameter, 252 * but w2k sends a wrong cookie when this value is to small 253 * this would cause looping forever, while getting 254 * the same data and same cookie forever 255 */ 256 if (max_attrs == 0) max_attrs = 0x0FFFFFFF; 257 258 ctrl[i] = talloc(ctrl, struct ldb_control); 259 ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID; 260 ctrl[i]->critical = crit; 261 control = talloc(ctrl[i], struct ldb_dirsync_control); 262 control->flags = flags; 263 control->max_attributes = max_attrs; 264 if (*cookie) { 265 control->cookie_len = ldb_base64_decode(cookie); 266 control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len); 267 } else { 268 control->cookie = NULL; 269 control->cookie_len = 0; 270 } 271 ctrl[i]->data = control; 272 273 continue; 274 } 275 276 if (strncmp(control_strings[i], "asq:", 4) == 0) { 277 struct ldb_asq_control *control; 278 const char *p; 279 char attr[256]; 280 int crit, ret; 281 282 attr[0] = '\0'; 283 p = &(control_strings[i][4]); 284 ret = sscanf(p, "%d:%255[^$]", &crit, attr); 285 if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) { 286 error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n"); 287 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n"); 288 error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string"); 289 ldb_set_errstring(ldb, error_string); 290 talloc_free(error_string); 291 return NULL; 292 } 293 294 ctrl[i] = talloc(ctrl, struct ldb_control); 295 if (!ctrl[i]) { 296 ldb_oom(ldb); 297 return NULL; 298 } 299 ctrl[i]->oid = LDB_CONTROL_ASQ_OID; 300 ctrl[i]->critical = crit; 301 control = talloc(ctrl[i], struct ldb_asq_control); 302 control->request = 1; 303 control->source_attribute = talloc_strdup(control, attr); 304 control->src_attr_len = strlen(attr); 305 ctrl[i]->data = control; 306 307 continue; 308 } 309 310 if (strncmp(control_strings[i], "extended_dn:", 12) == 0) { 311 struct ldb_extended_dn_control *control; 312 const char *p; 313 int crit, type, ret; 314 315 p = &(control_strings[i][12]); 316 ret = sscanf(p, "%d:%d", &crit, &type); 317 if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) { 318 ret = sscanf(p, "%d", &crit); 319 if ((ret != 1) || (crit < 0) || (crit > 1)) { 320 error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n"); 321 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)[:type(i)]\n"); 322 error_string = talloc_asprintf_append(error_string, " note: b = boolean\n"); 323 error_string = talloc_asprintf_append(error_string, " i = integer\n"); 324 error_string = talloc_asprintf_append(error_string, " valid values are: 0 - hexadecimal representation\n"); 325 error_string = talloc_asprintf_append(error_string, " 1 - normal string representation"); 326 ldb_set_errstring(ldb, error_string); 327 talloc_free(error_string); 328 return NULL; 329 } 330 control = NULL; 331 } else { 332 control = talloc(ctrl, struct ldb_extended_dn_control); 333 control->type = type; 334 } 335 336 ctrl[i] = talloc(ctrl, struct ldb_control); 337 if (!ctrl[i]) { 338 ldb_oom(ldb); 339 return NULL; 340 } 341 ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID; 342 ctrl[i]->critical = crit; 343 ctrl[i]->data = talloc_steal(ctrl[i], control); 344 345 continue; 346 } 347 348 if (strncmp(control_strings[i], "sd_flags:", 9) == 0) { 349 struct ldb_sd_flags_control *control; 350 const char *p; 351 int crit, ret; 352 unsigned secinfo_flags; 353 354 p = &(control_strings[i][9]); 355 ret = sscanf(p, "%d:%u", &crit, &secinfo_flags); 356 if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) { 357 error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n"); 358 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n"); 359 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number"); 360 ldb_set_errstring(ldb, error_string); 361 talloc_free(error_string); 362 return NULL; 363 } 364 365 ctrl[i] = talloc(ctrl, struct ldb_control); 366 if (!ctrl[i]) { 367 ldb_oom(ldb); 368 return NULL; 369 } 370 ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID; 371 ctrl[i]->critical = crit; 372 control = talloc(ctrl[i], struct ldb_sd_flags_control); 373 control->secinfo_flags = secinfo_flags; 374 ctrl[i]->data = control; 375 376 continue; 377 } 378 379 if (strncmp(control_strings[i], "search_options:", 15) == 0) { 380 struct ldb_search_options_control *control; 381 const char *p; 382 int crit, ret; 383 unsigned search_options; 384 385 p = &(control_strings[i][15]); 386 ret = sscanf(p, "%d:%u", &crit, &search_options); 387 if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) { 388 error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n"); 389 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n"); 390 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number"); 391 ldb_set_errstring(ldb, error_string); 392 talloc_free(error_string); 393 return NULL; 394 } 395 396 ctrl[i] = talloc(ctrl, struct ldb_control); 397 if (!ctrl[i]) { 398 ldb_oom(ldb); 399 return NULL; 400 } 401 ctrl[i]->oid = LDB_CONTROL_SEARCH_OPTIONS_OID; 402 ctrl[i]->critical = crit; 403 control = talloc(ctrl[i], struct ldb_search_options_control); 404 control->search_options = search_options; 405 ctrl[i]->data = control; 406 407 continue; 408 } 409 410 if (strncmp(control_strings[i], "domain_scope:", 13) == 0) { 411 const char *p; 412 int crit, ret; 413 414 p = &(control_strings[i][13]); 415 ret = sscanf(p, "%d", &crit); 416 if ((ret != 1) || (crit < 0) || (crit > 1)) { 417 error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n"); 418 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 419 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 420 ldb_set_errstring(ldb, error_string); 421 talloc_free(error_string); 422 return NULL; 423 } 424 425 ctrl[i] = talloc(ctrl, struct ldb_control); 426 if (!ctrl[i]) { 427 ldb_oom(ldb); 428 return NULL; 429 } 430 ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID; 431 ctrl[i]->critical = crit; 432 ctrl[i]->data = NULL; 433 434 continue; 435 } 436 437 if (strncmp(control_strings[i], "paged_results:", 14) == 0) { 438 struct ldb_paged_control *control; 439 const char *p; 440 int crit, size, ret; 441 442 p = &(control_strings[i][14]); 443 ret = sscanf(p, "%d:%d", &crit, &size); 444 445 if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) { 446 error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n"); 447 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n"); 448 error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number"); 449 ldb_set_errstring(ldb, error_string); 450 talloc_free(error_string); 451 return NULL; 452 } 453 454 ctrl[i] = talloc(ctrl, struct ldb_control); 455 if (!ctrl[i]) { 456 ldb_oom(ldb); 457 return NULL; 458 } 459 ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID; 460 ctrl[i]->critical = crit; 461 control = talloc(ctrl[i], struct ldb_paged_control); 462 control->size = size; 463 control->cookie = NULL; 464 control->cookie_len = 0; 465 ctrl[i]->data = control; 466 467 continue; 468 } 469 470 if (strncmp(control_strings[i], "server_sort:", 12) == 0) { 471 struct ldb_server_sort_control **control; 472 const char *p; 473 char attr[256]; 474 char rule[128]; 475 int crit, rev, ret; 476 477 attr[0] = '\0'; 478 rule[0] = '\0'; 479 p = &(control_strings[i][12]); 480 ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule); 481 if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') { 482 error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n"); 483 error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n"); 484 error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string"); 485 ldb_set_errstring(ldb, error_string); 486 talloc_free(error_string); 487 return NULL; 488 } 489 ctrl[i] = talloc(ctrl, struct ldb_control); 490 if (!ctrl[i]) { 491 ldb_oom(ldb); 492 return NULL; 493 } 494 ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID; 495 ctrl[i]->critical = crit; 496 control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2); 497 control[0] = talloc(control, struct ldb_server_sort_control); 498 control[0]->attributeName = talloc_strdup(control, attr); 499 if (rule[0]) 500 control[0]->orderingRule = talloc_strdup(control, rule); 501 else 502 control[0]->orderingRule = NULL; 503 control[0]->reverse = rev; 504 control[1] = NULL; 505 ctrl[i]->data = control; 506 507 continue; 508 } 509 510 if (strncmp(control_strings[i], "notification:", 13) == 0) { 511 const char *p; 512 int crit, ret; 513 514 p = &(control_strings[i][13]); 515 ret = sscanf(p, "%d", &crit); 516 if ((ret != 1) || (crit < 0) || (crit > 1)) { 517 error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n"); 518 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 519 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 520 ldb_set_errstring(ldb, error_string); 521 talloc_free(error_string); 522 return NULL; 523 } 524 525 ctrl[i] = talloc(ctrl, struct ldb_control); 526 if (!ctrl[i]) { 527 ldb_oom(ldb); 528 return NULL; 529 } 530 ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID; 531 ctrl[i]->critical = crit; 532 ctrl[i]->data = NULL; 533 534 continue; 535 } 536 537 if (strncmp(control_strings[i], "show_deleted:", 13) == 0) { 538 const char *p; 539 int crit, ret; 540 541 p = &(control_strings[i][13]); 542 ret = sscanf(p, "%d", &crit); 543 if ((ret != 1) || (crit < 0) || (crit > 1)) { 544 error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n"); 545 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 546 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 547 ldb_set_errstring(ldb, error_string); 548 talloc_free(error_string); 549 return NULL; 550 } 551 552 ctrl[i] = talloc(ctrl, struct ldb_control); 553 if (!ctrl[i]) { 554 ldb_oom(ldb); 555 return NULL; 556 } 557 ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID; 558 ctrl[i]->critical = crit; 559 ctrl[i]->data = NULL; 560 561 continue; 562 } 563 564 if (strncmp(control_strings[i], "show_deactivated_link:", 22) == 0) { 565 const char *p; 566 int crit, ret; 567 568 p = &(control_strings[i][22]); 569 ret = sscanf(p, "%d", &crit); 570 if ((ret != 1) || (crit < 0) || (crit > 1)) { 571 error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link control syntax\n"); 572 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 573 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 574 ldb_set_errstring(ldb, error_string); 575 talloc_free(error_string); 576 return NULL; 577 } 578 579 ctrl[i] = talloc(ctrl, struct ldb_control); 580 if (!ctrl[i]) { 581 ldb_oom(ldb); 582 return NULL; 583 } 584 ctrl[i]->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID; 585 ctrl[i]->critical = crit; 586 ctrl[i]->data = NULL; 587 588 continue; 589 } 590 591 if (strncmp(control_strings[i], "show_recycled:", 14) == 0) { 592 const char *p; 593 int crit, ret; 594 595 p = &(control_strings[i][14]); 596 ret = sscanf(p, "%d", &crit); 597 if ((ret != 1) || (crit < 0) || (crit > 1)) { 598 error_string = talloc_asprintf(mem_ctx, "invalid show_recycled control syntax\n"); 599 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 600 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 601 ldb_set_errstring(ldb, error_string); 602 talloc_free(error_string); 603 return NULL; 604 } 605 606 ctrl[i] = talloc(ctrl, struct ldb_control); 607 if (!ctrl[i]) { 608 ldb_oom(ldb); 609 return NULL; 610 } 611 ctrl[i]->oid = LDB_CONTROL_SHOW_RECYCLED_OID; 612 ctrl[i]->critical = crit; 613 ctrl[i]->data = NULL; 614 615 continue; 616 } 617 618 if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) { 619 const char *p; 620 int crit, ret; 621 622 p = &(control_strings[i][18]); 623 ret = sscanf(p, "%d", &crit); 624 if ((ret != 1) || (crit < 0) || (crit > 1)) { 625 error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n"); 626 error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n"); 627 error_string = talloc_asprintf_append(error_string, " note: b = boolean"); 628 ldb_set_errstring(ldb, error_string); 629 talloc_free(error_string); 630 return NULL; 631 } 632 633 ctrl[i] = talloc(ctrl, struct ldb_control); 634 if (!ctrl[i]) { 635 ldb_oom(ldb); 636 return NULL; 637 } 638 ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID; 639 ctrl[i]->critical = crit; 640 ctrl[i]->data = NULL; 641 642 continue; 643 } 644 645 /* no controls matched, throw an error */ 646 ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]); 647 return NULL; 1032 talloc_free(ctrl); 1033 return NULL; 1034 } 648 1035 } 649 1036 -
trunk/server/source4/lib/ldb/common/ldb_dn.c
r414 r745 80 80 }; 81 81 82 /* it is helpful to be able to break on this in gdb */ 83 static void ldb_dn_mark_invalid(struct ldb_dn *dn) 84 { 85 dn->invalid = true; 86 } 87 82 88 /* strdn may be NULL */ 83 struct ldb_dn *ldb_dn_from_ldb_val( void*mem_ctx,89 struct ldb_dn *ldb_dn_from_ldb_val(TALLOC_CTX *mem_ctx, 84 90 struct ldb_context *ldb, 85 91 const struct ldb_val *strdn) … … 90 96 91 97 if (strdn && strdn->data 92 && (str len((const char*)strdn->data) != strdn->length)) {98 && (strnlen((const char*)strdn->data, strdn->length) != strdn->length)) { 93 99 /* The RDN must not contain a character with value 0x0 */ 94 100 return NULL; … … 98 104 LDB_DN_NULL_FAILED(dn); 99 105 100 dn->ldb = ldb; 106 dn->ldb = talloc_get_type(ldb, struct ldb_context); 107 if (dn->ldb == NULL) { 108 /* the caller probably got the arguments to 109 ldb_dn_new() mixed up */ 110 talloc_free(dn); 111 return NULL; 112 } 101 113 102 114 if (strdn->data && strdn->length) { … … 143 155 144 156 /* strdn may be NULL */ 145 struct ldb_dn *ldb_dn_new( void*mem_ctx,157 struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx, 146 158 struct ldb_context *ldb, 147 159 const char *strdn) 148 160 { 149 161 struct ldb_val blob; 150 blob.data = strdn;162 blob.data = discard_const_p(uint8_t, strdn); 151 163 blob.length = strdn ? strlen(strdn) : 0; 152 164 return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob); 153 165 } 154 166 155 struct ldb_dn *ldb_dn_new_fmt( void*mem_ctx,167 struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, 156 168 struct ldb_context *ldb, 157 169 const char *new_fmt, ...) … … 175 187 } 176 188 189 /* see RFC2253 section 2.4 */ 177 190 static int ldb_dn_escape_internal(char *dst, const char *src, int len) 178 191 { 179 192 const char *p, *s; 180 193 char *d; 181 int l;194 size_t l; 182 195 183 196 p = s = src; … … 185 198 186 199 while (p - src < len) { 187 188 p += strcspn(p, ",=\n+<>#;\\\""); 200 p += strcspn(p, ",=\n\r+<>#;\\\" "); 189 201 190 202 if (p - src == len) /* found no escapable chars */ … … 194 206 memcpy(d, s, p - s); 195 207 d += (p - s); /* move to current position */ 196 197 if (*p) { /* it is a normal escapable character */ 208 209 switch (*p) { 210 case ' ': 211 if (p == src || (p-src)==(len-1)) { 212 /* if at the beginning or end 213 * of the string then escape */ 214 *d++ = '\\'; 215 *d++ = *p++; 216 } else { 217 /* otherwise don't escape */ 218 *d++ = *p++; 219 } 220 break; 221 222 case '#': 223 /* despite the RFC, windows escapes a # 224 anywhere in the string */ 225 case ',': 226 case '+': 227 case '"': 228 case '\\': 229 case '<': 230 case '>': 231 case '?': 232 /* these must be escaped using \c form */ 198 233 *d++ = '\\'; 199 234 *d++ = *p++; 200 } else { /* we have a zero byte in the string */ 201 strncpy(d, "\00", 3); /* escape the zero */ 202 d += 3; 203 p++; /* skip the zero */ 235 break; 236 237 default: { 238 /* any others get \XX form */ 239 unsigned char v; 240 const char *hexbytes = "0123456789ABCDEF"; 241 v = *(const unsigned char *)p; 242 *d++ = '\\'; 243 *d++ = hexbytes[v>>4]; 244 *d++ = hexbytes[v&0xF]; 245 p++; 246 break; 247 } 204 248 } 205 249 s = p; /* move forward */ … … 214 258 } 215 259 216 char *ldb_dn_escape_value( void*mem_ctx, struct ldb_val value)260 char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value) 217 261 { 218 262 char *dst; … … 245 289 { 246 290 char *p, *ex_name, *ex_value, *data, *d, *dt, *t; 247 bool trim = false;248 bool in_extended = false;291 bool trim = true; 292 bool in_extended = true; 249 293 bool in_ex_name = false; 250 294 bool in_ex_value = false; … … 254 298 bool is_oid = false; 255 299 bool escape = false; 256 unsigned x; 257 int l, ret; 300 unsigned int x; 301 size_t l; 302 int ret; 258 303 char *parse_dn; 304 bool is_index; 259 305 260 306 if ( ! dn || dn->invalid) return false; … … 274 320 } 275 321 276 /* The RDN size must be less than 255 characters */ 277 if (strlen(parse_dn) > 255) { 278 return false; 279 } 322 is_index = (strncmp(parse_dn, "DN=@INDEX:", 10) == 0); 280 323 281 324 /* Empty DNs */ … … 289 332 } 290 333 291 /* make sure we free this if alloced previously before replacing */ 292 talloc_free(dn->components); 293 294 talloc_free(dn->ext_components); 295 dn->ext_components = NULL; 334 /* make sure we free this if allocated previously before replacing */ 335 LDB_FREE(dn->components); 336 dn->comp_num = 0; 337 338 LDB_FREE(dn->ext_components); 339 dn->ext_comp_num = 0; 296 340 297 341 /* in the common case we have 3 or more components */ … … 301 345 return false; 302 346 } 303 dn->comp_num = 0;304 347 305 348 /* Components data space is allocated here once */ … … 310 353 311 354 p = parse_dn; 312 in_extended = true;313 in_ex_name = false;314 in_ex_value = false;315 trim = true;316 355 t = NULL; 317 356 d = dt = data; … … 384 423 &ex_val, &dn->ext_components[dn->ext_comp_num].value); 385 424 if (ret != LDB_SUCCESS) { 386 dn->invalid = true;425 ldb_dn_mark_invalid(dn); 387 426 goto failed; 388 427 } … … 399 438 continue; 400 439 } else { 401 dn->invalid = true;440 ldb_dn_mark_invalid(dn); 402 441 goto failed; 403 442 } … … 419 458 if (!isascii(*p)) { 420 459 /* attr names must be ascii only */ 421 dn->invalid = true;460 ldb_dn_mark_invalid(dn); 422 461 goto failed; 423 462 } … … 429 468 /* not a digit nor an alpha, 430 469 * invalid attribute name */ 431 dn->invalid = true;470 ldb_dn_mark_invalid(dn); 432 471 goto failed; 433 472 } … … 448 487 if (trim && (*p != '=')) { 449 488 /* spaces/tabs are not allowed */ 450 dn->invalid = true;489 ldb_dn_mark_invalid(dn); 451 490 goto failed; 452 491 } … … 477 516 if (!isascii(*p)) { 478 517 /* attr names must be ascii only */ 479 dn->invalid = true;518 ldb_dn_mark_invalid(dn); 480 519 goto failed; 481 520 } … … 484 523 /* not a digit nor a dot, 485 524 * invalid attribute oid */ 486 dn->invalid = true;525 ldb_dn_mark_invalid(dn); 487 526 goto failed; 488 527 } else 489 528 if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) { 490 529 /* not ALPHA, DIGIT or HYPHEN */ 491 dn->invalid = true;530 ldb_dn_mark_invalid(dn); 492 531 goto failed; 493 532 } … … 579 618 continue; 580 619 620 case '+': 581 621 case '=': 582 case '\n': 583 case '+': 622 /* to main compatibility with earlier 623 versions of ldb indexing, we have to 624 accept the base64 encoded binary index 625 values, which contain a '+' or '=' 626 which should normally be escaped */ 627 if (is_index) { 628 if ( t ) t = NULL; 629 *d++ = *p++; 630 l++; 631 break; 632 } 633 /* fall through */ 634 case '\"': 584 635 case '<': 585 636 case '>': 586 case '#':587 637 case ';': 588 case '\"':589 638 /* a string with not escaped specials is invalid (tested) */ 590 639 if ( ! escape) { 591 dn->invalid = true;640 ldb_dn_mark_invalid(dn); 592 641 goto failed; 593 642 } … … 616 665 default: 617 666 if (escape) { 618 if (sscanf(p, "%02x", &x) != 1) { 619 /* invalid escaping sequence */ 620 dn->invalid = true; 621 goto failed; 667 if (isxdigit(p[0]) && isxdigit(p[1])) { 668 if (sscanf(p, "%02x", &x) != 1) { 669 /* invalid escaping sequence */ 670 ldb_dn_mark_invalid(dn); 671 goto failed; 672 } 673 p += 2; 674 *d++ = (unsigned char)x; 675 } else { 676 *d++ = *p++; 622 677 } 678 623 679 escape = false; 624 625 p += 2;626 *d++ = (unsigned char)x;627 680 l++; 628 629 681 if ( t ) t = NULL; 630 682 break; … … 648 700 if (in_attr || in_quote) { 649 701 /* invalid dn */ 650 dn->invalid = true;702 ldb_dn_mark_invalid(dn); 651 703 goto failed; 652 704 } … … 674 726 675 727 failed: 728 LDB_FREE(dn->components); /* "data" is implicitly free'd */ 676 729 dn->comp_num = 0; 677 talloc_free(dn->components); 730 LDB_FREE(dn->ext_components); 731 dn->ext_comp_num = 0; 732 678 733 return false; 679 734 } … … 686 741 const char *ldb_dn_get_linearized(struct ldb_dn *dn) 687 742 { 688 int i, len; 743 unsigned int i; 744 size_t len; 689 745 char *d, *n; 690 746 … … 694 750 695 751 if ( ! dn->components) { 696 dn->invalid = true;752 ldb_dn_mark_invalid(dn); 697 753 return NULL; 698 754 } … … 741 797 } 742 798 743 char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode) 799 static int ldb_dn_extended_component_compare(const void *p1, const void *p2) 800 { 801 const struct ldb_dn_ext_component *ec1 = (const struct ldb_dn_ext_component *)p1; 802 const struct ldb_dn_ext_component *ec2 = (const struct ldb_dn_ext_component *)p2; 803 return strcmp(ec1->name, ec2->name); 804 } 805 806 char *ldb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int mode) 744 807 { 745 808 const char *linearized = ldb_dn_get_linearized(dn); 746 char *p ;747 int i;809 char *p = NULL; 810 unsigned int i; 748 811 749 812 if (!linearized) { … … 758 821 return NULL; 759 822 } 823 824 /* sort the extended components by name. The idea is to make 825 * the resulting DNs consistent, plus to ensure that we put 826 * 'DELETED' first, so it can be very quickly recognised 827 */ 828 TYPESAFE_QSORT(dn->ext_components, dn->ext_comp_num, 829 ldb_dn_extended_component_compare); 760 830 761 831 for (i = 0; i < dn->ext_comp_num; i++) { … … 767 837 768 838 ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name); 839 if (!ext_syntax) { 840 return NULL; 841 } 769 842 770 843 if (mode == 1) { … … 783 856 784 857 if (i == 0) { 785 p = talloc_asprintf(mem_ctx, "<%s=%s>", 786 858 p = talloc_asprintf(mem_ctx, "<%s=%s>", 859 name, val.data); 787 860 } else { 788 p = talloc_asprintf_append (p, ";<%s=%s>",789 name, val.data);861 p = talloc_asprintf_append_buffer(p, ";<%s=%s>", 862 name, val.data); 790 863 } 791 864 … … 798 871 799 872 if (dn->ext_comp_num && *linearized) { 800 p = talloc_asprintf_append (p, ";%s", linearized);873 p = talloc_asprintf_append_buffer(p, ";%s", linearized); 801 874 } 802 875 … … 808 881 } 809 882 810 811 812 char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn) 883 /* 884 filter out all but an acceptable list of extended DN components 885 */ 886 void ldb_dn_extended_filter(struct ldb_dn *dn, const char * const *accept_list) 887 { 888 unsigned int i; 889 for (i=0; i<dn->ext_comp_num; i++) { 890 if (!ldb_attr_in_list(accept_list, dn->ext_components[i].name)) { 891 memmove(&dn->ext_components[i], 892 &dn->ext_components[i+1], 893 (dn->ext_comp_num-(i+1))*sizeof(dn->ext_components[0])); 894 dn->ext_comp_num--; 895 i--; 896 } 897 } 898 LDB_FREE(dn->ext_linearized); 899 } 900 901 902 char *ldb_dn_alloc_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) 813 903 { 814 904 return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn)); … … 822 912 static bool ldb_dn_casefold_internal(struct ldb_dn *dn) 823 913 { 824 int i, ret; 914 unsigned int i; 915 int ret; 825 916 826 917 if ( ! dn || dn->invalid) return false; … … 867 958 const char *ldb_dn_get_casefold(struct ldb_dn *dn) 868 959 { 869 int i, len; 960 unsigned int i; 961 size_t len; 870 962 char *d, *n; 871 963 … … 924 1016 } 925 1017 926 char *ldb_dn_alloc_casefold( void*mem_ctx, struct ldb_dn *dn)1018 char *ldb_dn_alloc_casefold(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) 927 1019 { 928 1020 return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn)); … … 937 1029 { 938 1030 int ret; 939 int n_base, n_dn;1031 unsigned int n_base, n_dn; 940 1032 941 1033 if ( ! base || base->invalid) return 1; … … 973 1065 } 974 1066 975 if ( dn->comp_num == 0) {1067 if ((dn->comp_num == 0) || (base->comp_num == 0)) { 976 1068 if (dn->special && base->special) { 977 1069 return strcmp(base->linearized, dn->linearized); … … 988 1080 n_dn = dn->comp_num - 1; 989 1081 990 while (n_base >= 0) {1082 while (n_base != (unsigned int) -1) { 991 1083 char *b_name = base->components[n_base].cf_name; 992 1084 char *dn_name = dn->components[n_dn].cf_name; … … 1023 1115 int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1) 1024 1116 { 1025 int i, ret; 1117 unsigned int i; 1118 int ret; 1026 1119 1027 1120 if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) { … … 1094 1187 1095 1188 static struct ldb_dn_component ldb_dn_copy_component( 1096 void*mem_ctx,1189 TALLOC_CTX *mem_ctx, 1097 1190 struct ldb_dn_component *src) 1098 1191 { … … 1140 1233 1141 1234 static struct ldb_dn_ext_component ldb_dn_ext_copy_component( 1142 void*mem_ctx,1235 TALLOC_CTX *mem_ctx, 1143 1236 struct ldb_dn_ext_component *src) 1144 1237 { … … 1165 1258 } 1166 1259 1167 struct ldb_dn *ldb_dn_copy( void*mem_ctx, struct ldb_dn *dn)1260 struct ldb_dn *ldb_dn_copy(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) 1168 1261 { 1169 1262 struct ldb_dn *new_dn; … … 1181 1274 1182 1275 if (dn->components) { 1183 int i;1276 unsigned int i; 1184 1277 1185 1278 new_dn->components = … … 1204 1297 1205 1298 if (dn->ext_components) { 1206 int i;1299 unsigned int i; 1207 1300 1208 1301 new_dn->ext_components = … … 1270 1363 1271 1364 if (dn->components) { 1272 int i;1365 unsigned int i; 1273 1366 1274 1367 if ( ! ldb_dn_validate(base)) { … … 1288 1381 dn->comp_num + base->comp_num); 1289 1382 if ( ! dn->components) { 1290 dn->invalid = true;1383 ldb_dn_mark_invalid(dn); 1291 1384 return false; 1292 1385 } … … 1297 1390 &base->components[i]); 1298 1391 if (dn->components[dn->comp_num].value.data == NULL) { 1299 dn->invalid = true;1392 ldb_dn_mark_invalid(dn); 1300 1393 return false; 1301 1394 } … … 1328 1421 } 1329 1422 if ( ! t) { 1330 dn->invalid = true;1423 ldb_dn_mark_invalid(dn); 1331 1424 return false; 1332 1425 } … … 1337 1430 /* Wipe the ext_linearized DN, 1338 1431 * the GUID and SID are almost certainly no longer valid */ 1339 if (dn->ext_linearized) { 1340 LDB_FREE(dn->ext_linearized); 1341 } 1342 1432 LDB_FREE(dn->ext_linearized); 1343 1433 LDB_FREE(dn->ext_components); 1344 1434 dn->ext_comp_num = 0; 1435 1345 1436 return true; 1346 1437 } … … 1394 1485 1395 1486 if (dn->components) { 1396 int n, i, j; 1487 unsigned int n; 1488 unsigned int i, j; 1489 1490 if (dn->comp_num == 0) { 1491 return false; 1492 } 1397 1493 1398 1494 if ( ! ldb_dn_validate(child)) { … … 1414 1510 n); 1415 1511 if ( ! dn->components) { 1416 dn->invalid = true;1512 ldb_dn_mark_invalid(dn); 1417 1513 return false; 1418 1514 } 1419 1515 1420 for (i = dn->comp_num - 1, j = n - 1; i >= 0; i--, j--) { 1516 for (i = dn->comp_num - 1, j = n - 1; i != (unsigned int) -1; 1517 i--, j--) { 1421 1518 dn->components[j] = dn->components[i]; 1422 1519 } … … 1427 1524 &child->components[i]); 1428 1525 if (dn->components[i].value.data == NULL) { 1429 dn->invalid = true;1526 ldb_dn_mark_invalid(dn); 1430 1527 return false; 1431 1528 } … … 1442 1539 1443 1540 if (dn->linearized) { 1541 if (dn->linearized[0] == '\0') { 1542 return false; 1543 } 1444 1544 1445 1545 s = ldb_dn_get_linearized(child); … … 1450 1550 t = talloc_asprintf(dn, "%s,%s", s, dn->linearized); 1451 1551 if ( ! t) { 1452 dn->invalid = true;1552 ldb_dn_mark_invalid(dn); 1453 1553 return false; 1454 1554 } … … 1460 1560 * the GUID and SID are almost certainly no longer valid */ 1461 1561 LDB_FREE(dn->ext_linearized); 1462 1463 1562 LDB_FREE(dn->ext_components); 1464 1563 dn->ext_comp_num = 0; … … 1502 1601 bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num) 1503 1602 { 1504 int i;1603 unsigned int i; 1505 1604 1506 1605 if ( ! ldb_dn_validate(dn)) { … … 1513 1612 1514 1613 /* free components */ 1515 for (i = num; i > 0; i--) {1516 LDB_FREE(dn->components[ dn->comp_num -i].name);1517 LDB_FREE(dn->components[ dn->comp_num -i].value.data);1518 LDB_FREE(dn->components[ dn->comp_num -i].cf_name);1519 LDB_FREE(dn->components[ dn->comp_num -i].cf_value.data);1614 for (i = dn->comp_num - num; i < dn->comp_num; i++) { 1615 LDB_FREE(dn->components[i].name); 1616 LDB_FREE(dn->components[i].value.data); 1617 LDB_FREE(dn->components[i].cf_name); 1618 LDB_FREE(dn->components[i].cf_value.data); 1520 1619 } 1521 1620 … … 1536 1635 * the GUID and SID are almost certainly no longer valid */ 1537 1636 LDB_FREE(dn->ext_linearized); 1538 1539 1637 LDB_FREE(dn->ext_components); 1540 1638 dn->ext_comp_num = 0; … … 1545 1643 bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num) 1546 1644 { 1547 int i, j;1645 unsigned int i, j; 1548 1646 1549 1647 if ( ! ldb_dn_validate(dn)) { … … 1581 1679 * the GUID and SID are almost certainly no longer valid */ 1582 1680 LDB_FREE(dn->ext_linearized); 1583 1584 1681 LDB_FREE(dn->ext_components); 1585 1682 dn->ext_comp_num = 0; 1683 1586 1684 return true; 1587 1685 } 1588 1686 1589 struct ldb_dn *ldb_dn_get_parent( void*mem_ctx, struct ldb_dn *dn)1687 struct ldb_dn *ldb_dn_get_parent(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) 1590 1688 { 1591 1689 struct ldb_dn *new_dn; … … 1601 1699 } 1602 1700 1603 /* Wipe the ext_linearized DN,1604 * the GUID and SID are almost certainly no longer valid */1605 LDB_FREE(dn->ext_linearized);1606 1607 LDB_FREE(dn->ext_components);1608 dn->ext_comp_num = 0;1609 1701 return new_dn; 1610 1702 } … … 1619 1711 1620 1712 */ 1621 static char *ldb_dn_canonical( void*mem_ctx, struct ldb_dn *dn, int ex_format) {1622 int i;1713 static char *ldb_dn_canonical(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int ex_format) { 1714 unsigned int i; 1623 1715 TALLOC_CTX *tmpctx; 1624 1716 char *cracked = NULL; … … 1632 1724 1633 1725 /* Walk backwards down the DN, grabbing 'dc' components at first */ 1634 for (i = dn->comp_num - 1 ; i >= 0; i--) {1726 for (i = dn->comp_num - 1; i != (unsigned int) -1; i--) { 1635 1727 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) { 1636 1728 break; … … 1651 1743 1652 1744 /* Only domain components? Finish here */ 1653 if (i < 0) {1745 if (i == (unsigned int) -1) { 1654 1746 cracked = talloc_strdup_append_buffer(cracked, format); 1655 1747 talloc_steal(mem_ctx, cracked); … … 1679 1771 1680 1772 /* Wrapper functions for the above, for the two different string formats */ 1681 char *ldb_dn_canonical_string( void*mem_ctx, struct ldb_dn *dn) {1773 char *ldb_dn_canonical_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) { 1682 1774 return ldb_dn_canonical(mem_ctx, dn, 0); 1683 1775 1684 1776 } 1685 1777 1686 char *ldb_dn_canonical_ex_string( void*mem_ctx, struct ldb_dn *dn) {1778 char *ldb_dn_canonical_ex_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn) { 1687 1779 return ldb_dn_canonical(mem_ctx, dn, 1); 1688 1780 } … … 1694 1786 } 1695 1787 return dn->comp_num; 1788 } 1789 1790 int ldb_dn_get_extended_comp_num(struct ldb_dn *dn) 1791 { 1792 if ( ! ldb_dn_validate(dn)) { 1793 return -1; 1794 } 1795 return dn->ext_comp_num; 1696 1796 } 1697 1797 … … 1765 1865 1766 1866 if (dn->valid_case) { 1767 int i;1867 unsigned int i; 1768 1868 for (i = 0; i < dn->comp_num; i++) { 1769 1869 LDB_FREE(dn->components[i].cf_name); … … 1778 1878 * the GUID and SID are almost certainly no longer valid */ 1779 1879 LDB_FREE(dn->ext_linearized); 1780 1880 LDB_FREE(dn->ext_components); 1781 1881 dn->ext_comp_num = 0; 1782 LDB_FREE(dn->ext_components); 1882 1783 1883 return LDB_SUCCESS; 1784 1884 } … … 1787 1887 const char *name) 1788 1888 { 1789 int i;1889 unsigned int i; 1790 1890 if ( ! ldb_dn_validate(dn)) { 1791 1891 return NULL; … … 1803 1903 { 1804 1904 struct ldb_dn_ext_component *p; 1805 int i; 1905 unsigned int i; 1906 struct ldb_val v2; 1806 1907 1807 1908 if ( ! ldb_dn_validate(dn)) { 1808 1909 return LDB_ERR_OTHER; 1910 } 1911 1912 if (!ldb_dn_extended_syntax_by_name(dn->ldb, name)) { 1913 /* We don't know how to handle this type of thing */ 1914 return LDB_ERR_INVALID_DN_SYNTAX; 1809 1915 } 1810 1916 … … 1819 1925 if (!dn->ext_components[i].name || 1820 1926 !dn->ext_components[i].value.data) { 1821 dn->invalid = true;1927 ldb_dn_mark_invalid(dn); 1822 1928 return LDB_ERR_OPERATIONS_ERROR; 1823 1929 } 1824 1825 1930 } else { 1826 1931 if (i != (dn->ext_comp_num - 1)) { … … 1837 1942 dn->ext_comp_num); 1838 1943 if (!dn->ext_components) { 1839 dn->invalid = true;1944 ldb_dn_mark_invalid(dn); 1840 1945 return LDB_ERR_OPERATIONS_ERROR; 1841 1946 } 1842 return LDB_SUCCESS; 1843 } 1844 } 1845 } 1947 } 1948 LDB_FREE(dn->ext_linearized); 1949 1950 return LDB_SUCCESS; 1951 } 1952 } 1953 1954 if (val == NULL) { 1955 /* removing a value that doesn't exist is not an error */ 1956 return LDB_SUCCESS; 1957 } 1958 1959 v2 = *val; 1846 1960 1847 1961 p = dn->ext_components … … 1851 1965 dn->ext_comp_num + 1); 1852 1966 if (!dn->ext_components) { 1853 dn->invalid = true;1967 ldb_dn_mark_invalid(dn); 1854 1968 return LDB_ERR_OPERATIONS_ERROR; 1855 1969 } 1856 1970 1857 p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, val);1971 p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, &v2); 1858 1972 p[dn->ext_comp_num].name = talloc_strdup(p, name); 1859 1973 1860 1974 if (!dn->ext_components[i].name || !dn->ext_components[i].value.data) { 1861 dn->invalid = true;1975 ldb_dn_mark_invalid(dn); 1862 1976 return LDB_ERR_OPERATIONS_ERROR; 1863 1977 } … … 1865 1979 dn->ext_comp_num++; 1866 1980 1981 LDB_FREE(dn->ext_linearized); 1982 1867 1983 return LDB_SUCCESS; 1868 1984 } … … 1870 1986 void ldb_dn_remove_extended_components(struct ldb_dn *dn) 1871 1987 { 1988 LDB_FREE(dn->ext_linearized); 1989 LDB_FREE(dn->ext_components); 1872 1990 dn->ext_comp_num = 0; 1873 LDB_FREE(dn->ext_components);1874 1991 } 1875 1992 … … 1906 2023 return false; 1907 2024 } 2025 2026 /* 2027 this updates dn->components, taking the components from ref_dn. 2028 This is used by code that wants to update the DN path of a DN 2029 while not impacting on the extended DN components 2030 */ 2031 int ldb_dn_update_components(struct ldb_dn *dn, const struct ldb_dn *ref_dn) 2032 { 2033 dn->components = talloc_realloc(dn, dn->components, 2034 struct ldb_dn_component, ref_dn->comp_num); 2035 if (!dn->components) { 2036 return LDB_ERR_OPERATIONS_ERROR; 2037 } 2038 memcpy(dn->components, ref_dn->components, 2039 sizeof(struct ldb_dn_component)*ref_dn->comp_num); 2040 dn->comp_num = ref_dn->comp_num; 2041 2042 LDB_FREE(dn->casefold); 2043 LDB_FREE(dn->linearized); 2044 LDB_FREE(dn->ext_linearized); 2045 2046 return LDB_SUCCESS; 2047 } 2048 2049 /* 2050 minimise a DN. The caller must pass in a validated DN. 2051 2052 If the DN has an extended component then only the first extended 2053 component is kept, the DN string is stripped. 2054 2055 The existing dn is modified 2056 */ 2057 bool ldb_dn_minimise(struct ldb_dn *dn) 2058 { 2059 unsigned int i; 2060 2061 if (!ldb_dn_validate(dn)) { 2062 return false; 2063 } 2064 if (dn->ext_comp_num == 0) { 2065 return true; 2066 } 2067 2068 /* free components */ 2069 for (i = 0; i < dn->comp_num; i++) { 2070 LDB_FREE(dn->components[i].name); 2071 LDB_FREE(dn->components[i].value.data); 2072 LDB_FREE(dn->components[i].cf_name); 2073 LDB_FREE(dn->components[i].cf_value.data); 2074 } 2075 dn->comp_num = 0; 2076 dn->valid_case = false; 2077 2078 LDB_FREE(dn->casefold); 2079 LDB_FREE(dn->linearized); 2080 2081 /* note that we don't free dn->components as this there are 2082 * several places in ldb_dn.c that rely on it being non-NULL 2083 * for an exploded DN 2084 */ 2085 2086 for (i = 1; i < dn->ext_comp_num; i++) { 2087 LDB_FREE(dn->ext_components[i].name); 2088 LDB_FREE(dn->ext_components[i].value.data); 2089 } 2090 dn->ext_comp_num = 1; 2091 2092 dn->ext_components = talloc_realloc(dn, dn->ext_components, struct ldb_dn_ext_component, 1); 2093 if (dn->ext_components == NULL) { 2094 ldb_dn_mark_invalid(dn); 2095 return false; 2096 } 2097 2098 LDB_FREE(dn->ext_linearized); 2099 2100 return true; 2101 } -
trunk/server/source4/lib/ldb/common/ldb_ldif.c
r414 r745 42 42 43 43 */ 44 static int ldb_read_data_file( void*mem_ctx, struct ldb_val *value)44 static int ldb_read_data_file(TALLOC_CTX *mem_ctx, struct ldb_val *value) 45 45 { 46 46 struct stat statbuf; … … 151 151 caller frees 152 152 */ 153 char *ldb_base64_encode( void*mem_ctx, const char *buf, int len)153 char *ldb_base64_encode(TALLOC_CTX *mem_ctx, const char *buf, int len) 154 154 { 155 155 const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; … … 191 191 uint8_t *p = val->data; 192 192 193 if (ldb->flags & LDB_FLG_SHOW_BINARY) {194 return 0;195 }196 197 193 if (val->length == 0) { 198 194 return 0; … … 220 216 const char *buf, size_t length, int start_pos) 221 217 { 222 unsigned int i;218 size_t i; 223 219 int total=0, ret; 224 220 … … 334 330 for (j=0;j<msg->elements[i].num_values;j++) { 335 331 struct ldb_val v; 332 bool use_b64_encode; 336 333 ret = a->syntax->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v); 337 334 if (ret != LDB_SUCCESS) { 338 335 v = msg->elements[i].values[j]; 339 336 } 340 if (ret != LDB_SUCCESS || ldb_should_b64_encode(ldb, &v)) { 337 use_b64_encode = !(ldb->flags & LDB_FLG_SHOW_BINARY) 338 && ldb_should_b64_encode(ldb, &v); 339 if (ret != LDB_SUCCESS || use_b64_encode) { 341 340 ret = fprintf_fn(private_data, "%s:: ", 342 341 msg->elements[i].name); … … 374 373 CHECK_RET; 375 374 375 talloc_free(mem_ctx); 376 376 377 return total; 377 378 } … … 448 449 449 450 /* simple ldif attribute parser */ 450 static int next_attr( void*mem_ctx, char **s, const char **attr, struct ldb_val *value)451 static int next_attr(TALLOC_CTX *mem_ctx, char **s, const char **attr, struct ldb_val *value) 451 452 { 452 453 char *p; … … 509 510 int len = ldb_read_data_file(mem_ctx, value); 510 511 if (len == -1) { 511 /* an error occur edhile trying to retrieve the file */512 /* an error occurred while trying to retrieve the file */ 512 513 return -1; 513 514 } -
trunk/server/source4/lib/ldb/common/ldb_match.c
r414 r745 82 82 const struct ldb_message *msg, 83 83 const struct ldb_parse_tree *tree, 84 enum ldb_scope scope) 85 { 84 enum ldb_scope scope, bool *matched) 85 { 86 const struct ldb_schema_attribute *a; 87 struct ldb_message_element *el; 88 86 89 if (ldb_attr_dn(tree->u.present.attr) == 0) { 87 return 1; 88 } 89 90 if (ldb_msg_find_element(msg, tree->u.present.attr)) { 91 return 1; 92 } 93 94 return 0; 90 *matched = true; 91 return LDB_SUCCESS; 92 } 93 94 el = ldb_msg_find_element(msg, tree->u.present.attr); 95 if (el == NULL) { 96 *matched = false; 97 return LDB_SUCCESS; 98 } 99 100 a = ldb_schema_attribute_by_name(ldb, el->name); 101 if (!a) { 102 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 103 } 104 105 if (a->syntax->operator_fn) { 106 unsigned int i; 107 for (i = 0; i < el->num_values; i++) { 108 int ret = a->syntax->operator_fn(ldb, LDB_OP_PRESENT, a, &el->values[i], NULL, matched); 109 if (ret != LDB_SUCCESS) return ret; 110 if (*matched) return LDB_SUCCESS; 111 } 112 *matched = false; 113 return LDB_SUCCESS; 114 } 115 116 *matched = true; 117 return LDB_SUCCESS; 95 118 } 96 119 … … 99 122 const struct ldb_parse_tree *tree, 100 123 enum ldb_scope scope, 101 enum ldb_parse_op comp_op )124 enum ldb_parse_op comp_op, bool *matched) 102 125 { 103 126 unsigned int i; 104 127 struct ldb_message_element *el; 105 128 const struct ldb_schema_attribute *a; 106 int ret;107 129 108 130 /* FIXME: APPROX comparison not handled yet */ 109 if (comp_op == LDB_OP_APPROX) return 0; 131 if (comp_op == LDB_OP_APPROX) { 132 return LDB_ERR_INAPPROPRIATE_MATCHING; 133 } 110 134 111 135 el = ldb_msg_find_element(msg, tree->u.comparison.attr); 112 136 if (el == NULL) { 113 return 0; 137 *matched = false; 138 return LDB_SUCCESS; 114 139 } 115 140 116 141 a = ldb_schema_attribute_by_name(ldb, el->name); 142 if (!a) { 143 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 144 } 117 145 118 146 for (i = 0; i < el->num_values; i++) { 119 ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value); 120 121 if (ret == 0) { 122 return 1; 123 } 124 if (ret > 0 && comp_op == LDB_OP_GREATER) { 125 return 1; 126 } 127 if (ret < 0 && comp_op == LDB_OP_LESS) { 128 return 1; 129 } 130 } 131 132 return 0; 147 if (a->syntax->operator_fn) { 148 int ret; 149 ret = a->syntax->operator_fn(ldb, comp_op, a, &el->values[i], &tree->u.comparison.value, matched); 150 if (ret != LDB_SUCCESS) return ret; 151 if (*matched) return LDB_SUCCESS; 152 } else { 153 int ret = a->syntax->comparison_fn(ldb, ldb, &el->values[i], &tree->u.comparison.value); 154 155 if (ret == 0) { 156 *matched = true; 157 return LDB_SUCCESS; 158 } 159 if (ret > 0 && comp_op == LDB_OP_GREATER) { 160 *matched = true; 161 return LDB_SUCCESS; 162 } 163 if (ret < 0 && comp_op == LDB_OP_LESS) { 164 *matched = true; 165 return LDB_SUCCESS; 166 } 167 } 168 } 169 170 *matched = false; 171 return LDB_SUCCESS; 133 172 } 134 173 … … 139 178 const struct ldb_message *msg, 140 179 const struct ldb_parse_tree *tree, 141 enum ldb_scope scope) 180 enum ldb_scope scope, 181 bool *matched) 142 182 { 143 183 unsigned int i; … … 150 190 valuedn = ldb_dn_from_ldb_val(ldb, ldb, &tree->u.equality.value); 151 191 if (valuedn == NULL) { 152 return 0;192 return LDB_ERR_INVALID_DN_SYNTAX; 153 193 } 154 194 … … 157 197 talloc_free(valuedn); 158 198 159 if (ret == 0) return 1;160 return 0;199 *matched = (ret == 0); 200 return LDB_SUCCESS; 161 201 } 162 202 … … 165 205 el = ldb_msg_find_element(msg, tree->u.equality.attr); 166 206 if (el == NULL) { 167 return 0; 207 *matched = false; 208 return LDB_SUCCESS; 168 209 } 169 210 170 211 a = ldb_schema_attribute_by_name(ldb, el->name); 212 if (a == NULL) { 213 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 214 } 171 215 172 216 for (i=0;i<el->num_values;i++) { 173 if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value, 174 &el->values[i]) == 0) { 175 return 1; 176 } 177 } 178 179 return 0; 217 if (a->syntax->operator_fn) { 218 ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a, 219 &tree->u.equality.value, &el->values[i], matched); 220 if (ret != LDB_SUCCESS) return ret; 221 if (*matched) return LDB_SUCCESS; 222 } else { 223 if (a->syntax->comparison_fn(ldb, ldb, &tree->u.equality.value, 224 &el->values[i]) == 0) { 225 *matched = true; 226 return LDB_SUCCESS; 227 } 228 } 229 } 230 231 *matched = false; 232 return LDB_SUCCESS; 180 233 } 181 234 182 235 static int ldb_wildcard_compare(struct ldb_context *ldb, 183 236 const struct ldb_parse_tree *tree, 184 const struct ldb_val value )237 const struct ldb_val value, bool *matched) 185 238 { 186 239 const struct ldb_schema_attribute *a; … … 190 243 char *p, *g; 191 244 uint8_t *save_p = NULL; 192 int c = 0;245 unsigned int c = 0; 193 246 194 247 a = ldb_schema_attribute_by_name(ldb, tree->u.substring.attr); 195 196 if(a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) 197 return -1; 248 if (!a) { 249 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 250 } 251 252 if (a->syntax->canonicalise_fn(ldb, ldb, &value, &val) != 0) { 253 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 254 } 198 255 199 256 save_p = val.data; … … 203 260 204 261 chunk = tree->u.substring.chunks[c]; 205 if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;262 if (a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch; 206 263 207 264 /* This deals with wildcard prefix searches on binary attributes (eg objectGUID) */ 208 265 if (cnk.length > val.length) { 209 goto failed;210 } 211 if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto failed;266 goto mismatch; 267 } 268 if (memcmp((char *)val.data, (char *)cnk.data, cnk.length) != 0) goto mismatch; 212 269 val.length -= cnk.length; 213 270 val.data += cnk.length; … … 220 277 221 278 chunk = tree->u.substring.chunks[c]; 222 if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto failed;279 if(a->syntax->canonicalise_fn(ldb, ldb, chunk, &cnk) != 0) goto mismatch; 223 280 224 281 /* FIXME: case of embedded nulls */ 225 282 p = strstr((char *)val.data, (char *)cnk.data); 226 if (p == NULL) goto failed;283 if (p == NULL) goto mismatch; 227 284 if ( (! tree->u.substring.chunks[c + 1]) && (! tree->u.substring.end_with_wildcard) ) { 228 285 do { /* greedy */ … … 238 295 } 239 296 240 if ( (! tree->u.substring.end_with_wildcard) && (*(val.data) != 0) ) goto failed; /* last chunk have not reached end of string */ 297 /* last chunk may not have reached end of string */ 298 if ( (! tree->u.substring.end_with_wildcard) && (*(val.data) != 0) ) goto mismatch; 241 299 talloc_free(save_p); 242 return 1; 243 244 failed: 300 *matched = true; 301 return LDB_SUCCESS; 302 303 mismatch: 304 *matched = false; 245 305 talloc_free(save_p); 246 306 talloc_free(cnk.data); 247 return 0;307 return LDB_SUCCESS; 248 308 } 249 309 … … 254 314 const struct ldb_message *msg, 255 315 const struct ldb_parse_tree *tree, 256 enum ldb_scope scope )316 enum ldb_scope scope, bool *matched) 257 317 { 258 318 unsigned int i; … … 261 321 el = ldb_msg_find_element(msg, tree->u.substring.attr); 262 322 if (el == NULL) { 263 return 0; 323 *matched = false; 324 return LDB_SUCCESS; 264 325 } 265 326 266 327 for (i = 0; i < el->num_values; i++) { 267 if (ldb_wildcard_compare(ldb, tree, el->values[i]) == 1) { 268 return 1; 269 } 270 } 271 272 return 0; 328 int ret; 329 ret = ldb_wildcard_compare(ldb, tree, el->values[i], matched); 330 if (ret != LDB_SUCCESS) return ret; 331 if (*matched) return LDB_SUCCESS; 332 } 333 334 *matched = false; 335 return LDB_SUCCESS; 273 336 } 274 337 … … 277 340 bitwise-and comparator 278 341 */ 279 static int ldb_comparator_and(const struct ldb_val *v1, const struct ldb_val *v2) 342 static int ldb_comparator_bitmask(const char *oid, const struct ldb_val *v1, const struct ldb_val *v2, 343 bool *matched) 280 344 { 281 345 uint64_t i1, i2; 282 i1 = strtoull((char *)v1->data, NULL, 0); 283 i2 = strtoull((char *)v2->data, NULL, 0); 284 return ((i1 & i2) == i2); 285 } 286 287 /* 288 bitwise-or comparator 289 */ 290 static int ldb_comparator_or(const struct ldb_val *v1, const struct ldb_val *v2) 291 { 292 uint64_t i1, i2; 293 i1 = strtoull((char *)v1->data, NULL, 0); 294 i2 = strtoull((char *)v2->data, NULL, 0); 295 return ((i1 & i2) != 0); 346 char ibuf[100]; 347 char *endptr = NULL; 348 349 if (v1->length >= sizeof(ibuf)-1) { 350 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 351 } 352 memcpy(ibuf, (char *)v1->data, v1->length); 353 ibuf[v1->length] = 0; 354 i1 = strtoull(ibuf, &endptr, 0); 355 if (endptr != NULL) { 356 if (endptr == ibuf || *endptr != 0) { 357 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 358 } 359 } 360 361 if (v2->length >= sizeof(ibuf)-1) { 362 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 363 } 364 endptr = NULL; 365 memcpy(ibuf, (char *)v2->data, v2->length); 366 ibuf[v2->length] = 0; 367 i2 = strtoull(ibuf, &endptr, 0); 368 if (endptr != NULL) { 369 if (endptr == ibuf || *endptr != 0) { 370 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 371 } 372 } 373 if (strcmp(LDB_OID_COMPARATOR_AND, oid) == 0) { 374 *matched = ((i1 & i2) == i2); 375 } else if (strcmp(LDB_OID_COMPARATOR_OR, oid) == 0) { 376 *matched = ((i1 & i2) != 0); 377 } else { 378 return LDB_ERR_INAPPROPRIATE_MATCHING; 379 } 380 return LDB_SUCCESS; 296 381 } 297 382 … … 303 388 const struct ldb_message *msg, 304 389 const struct ldb_parse_tree *tree, 305 enum ldb_scope scope )306 { 307 int i;390 enum ldb_scope scope, bool *matched) 391 { 392 unsigned int i; 308 393 const struct { 309 394 const char *oid; 310 int (*comparator)(const struct ldb_val *, const struct ldb_val *);395 int (*comparator)(const char *, const struct ldb_val *, const struct ldb_val *, bool *); 311 396 } rules[] = { 312 { LDB_OID_COMPARATOR_AND, ldb_comparator_ and},313 { LDB_OID_COMPARATOR_OR, ldb_comparator_ or}397 { LDB_OID_COMPARATOR_AND, ldb_comparator_bitmask}, 398 { LDB_OID_COMPARATOR_OR, ldb_comparator_bitmask} 314 399 }; 315 int (*comp)(const struct ldb_val *, const struct ldb_val *) = NULL;400 int (*comp)(const char *,const struct ldb_val *, const struct ldb_val *, bool *) = NULL; 316 401 struct ldb_message_element *el; 317 402 318 403 if (tree->u.extended.dnAttributes) { 319 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: dnAttributes extended match not supported yet"); 320 return -1; 404 /* FIXME: We really need to find out what this ":dn" part in 405 * an extended match means and how to handle it. For now print 406 * only a warning to have s3 winbind and other tools working 407 * against us. - Matthias */ 408 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb: dnAttributes extended match not supported yet"); 321 409 } 322 410 if (tree->u.extended.rule_id == NULL) { 323 411 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet"); 324 return -1;412 return LDB_ERR_INAPPROPRIATE_MATCHING; 325 413 } 326 414 if (tree->u.extended.attr == NULL) { 327 415 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet"); 328 return -1;416 return LDB_ERR_INAPPROPRIATE_MATCHING; 329 417 } 330 418 … … 338 426 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s", 339 427 tree->u.extended.rule_id); 340 return -1;428 return LDB_ERR_INAPPROPRIATE_MATCHING; 341 429 } 342 430 … … 344 432 el = ldb_msg_find_element(msg, tree->u.extended.attr); 345 433 if (el == NULL) { 346 return 0; 434 *matched = false; 435 return LDB_SUCCESS; 347 436 } 348 437 349 438 for (i=0;i<el->num_values;i++) { 350 int ret = comp(&el->values[i], &tree->u.extended.value); 351 if (ret == -1 || ret == 1) return ret; 352 } 353 354 return 0; 439 int ret = comp(tree->u.extended.rule_id, &el->values[i], &tree->u.extended.value, matched); 440 if (ret != LDB_SUCCESS) return ret; 441 if (*matched) return LDB_SUCCESS; 442 } 443 444 *matched = false; 445 return LDB_SUCCESS; 355 446 } 356 447 … … 366 457 const struct ldb_message *msg, 367 458 const struct ldb_parse_tree *tree, 368 enum ldb_scope scope )459 enum ldb_scope scope, bool *matched) 369 460 { 370 461 unsigned int i; 371 int v; 462 int ret; 463 464 *matched = false; 372 465 373 466 switch (tree->operation) { 374 467 case LDB_OP_AND: 375 468 for (i=0;i<tree->u.list.num_elements;i++) { 376 v = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope); 377 if (!v) return 0; 378 } 379 return 1; 469 ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched); 470 if (ret != LDB_SUCCESS) return ret; 471 if (!*matched) return LDB_SUCCESS; 472 } 473 *matched = true; 474 return LDB_SUCCESS; 380 475 381 476 case LDB_OP_OR: 382 477 for (i=0;i<tree->u.list.num_elements;i++) { 383 v = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope); 384 if (v) return 1; 385 } 386 return 0; 478 ret = ldb_match_message(ldb, msg, tree->u.list.elements[i], scope, matched); 479 if (ret != LDB_SUCCESS) return ret; 480 if (*matched) return LDB_SUCCESS; 481 } 482 *matched = false; 483 return LDB_SUCCESS; 387 484 388 485 case LDB_OP_NOT: 389 return ! ldb_match_message(ldb, msg, tree->u.isnot.child, scope); 486 ret = ldb_match_message(ldb, msg, tree->u.isnot.child, scope, matched); 487 if (ret != LDB_SUCCESS) return ret; 488 *matched = ! *matched; 489 return LDB_SUCCESS; 390 490 391 491 case LDB_OP_EQUALITY: 392 return ldb_match_equality(ldb, msg, tree, scope );492 return ldb_match_equality(ldb, msg, tree, scope, matched); 393 493 394 494 case LDB_OP_SUBSTRING: 395 return ldb_match_substring(ldb, msg, tree, scope );495 return ldb_match_substring(ldb, msg, tree, scope, matched); 396 496 397 497 case LDB_OP_GREATER: 398 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER );498 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_GREATER, matched); 399 499 400 500 case LDB_OP_LESS: 401 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS );501 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_LESS, matched); 402 502 403 503 case LDB_OP_PRESENT: 404 return ldb_match_present(ldb, msg, tree, scope );504 return ldb_match_present(ldb, msg, tree, scope, matched); 405 505 406 506 case LDB_OP_APPROX: 407 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX );507 return ldb_match_comparison(ldb, msg, tree, scope, LDB_OP_APPROX, matched); 408 508 409 509 case LDB_OP_EXTENDED: 410 return ldb_match_extended(ldb, msg, tree, scope); 411 412 } 413 414 return 0; 510 return ldb_match_extended(ldb, msg, tree, scope, matched); 511 } 512 513 return LDB_ERR_INAPPROPRIATE_MATCHING; 415 514 } 416 515 … … 421 520 enum ldb_scope scope) 422 521 { 522 bool matched; 523 int ret; 524 423 525 if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) { 424 526 return 0; 425 527 } 426 528 427 return ldb_match_message(ldb, msg, tree, scope); 428 } 529 ret = ldb_match_message(ldb, msg, tree, scope, &matched); 530 if (ret != LDB_SUCCESS) { 531 /* to match the old API, we need to consider this a 532 failure to match */ 533 return 0; 534 } 535 return matched?1:0; 536 } 537 538 int ldb_match_msg_error(struct ldb_context *ldb, 539 const struct ldb_message *msg, 540 const struct ldb_parse_tree *tree, 541 struct ldb_dn *base, 542 enum ldb_scope scope, 543 bool *matched) 544 { 545 if ( ! ldb_match_scope(ldb, base, msg->dn, scope) ) { 546 *matched = false; 547 return LDB_SUCCESS; 548 } 549 550 return ldb_match_message(ldb, msg, tree, scope, matched); 551 } 552 553 int ldb_match_msg_objectclass(const struct ldb_message *msg, 554 const char *objectclass) 555 { 556 unsigned int i; 557 struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass"); 558 if (!el) { 559 return 0; 560 } 561 for (i=0; i < el->num_values; i++) { 562 if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) { 563 return 1; 564 } 565 } 566 return 0; 567 } 568 569 570 -
trunk/server/source4/lib/ldb/common/ldb_modules.c
r414 r745 34 34 #include "ldb_private.h" 35 35 #include "dlinklist.h" 36 37 #define LDB_MODULE_PREFIX "modules:" 38 #define LDB_MODULE_PREFIX_LEN 8 39 40 static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name, 41 const char *symbol); 42 43 void ldb_set_modules_dir(struct ldb_context *ldb, const char *path) 44 { 45 talloc_free(ldb->modules_dir); 46 ldb->modules_dir = talloc_strdup(ldb, path); 47 } 36 #include "system/dir.h" 48 37 49 38 static char *ldb_modules_strdup_no_spaces(TALLOC_CTX *mem_ctx, const char *string) 50 39 { 51 int i, len;40 size_t i, len; 52 41 char *trimmed; 53 42 … … 80 69 const char **m; 81 70 char *modstr, *p; 82 int i;71 unsigned int i; 83 72 84 73 /* spaces not admitted */ … … 96 85 } 97 86 talloc_steal(modules, modstr); 87 88 if (modstr[0] == '\0') { 89 modules[0] = NULL; 90 m = (const char **)modules; 91 return m; 92 } 98 93 99 94 i = 0; … … 131 126 } *registered_modules = NULL; 132 127 133 static const struct ldb_builtins { 134 const struct ldb_backend_ops *backend_ops; 135 const struct ldb_module_ops *module_ops; 136 } builtins[]; 137 138 static ldb_connect_fn ldb_find_backend(const char *url) 128 static struct backends_list_entry *ldb_find_backend(const char *url_prefix) 139 129 { 140 130 struct backends_list_entry *backend; 141 int i;142 143 for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {144 if (builtins[i].backend_ops == NULL) continue;145 146 if (strncmp(builtins[i].backend_ops->name, url,147 strlen(builtins[i].backend_ops->name)) == 0) {148 return builtins[i].backend_ops->connect_fn;149 }150 }151 131 152 132 for (backend = ldb_backends; backend; backend = backend->next) { 153 if (strncmp(backend->ops->name, url, 154 strlen(backend->ops->name)) == 0) { 155 return backend->ops->connect_fn; 133 if (strcmp(backend->ops->name, url_prefix) == 0) { 134 return backend; 156 135 } 157 136 } … … 161 140 162 141 /* 163 register a new ldb backend 142 register a new ldb backend 143 144 if override is true, then override any existing backend for this prefix 164 145 */ 165 int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn )166 { 167 struct ldb_backend_ops *backend;168 struct backends_list_entry *entry; 169 170 backend = talloc(talloc_autofree_context(), struct ldb_backend_ops);171 if (!backend) return LDB_ERR_OPERATIONS_ERROR;172 173 entry = talloc(talloc_autofree_context(), struct backends_list_entry);174 if (!entry){175 talloc_free(backend);176 return LDB_ERR_OPERATIONS_ERROR;177 }178 179 if (ldb_find_backend(url_prefix)) {180 return LDB_SUCCESS;181 }182 183 /* Maybe check for duplicity here later on? */184 185 backend->name = talloc_strdup(backend, url_prefix);186 backend->connect_fn = connectfn; 187 entry->ops = backend;188 DLIST_ADD(ldb_backends, entry);146 int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn, bool override) 147 { 148 struct backends_list_entry *be; 149 150 be = ldb_find_backend(url_prefix); 151 if (be) { 152 if (!override) { 153 return LDB_SUCCESS; 154 } 155 } else { 156 be = talloc_zero(ldb_backends, struct backends_list_entry); 157 if (!be) { 158 return LDB_ERR_OPERATIONS_ERROR; 159 } 160 be->ops = talloc_zero(be, struct ldb_backend_ops); 161 if (!be->ops) { 162 talloc_free(be); 163 return LDB_ERR_OPERATIONS_ERROR; 164 } 165 DLIST_ADD_END(ldb_backends, be, struct backends_list_entry); 166 } 167 168 be->ops->name = url_prefix; 169 be->ops->connect_fn = connectfn; 189 170 190 171 return LDB_SUCCESS; … … 205 186 module may wish to direct certain requests at a particular backend. 206 187 */ 207 int ldb_ connect_backend(struct ldb_context *ldb,208 const char *url,209 const char *options[],210 struct ldb_module **backend_module)188 int ldb_module_connect_backend(struct ldb_context *ldb, 189 const char *url, 190 const char *options[], 191 struct ldb_module **backend_module) 211 192 { 212 193 int ret; 213 194 char *backend; 214 ldb_connect_fn fn;195 struct backends_list_entry *be; 215 196 216 197 if (strchr(url, ':') != NULL) { … … 221 202 } 222 203 223 fn = ldb_find_backend(backend); 224 225 if (fn == NULL) { 226 struct ldb_backend_ops *ops; 227 char *symbol_name = talloc_asprintf(ldb, "ldb_%s_backend_ops", backend); 228 if (symbol_name == NULL) { 229 return LDB_ERR_OPERATIONS_ERROR; 230 } 231 ops = ldb_dso_load_symbol(ldb, backend, symbol_name); 232 if (ops != NULL) { 233 fn = ops->connect_fn; 234 } 235 talloc_free(symbol_name); 236 } 204 be = ldb_find_backend(backend); 237 205 238 206 talloc_free(backend); 239 207 240 if ( fn== NULL) {208 if (be == NULL) { 241 209 ldb_debug(ldb, LDB_DEBUG_FATAL, 242 "Unable to find backend for '%s' ", url);210 "Unable to find backend for '%s' - do you need to set LDB_MODULES_PATH?", url); 243 211 return LDB_ERR_OTHER; 244 212 } 245 213 246 ret = fn(ldb, url, ldb->flags, options, backend_module);214 ret = be->ops->connect_fn(ldb, url, ldb->flags, options, backend_module); 247 215 248 216 if (ret != LDB_SUCCESS) { 249 217 ldb_debug(ldb, LDB_DEBUG_ERROR, 250 "Failed to connect to '%s' ", url);218 "Failed to connect to '%s' with backend '%s'", url, be->ops->name); 251 219 return ret; 252 220 } … … 254 222 } 255 223 224 static struct ldb_hooks { 225 struct ldb_hooks *next, *prev; 226 ldb_hook_fn hook_fn; 227 } *ldb_hooks; 228 229 /* 230 register a ldb hook function 231 */ 232 int ldb_register_hook(ldb_hook_fn hook_fn) 233 { 234 struct ldb_hooks *lc; 235 lc = talloc_zero(ldb_hooks, struct ldb_hooks); 236 if (lc == NULL) { 237 return LDB_ERR_OPERATIONS_ERROR; 238 } 239 lc->hook_fn = hook_fn; 240 DLIST_ADD_END(ldb_hooks, lc, struct ldb_hooks); 241 return LDB_SUCCESS; 242 } 243 244 /* 245 call ldb hooks of a given type 246 */ 247 int ldb_modules_hook(struct ldb_context *ldb, enum ldb_module_hook_type t) 248 { 249 struct ldb_hooks *lc; 250 for (lc = ldb_hooks; lc; lc=lc->next) { 251 int ret = lc->hook_fn(ldb, t); 252 if (ret != LDB_SUCCESS) { 253 return ret; 254 } 255 } 256 return LDB_SUCCESS; 257 } 258 259 256 260 static const struct ldb_module_ops *ldb_find_module_ops(const char *name) 257 261 { 258 262 struct ops_list_entry *e; 259 int i;260 261 for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {262 if (builtins[i].module_ops == NULL) continue;263 264 if (strcmp(builtins[i].module_ops->name, name) == 0)265 return builtins[i].module_ops;266 }267 263 268 264 for (e = registered_modules; e; e = e->next) { … … 277 273 int ldb_register_module(const struct ldb_module_ops *ops) 278 274 { 279 struct ops_list_entry *entry = talloc(talloc_autofree_context(), struct ops_list_entry);275 struct ops_list_entry *entry; 280 276 281 277 if (ldb_find_module_ops(ops->name) != NULL) 282 return -1; 283 278 return LDB_ERR_ENTRY_ALREADY_EXISTS; 279 280 entry = talloc(talloc_autofree_context(), struct ops_list_entry); 284 281 if (entry == NULL) 285 282 return -1; … … 292 289 } 293 290 294 static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name, 295 const char *symbol) 296 { 297 char *path; 298 void *handle; 299 void *sym; 300 301 if (ldb->modules_dir == NULL) 302 return NULL; 303 304 path = talloc_asprintf(ldb, "%s/%s.%s", ldb->modules_dir, name, 305 SHLIBEXT); 306 307 ldb_debug(ldb, LDB_DEBUG_TRACE, "trying to load %s from %s", name, path); 308 309 handle = dlopen(path, RTLD_NOW); 310 if (handle == NULL) { 311 ldb_debug(ldb, LDB_DEBUG_WARNING, "unable to load %s from %s: %s", name, path, dlerror()); 312 return NULL; 313 } 314 315 sym = (int (*)(void))dlsym(handle, symbol); 316 317 if (sym == NULL) { 318 ldb_debug(ldb, LDB_DEBUG_ERROR, "no symbol `%s' found in %s: %s", symbol, path, dlerror()); 319 return NULL; 320 } 321 322 talloc_free(path); 323 324 return sym; 325 } 326 327 int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, struct ldb_module *backend, struct ldb_module **out) 291 /* 292 load a list of modules 293 */ 294 int ldb_module_load_list(struct ldb_context *ldb, const char **module_list, 295 struct ldb_module *backend, struct ldb_module **out) 328 296 { 329 297 struct ldb_module *module; 330 int i;298 unsigned int i; 331 299 332 300 module = backend; 333 301 334 for (i = 0; module_list [i] != NULL; i++) {302 for (i = 0; module_list && module_list[i] != NULL; i++) { 335 303 struct ldb_module *current; 336 304 const struct ldb_module_ops *ops; … … 341 309 342 310 ops = ldb_find_module_ops(module_list[i]); 311 343 312 if (ops == NULL) { 344 char *symbol_name = talloc_asprintf(ldb, "ldb_%s_module_ops", 345 module_list[i]); 346 if (symbol_name == NULL) { 347 return LDB_ERR_OPERATIONS_ERROR; 348 } 349 ops = ldb_dso_load_symbol(ldb, module_list[i], symbol_name); 350 talloc_free(symbol_name); 351 } 352 353 if (ops == NULL) { 354 ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found", 313 ldb_debug(ldb, LDB_DEBUG_FATAL, "WARNING: Module [%s] not found - do you need to set LDB_MODULES_PATH?", 355 314 module_list[i]); 356 continue;315 return LDB_ERR_OPERATIONS_ERROR; 357 316 } 358 317 … … 372 331 } 373 332 374 int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module) 333 /* 334 initialise a chain of modules 335 */ 336 int ldb_module_init_chain(struct ldb_context *ldb, struct ldb_module *module) 375 337 { 376 338 while (module && module->ops->init_context == NULL) … … 383 345 int ret = module->ops->init_context(module); 384 346 if (ret != LDB_SUCCESS) { 385 ldb_debug(ldb, LDB_DEBUG_FATAL, "module %s initialization failed", module->ops->name); 347 ldb_debug(ldb, LDB_DEBUG_FATAL, "module %s initialization failed : %s", 348 module->ops->name, ldb_strerror(ret)); 386 349 return ret; 387 350 } … … 393 356 int ldb_load_modules(struct ldb_context *ldb, const char *options[]) 394 357 { 358 const char *modules_string; 395 359 const char **modules = NULL; 396 int i;397 360 int ret; 398 361 TALLOC_CTX *mem_ctx = talloc_new(ldb); … … 405 368 /* check if we have a custom module list passd as ldb option */ 406 369 if (options) { 407 for (i = 0; options[i] != NULL; i++) { 408 if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) { 409 modules = ldb_modules_list_from_string(ldb, mem_ctx, &options[i][LDB_MODULE_PREFIX_LEN]); 410 } 370 modules_string = ldb_options_find(ldb, options, "modules"); 371 if (modules_string) { 372 modules = ldb_modules_list_from_string(ldb, mem_ctx, modules_string); 411 373 } 412 374 } … … 454 416 455 417 if (modules != NULL) { 456 ret = ldb_ load_modules_list(ldb, modules, ldb->modules, &ldb->modules);418 ret = ldb_module_load_list(ldb, modules, ldb->modules, &ldb->modules); 457 419 if (ret != LDB_SUCCESS) { 458 420 talloc_free(mem_ctx); … … 463 425 } 464 426 465 ret = ldb_ init_module_chain(ldb, ldb->modules);427 ret = ldb_module_init_chain(ldb, ldb->modules); 466 428 talloc_free(mem_ctx); 467 429 return ret; … … 476 438 module = module->next; \ 477 439 while (module && module->ops->op == NULL) module = module->next; \ 440 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { \ 441 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_trace_next_request: (%s)->" #op, \ 442 module->ops->name); \ 443 } \ 478 444 } while (0) 479 445 … … 516 482 { 517 483 return module->ldb; 484 } 485 486 const struct ldb_module_ops *ldb_module_get_ops(struct ldb_module *module) 487 { 488 return module->ops; 518 489 } 519 490 … … 592 563 * corner for module developers to cut themselves on 593 564 */ 594 ldb_module_done(request, NULL, NULL, ret);565 ret = ldb_module_done(request, NULL, NULL, ret); 595 566 } 596 567 return ret; … … 601 572 module = module->next; 602 573 603 return ldb_ init_module_chain(module->ldb, module);574 return ldb_module_init_chain(module->ldb, module); 604 575 } 605 576 606 577 int ldb_next_start_trans(struct ldb_module *module) 607 578 { 579 int ret; 608 580 FIND_OP(module, start_transaction); 609 return module->ops->start_transaction(module); 581 ret = module->ops->start_transaction(module); 582 if (ret == LDB_SUCCESS) { 583 return ret; 584 } 585 if (!ldb_errstring(module->ldb)) { 586 /* Set a default error string, to place the blame somewhere */ 587 ldb_asprintf_errstring(module->ldb, "start_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); 588 } 589 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { 590 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_start_trans error: %s", 591 ldb_errstring(module->ldb)); 592 } 593 return ret; 610 594 } 611 595 612 596 int ldb_next_end_trans(struct ldb_module *module) 613 597 { 598 int ret; 614 599 FIND_OP(module, end_transaction); 615 return module->ops->end_transaction(module); 600 ret = module->ops->end_transaction(module); 601 if (ret == LDB_SUCCESS) { 602 return ret; 603 } 604 if (!ldb_errstring(module->ldb)) { 605 /* Set a default error string, to place the blame somewhere */ 606 ldb_asprintf_errstring(module->ldb, "end_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); 607 } 608 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { 609 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_end_trans error: %s", 610 ldb_errstring(module->ldb)); 611 } 612 return ret; 616 613 } 617 614 618 615 int ldb_next_prepare_commit(struct ldb_module *module) 619 616 { 617 int ret; 620 618 FIND_OP_NOERR(module, prepare_commit); 621 619 if (module == NULL) { … … 624 622 return LDB_SUCCESS; 625 623 } 626 return module->ops->prepare_commit(module); 624 ret = module->ops->prepare_commit(module); 625 if (ret == LDB_SUCCESS) { 626 return ret; 627 } 628 if (!ldb_errstring(module->ldb)) { 629 /* Set a default error string, to place the blame somewhere */ 630 ldb_asprintf_errstring(module->ldb, "prepare_commit error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); 631 } 632 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { 633 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_prepare_commit error: %s", 634 ldb_errstring(module->ldb)); 635 } 636 return ret; 627 637 } 628 638 629 639 int ldb_next_del_trans(struct ldb_module *module) 630 640 { 641 int ret; 631 642 FIND_OP(module, del_transaction); 632 return module->ops->del_transaction(module); 643 ret = module->ops->del_transaction(module); 644 if (ret == LDB_SUCCESS) { 645 return ret; 646 } 647 if (!ldb_errstring(module->ldb)) { 648 /* Set a default error string, to place the blame somewhere */ 649 ldb_asprintf_errstring(module->ldb, "del_trans error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); 650 } 651 if ((module && module->ldb->flags & LDB_FLG_ENABLE_TRACING)) { 652 ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_next_del_trans error: %s", 653 ldb_errstring(module->ldb)); 654 } 655 return ret; 633 656 } 634 657 … … 647 670 h->ldb = ldb; 648 671 h->flags = 0; 672 h->location = NULL; 673 h->parent = NULL; 649 674 650 675 return h; … … 729 754 * ctrls: controls to send in the reply (must be a talloc pointer, steal) 730 755 * response: results for extended request (steal) 731 * error: LDB_SUCCESS for a succes ful return756 * error: LDB_SUCCESS for a successful return 732 757 * any other ldb error otherwise 733 758 */ … … 763 788 } 764 789 765 req->callback(req, ares); 766 return error; 790 return req->callback(req, ares); 767 791 } 768 792 769 793 /* to be used *only* in modules init functions. 770 * this function i synchronous and will register794 * this function is synchronous and will register 771 795 * the requested OID in the rootdse module if present 772 796 * otherwise it will return an error */ … … 801 825 } 802 826 803 #ifndef STATIC_LIBLDB_MODULES 804 805 #ifdef HAVE_LDB_LDAP 806 #define LDAP_BACKEND LDB_BACKEND(ldap), LDB_BACKEND(ldapi), LDB_BACKEND(ldaps), 807 #else 808 #define LDAP_BACKEND 827 static int ldb_modules_load_dir(const char *modules_dir, const char *version); 828 829 830 /* 831 load one module. A static list of loaded module inode numbers is 832 used to prevent a module being loaded twice 833 834 dlopen() is used on the module, and dlsym() is then used to look for 835 a ldb_init_module() function. If present, that function is called 836 with the ldb version number as an argument. 837 838 The ldb_init_module() function will typically call 839 ldb_register_module() and ldb_register_backend() to register a 840 module or backend, but it may also be used to register command line 841 handling functions, ldif handlers or any other local 842 modififications. 843 844 The ldb_init_module() function does not get a ldb_context passed in, 845 as modules will be used for multiple ldb context handles. The call 846 from the first ldb_init() is just a convenient way to ensure it is 847 called early enough. 848 */ 849 static int ldb_modules_load_path(const char *path, const char *version) 850 { 851 void *handle; 852 int (*init_fn)(const char *); 853 int ret; 854 struct stat st; 855 static struct loaded { 856 struct loaded *next, *prev; 857 ino_t st_ino; 858 dev_t st_dev; 859 } *loaded; 860 struct loaded *le; 861 int dlopen_flags; 862 863 ret = stat(path, &st); 864 if (ret != 0) { 865 fprintf(stderr, "ldb: unable to stat module %s : %s\n", path, strerror(errno)); 866 return LDB_ERR_UNAVAILABLE; 867 } 868 869 for (le=loaded; le; le=le->next) { 870 if (le->st_ino == st.st_ino && 871 le->st_dev == st.st_dev) { 872 /* its already loaded */ 873 return LDB_SUCCESS; 874 } 875 } 876 877 le = talloc(loaded, struct loaded); 878 if (le == NULL) { 879 fprintf(stderr, "ldb: unable to allocated loaded entry\n"); 880 return LDB_ERR_UNAVAILABLE; 881 } 882 883 le->st_ino = st.st_ino; 884 le->st_dev = st.st_dev; 885 886 DLIST_ADD_END(loaded, le, struct loaded); 887 888 /* if it is a directory, recurse */ 889 if (S_ISDIR(st.st_mode)) { 890 return ldb_modules_load_dir(path, version); 891 } 892 893 dlopen_flags = RTLD_NOW; 894 #ifdef RTLD_DEEPBIND 895 /* use deepbind if possible, to avoid issues with different 896 system library varients, for example ldb modules may be linked 897 against Heimdal while the application may use MIT kerberos 898 899 See the dlopen manpage for details 900 */ 901 dlopen_flags |= RTLD_DEEPBIND; 809 902 #endif 810 903 811 #ifdef HAVE_LDB_SQLITE3 812 #define SQLITE3_BACKEND LDB_BACKEND(sqlite3), 813 #else 814 #define SQLITE3_BACKEND 815 #endif 816 817 #define STATIC_LIBLDB_MODULES \ 818 LDB_BACKEND(tdb), \ 819 LDAP_BACKEND \ 820 SQLITE3_BACKEND \ 821 LDB_MODULE(rdn_name), \ 822 LDB_MODULE(paged_results), \ 823 LDB_MODULE(server_sort), \ 824 LDB_MODULE(asq), \ 825 NULL 826 #endif 827 828 /* 829 * this is a bit hacked, as STATIC_LIBLDB_MODULES contains ',' 830 * between the elements and we want to autogenerate the 831 * extern struct declarations, so we do some hacks and let the 832 * ',' appear in an unused function prototype. 833 */ 834 #undef NULL 835 #define NULL LDB_MODULE(NULL), 836 837 #define LDB_BACKEND(name) \ 838 int); \ 839 extern const struct ldb_backend_ops ldb_ ## name ## _backend_ops;\ 840 extern void ldb_noop ## name (int 841 #define LDB_MODULE(name) \ 842 int); \ 843 extern const struct ldb_module_ops ldb_ ## name ## _module_ops;\ 844 extern void ldb_noop ## name (int 845 846 extern void ldb_start_noop(int, 847 STATIC_LIBLDB_MODULES 848 int); 849 850 #undef NULL 851 #define NULL { \ 852 .backend_ops = (void *)0, \ 853 .module_ops = (void *)0 \ 854 } 855 856 #undef LDB_BACKEND 857 #define LDB_BACKEND(name) { \ 858 .backend_ops = &ldb_ ## name ## _backend_ops, \ 859 .module_ops = (void *)0 \ 860 } 861 #undef LDB_MODULE 862 #define LDB_MODULE(name) { \ 863 .backend_ops = (void *)0, \ 864 .module_ops = &ldb_ ## name ## _module_ops \ 865 } 866 867 static const struct ldb_builtins builtins[] = { 868 STATIC_LIBLDB_MODULES 869 }; 904 handle = dlopen(path, dlopen_flags); 905 if (handle == NULL) { 906 fprintf(stderr, "ldb: unable to dlopen %s : %s\n", path, dlerror()); 907 return LDB_SUCCESS; 908 } 909 910 init_fn = dlsym(handle, "ldb_init_module"); 911 if (init_fn == NULL) { 912 /* ignore it, it could be an old-style 913 * module. Once we've converted all modules we 914 * could consider this an error */ 915 dlclose(handle); 916 return LDB_SUCCESS; 917 } 918 919 ret = init_fn(version); 920 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { 921 /* the module is already registered - ignore this, as 922 * it can happen if LDB_MODULES_PATH points at both 923 * the build and install directory 924 */ 925 ret = LDB_SUCCESS; 926 } 927 return ret; 928 } 929 930 static int qsort_string(const char **s1, const char **s2) 931 { 932 return strcmp(*s1, *s2); 933 } 934 935 936 /* 937 load all modules from the given ldb modules directory. This is run once 938 during the first ldb_init() call. 939 940 Modules are loaded in alphabetical order to ensure that any module 941 load ordering dependencies are reproducible. Modules should avoid 942 relying on load order 943 */ 944 static int ldb_modules_load_dir(const char *modules_dir, const char *version) 945 { 946 DIR *dir; 947 struct dirent *de; 948 const char **modlist = NULL; 949 TALLOC_CTX *tmp_ctx = talloc_new(NULL); 950 unsigned i, num_modules = 0; 951 952 dir = opendir(modules_dir); 953 if (dir == NULL) { 954 if (errno == ENOENT) { 955 talloc_free(tmp_ctx); 956 /* we don't have any modules */ 957 return LDB_SUCCESS; 958 } 959 talloc_free(tmp_ctx); 960 fprintf(stderr, "ldb: unable to open modules directory '%s' - %s\n", 961 modules_dir, strerror(errno)); 962 return LDB_ERR_UNAVAILABLE; 963 } 964 965 966 while ((de = readdir(dir))) { 967 if (ISDOT(de->d_name) || ISDOTDOT(de->d_name)) 968 continue; 969 970 modlist = talloc_realloc(tmp_ctx, modlist, const char *, num_modules+1); 971 if (modlist == NULL) { 972 talloc_free(tmp_ctx); 973 closedir(dir); 974 fprintf(stderr, "ldb: unable to allocate modules list\n"); 975 return LDB_ERR_UNAVAILABLE; 976 } 977 modlist[num_modules] = talloc_asprintf(modlist, "%s/%s", modules_dir, de->d_name); 978 if (modlist[num_modules] == NULL) { 979 talloc_free(tmp_ctx); 980 closedir(dir); 981 fprintf(stderr, "ldb: unable to allocate module list entry\n"); 982 return LDB_ERR_UNAVAILABLE; 983 } 984 num_modules++; 985 } 986 987 closedir(dir); 988 989 /* sort the directory, so we get consistent load ordering */ 990 TYPESAFE_QSORT(modlist, num_modules, qsort_string); 991 992 for (i=0; i<num_modules; i++) { 993 int ret = ldb_modules_load_path(modlist[i], version); 994 if (ret != LDB_SUCCESS) { 995 fprintf(stderr, "ldb: failed to initialise module %s : %s\n", 996 modlist[i], ldb_strerror(ret)); 997 talloc_free(tmp_ctx); 998 return ret; 999 } 1000 } 1001 1002 talloc_free(tmp_ctx); 1003 1004 return LDB_SUCCESS; 1005 } 1006 1007 /* 1008 load any additional modules from the given directory 1009 */ 1010 void ldb_set_modules_dir(struct ldb_context *ldb, const char *path) 1011 { 1012 int ret = ldb_modules_load_path(path, LDB_VERSION); 1013 if (ret != LDB_SUCCESS) { 1014 ldb_asprintf_errstring(ldb, "Failed to load modules from: %s\n", path); 1015 } 1016 } 1017 1018 1019 /* 1020 load all modules static (builtin) modules 1021 */ 1022 static int ldb_modules_load_static(const char *version) 1023 { 1024 static bool initialised; 1025 #define _MODULE_PROTO(init) extern int init(const char *); 1026 STATIC_ldb_MODULES_PROTO; 1027 const ldb_module_init_fn static_init_functions[] = { STATIC_ldb_MODULES }; 1028 unsigned i; 1029 1030 if (initialised) { 1031 return LDB_SUCCESS; 1032 } 1033 initialised = true; 1034 1035 for (i=0; static_init_functions[i]; i++) { 1036 int ret = static_init_functions[i](version); 1037 if (ret != LDB_SUCCESS) { 1038 return ret; 1039 } 1040 } 1041 return LDB_SUCCESS; 1042 } 1043 1044 /* 1045 load all modules from the given ldb modules path, colon 1046 separated. 1047 1048 modules are loaded recursively for all subdirectories in the paths 1049 */ 1050 int ldb_modules_load(const char *modules_path, const char *version) 1051 { 1052 char *tok, *path, *tok_ptr=NULL; 1053 int ret; 1054 1055 ret = ldb_modules_load_static(version); 1056 if (ret != LDB_SUCCESS) { 1057 return ret; 1058 } 1059 1060 path = talloc_strdup(NULL, modules_path); 1061 if (path == NULL) { 1062 fprintf(stderr, "ldb: failed to allocate modules_path\n"); 1063 return LDB_ERR_UNAVAILABLE; 1064 } 1065 1066 for (tok=strtok_r(path, ":", &tok_ptr); 1067 tok; 1068 tok=strtok_r(NULL, ":", &tok_ptr)) { 1069 ret = ldb_modules_load_path(tok, version); 1070 if (ret != LDB_SUCCESS) { 1071 talloc_free(path); 1072 return ret; 1073 } 1074 } 1075 talloc_free(path); 1076 1077 return LDB_SUCCESS; 1078 } 1079 1080 1081 /* 1082 return a string representation of the calling chain for the given 1083 ldb request 1084 */ 1085 char *ldb_module_call_chain(struct ldb_request *req, TALLOC_CTX *mem_ctx) 1086 { 1087 char *ret; 1088 int i=0; 1089 1090 ret = talloc_strdup(mem_ctx, ""); 1091 if (ret == NULL) { 1092 return NULL; 1093 } 1094 1095 while (req && req->handle) { 1096 char *s = talloc_asprintf_append_buffer(ret, "req[%u] %p : %s\n", 1097 i++, req, ldb_req_location(req)); 1098 if (s == NULL) { 1099 talloc_free(ret); 1100 return NULL; 1101 } 1102 ret = s; 1103 req = req->handle->parent; 1104 } 1105 return ret; 1106 } 1107 1108 1109 /* 1110 return the next module in the chain 1111 */ 1112 struct ldb_module *ldb_module_next(struct ldb_module *module) 1113 { 1114 return module->next; 1115 } 1116 1117 /* 1118 set the next module in the module chain 1119 */ 1120 void ldb_module_set_next(struct ldb_module *module, struct ldb_module *next) 1121 { 1122 module->next = next; 1123 } 1124 1125 1126 /* 1127 get the popt_options pointer in the ldb structure. This allows a ldb 1128 module to change the command line parsing 1129 */ 1130 struct poptOption **ldb_module_popt_options(struct ldb_context *ldb) 1131 { 1132 return &ldb->popt_options; 1133 } 1134 1135 1136 /* 1137 return the current ldb flags LDB_FLG_* 1138 */ 1139 uint32_t ldb_module_flags(struct ldb_context *ldb) 1140 { 1141 return ldb->flags; 1142 } -
trunk/server/source4/lib/ldb/common/ldb_msg.c
r414 r745 37 37 create a new ldb_message in a given memory context (NULL for top level) 38 38 */ 39 struct ldb_message *ldb_msg_new( void*mem_ctx)39 struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx) 40 40 { 41 41 return talloc_zero(mem_ctx, struct ldb_message); … … 64 64 { 65 65 if (v1->length != v2->length) return 0; 66 66 if (v1->data == v2->data) return 1; 67 67 if (v1->length == 0) return 1; 68 68 … … 93 93 duplicate a ldb_val structure 94 94 */ 95 struct ldb_val ldb_val_dup( void*mem_ctx, const struct ldb_val *v)95 struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v) 96 96 { 97 97 struct ldb_val v2; … … 115 115 } 116 116 117 /* 118 add an empty element to a message 119 */ 120 int ldb_msg_add_empty( struct ldb_message *msg, 121 const char *attr_name, 122 int flags, 123 struct ldb_message_element **return_el) 117 /** 118 * Adds new empty element to msg->elements 119 */ 120 static int _ldb_msg_add_el(struct ldb_message *msg, 121 struct ldb_message_element **return_el) 124 122 { 125 123 struct ldb_message_element *els; 126 124 127 els = talloc_realloc(msg, msg->elements, 128 struct ldb_message_element, msg->num_elements+1); 125 /* 126 * TODO: Find out a way to assert on input parameters. 127 * msg and return_el must be valid 128 */ 129 130 els = talloc_realloc(msg, msg->elements, 131 struct ldb_message_element, msg->num_elements + 1); 129 132 if (!els) { 130 133 errno = ENOMEM; … … 132 135 } 133 136 134 els[msg->num_elements].values = NULL; 135 els[msg->num_elements].num_values = 0; 136 els[msg->num_elements].flags = flags; 137 els[msg->num_elements].name = talloc_strdup(els, attr_name); 138 if (!els[msg->num_elements].name) { 137 ZERO_STRUCT(els[msg->num_elements]); 138 139 msg->elements = els; 140 msg->num_elements++; 141 142 *return_el = &els[msg->num_elements-1]; 143 144 return LDB_SUCCESS; 145 } 146 147 /** 148 * Add an empty element with a given name to a message 149 */ 150 int ldb_msg_add_empty(struct ldb_message *msg, 151 const char *attr_name, 152 int flags, 153 struct ldb_message_element **return_el) 154 { 155 int ret; 156 struct ldb_message_element *el; 157 158 ret = _ldb_msg_add_el(msg, &el); 159 if (ret != LDB_SUCCESS) { 160 return ret; 161 } 162 163 /* initialize newly added element */ 164 el->flags = flags; 165 el->name = talloc_strdup(msg->elements, attr_name); 166 if (!el->name) { 139 167 errno = ENOMEM; 140 168 return LDB_ERR_OPERATIONS_ERROR; 141 169 } 142 170 143 msg->elements = els;144 msg->num_elements++;145 146 171 if (return_el) { 147 *return_el = &els[msg->num_elements-1];172 *return_el = el; 148 173 } 149 174 … … 151 176 } 152 177 153 /* 154 add an empty element to a message 155 */ 178 /** 179 * Adds an element to a message. 180 * 181 * NOTE: Ownership of ldb_message_element fields 182 * is NOT transferred. Thus, if *el pointer 183 * is invalidated for some reason, this will 184 * corrupt *msg contents also 185 */ 156 186 int ldb_msg_add(struct ldb_message *msg, 157 187 const struct ldb_message_element *el, 158 188 int flags) 159 189 { 190 int ret; 191 struct ldb_message_element *el_new; 160 192 /* We have to copy this, just in case *el is a pointer into 161 193 * what ldb_msg_add_empty() is about to realloc() */ 162 194 struct ldb_message_element el_copy = *el; 163 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) { 164 return LDB_ERR_OPERATIONS_ERROR; 165 } 166 167 msg->elements[msg->num_elements-1] = el_copy; 168 msg->elements[msg->num_elements-1].flags = flags; 195 196 ret = _ldb_msg_add_el(msg, &el_new); 197 if (ret != LDB_SUCCESS) { 198 return ret; 199 } 200 201 el_new->flags = flags; 202 el_new->name = el_copy.name; 203 el_new->num_values = el_copy.num_values; 204 el_new->values = el_copy.values; 169 205 170 206 return LDB_SUCCESS; … … 191 227 } 192 228 193 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1); 229 vals = talloc_realloc(msg->elements, el->values, struct ldb_val, 230 el->num_values+1); 194 231 if (!vals) { 195 232 errno = ENOMEM; … … 238 275 239 276 if (val.length == 0) { 240 /* allow empty strings as non-exist ant attributes */277 /* allow empty strings as non-existent attributes */ 241 278 return LDB_SUCCESS; 242 279 } … … 256 293 val.length = strlen(str); 257 294 295 if (val.length == 0) { 296 /* allow empty strings as non-existent attributes */ 297 return LDB_SUCCESS; 298 } 299 258 300 return ldb_msg_add_steal_value(msg, attr_name, &val); 301 } 302 303 /* 304 add a DN element to a message 305 WARNING: this uses the linearized string from the dn, and does not 306 copy the string. 307 */ 308 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name, 309 struct ldb_dn *dn) 310 { 311 char *str = ldb_dn_alloc_linearized(msg, dn); 312 313 if (str == NULL) { 314 /* we don't want to have unknown DNs added */ 315 return LDB_ERR_OPERATIONS_ERROR; 316 } 317 318 return ldb_msg_add_steal_string(msg, attr_name, str); 259 319 } 260 320 … … 283 343 /* 284 344 compare two ldb_message_element structures 285 assumes case sen istive comparison345 assumes case sensitive comparison 286 346 */ 287 347 int ldb_msg_element_compare(struct ldb_message_element *el1, … … 342 402 unsigned int default_value) 343 403 { 404 unsigned int ret; 344 405 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); 345 406 if (!v || !v->data) { 346 407 return default_value; 347 408 } 409 410 /* in LDAP there're only int32_t values */ 411 errno = 0; 412 ret = strtol((const char *)v->data, NULL, 0); 413 if (errno == 0) { 414 return ret; 415 } 416 348 417 return strtoul((const char *)v->data, NULL, 0); 349 418 } … … 364 433 uint64_t default_value) 365 434 { 435 uint64_t ret; 366 436 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name); 367 437 if (!v || !v->data) { 368 438 return default_value; 369 439 } 440 441 /* in LDAP there're only int64_t values */ 442 errno = 0; 443 ret = strtoll((const char *)v->data, NULL, 0); 444 if (errno == 0) { 445 return ret; 446 } 447 370 448 return strtoull((const char *)v->data, NULL, 0); 371 449 } … … 411 489 412 490 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb, 413 void*mem_ctx,491 TALLOC_CTX *mem_ctx, 414 492 const struct ldb_message *msg, 415 493 const char *attr_name) … … 435 513 void ldb_msg_sort_elements(struct ldb_message *msg) 436 514 { 437 qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),438 (comparison_fn_t)ldb_msg_element_compare_name);515 TYPESAFE_QSORT(msg->elements, msg->num_elements, 516 ldb_msg_element_compare_name); 439 517 } 440 518 … … 447 525 { 448 526 struct ldb_message *msg2; 449 int i;527 unsigned int i; 450 528 451 529 msg2 = talloc(mem_ctx, struct ldb_message); … … 477 555 { 478 556 struct ldb_message *msg2; 479 int i, j;557 unsigned int i, j; 480 558 481 559 msg2 = ldb_msg_copy_shallow(mem_ctx, msg); … … 507 585 508 586 509 /* 510 canonicalise a message, merging elements of the same name511 */587 /** 588 * Canonicalize a message, merging elements of the same name 589 */ 512 590 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, 513 591 const struct ldb_message *msg) 514 592 { 515 int i;593 int ret; 516 594 struct ldb_message *msg2; 517 595 518 msg2 = ldb_msg_copy(ldb, msg); 519 if (msg2 == NULL) return NULL; 596 /* 597 * Preserve previous behavior and allocate 598 * *msg2 into *ldb context 599 */ 600 ret = ldb_msg_normalize(ldb, ldb, msg, &msg2); 601 if (ret != LDB_SUCCESS) { 602 return NULL; 603 } 604 605 return msg2; 606 } 607 608 /** 609 * Canonicalize a message, merging elements of the same name 610 */ 611 int ldb_msg_normalize(struct ldb_context *ldb, 612 TALLOC_CTX *mem_ctx, 613 const struct ldb_message *msg, 614 struct ldb_message **_msg_out) 615 { 616 unsigned int i; 617 struct ldb_message *msg2; 618 619 msg2 = ldb_msg_copy(mem_ctx, msg); 620 if (msg2 == NULL) { 621 return LDB_ERR_OPERATIONS_ERROR; 622 } 520 623 521 624 ldb_msg_sort_elements(msg2); 522 625 523 for (i=1; i<msg2->num_elements;i++) {626 for (i=1; i < msg2->num_elements; i++) { 524 627 struct ldb_message_element *el1 = &msg2->elements[i-1]; 525 628 struct ldb_message_element *el2 = &msg2->elements[i]; 629 526 630 if (ldb_msg_element_compare_name(el1, el2) == 0) { 527 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val, 528 el1->num_values + el2->num_values); 529 if (el1->values == NULL) { 530 return NULL; 631 el1->values = talloc_realloc(msg2->elements, 632 el1->values, struct ldb_val, 633 el1->num_values + el2->num_values); 634 if (el1->num_values + el2->num_values > 0 && el1->values == NULL) { 635 talloc_free(msg2); 636 return LDB_ERR_OPERATIONS_ERROR; 531 637 } 532 638 memcpy(el1->values + el1->num_values, … … 535 641 el1->num_values += el2->num_values; 536 642 talloc_free(discard_const_p(char, el2->name)); 537 if ( i+1<msg2->num_elements) {538 memmove(el2, el2+1, sizeof(struct ldb_message_element) * 643 if ((i+1) < msg2->num_elements) { 644 memmove(el2, el2+1, sizeof(struct ldb_message_element) * 539 645 (msg2->num_elements - (i+1))); 540 646 } … … 544 650 } 545 651 546 return msg2; 547 } 548 549 550 /* 551 return a ldb_message representing the differences between msg1 and msg2. If you 552 then use this in a ldb_modify() call it can be used to save edits to a message 553 */ 652 *_msg_out = msg2; 653 return LDB_SUCCESS; 654 } 655 656 657 /** 658 * return a ldb_message representing the differences between msg1 and msg2. 659 * If you then use this in a ldb_modify() call, 660 * it can be used to save edits to a message 661 */ 554 662 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, 555 663 struct ldb_message *msg1, 556 664 struct ldb_message *msg2) 557 665 { 666 int ldb_ret; 667 struct ldb_message *mod; 668 669 ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod); 670 if (ldb_ret != LDB_SUCCESS) { 671 return NULL; 672 } 673 674 return mod; 675 } 676 677 /** 678 * return a ldb_message representing the differences between msg1 and msg2. 679 * If you then use this in a ldb_modify() call it can be used to save edits to a message 680 * 681 * Result message is constructed as follows: 682 * - LDB_FLAG_MOD_ADD - elements found only in msg2 683 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1 684 * Value for msg2 element is used 685 * - LDB_FLAG_MOD_DELETE - elements found only in msg2 686 * 687 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR 688 */ 689 int ldb_msg_difference(struct ldb_context *ldb, 690 TALLOC_CTX *mem_ctx, 691 struct ldb_message *msg1, 692 struct ldb_message *msg2, 693 struct ldb_message **_msg_out) 694 { 695 int ldb_res; 696 unsigned int i; 558 697 struct ldb_message *mod; 559 698 struct ldb_message_element *el; 560 unsigned int i; 561 562 mod = ldb_msg_new(ldb); 699 TALLOC_CTX *temp_ctx; 700 701 temp_ctx = talloc_new(mem_ctx); 702 if (!temp_ctx) { 703 return LDB_ERR_OPERATIONS_ERROR; 704 } 705 706 mod = ldb_msg_new(temp_ctx); 707 if (mod == NULL) { 708 goto failed; 709 } 563 710 564 711 mod->dn = msg1->dn; … … 566 713 mod->elements = NULL; 567 714 568 msg2 = ldb_msg_canonicalize(ldb, msg2); 569 if (msg2 == NULL) { 570 return NULL; 571 } 572 573 /* look in msg2 to find elements that need to be added 574 or modified */ 715 /* 716 * Canonicalize *msg2 so we have no repeated elements 717 * Resulting message is allocated in *mod's mem context, 718 * as we are going to move some elements from *msg2 to 719 * *mod object later 720 */ 721 ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2); 722 if (ldb_res != LDB_SUCCESS) { 723 goto failed; 724 } 725 726 /* look in msg2 to find elements that need to be added or modified */ 575 727 for (i=0;i<msg2->num_elements;i++) { 576 728 el = ldb_msg_find_element(msg1, msg2->elements[i].name); … … 580 732 } 581 733 582 if (ldb_msg_add(mod, 583 &msg2->elements[i], 584 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) { 585 return NULL; 734 ldb_res = ldb_msg_add(mod, 735 &msg2->elements[i], 736 el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD); 737 if (ldb_res != LDB_SUCCESS) { 738 goto failed; 586 739 } 587 740 } … … 590 743 for (i=0;i<msg1->num_elements;i++) { 591 744 el = ldb_msg_find_element(msg2, msg1->elements[i].name); 592 if (!el) { 593 if (ldb_msg_add_empty(mod, 594 msg1->elements[i].name, 595 LDB_FLAG_MOD_DELETE, NULL) != 0) { 596 return NULL; 745 if (el == NULL) { 746 ldb_res = ldb_msg_add_empty(mod, 747 msg1->elements[i].name, 748 LDB_FLAG_MOD_DELETE, NULL); 749 if (ldb_res != LDB_SUCCESS) { 750 goto failed; 597 751 } 598 752 } 599 753 } 600 754 601 return mod; 602 } 755 /* steal resulting message into supplied context */ 756 talloc_steal(mem_ctx, mod); 757 *_msg_out = mod; 758 759 talloc_free(temp_ctx); 760 return LDB_SUCCESS; 761 762 failed: 763 talloc_free(temp_ctx); 764 return LDB_ERR_OPERATIONS_ERROR; 765 } 766 603 767 604 768 int ldb_msg_sanity_check(struct ldb_context *ldb, 605 769 const struct ldb_message *msg) 606 770 { 607 int i, j;771 unsigned int i, j; 608 772 609 773 /* basic check on DN */ … … 643 807 { 644 808 const char **ret; 645 int i; 809 unsigned int i; 810 646 811 for (i=0;attrs && attrs[i];i++) /* noop */ ; 647 812 ret = talloc_array(mem_ctx, const char *, i+1); … … 664 829 { 665 830 const char **ret; 666 int i;831 unsigned int i; 667 832 bool found = false; 833 668 834 for (i=0;attrs && attrs[i];i++) { 669 835 if (ldb_attr_cmp(attrs[i], new_attr) == 0) { … … 692 858 int ldb_attr_in_list(const char * const *attrs, const char *attr) 693 859 { 694 int i;860 unsigned int i; 695 861 for (i=0;attrs && attrs[i];i++) { 696 862 if (ldb_attr_cmp(attrs[i], attr) == 0) { … … 725 891 { 726 892 struct ldb_message_element *el = ldb_msg_find_element(msg, attr); 893 int ret; 894 727 895 if (el == NULL) { 728 896 return LDB_SUCCESS; 729 897 } 730 if (ldb_msg_add(msg, el, 0) != 0) { 731 return LDB_ERR_OPERATIONS_ERROR; 898 ret = ldb_msg_add(msg, el, 0); 899 if (ret != LDB_SUCCESS) { 900 return ret; 732 901 } 733 902 return ldb_msg_rename_attr(msg, attr, replace); … … 739 908 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el) 740 909 { 741 int n = (el - msg->elements);910 ptrdiff_t n = (el - msg->elements); 742 911 if (n >= msg->num_elements) { 743 912 /* should we abort() here? */ … … 756 925 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr) 757 926 { 758 struct ldb_message_element *el = ldb_msg_find_element(msg, attr); 759 if (el) { 927 struct ldb_message_element *el; 928 929 while ((el = ldb_msg_find_element(msg, attr)) != NULL) { 760 930 ldb_msg_remove_element(msg, el); 761 931 } … … 803 973 804 974 memset(&tm, 0, sizeof(tm)); 805 if (sscanf(s, "%04u%02u%02u%02u%02u%02u ",975 if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z", 806 976 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 807 977 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { … … 812 982 813 983 return timegm(&tm); 984 } 985 986 /* 987 convert a LDAP GeneralizedTime string in ldb_val format to a 988 time_t. 989 */ 990 int ldb_val_to_time(const struct ldb_val *v, time_t *t) 991 { 992 struct tm tm; 993 994 if (v == NULL || !v->data || v->length < 17) { 995 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 996 } 997 998 memset(&tm, 0, sizeof(tm)); 999 1000 if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z", 1001 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 1002 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { 1003 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; 1004 } 1005 tm.tm_year -= 1900; 1006 tm.tm_mon -= 1; 1007 1008 *t = timegm(&tm); 1009 1010 return LDB_SUCCESS; 814 1011 } 815 1012 … … 855 1052 856 1053 memset(&tm, 0, sizeof(tm)); 857 if (sscanf(s, "%02u%02u%02u%02u%02u%02u ",1054 if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ", 858 1055 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 859 1056 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { … … 874 1071 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f) 875 1072 { 876 int i;1073 unsigned int i; 877 1074 878 1075 for (i = 0; i < result->count; i++) { … … 885 1082 } 886 1083 887 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value) 1084 /* 1085 checks for a string attribute. Returns "1" on match and otherwise "0". 1086 */ 1087 int ldb_msg_check_string_attribute(const struct ldb_message *msg, 1088 const char *name, const char *value) 888 1089 { 889 1090 struct ldb_message_element *el; … … 891 1092 892 1093 el = ldb_msg_find_element(msg, name); 893 if (el == NULL) 1094 if (el == NULL) { 894 1095 return 0; 1096 } 895 1097 896 1098 val.data = discard_const_p(uint8_t, value); 897 1099 val.length = strlen(value); 898 1100 899 if (ldb_msg_find_val(el, &val)) 1101 if (ldb_msg_find_val(el, &val)) { 900 1102 return 1; 1103 } 901 1104 902 1105 return 0; 903 1106 } 1107 -
trunk/server/source4/lib/ldb/common/ldb_parse.c
r414 r745 43 43 #include "ldb_private.h" 44 44 #include "system/locale.h" 45 46 static int ldb_parse_hex2char(const char *x) 47 { 48 if (isxdigit(x[0]) && isxdigit(x[1])) { 49 const char h1 = x[0], h2 = x[1]; 50 int c = 0; 51 52 if (h1 >= 'a') c = h1 - (int)'a' + 10; 53 else if (h1 >= 'A') c = h1 - (int)'A' + 10; 54 else if (h1 >= '0') c = h1 - (int)'0'; 55 c = c << 4; 56 if (h2 >= 'a') c += h2 - (int)'a' + 10; 57 else if (h2 >= 'A') c += h2 - (int)'A' + 10; 58 else if (h2 >= '0') c += h2 - (int)'0'; 59 60 return c; 61 } 62 63 return -1; 64 } 45 65 46 66 /* … … 60 80 Used in LDAP filters. 61 81 */ 62 struct ldb_val ldb_binary_decode( void*mem_ctx, const char *str)63 { 64 int i, j;82 struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str) 83 { 84 size_t i, j; 65 85 struct ldb_val ret; 66 int slen = str?strlen(str):0;86 size_t slen = str?strlen(str):0; 67 87 68 88 ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1); … … 72 92 for (i=j=0;i<slen;i++) { 73 93 if (str[i] == '\\') { 74 unsigned c; 75 if (sscanf(&str[i+1], "%02X", &c) != 1) { 94 int c; 95 96 c = ldb_parse_hex2char(&str[i+1]); 97 if (c == -1) { 76 98 talloc_free(ret.data); 77 99 memset(&ret, 0, sizeof(ret)); … … 95 117 non-printable or '\' characters 96 118 */ 97 char *ldb_binary_encode( void*mem_ctx, struct ldb_val val)98 { 99 int i;119 char *ldb_binary_encode(TALLOC_CTX *mem_ctx, struct ldb_val val) 120 { 121 size_t i; 100 122 char *ret; 101 int len = val.length;123 size_t len = val.length; 102 124 unsigned char *buf = val.data; 103 125 … … 130 152 in escaping user data in ldap filters. 131 153 */ 132 char *ldb_binary_encode_string( void*mem_ctx, const char *string)154 char *ldb_binary_encode_string(TALLOC_CTX *mem_ctx, const char *string) 133 155 { 134 156 struct ldb_val val; 157 if (string == NULL) { 158 return NULL; 159 } 135 160 val.data = discard_const_p(uint8_t, string); 136 161 val.length = strlen(string); … … 160 185 chunks separated by wildcards that makes the value portion of the filter 161 186 */ 162 static struct ldb_val **ldb_wildcard_decode( void*mem_ctx, const char *string)187 static struct ldb_val **ldb_wildcard_decode(TALLOC_CTX *mem_ctx, const char *string) 163 188 { 164 189 struct ldb_val **ret = NULL; 165 int val = 0;190 unsigned int val = 0; 166 191 char *wc, *str; 167 192 … … 200 225 } 201 226 202 static struct ldb_parse_tree *ldb_parse_filter( void*mem_ctx, const char **s);227 static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s); 203 228 204 229 … … 254 279 } 255 280 256 static enum ldb_parse_op ldb_parse_filtertype( void*mem_ctx, char **type, char **value, const char **s)281 static enum ldb_parse_op ldb_parse_filtertype(TALLOC_CTX *mem_ctx, char **type, char **value, const char **s) 257 282 { 258 283 enum ldb_parse_op filter = 0; … … 352 377 <simple> ::= <attributetype> <filtertype> <attributevalue> 353 378 */ 354 static struct ldb_parse_tree *ldb_parse_simple( void*mem_ctx, const char **s)379 static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *mem_ctx, const char **s) 355 380 { 356 381 char *attr, *value; … … 467 492 <filterlist> ::= <filter> | <filter> <filterlist> 468 493 */ 469 static struct ldb_parse_tree *ldb_parse_filterlist( void*mem_ctx, const char **s)494 static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const char **s) 470 495 { 471 496 struct ldb_parse_tree *ret, *next; … … 535 560 <not> ::= '!' <filter> 536 561 */ 537 static struct ldb_parse_tree *ldb_parse_not( void*mem_ctx, const char **s)562 static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s) 538 563 { 539 564 struct ldb_parse_tree *ret; … … 567 592 <filtercomp> ::= <and> | <or> | <not> | <simple> 568 593 */ 569 static struct ldb_parse_tree *ldb_parse_filtercomp( void*mem_ctx, const char **s)594 static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const char **s) 570 595 { 571 596 struct ldb_parse_tree *ret; … … 604 629 <filter> ::= '(' <filtercomp> ')' 605 630 */ 606 static struct ldb_parse_tree *ldb_parse_filter( void*mem_ctx, const char **s)631 static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s) 607 632 { 608 633 struct ldb_parse_tree *ret; … … 636 661 expression ::= <simple> | <filter> 637 662 */ 638 struct ldb_parse_tree *ldb_parse_tree( void*mem_ctx, const char *s)663 struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s) 639 664 { 640 665 if (s == NULL || *s == 0) { … … 655 680 construct a ldap parse filter given a parse tree 656 681 */ 657 char *ldb_filter_from_tree( void *mem_ctx,struct ldb_parse_tree *tree)682 char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, const struct ldb_parse_tree *tree) 658 683 { 659 684 char *s, *s2, *ret; 660 int i;685 unsigned int i; 661 686 662 687 if (tree == NULL) { … … 774 799 775 800 /* 776 replace any occur ances of an attribute name in the parse tree with a801 replace any occurrences of an attribute name in the parse tree with a 777 802 new name 778 803 */ … … 781 806 const char *replace) 782 807 { 783 int i;808 unsigned int i; 784 809 switch (tree->operation) { 785 810 case LDB_OP_AND: … … 827 852 const struct ldb_parse_tree *ot) 828 853 { 829 int i;854 unsigned int i; 830 855 struct ldb_parse_tree *nt; 831 856 -
trunk/server/source4/lib/ldb/common/ldb_utf8.c
r414 r745 54 54 NOTE: does not handle UTF8 55 55 */ 56 char *ldb_casefold_default(void *context, void*mem_ctx, const char *s, size_t n)56 char *ldb_casefold_default(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n) 57 57 { 58 int i;58 size_t i; 59 59 char *ret = talloc_strndup(mem_ctx, s, n); 60 60 if (!s) { … … 73 73 } 74 74 75 char *ldb_casefold(struct ldb_context *ldb, void*mem_ctx, const char *s, size_t n)75 char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n) 76 76 { 77 77 return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s, n); … … 85 85 int ldb_valid_attr_name(const char *s) 86 86 { 87 int i;87 size_t i; 88 88 89 89 if (!s || !s[0]) … … 110 110 } 111 111 112 char *ldb_attr_casefold( void*mem_ctx, const char *s)112 char *ldb_attr_casefold(TALLOC_CTX *mem_ctx, const char *s) 113 113 { 114 int i;114 size_t i; 115 115 char *ret = talloc_strdup(mem_ctx, s); 116 116 if (!ret) { -
trunk/server/source4/lib/ldb/include/dlinklist.h
r414 r745 2 2 Unix SMB/CIFS implementation. 3 3 some simple double linked list macros 4 Copyright (C) Andrew Tridgell 1998 4 5 Copyright (C) Andrew Tridgell 1998-2010 6 7 ** NOTE! The following LGPL license applies to the ldb 8 ** library. This does NOT imply that all of Samba is released 9 ** under the LGPL 5 10 6 This program is free software; you can redistribute it and/or modify7 it under the terms of the GNU General Public License as published by8 the Free Software Foundation; either version 3 of the License, or9 (at your option) any later version.10 11 This programis distributed in the hope that it will be useful,11 This library is free software; you can redistribute it and/or 12 modify it under the terms of the GNU Lesser General Public 13 License as published by the Free Software Foundation; either 14 version 3 of the License, or (at your option) any later version. 15 16 This library is distributed in the hope that it will be useful, 12 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNUGeneral Public License for more details.15 16 You should have received a copy of the GNU General Public License17 along with this program. If not, see <http://www.gnu.org/licenses/>.18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 Lesser General Public License for more details. 20 21 You should have received a copy of the GNU Lesser General Public 22 License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 23 */ 19 24 … … 24 29 #define _DLINKLIST_H 25 30 31 /* 32 February 2010 - changed list format to have a prev pointer from the 33 list head. This makes DLIST_ADD_END() O(1) even though we only have 34 one list pointer. 26 35 27 /* hook into the front of the list */ 36 The scheme is as follows: 37 38 1) with no entries in the list: 39 list_head == NULL 40 41 2) with 1 entry in the list: 42 list_head->next == NULL 43 list_head->prev == list_head 44 45 3) with 2 entries in the list: 46 list_head->next == element2 47 list_head->prev == element2 48 element2->prev == list_head 49 element2->next == NULL 50 51 4) with N entries in the list: 52 list_head->next == element2 53 list_head->prev == elementN 54 elementN->prev == element{N-1} 55 elementN->next == NULL 56 57 This allows us to find the tail of the list by using 58 list_head->prev, which means we can add to the end of the list in 59 O(1) time 60 61 62 Note that the 'type' arguments below are no longer needed, but 63 are kept for now to prevent an incompatible argument change 64 */ 65 66 67 /* 68 add an element at the front of a list 69 */ 28 70 #define DLIST_ADD(list, p) \ 29 71 do { \ 30 72 if (!(list)) { \ 31 ( list) = (p);\32 (p)->next = (p)->prev =NULL; \73 (p)->prev = (list) = (p); \ 74 (p)->next = NULL; \ 33 75 } else { \ 76 (p)->prev = (list)->prev; \ 34 77 (list)->prev = (p); \ 35 78 (p)->next = (list); \ 36 (p)->prev = NULL; \37 79 (list) = (p); \ 38 } \80 } \ 39 81 } while (0) 40 82 41 /* remove an element from a list - element doesn't have to be in list. */ 83 /* 84 remove an element from a list 85 Note that the element doesn't have to be in the list. If it 86 isn't then this is a no-op 87 */ 42 88 #define DLIST_REMOVE(list, p) \ 43 89 do { \ 44 90 if ((p) == (list)) { \ 91 if ((p)->next) (p)->next->prev = (p)->prev; \ 45 92 (list) = (p)->next; \ 46 if (list) (list)->prev = NULL; \ 93 } else if ((list) && (p) == (list)->prev) { \ 94 (p)->prev->next = NULL; \ 95 (list)->prev = (p)->prev; \ 47 96 } else { \ 48 97 if ((p)->prev) (p)->prev->next = (p)->next; \ 49 98 if ((p)->next) (p)->next->prev = (p)->prev; \ 50 99 } \ 51 if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL;\100 if ((p) != (list)) (p)->next = (p)->prev = NULL; \ 52 101 } while (0) 53 102 54 /* promote an element to the top of the list */ 55 #define DLIST_PROMOTE(list, p) \ 103 /* 104 find the head of the list given any element in it. 105 Note that this costs O(N), so you should avoid this macro 106 if at all possible! 107 */ 108 #define DLIST_HEAD(p, result_head) \ 56 109 do { \ 57 DLIST_REMOVE(list,p); \58 DLIST_ADD(list, p); \59 } while 110 (result_head) = (p); \ 111 while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ 112 } while(0) 60 113 61 /* hook into the end of the list - needs the entry type */ 62 #define DLIST_ADD_END(list, p, type) \ 63 do { \ 64 if (!(list)) { \ 65 (list) = (p); \ 66 (p)->next = (p)->prev = NULL; \ 67 } else { \ 68 type tmp; \ 69 for (tmp = (list); tmp->next; tmp = tmp->next) ; \ 70 tmp->next = (p); \ 71 (p)->next = NULL; \ 72 (p)->prev = tmp; \ 73 } \ 74 } while (0) 114 /* return the last element in the list */ 115 #define DLIST_TAIL(list) ((list)?(list)->prev:NULL) 116 117 /* return the previous element in the list. */ 118 #define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) 75 119 76 120 /* insert 'p' after the given element 'el' in a list. If el is NULL then … … 81 125 DLIST_ADD(list, p); \ 82 126 } else { \ 83 p->prev = el; \ 84 p->next = el->next; \ 85 el->next = p; \ 86 if (p->next) p->next->prev = p; \ 127 (p)->prev = (el); \ 128 (p)->next = (el)->next; \ 129 (el)->next = (p); \ 130 if ((p)->next) (p)->next->prev = (p); \ 131 if ((list)->prev == (el)) (list)->prev = (p); \ 87 132 }\ 88 133 } while (0) 89 134 90 /* demote an element to the end of the list, needs the entry type */ 91 #define DLIST_DEMOTE(list, p, type) \ 135 136 /* 137 add to the end of a list. 138 Note that 'type' is ignored 139 */ 140 #define DLIST_ADD_END(list, p, type) \ 92 141 do { \ 93 DLIST_REMOVE(list, p); \ 94 DLIST_ADD_END(list, p, type); \ 142 if (!(list)) { \ 143 DLIST_ADD(list, p); \ 144 } else { \ 145 DLIST_ADD_AFTER(list, p, (list)->prev); \ 146 } \ 95 147 } while (0) 96 148 97 /* concatenate two lists - putting all elements of the 2nd list at the 98 end of the first list */ 99 #define DLIST_CONCATENATE(list1, list2, type) \ 149 /* promote an element to the from of a list */ 150 #define DLIST_PROMOTE(list, p) \ 100 151 do { \ 101 if (!(list1)) { \ 102 (list1) = (list2); \ 103 } else { \ 104 type tmp; \ 105 for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ 106 tmp->next = (list2); \ 107 if (list2) { \ 108 (list2)->prev = tmp; \ 109 } \ 152 DLIST_REMOVE(list, p); \ 153 DLIST_ADD(list, p); \ 154 } while (0) 155 156 /* 157 demote an element to the end of a list. 158 Note that 'type' is ignored 159 */ 160 #define DLIST_DEMOTE(list, p, type) \ 161 do { \ 162 DLIST_REMOVE(list, p); \ 163 DLIST_ADD_END(list, p, NULL); \ 164 } while (0) 165 166 /* 167 concatenate two lists - putting all elements of the 2nd list at the 168 end of the first list. 169 Note that 'type' is ignored 170 */ 171 #define DLIST_CONCATENATE(list1, list2, type) \ 172 do { \ 173 if (!(list1)) { \ 174 (list1) = (list2); \ 175 } else { \ 176 (list1)->prev->next = (list2); \ 177 if (list2) { \ 178 void *_tmplist = (void *)(list1)->prev; \ 179 (list1)->prev = (list2)->prev; \ 180 (list2)->prev = _tmplist; \ 110 181 } \ 182 } \ 111 183 } while (0) 112 184 -
trunk/server/source4/lib/ldb/include/ldb.h
r414 r745 48 48 49 49 #include <stdbool.h> 50 #include "talloc.h" 51 #include "tevent.h" 52 #include "ldb_errors.h" 50 #include <talloc.h> 51 #include <tevent.h> 52 #include <ldb_version.h> 53 #include <ldb_errors.h> 53 54 54 55 /* … … 86 87 #ifndef PRINTF_ATTRIBUTE 87 88 #define PRINTF_ATTRIBUTE(a,b) 89 #endif 90 91 #ifndef _DEPRECATED_ 92 #if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) 93 #define _DEPRECATED_ __attribute__ ((deprecated)) 94 #else 95 #define _DEPRECATED_ 96 #endif 88 97 #endif 89 98 /*! \endcond */ … … 103 112 104 113 /** 114 use this to extract the mod type from the operation 115 */ 116 #define LDB_FLAG_MOD_TYPE(flags) ((flags) & LDB_FLAG_MOD_MASK) 117 118 /** 105 119 Flag value used in ldap_modify() to indicate that attributes are 106 120 being added. … … 125 139 */ 126 140 #define LDB_FLAG_MOD_DELETE 3 141 142 /** 143 flag bits on an element usable only by the internal implementation 144 */ 145 #define LDB_FLAG_INTERNAL_MASK 0xFFFFFFF0 127 146 128 147 /** … … 297 316 298 317 struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s); 299 char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, struct ldb_parse_tree *tree);318 char *ldb_filter_from_tree(TALLOC_CTX *mem_ctx, const struct ldb_parse_tree *tree); 300 319 301 320 /** … … 336 355 typedef int (*ldb_attr_handler_t)(struct ldb_context *, TALLOC_CTX *mem_ctx, const struct ldb_val *, struct ldb_val *); 337 356 typedef int (*ldb_attr_comparison_t)(struct ldb_context *, TALLOC_CTX *mem_ctx, const struct ldb_val *, const struct ldb_val *); 357 struct ldb_schema_attribute; 358 typedef int (*ldb_attr_operator_t)(struct ldb_context *, enum ldb_parse_op operation, 359 const struct ldb_schema_attribute *a, 360 const struct ldb_val *, const struct ldb_val *, bool *matched); 338 361 339 362 /* … … 353 376 ldb_attr_handler_t canonicalise_fn; 354 377 ldb_attr_comparison_t comparison_fn; 378 ldb_attr_operator_t operator_fn; 355 379 }; 356 380 … … 457 481 typedef int (*ldb_qsort_cmp_fn_t) (void *v1, void *v2, void *opaque); 458 482 483 /* Individual controls */ 484 485 /** 486 OID for getting and manipulating attributes from the ldb 487 without interception in the operational module. 488 It can be used to access attribute that used to be stored in the sam 489 and that are now calculated. 490 */ 491 #define LDB_CONTROL_BYPASS_OPERATIONAL_OID "1.3.6.1.4.1.7165.4.3.13" 492 #define LDB_CONTROL_BYPASS_OPERATIONAL_NAME "bypassoperational" 493 494 /** 495 OID for recalculate SD control. This control force the 496 dsdb code to recalculate the SD of the object as if the 497 object was just created. 498 499 */ 500 #define LDB_CONTROL_RECALCULATE_SD_OID "1.3.6.1.4.1.7165.4.3.5" 501 #define LDB_CONTROL_RECALCULATE_SD_NAME "recalculate_sd" 502 503 /** 504 REVEAL_INTERNALS is used to reveal internal attributes and DN 505 components which are not normally shown to the user 506 */ 507 #define LDB_CONTROL_REVEAL_INTERNALS "1.3.6.1.4.1.7165.4.3.6" 508 #define LDB_CONTROL_REVEAL_INTERNALS_NAME "reveal_internals" 509 510 /** 511 LDB_CONTROL_AS_SYSTEM is used to skip access checks on operations 512 that are performed by the system, but with a user's credentials, e.g. 513 updating prefix map 514 */ 515 #define LDB_CONTROL_AS_SYSTEM_OID "1.3.6.1.4.1.7165.4.3.7" 516 517 /** 518 LDB_CONTROL_PROVISION_OID is used to skip some constraint checks. It's is 519 mainly thought to be used for the provisioning. 520 */ 521 #define LDB_CONTROL_PROVISION_OID "1.3.6.1.4.1.7165.4.3.16" 522 #define LDB_CONTROL_PROVISION_NAME "provision" 523 524 /* AD controls */ 525 459 526 /** 460 527 OID for the paged results control. This control is included in the … … 466 533 */ 467 534 #define LDB_CONTROL_PAGED_RESULTS_OID "1.2.840.113556.1.4.319" 535 #define LDB_CONTROL_PAGED_RESULTS_NAME "paged_result" 468 536 469 537 /** … … 473 541 */ 474 542 #define LDB_CONTROL_SD_FLAGS_OID "1.2.840.113556.1.4.801" 543 #define LDB_CONTROL_SD_FLAGS_NAME "sd_flags" 475 544 476 545 /** … … 480 549 */ 481 550 #define LDB_CONTROL_DOMAIN_SCOPE_OID "1.2.840.113556.1.4.1339" 551 #define LDB_CONTROL_DOMAIN_SCOPE_NAME "domain_scope" 482 552 483 553 /** … … 487 557 */ 488 558 #define LDB_CONTROL_SEARCH_OPTIONS_OID "1.2.840.113556.1.4.1340" 559 #define LDB_CONTROL_SEARCH_OPTIONS_NAME "search_options" 489 560 490 561 /** … … 494 565 */ 495 566 #define LDB_CONTROL_NOTIFICATION_OID "1.2.840.113556.1.4.528" 567 #define LDB_CONTROL_NOTIFICATION_NAME "notification" 568 569 /** 570 OID for performing subtree deletes 571 572 \sa <a href="http://msdn.microsoft.com/en-us/library/aa366991(v=VS.85).aspx">Microsoft documentation of this OID</a> 573 */ 574 #define LDB_CONTROL_TREE_DELETE_OID "1.2.840.113556.1.4.805" 575 #define LDB_CONTROL_TREE_DELETE_NAME "tree_delete" 496 576 497 577 /** … … 501 581 */ 502 582 #define LDB_CONTROL_SHOW_DELETED_OID "1.2.840.113556.1.4.417" 583 #define LDB_CONTROL_SHOW_DELETED_NAME "show_deleted" 503 584 504 585 /** … … 508 589 */ 509 590 #define LDB_CONTROL_SHOW_RECYCLED_OID "1.2.840.113556.1.4.2064" 591 #define LDB_CONTROL_SHOW_RECYCLED_NAME "show_recycled" 510 592 511 593 /** … … 515 597 */ 516 598 #define LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID "1.2.840.113556.1.4.2065" 599 #define LDB_CONTROL_SHOW_DEACTIVATED_LINK_NAME "show_deactivated_link" 517 600 518 601 /** … … 522 605 */ 523 606 #define LDB_CONTROL_EXTENDED_DN_OID "1.2.840.113556.1.4.529" 607 #define LDB_CONTROL_EXTENDED_DN_NAME "extended_dn" 524 608 525 609 /** … … 536 620 */ 537 621 #define LDB_CONTROL_SERVER_SORT_OID "1.2.840.113556.1.4.473" 622 #define LDB_CONTROL_SERVER_SORT_NAME "server_sort" 538 623 539 624 /** … … 547 632 */ 548 633 #define LDB_CONTROL_SORT_RESP_OID "1.2.840.113556.1.4.474" 634 #define LDB_CONTROL_SORT_RESP_NAME "server_sort_resp" 549 635 550 636 /** … … 555 641 */ 556 642 #define LDB_CONTROL_ASQ_OID "1.2.840.113556.1.4.1504" 643 #define LDB_CONTROL_ASQ_NAME "asq" 557 644 558 645 /** … … 563 650 */ 564 651 #define LDB_CONTROL_DIRSYNC_OID "1.2.840.113556.1.4.841" 652 #define LDB_CONTROL_DIRSYNC_NAME "dirsync" 565 653 566 654 … … 572 660 */ 573 661 #define LDB_CONTROL_VLV_REQ_OID "2.16.840.1.113730.3.4.9" 662 #define LDB_CONTROL_VLV_REQ_NAME "vlv" 574 663 575 664 /** … … 580 669 */ 581 670 #define LDB_CONTROL_VLV_RESP_OID "2.16.840.1.113730.3.4.10" 671 #define LDB_CONTROL_VLV_RESP_NAME "vlv_resp" 582 672 583 673 /** … … 588 678 */ 589 679 #define LDB_CONTROL_PERMISSIVE_MODIFY_OID "1.2.840.113556.1.4.1413" 680 #define LDB_CONTROL_PERMISSIVE_MODIFY_NAME "permissive_modify" 681 682 /** 683 OID to allow the server to be more 'fast and loose' with the data being added. 684 685 \sa <a href="http://msdn.microsoft.com/en-us/library/aa366982(v=VS.85).aspx">Microsoft documentation of this OID</a> 686 */ 687 #define LDB_CONTROL_SERVER_LAZY_COMMIT "1.2.840.113556.1.4.619" 688 689 /** 690 Control for RODC join -see [MS-ADTS] section 3.1.1.3.4.1.23 691 692 \sa <a href="">Microsoft documentation of this OID</a> 693 */ 694 #define LDB_CONTROL_RODC_DCPROMO_OID "1.2.840.113556.1.4.1341" 695 #define LDB_CONTROL_RODC_DCPROMO_NAME "rodc_join" 696 697 /* Other standardised controls */ 698 699 /** 700 OID for the allowing client to request temporary relaxed 701 enforcement of constraints of the x.500 model. 702 703 Mainly used for the OpenLDAP backend. 704 705 \sa <a href="http://opends.dev.java.net/public/standards/draft-zeilenga-ldap-managedit.txt">draft managedit</a>. 706 */ 707 #define LDB_CONTROL_RELAX_OID "1.3.6.1.4.1.4203.666.5.12" 708 #define LDB_CONTROL_RELAX_NAME "relax" 709 710 /* Extended operations */ 711 712 /** 713 OID for LDAP Extended Operation SEQUENCE_NUMBER 714 715 This extended operation is used to retrieve the extended sequence number. 716 */ 717 #define LDB_EXTENDED_SEQUENCE_NUMBER "1.3.6.1.4.1.7165.4.4.3" 718 719 /** 720 OID for LDAP Extended Operation PASSWORD_CHANGE. 721 722 This Extended operation is used to allow user password changes by the user 723 itself. 724 */ 725 #define LDB_EXTENDED_PASSWORD_CHANGE_OID "1.3.6.1.4.1.4203.1.11.1" 726 727 728 /** 729 OID for LDAP Extended Operation FAST_BIND 730 731 This Extended operations is used to perform a fast bind. 732 */ 733 #define LDB_EXTENDED_FAST_BIND_OID "1.2.840.113556.1.4.1781" 590 734 591 735 /** 592 736 OID for LDAP Extended Operation START_TLS. 593 737 594 This Extended operation is used to start a new TLS 595 channel on top of a cleartext channel.738 This Extended operation is used to start a new TLS channel on top of a clear 739 text channel. 596 740 */ 597 741 #define LDB_EXTENDED_START_TLS_OID "1.3.6.1.4.1.1466.20037" 598 742 599 743 /** 744 OID for LDAP Extended Operation DYNAMIC_REFRESH. 745 746 This Extended operation is used to create and maintain objects which exist 747 only a specific time, e.g. when a certain client or a certain person is 748 logged in. Data refreshes have to be periodically sent in a specific 749 interval. Otherwise the entry is going to be removed. 600 750 */ 601 751 #define LDB_EXTENDED_DYNAMIC_OID "1.3.6.1.4.1.1466.101.119.1" 602 603 /**604 */605 #define LDB_EXTENDED_FAST_BIND_OID "1.2.840.113556.1.4.1781"606 752 607 753 struct ldb_sd_flags_control { … … 736 882 }; 737 883 738 #define LDB_EXTENDED_SEQUENCE_NUMBER "1.3.6.1.4.1.7165.4.4.3"739 740 884 enum ldb_sequence_type { 741 885 LDB_SEQ_HIGHEST_SEQ, … … 964 1108 int ldb_op_default_callback(struct ldb_request *req, struct ldb_reply *ares); 965 1109 1110 int ldb_modify_default_callback(struct ldb_request *req, struct ldb_reply *ares); 966 1111 967 1112 /** … … 1118 1263 1119 1264 /** 1265 replace a ldb_control in a ldb_request 1266 1267 \param req the request struct where to add the control 1268 \param oid the object identifier of the control as string 1269 \param critical whether the control should be critical or not 1270 \param data a talloc pointer to the control specific data 1271 1272 \return result code (LDB_SUCCESS on success, or a failure code) 1273 */ 1274 int ldb_request_replace_control(struct ldb_request *req, const char *oid, bool critical, void *data); 1275 1276 /** 1120 1277 check if a control with the specified "oid" exist and return it 1121 1278 \param req the request struct where to add the control … … 1309 1466 int ldb_transaction_cancel(struct ldb_context *ldb); 1310 1467 1468 /* 1469 cancel a transaction with no error if no transaction is pending 1470 used when we fork() to clear any parent transactions 1471 */ 1472 int ldb_transaction_cancel_noerr(struct ldb_context *ldb); 1473 1311 1474 1312 1475 /** … … 1551 1714 \param mode Style of extended DN to return (0 is HEX representation of binary form, 1 is a string form) 1552 1715 */ 1553 char *ldb_dn_get_extended_linearized( void*mem_ctx, struct ldb_dn *dn, int mode);1716 char *ldb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, int mode); 1554 1717 const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name); 1555 1718 int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val); 1556 1719 void ldb_dn_extended_filter(struct ldb_dn *dn, const char * const *accept_list); 1557 1720 void ldb_dn_remove_extended_components(struct ldb_dn *dn); 1558 1721 bool ldb_dn_has_extended(struct ldb_dn *dn); … … 1591 1754 */ 1592 1755 1593 struct ldb_dn *ldb_dn_from_ldb_val( void*mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn);1756 struct ldb_dn *ldb_dn_from_ldb_val(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn); 1594 1757 1595 1758 /** … … 1620 1783 char *ldb_dn_canonical_ex_string(TALLOC_CTX *mem_ctx, struct ldb_dn *dn); 1621 1784 int ldb_dn_get_comp_num(struct ldb_dn *dn); 1785 int ldb_dn_get_extended_comp_num(struct ldb_dn *dn); 1622 1786 const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num); 1623 1787 const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num); … … 1630 1794 bool ldb_dn_check_special(struct ldb_dn *dn, const char *check); 1631 1795 bool ldb_dn_is_null(struct ldb_dn *dn); 1796 int ldb_dn_update_components(struct ldb_dn *dn, const struct ldb_dn *ref_dn); 1632 1797 1633 1798 … … 1713 1878 int ldb_msg_add_string(struct ldb_message *msg, 1714 1879 const char *attr_name, const char *str); 1880 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name, 1881 struct ldb_dn *dn); 1715 1882 int ldb_msg_add_fmt(struct ldb_message *msg, 1716 1883 const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); … … 1766 1933 const struct ldb_message *msg); 1767 1934 1935 /* 1936 * ldb_msg_canonicalize() is now depreciated 1937 * Please use ldb_msg_normalize() instead 1938 * 1939 * NOTE: Returned ldb_message object is allocated 1940 * into *ldb's context. Callers are recommended 1941 * to steal the returned object into a TALLOC_CTX 1942 * with short lifetime. 1943 */ 1768 1944 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, 1769 const struct ldb_message *msg); 1770 1771 1945 const struct ldb_message *msg) _DEPRECATED_; 1946 1947 int ldb_msg_normalize(struct ldb_context *ldb, 1948 TALLOC_CTX *mem_ctx, 1949 const struct ldb_message *msg, 1950 struct ldb_message **_msg_out); 1951 1952 1953 /* 1954 * ldb_msg_diff() is now depreciated 1955 * Please use ldb_msg_difference() instead 1956 * 1957 * NOTE: Returned ldb_message object is allocated 1958 * into *ldb's context. Callers are recommended 1959 * to steal the returned object into a TALLOC_CTX 1960 * with short lifetime. 1961 */ 1772 1962 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, 1773 1963 struct ldb_message *msg1, 1774 struct ldb_message *msg2); 1775 1964 struct ldb_message *msg2) _DEPRECATED_; 1965 1966 /** 1967 * return a ldb_message representing the differences between msg1 and msg2. 1968 * If you then use this in a ldb_modify() call, 1969 * it can be used to save edits to a message 1970 * 1971 * Result message is constructed as follows: 1972 * - LDB_FLAG_MOD_ADD - elements found only in msg2 1973 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have 1974 * different value in msg1 1975 * Value for msg2 element is used 1976 * - LDB_FLAG_MOD_DELETE - elements found only in msg2 1977 * 1978 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR 1979 */ 1980 int ldb_msg_difference(struct ldb_context *ldb, 1981 TALLOC_CTX *mem_ctx, 1982 struct ldb_message *msg1, 1983 struct ldb_message *msg2, 1984 struct ldb_message **_msg_out); 1985 1986 /** 1987 Tries to find a certain string attribute in a message 1988 1989 \param msg the message to check 1990 \param name attribute name 1991 \param value attribute value 1992 1993 \return 1 on match and 0 otherwise. 1994 */ 1776 1995 int ldb_msg_check_string_attribute(const struct ldb_message *msg, 1777 1996 const char *name, … … 1880 2099 1881 2100 /** 2101 convert a LDAP GeneralizedTime string in ldb_val format to a 2102 time_t. 2103 */ 2104 int ldb_val_to_time(const struct ldb_val *v, time_t *t); 2105 2106 /** 1882 2107 Convert a time structure to a string 1883 2108 … … 1908 2133 void ldb_qsort (void *const pbase, size_t total_elems, size_t size, void *opaque, ldb_qsort_cmp_fn_t cmp); 1909 2134 1910 2135 #ifndef discard_const 2136 #define discard_const(ptr) ((void *)((uintptr_t)(ptr))) 2137 #endif 2138 2139 /* 2140 a wrapper around ldb_qsort() that ensures the comparison function is 2141 type safe. This will produce a compilation warning if the types 2142 don't match 2143 */ 2144 #define LDB_TYPESAFE_QSORT(base, numel, opaque, comparison) \ 2145 do { \ 2146 if (numel > 1) { \ 2147 ldb_qsort(base, numel, sizeof((base)[0]), discard_const(opaque), (ldb_qsort_cmp_fn_t)comparison); \ 2148 comparison(&((base)[0]), &((base)[1]), opaque); \ 2149 } \ 2150 } while (0) 2151 2152 /* allow ldb to also call TYPESAFE_QSORT() */ 2153 #ifndef TYPESAFE_QSORT 2154 #define TYPESAFE_QSORT(base, numel, comparison) \ 2155 do { \ 2156 if (numel > 1) { \ 2157 qsort(base, numel, sizeof((base)[0]), (int (*)(const void *, const void *))comparison); \ 2158 comparison(&((base)[0]), &((base)[1])); \ 2159 } \ 2160 } while (0) 2161 #endif 2162 2163 2164 2165 /** 2166 Convert a control into its string representation. 2167 2168 \param mem_ctx TALLOC context to return result on, and to allocate error_string on 2169 \param control A struct ldb_control to convert 2170 2171 \return string representation of the control 2172 */ 2173 char* ldb_control_to_string(TALLOC_CTX *mem_ctx, const struct ldb_control *control); 2174 /** 2175 Convert a string representing a control into a ldb_control structure 2176 2177 \param ldb LDB context 2178 \param mem_ctx TALLOC context to return result on, and to allocate error_string on 2179 \param control_strings A string-formatted control 2180 2181 \return a ldb_control element 2182 */ 2183 struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *control_strings); 1911 2184 /** 1912 2185 Convert an array of string represention of a control into an array of ldb_control structures … … 1929 2202 1930 2203 2204 struct ldb_dn *ldb_dn_binary_from_ldb_val(TALLOC_CTX *mem_ctx, 2205 struct ldb_context *ldb, 2206 const struct ldb_val *strdn); 2207 2208 int ldb_dn_get_binary(struct ldb_dn *dn, struct ldb_val *val); 2209 int ldb_dn_set_binary(struct ldb_dn *dn, struct ldb_val *val); 2210 2211 /* debugging functions for ldb requests */ 2212 void ldb_req_set_location(struct ldb_request *req, const char *location); 2213 const char *ldb_req_location(struct ldb_request *req); 2214 2215 /* set the location marker on a request handle - used for debugging */ 2216 #define LDB_REQ_SET_LOCATION(req) ldb_req_set_location(req, __location__) 2217 2218 /* 2219 minimise a DN. The caller must pass in a validated DN. 2220 2221 If the DN has an extended component then only the first extended 2222 component is kept, the DN string is stripped. 2223 2224 The existing dn is modified 2225 */ 2226 bool ldb_dn_minimise(struct ldb_dn *dn); 2227 1931 2228 #endif -
trunk/server/source4/lib/ldb/include/ldb_errors.h
r414 r745 198 198 199 199 /** 200 The function referred to an alias which points to a non-exist ant200 The function referred to an alias which points to a non-existent 201 201 object in the database. 202 202 */ -
trunk/server/source4/lib/ldb/include/ldb_handlers.h
r414 r745 36 36 int ldb_comparison_binary( struct ldb_context *ldb, void *mem_ctx, 37 37 const struct ldb_val *v1, const struct ldb_val *v2); 38 int db_handler_fold( struct ldb_context *ldb, void *mem_ctx,39 const struct ldb_val *in, struct ldb_val *out);40 38 int ldb_comparison_fold( struct ldb_context *ldb, void *mem_ctx, 41 39 const struct ldb_val *v1, const struct ldb_val *v2); -
trunk/server/source4/lib/ldb/include/ldb_module.h
r414 r745 34 34 #define _LDB_MODULE_H_ 35 35 36 #include "ldb.h"36 #include <ldb.h> 37 37 38 38 struct ldb_context; 39 39 struct ldb_module; 40 41 /** 42 internal flag bits on message elements. Must be within LDB_FLAG_INTERNAL_MASK 43 */ 44 #define LDB_FLAG_INTERNAL_DISABLE_VALIDATION 0x10 45 46 /* disable any single value checking on this attribute */ 47 #define LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK 0x20 48 49 /* attribute has failed access check and must not be exposed */ 50 #define LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE 0x40 51 52 /* force single value checking on this attribute */ 53 #define LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK 0x80 54 40 55 41 56 /* … … 68 83 void ldb_debug_end(struct ldb_context *ldb, enum ldb_debug_level level); 69 84 70 #define ldb_oom(ldb) ldb_debug_set(ldb, LDB_DEBUG_FATAL, "ldb out of memory at %s:%d\n", __FILE__, __LINE__) 85 #define ldb_error(ldb, ecode, reason) ldb_error_at(ldb, ecode, reason, __FILE__, __LINE__) 86 87 #define ldb_oom(ldb) ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "ldb out of memory") 88 #define ldb_module_oom(module) ldb_oom(ldb_module_get_ctx(module)) 89 #define ldb_operr(ldb) ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "operations error") 71 90 72 91 /* The following definitions come from lib/ldb/common/ldb.c */ … … 99 118 void *private_data); 100 119 120 /* A useful function to build comparison functions with */ 121 int ldb_any_comparison(struct ldb_context *ldb, void *mem_ctx, 122 ldb_attr_handler_t canonicalise_fn, 123 const struct ldb_val *v1, 124 const struct ldb_val *v2); 125 101 126 /* The following definitions come from lib/ldb/common/ldb_controls.c */ 102 struct ldb_control *get_control_from_list(struct ldb_control **controls, const char *oid); 103 int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver); 104 int check_critical_controls(struct ldb_control **controls); 127 int ldb_save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver); 128 /* Returns a list of controls, except the one specified. Included 129 * controls become a child of returned list if they were children of 130 * controls_in */ 131 struct ldb_control **ldb_controls_except_specified(struct ldb_control **controls_in, 132 TALLOC_CTX *mem_ctx, 133 struct ldb_control *exclude); 134 int ldb_check_critical_controls(struct ldb_control **controls); 105 135 106 136 /* The following definitions come from lib/ldb/common/ldb_ldif.c */ … … 114 144 enum ldb_scope scope); 115 145 146 int ldb_match_msg_error(struct ldb_context *ldb, 147 const struct ldb_message *msg, 148 const struct ldb_parse_tree *tree, 149 struct ldb_dn *base, 150 enum ldb_scope scope, 151 bool *matched); 152 153 int ldb_match_msg_objectclass(const struct ldb_message *msg, 154 const char *objectclass); 155 116 156 /* The following definitions come from lib/ldb/common/ldb_modules.c */ 117 157 … … 125 165 void *ldb_module_get_private(struct ldb_module *module); 126 166 void ldb_module_set_private(struct ldb_module *module, void *private_data); 167 const struct ldb_module_ops *ldb_module_get_ops(struct ldb_module *module); 127 168 128 169 int ldb_next_request(struct ldb_module *module, struct ldb_request *request); … … 136 177 void ldb_asprintf_errstring(struct ldb_context *ldb, const char *format, ...) PRINTF_ATTRIBUTE(2,3); 137 178 void ldb_reset_err_string(struct ldb_context *ldb); 179 int ldb_error_at(struct ldb_context *ldb, int ecode, const char *reason, const char *file, int line); 138 180 139 181 const char *ldb_default_modules_dir(void); … … 152 194 const char *ldb_default_modules_dir(void); 153 195 154 int ldb_register_backend(const char *url_prefix, ldb_connect_fn );196 int ldb_register_backend(const char *url_prefix, ldb_connect_fn, bool); 155 197 156 198 struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb); … … 171 213 172 214 void ldb_set_default_dns(struct ldb_context *ldb); 215 /** 216 Add a ldb_control to a ldb_reply 217 218 \param ares the reply struct where to add the control 219 \param oid the object identifier of the control as string 220 \param critical whether the control should be critical or not 221 \param data a talloc pointer to the control specific data 222 223 \return result code (LDB_SUCCESS on success, or a failure code) 224 */ 225 int ldb_reply_add_control(struct ldb_reply *ares, const char *oid, bool critical, void *data); 226 227 /** 228 mark a request as untrusted. This tells the rootdse module to remove 229 unregistered controls 230 */ 231 void ldb_req_mark_untrusted(struct ldb_request *req); 232 233 /** 234 mark a request as trusted. 235 */ 236 void ldb_req_mark_trusted(struct ldb_request *req); 237 238 /** 239 return true is a request is untrusted 240 */ 241 bool ldb_req_is_untrusted(struct ldb_request *req); 242 243 /* load all modules from the given directory */ 244 int ldb_modules_load(const char *modules_path, const char *version); 245 246 /* init functions prototype */ 247 typedef int (*ldb_module_init_fn)(const char *); 248 249 /* 250 general ldb hook function 251 */ 252 enum ldb_module_hook_type { LDB_MODULE_HOOK_CMDLINE_OPTIONS = 1, 253 LDB_MODULE_HOOK_CMDLINE_PRECONNECT = 2, 254 LDB_MODULE_HOOK_CMDLINE_POSTCONNECT = 3 }; 255 256 typedef int (*ldb_hook_fn)(struct ldb_context *, enum ldb_module_hook_type ); 257 258 /* 259 register a ldb hook function 260 */ 261 int ldb_register_hook(ldb_hook_fn hook_fn); 262 263 /* 264 call ldb hooks of a given type 265 */ 266 int ldb_modules_hook(struct ldb_context *ldb, enum ldb_module_hook_type t); 267 268 #define LDB_MODULE_CHECK_VERSION(version) do { \ 269 if (strcmp(version, LDB_VERSION) != 0) { \ 270 fprintf(stderr, "ldb: module version mismatch in %s : ldb_version=%s module_version=%s\n", \ 271 __FILE__, version, LDB_VERSION); \ 272 return LDB_ERR_UNAVAILABLE; \ 273 }} while (0) 274 275 276 /* 277 return a string representation of the calling chain for the given 278 ldb request 279 */ 280 char *ldb_module_call_chain(struct ldb_request *req, TALLOC_CTX *mem_ctx); 281 282 /* 283 return the next module in the chain 284 */ 285 struct ldb_module *ldb_module_next(struct ldb_module *module); 286 287 /* 288 set the next module in the module chain 289 */ 290 void ldb_module_set_next(struct ldb_module *module, struct ldb_module *next); 291 292 /* 293 load a list of modules 294 */ 295 int ldb_module_load_list(struct ldb_context *ldb, const char **module_list, 296 struct ldb_module *backend, struct ldb_module **out); 297 298 /* 299 get the popt_options pointer in the ldb structure. This allows a ldb 300 module to change the command line parsing 301 */ 302 struct poptOption **ldb_module_popt_options(struct ldb_context *ldb); 303 304 /* modules are called in inverse order on the stack. 305 Lets place them as an admin would think the right order is. 306 Modules order is important */ 307 const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *string); 308 309 /* 310 return the current ldb flags LDB_FLG_* 311 */ 312 uint32_t ldb_module_flags(struct ldb_context *ldb); 313 314 int ldb_module_connect_backend(struct ldb_context *ldb, 315 const char *url, 316 const char *options[], 317 struct ldb_module **backend_module); 318 319 /* 320 initialise a chain of modules 321 */ 322 int ldb_module_init_chain(struct ldb_context *ldb, struct ldb_module *module); 323 324 /* 325 * prototype for the init function defined by dynamically loaded modules 326 */ 327 int ldb_init_module(const char *version); 328 173 329 174 330 #endif -
trunk/server/source4/lib/ldb/include/ldb_private.h
r414 r745 38 38 #define _LDB_PRIVATE_H_ 1 39 39 40 #include "ldb_includes.h" 40 #include "replace.h" 41 #include "system/filesys.h" 42 #include "system/time.h" 41 43 #include "ldb.h" 42 44 #include "ldb_module.h" … … 49 51 50 52 #define LDB_HANDLE_FLAG_DONE_CALLED 1 53 /* call is from an untrusted source - eg. over ldap:// */ 54 #define LDB_HANDLE_FLAG_UNTRUSTED 2 51 55 52 56 struct ldb_handle { … … 56 60 unsigned flags; 57 61 unsigned nesting; 62 63 /* used for debugging */ 64 struct ldb_request *parent; 65 const char *location; 58 66 }; 59 67 … … 113 121 unsigned int create_perms; 114 122 115 char *modules_dir;116 117 123 struct tevent_context *ev_ctx; 118 124 … … 120 126 121 127 char *partial_debug; 128 129 struct poptOption *popt_options; 122 130 }; 123 131 124 132 /* The following definitions come from lib/ldb/common/ldb.c */ 125 126 int ldb_connect_backend(struct ldb_context *ldb, const char *url, const char *options[],127 struct ldb_module **backend_module);128 129 133 130 134 extern const struct ldb_module_ops ldb_objectclass_module_ops; … … 158 162 159 163 /* The following definitions come from lib/ldb/common/ldb_utf8.c */ 160 char *ldb_casefold_default(void *context, void*mem_ctx, const char *s, size_t n);164 char *ldb_casefold_default(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n); 161 165 162 166 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f); … … 166 170 167 171 const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *string); 168 int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, struct ldb_module *backend, struct ldb_module **out);169 172 int ldb_load_modules(struct ldb_context *ldb, const char *options[]); 170 int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module);171 173 172 struct ldb_val ldb_binary_decode(void *mem_ctx, const char *str); 174 struct ldb_val ldb_binary_decode(TALLOC_CTX *mem_ctx, const char *str); 175 176 177 /* The following definitions come from lib/ldb/common/ldb_options.c */ 178 179 const char *ldb_options_find(struct ldb_context *ldb, const char *options[], 180 const char *option_name); 173 181 174 182 #endif -
trunk/server/source4/lib/ldb/ldb.pc.in
r414 r745 10 10 Requires.private: tdb 11 11 Requires: talloc 12 Libs: -L${libdir} -lldb12 Libs: @LIB_RPATH@ -L${libdir} -lldb 13 13 Libs.private: @LDAP_LIBS@ 14 14 Cflags: -I${includedir} -
trunk/server/source4/lib/ldb/ldb_ldap/ldb_ldap.c
r414 r745 34 34 * Modifications: 35 35 * 36 * - description: make the module use async ronous calls36 * - description: make the module use asynchronous calls 37 37 * date: Feb 2006 38 38 * author: Simo Sorce 39 39 */ 40 40 41 #include "ldb_includes.h" 41 #include "replace.h" 42 #include "system/filesys.h" 43 #include "system/time.h" 42 44 #include "ldb_module.h" 45 #include "ldb_private.h" 43 46 44 47 #define LDAP_DEPRECATED 1 … … 118 121 goto failed; 119 122 } 120 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;123 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = (char *)el->values[j].data; 121 124 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length; 122 125 } … … 254 257 255 258 ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope, 256 expression,257 discard_const_p(char *, req->op.search.attrs),258 0,259 NULL,260 NULL,261 &tv,262 LDAP_NO_LIMIT,263 &lldb_ac->msgid);259 expression, 260 discard_const_p(char *, req->op.search.attrs), 261 0, 262 NULL, 263 NULL, 264 &tv, 265 LDAP_NO_LIMIT, 266 &lldb_ac->msgid); 264 267 265 268 if (ret != LDAP_SUCCESS) { … … 283 286 int ret; 284 287 285 ldb _module_get_ctx(module);288 ldb = ldb_module_get_ctx(module); 286 289 287 290 ldb_request_set_state(req, LDB_ASYNC_PENDING); … … 322 325 int ret; 323 326 324 ldb _module_get_ctx(module);327 ldb = ldb_module_get_ctx(module); 325 328 326 329 ldb_request_set_state(req, LDB_ASYNC_PENDING); … … 360 363 int ret; 361 364 362 ldb _module_get_ctx(module);365 ldb = ldb_module_get_ctx(module); 363 366 364 367 ldb_request_set_state(req, LDB_ASYNC_PENDING); … … 387 390 struct ldb_module *module = lldb_ac->module; 388 391 struct ldb_request *req = lldb_ac->req; 392 const char *rdn_name; 393 const struct ldb_val *rdn_val; 389 394 char *old_dn; 390 395 char *newrdn; 391 396 char *parentdn; 392 397 int ret; 393 398 394 ldb _module_get_ctx(module);399 ldb = ldb_module_get_ctx(module); 395 400 396 401 ldb_request_set_state(req, LDB_ASYNC_PENDING); … … 401 406 } 402 407 403 newrdn = talloc_asprintf(lldb_ac, "%s=%s", 404 ldb_dn_get_rdn_name(req->op.rename.newdn), 405 ldb_dn_escape_value(lldb, *(ldb_dn_get_rdn_val(req->op.rename.newdn)))); 408 rdn_name = ldb_dn_get_rdn_name(req->op.rename.newdn); 409 rdn_val = ldb_dn_get_rdn_val(req->op.rename.newdn); 410 411 if ((rdn_name != NULL) && (rdn_val != NULL)) { 412 newrdn = talloc_asprintf(lldb_ac, "%s=%s", rdn_name, 413 rdn_val->length > 0 ? ldb_dn_escape_value(lldb, *rdn_val) : ""); 414 } else { 415 newrdn = talloc_strdup(lldb_ac, ""); 416 } 406 417 if (!newrdn) { 407 418 return LDB_ERR_OPERATIONS_ERROR; … … 445 456 } 446 457 447 void lldb_request_done(struct lldb_context *ac,458 static void lldb_request_done(struct lldb_context *ac, 448 459 struct ldb_control **ctrls, int error) 449 460 { … … 484 495 bool request_done; 485 496 bool lret; 497 unsigned int i; 486 498 int ret; 487 int i;488 499 489 500 ldb = ldb_module_get_ctx(ac->module); … … 503 514 ldbmsg = ldb_msg_new(ac); 504 515 if (!ldbmsg) { 516 ldb_oom(ldb); 505 517 ret = LDB_ERR_OPERATIONS_ERROR; 506 518 break; … … 509 521 dn = ldap_get_dn(lldb->ldap, msg); 510 522 if (!dn) { 523 ldb_oom(ldb); 511 524 talloc_free(ldbmsg); 512 525 ret = LDB_ERR_OPERATIONS_ERROR; … … 515 528 ldbmsg->dn = ldb_dn_new(ldbmsg, ldb, dn); 516 529 if ( ! ldb_dn_validate(ldbmsg->dn)) { 530 ldb_asprintf_errstring(ldb, "Invalid DN '%s' in reply", dn); 517 531 talloc_free(ldbmsg); 518 532 ret = LDB_ERR_OPERATIONS_ERROR; 533 ldap_memfree(dn); 519 534 break; 520 535 } … … 540 555 ret = ldb_module_send_entry(ac->req, ldbmsg, NULL /* controls not yet supported */); 541 556 if (ret != LDB_SUCCESS) { 542 557 ldb_asprintf_errstring(ldb, "entry send failed: %s", 558 ldb_errstring(ldb)); 543 559 callback_failed = true; 544 560 } … … 550 566 case LDAP_RES_SEARCH_REFERENCE: 551 567 552 if (ldap_parse_result(lldb->ldap, result, &ret, 553 &matcheddnp, &errmsgp, 554 &referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) { 568 ret = ldap_parse_reference(lldb->ldap, result, 569 &referralsp, &serverctrlsp, 0); 570 if (ret != LDAP_SUCCESS) { 571 ldb_asprintf_errstring(ldb, "ldap reference parse error: %s : %s", 572 ldap_err2string(ret), errmsgp); 555 573 ret = LDB_ERR_OPERATIONS_ERROR; 556 }557 if (ret != LDB_SUCCESS) {558 574 break; 559 575 } 560 576 if (referralsp == NULL) { 577 ldb_asprintf_errstring(ldb, "empty ldap referrals list"); 561 578 ret = LDB_ERR_PROTOCOL_ERROR; 562 579 break; … … 568 585 ret = ldb_module_send_referral(ac->req, referral); 569 586 if (ret != LDB_SUCCESS) { 587 ldb_asprintf_errstring(ldb, "referral send failed: %s", 588 ldb_errstring(ldb)); 570 589 callback_failed = true; 571 590 break; … … 586 605 } 587 606 if (ret != LDB_SUCCESS) { 607 ldb_asprintf_errstring(ldb, "ldap parse error for type %d: %s : %s", 608 type, ldap_err2string(ret), errmsgp); 588 609 break; 589 610 } … … 598 619 599 620 default: 621 ldb_asprintf_errstring(ldb, "unknown ldap return type: %d", type); 600 622 ret = LDB_ERR_PROTOCOL_ERROR; 601 623 break; … … 799 821 default: 800 822 /* no other op supported */ 801 ret = LDB_ERR_ OPERATIONS_ERROR;823 ret = LDB_ERR_PROTOCOL_ERROR; 802 824 break; 803 825 } … … 846 868 } 847 869 870 871 /* 872 optionally perform a bind 873 */ 874 static int lldb_bind(struct ldb_module *module, 875 const char *options[]) 876 { 877 const char *bind_mechanism; 878 struct lldb_private *lldb; 879 struct ldb_context *ldb = ldb_module_get_ctx(module); 880 int ret; 881 882 bind_mechanism = ldb_options_find(ldb, options, "bindMech"); 883 if (bind_mechanism == NULL) { 884 /* no bind wanted */ 885 return LDB_SUCCESS; 886 } 887 888 lldb = talloc_get_type(ldb_module_get_private(module), struct lldb_private); 889 890 if (strcmp(bind_mechanism, "simple") == 0) { 891 const char *bind_id, *bind_secret; 892 893 bind_id = ldb_options_find(ldb, options, "bindID"); 894 bind_secret = ldb_options_find(ldb, options, "bindSecret"); 895 if (bind_id == NULL || bind_secret == NULL) { 896 ldb_asprintf_errstring(ldb, "simple bind requires bindID and bindSecret"); 897 return LDB_ERR_OPERATIONS_ERROR; 898 } 899 900 ret = ldap_simple_bind_s(lldb->ldap, bind_id, bind_secret); 901 if (ret != LDAP_SUCCESS) { 902 ldb_asprintf_errstring(ldb, "bind failed: %s", ldap_err2string(ret)); 903 return ret; 904 } 905 return LDB_SUCCESS; 906 } 907 908 ldb_asprintf_errstring(ldb, "bind failed: unknown mechanism %s", bind_mechanism); 909 return LDB_ERR_INAPPROPRIATE_AUTHENTICATION; 910 } 911 848 912 /* 849 913 connect to the database … … 861 925 862 926 module = ldb_module_new(ldb, ldb, "ldb_ldap backend", &lldb_ops); 863 if (!module) return -1;927 if (!module) return LDB_ERR_OPERATIONS_ERROR; 864 928 865 929 lldb = talloc_zero(module, struct lldb_private); … … 887 951 888 952 *_module = module; 889 return 0; 953 954 ret = lldb_bind(module, options); 955 if (ret != LDB_SUCCESS) { 956 goto failed; 957 } 958 959 960 return LDB_SUCCESS; 890 961 891 962 failed: 892 963 talloc_free(module); 893 return -1; 894 } 895 896 const struct ldb_backend_ops ldb_ldap_backend_ops = { 897 .name = "ldap", 898 .connect_fn = lldb_connect 899 }; 900 901 const struct ldb_backend_ops ldb_ldapi_backend_ops = { 902 .name = "ldapi", 903 .connect_fn = lldb_connect 904 }; 905 906 const struct ldb_backend_ops ldb_ldaps_backend_ops = { 907 .name = "ldaps", 908 .connect_fn = lldb_connect 909 }; 964 return LDB_ERR_OPERATIONS_ERROR; 965 } 966 967 /* 968 initialise the module 969 */ 970 int ldb_ldap_init(const char *version) 971 { 972 int ret, i; 973 const char *names[] = { "ldap", "ldaps", "ldapi", NULL }; 974 LDB_MODULE_CHECK_VERSION(version); 975 for (i=0; names[i]; i++) { 976 ret = ldb_register_backend(names[i], lldb_connect, false); 977 if (ret != LDB_SUCCESS) { 978 return ret; 979 } 980 } 981 return LDB_SUCCESS; 982 } -
trunk/server/source4/lib/ldb/ldb_map/ldb_map.c
r414 r745 36 36 */ 37 37 38 #include "ldb_includes.h" 38 #include "replace.h" 39 #include "system/filesys.h" 40 #include "system/time.h" 39 41 #include "ldb_map.h" 40 42 #include "ldb_map_private.h" … … 257 259 static const struct ldb_map_objectclass *map_objectclass_find_local(const struct ldb_map_context *data, const char *name) 258 260 { 259 int i;261 unsigned int i; 260 262 261 263 for (i = 0; data->objectclass_maps && data->objectclass_maps[i].local_name; i++) { … … 271 273 static const struct ldb_map_objectclass *map_objectclass_find_remote(const struct ldb_map_context *data, const char *name) 272 274 { 273 int i;275 unsigned int i; 274 276 275 277 for (i = 0; data->objectclass_maps && data->objectclass_maps[i].remote_name; i++) { … … 285 287 const struct ldb_map_attribute *map_attr_find_local(const struct ldb_map_context *data, const char *name) 286 288 { 287 int i;289 unsigned int i; 288 290 289 291 for (i = 0; data->attribute_maps[i].local_name; i++) { … … 306 308 const struct ldb_map_attribute *map; 307 309 const struct ldb_map_attribute *wildcard = NULL; 308 int i, j;310 unsigned int i, j; 309 311 310 312 for (i = 0; data->attribute_maps[i].local_name; i++) { … … 315 317 316 318 switch (map->type) { 317 case MAP_IGNORE:319 case LDB_MAP_IGNORE: 318 320 break; 319 321 320 case MAP_KEEP:322 case LDB_MAP_KEEP: 321 323 if (ldb_attr_cmp(map->local_name, name) == 0) { 322 324 return map; … … 324 326 break; 325 327 326 case MAP_RENAME:327 case MAP_CONVERT:328 case LDB_MAP_RENAME: 329 case LDB_MAP_CONVERT: 328 330 if (ldb_attr_cmp(map->u.rename.remote_name, name) == 0) { 329 331 return map; … … 331 333 break; 332 334 333 case MAP_GENERATE:335 case LDB_MAP_GENERATE: 334 336 for (j = 0; map->u.generate.remote_names && map->u.generate.remote_names[j]; j++) { 335 337 if (ldb_attr_cmp(map->u.generate.remote_names[j], name) == 0) { … … 357 359 return false; 358 360 } 359 if (map->type == MAP_IGNORE) {361 if (map->type == LDB_MAP_IGNORE) { 360 362 return false; 361 363 } … … 372 374 373 375 switch (map->type) { 374 case MAP_KEEP:376 case LDB_MAP_KEEP: 375 377 return talloc_strdup(mem_ctx, attr); 376 378 377 case MAP_RENAME:378 case MAP_CONVERT:379 case LDB_MAP_RENAME: 380 case LDB_MAP_CONVERT: 379 381 return talloc_strdup(mem_ctx, map->u.rename.remote_name); 380 382 … … 391 393 } 392 394 393 if (map->type == MAP_KEEP) {395 if (map->type == LDB_MAP_KEEP) { 394 396 return talloc_strdup(mem_ctx, attr); 395 397 } … … 403 405 const char ***attrs, const char * const *more_attrs) 404 406 { 405 int i, j, k;407 unsigned int i, j, k; 406 408 407 409 for (i = 0; *attrs && (*attrs)[i]; i++) /* noop */ ; … … 430 432 const struct ldb_map_attribute *map, const struct ldb_val *val) 431 433 { 432 if (map && (map->type == MAP_CONVERT) && (map->u.convert.convert_local)) {434 if (map && (map->type == LDB_MAP_CONVERT) && (map->u.convert.convert_local)) { 433 435 return map->u.convert.convert_local(module, mem_ctx, val); 434 436 } … … 441 443 const struct ldb_map_attribute *map, const struct ldb_val *val) 442 444 { 443 if (map && (map->type == MAP_CONVERT) && (map->u.convert.convert_remote)) {445 if (map && (map->type == LDB_MAP_CONVERT) && (map->u.convert.convert_remote)) { 444 446 return map->u.convert.convert_remote(module, mem_ctx, val); 445 447 } … … 494 496 /* Unknown attribute - leave this RDN as is and hope the best... */ 495 497 if (map == NULL) { 496 map_type = MAP_KEEP;498 map_type = LDB_MAP_KEEP; 497 499 } else { 498 500 map_type = map->type; … … 500 502 501 503 switch (map_type) { 502 case MAP_IGNORE:503 case MAP_GENERATE:504 case LDB_MAP_IGNORE: 505 case LDB_MAP_GENERATE: 504 506 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " 505 " MAP_IGNORE/MAP_GENERATE attribute '%s' "507 "LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' " 506 508 "used in DN!", ldb_dn_get_component_name(dn, i)); 507 509 goto failed; 508 510 509 case MAP_CONVERT:511 case LDB_MAP_CONVERT: 510 512 if (map->u.convert.convert_local == NULL) { 511 513 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " … … 515 517 } 516 518 /* fall through */ 517 case MAP_KEEP:518 case MAP_RENAME:519 case LDB_MAP_KEEP: 520 case LDB_MAP_RENAME: 519 521 name = map_attr_map_local(newdn, map, ldb_dn_get_component_name(dn, i)); 520 522 if (name == NULL) goto failed; … … 569 571 /* Unknown attribute - leave this RDN as is and hope the best... */ 570 572 if (map == NULL) { 571 map_type = MAP_KEEP;573 map_type = LDB_MAP_KEEP; 572 574 } else { 573 575 map_type = map->type; … … 575 577 576 578 switch (map_type) { 577 case MAP_IGNORE:578 case MAP_GENERATE:579 case LDB_MAP_IGNORE: 580 case LDB_MAP_GENERATE: 579 581 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " 580 " MAP_IGNORE/MAP_GENERATE attribute '%s' "582 "LDB_MAP_IGNORE/LDB_MAP_GENERATE attribute '%s' " 581 583 "used in DN!", ldb_dn_get_component_name(dn, i)); 582 584 goto failed; 583 585 584 case MAP_CONVERT:586 case LDB_MAP_CONVERT: 585 587 if (map->u.convert.convert_remote == NULL) { 586 588 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " … … 590 592 } 591 593 /* fall through */ 592 case MAP_KEEP:593 case MAP_RENAME:594 case LDB_MAP_KEEP: 595 case LDB_MAP_RENAME: 594 596 name = map_attr_map_remote(newdn, map, ldb_dn_get_component_name(dn, i)); 595 597 if (name == NULL) goto failed; … … 715 717 struct ldb_val val; 716 718 bool found_extensibleObject = false; 717 int i;719 unsigned int i; 718 720 719 721 ldb = ldb_module_get_ctx(module); … … 790 792 struct ldb_message_element *el, *oc; 791 793 struct ldb_val val; 792 int i;794 unsigned int i; 793 795 794 796 ldb = ldb_module_get_ctx(module); … … 843 845 static const struct ldb_map_attribute objectclass_convert_map = { 844 846 .local_name = "objectClass", 845 .type = MAP_CONVERT,847 .type = LDB_MAP_CONVERT, 846 848 .u = { 847 849 .convert = { … … 892 894 context, callback, 893 895 ac->req); 896 LDB_REQ_SET_LOCATION(req); 894 897 if (ret != LDB_SUCCESS) { 895 898 return NULL; … … 939 942 context, callback, 940 943 ac->req); 944 LDB_REQ_SET_LOCATION(req); 941 945 if (ret != LDB_SUCCESS) { 942 946 goto failed; … … 958 962 { 959 963 .local_name = "dn", 960 .type = MAP_CONVERT,964 .type = LDB_MAP_CONVERT, 961 965 .u = { 962 966 .convert = { … … 974 978 static const struct ldb_map_attribute objectclass_attribute_map = { 975 979 .local_name = "objectClass", 976 .type = MAP_GENERATE,980 .type = LDB_MAP_GENERATE, 977 981 .convert_operator = map_objectclass_convert_operator, 978 982 .u = { … … 1044 1048 const char * const *wildcard_attributes) 1045 1049 { 1046 int i, j, last;1050 unsigned int i, j, last; 1047 1051 last = 0; 1048 1052 -
trunk/server/source4/lib/ldb/ldb_map/ldb_map.h
r414 r745 60 60 61 61 enum ldb_map_attr_type { 62 MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely. */63 MAP_KEEP, /* Keep as is. Same name locally and remotely. */64 MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */65 MAP_CONVERT, /* Rename + convert data */66 MAP_GENERATE /* Use generate function for generating new name/data.62 LDB_MAP_IGNORE, /* Ignore this local attribute. Doesn't exist remotely. */ 63 LDB_MAP_KEEP, /* Keep as is. Same name locally and remotely. */ 64 LDB_MAP_RENAME, /* Simply rename the attribute. Name changes, data is the same */ 65 LDB_MAP_CONVERT, /* Rename + convert data */ 66 LDB_MAP_GENERATE /* Use generate function for generating new name/data. 67 67 Used for generating attributes based on 68 68 multiple remote attributes. */ … … 158 158 const char *name); 159 159 160 int map_add(struct ldb_module *module, struct ldb_request *req);161 int map_search(struct ldb_module *module, struct ldb_request *req);162 int map_rename(struct ldb_module *module, struct ldb_request *req);163 int map_delete(struct ldb_module *module, struct ldb_request *req);164 int map_modify(struct ldb_module *module, struct ldb_request *req);160 int ldb_map_add(struct ldb_module *module, struct ldb_request *req); 161 int ldb_map_search(struct ldb_module *module, struct ldb_request *req); 162 int ldb_map_rename(struct ldb_module *module, struct ldb_request *req); 163 int ldb_map_delete(struct ldb_module *module, struct ldb_request *req); 164 int ldb_map_modify(struct ldb_module *module, struct ldb_request *req); 165 165 166 166 #define LDB_MAP_OPS \ 167 .add = map_add, \168 .modify = map_modify, \169 .del = map_delete, \170 .rename = map_rename, \171 .search = map_search,167 .add = ldb_map_add, \ 168 .modify = ldb_map_modify, \ 169 .del = ldb_map_delete, \ 170 .rename = ldb_map_rename, \ 171 .search = ldb_map_search, 172 172 173 173 #endif /* __LDB_MAP_H__ */ -
trunk/server/source4/lib/ldb/ldb_map/ldb_map_inbound.c
r414 r745 25 25 */ 26 26 27 #include "ldb_includes.h" 27 #include "replace.h" 28 #include "system/filesys.h" 29 #include "system/time.h" 28 30 #include "ldb_map.h" 29 31 #include "ldb_map_private.h" … … 37 39 { 38 40 struct ldb_message_element *el; 39 int i;41 unsigned int i; 40 42 41 43 el = talloc_zero(mem_ctx, struct ldb_message_element); … … 80 82 81 83 switch (map->type) { 82 case MAP_IGNORE:84 case LDB_MAP_IGNORE: 83 85 goto local; 84 86 85 case MAP_CONVERT:87 case LDB_MAP_CONVERT: 86 88 if (map->u.convert.convert_local == NULL) { 87 89 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: " … … 92 94 } 93 95 /* fall through */ 94 case MAP_KEEP:95 case MAP_RENAME:96 case LDB_MAP_KEEP: 97 case LDB_MAP_RENAME: 96 98 el = ldb_msg_el_map_local(module, remote, map, old); 97 99 break; 98 100 99 case MAP_GENERATE:101 case LDB_MAP_GENERATE: 100 102 if (map->u.generate.generate_remote == NULL) { 101 103 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: " … … 142 144 const struct ldb_map_context *data = map_get_context(module); 143 145 bool ret; 144 int i;146 unsigned int i; 145 147 146 148 for (i = 0; i < msg->num_elements; i++) { … … 160 162 /* const char * const names[]; */ 161 163 struct ldb_context *ldb; 162 int i, ret; 164 unsigned int i; 165 int ret; 163 166 164 167 ldb = ldb_module_get_ctx(module); … … 357 360 358 361 /* Add a record. */ 359 int map_add(struct ldb_module *module, struct ldb_request *req)362 int ldb_map_add(struct ldb_module *module, struct ldb_request *req) 360 363 { 361 364 const struct ldb_message *msg = req->op.add.message; … … 363 366 struct map_context *ac; 364 367 struct ldb_message *remote_msg; 365 const char *dn;366 368 int ret; 367 369 … … 415 417 ac, map_op_remote_callback, 416 418 req); 419 LDB_REQ_SET_LOCATION(ac->remote_req); 417 420 if (ret != LDB_SUCCESS) { 418 421 return LDB_ERR_OPERATIONS_ERROR; … … 427 430 /* Store remote DN in 'IS_MAPPED' */ 428 431 /* TODO: use GUIDs here instead */ 429 dn = ldb_dn_alloc_linearized(ac->local_msg, remote_msg->dn); 430 if (ldb_msg_add_string(ac->local_msg, IS_MAPPED, dn) != 0) { 432 ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED, 433 remote_msg->dn); 434 if (ret != LDB_SUCCESS) { 431 435 return LDB_ERR_OPERATIONS_ERROR; 432 436 } … … 451 455 map_op_local_callback, 452 456 ac->req); 457 LDB_REQ_SET_LOCATION(local_req); 453 458 if (ret != LDB_SUCCESS) { 454 459 return LDB_ERR_OPERATIONS_ERROR; … … 462 467 463 468 /* Modify a record. */ 464 int map_modify(struct ldb_module *module, struct ldb_request *req)469 int ldb_map_modify(struct ldb_module *module, struct ldb_request *req) 465 470 { 466 471 const struct ldb_message *msg = req->op.mod.message; … … 522 527 ac, map_op_remote_callback, 523 528 req); 529 LDB_REQ_SET_LOCATION(ac->remote_req); 524 530 if (ret != LDB_SUCCESS) { 525 531 return LDB_ERR_OPERATIONS_ERROR; … … 546 552 struct ldb_request *local_req; 547 553 struct ldb_context *ldb; 548 char *dn;549 554 int ret; 550 555 … … 559 564 return LDB_ERR_OPERATIONS_ERROR; 560 565 } 561 dn = ldb_dn_alloc_linearized(ac->local_msg,562 ac->remote_req->op.mod.message->dn);563 if ( ldb_msg_add_string(ac->local_msg, IS_MAPPED, dn)!= 0) {566 ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED, 567 ac->remote_req->op.mod.message->dn); 568 if (ret != 0) { 564 569 return LDB_ERR_OPERATIONS_ERROR; 565 570 } … … 572 577 map_op_local_callback, 573 578 ac->req); 579 LDB_REQ_SET_LOCATION(local_req); 574 580 if (ret != LDB_SUCCESS) { 575 581 return LDB_ERR_OPERATIONS_ERROR; … … 583 589 map_op_local_callback, 584 590 ac->req); 591 LDB_REQ_SET_LOCATION(local_req); 585 592 if (ret != LDB_SUCCESS) { 586 593 return LDB_ERR_OPERATIONS_ERROR; … … 596 603 597 604 /* Delete a record. */ 598 int map_delete(struct ldb_module *module, struct ldb_request *req)605 int ldb_map_delete(struct ldb_module *module, struct ldb_request *req) 599 606 { 600 607 struct ldb_request *search_req; … … 629 636 map_op_remote_callback, 630 637 req); 638 LDB_REQ_SET_LOCATION(ac->remote_req); 631 639 if (ret != LDB_SUCCESS) { 632 640 return LDB_ERR_OPERATIONS_ERROR; … … 671 679 map_op_local_callback, 672 680 ac->req); 681 LDB_REQ_SET_LOCATION(local_req); 673 682 if (ret != LDB_SUCCESS) { 674 683 return LDB_ERR_OPERATIONS_ERROR; … … 682 691 683 692 /* Rename a record. */ 684 int map_rename(struct ldb_module *module, struct ldb_request *req)693 int ldb_map_rename(struct ldb_module *module, struct ldb_request *req) 685 694 { 686 695 struct ldb_request *search_req; … … 722 731 ac, map_op_remote_callback, 723 732 req); 733 LDB_REQ_SET_LOCATION(ac->remote_req); 724 734 if (ret != LDB_SUCCESS) { 725 735 return LDB_ERR_OPERATIONS_ERROR; … … 765 775 map_rename_local_callback, 766 776 ac->req); 777 LDB_REQ_SET_LOCATION(local_req); 767 778 if (ret != LDB_SUCCESS) { 768 779 return LDB_ERR_OPERATIONS_ERROR; -
trunk/server/source4/lib/ldb/ldb_map/ldb_map_outbound.c
r414 r745 26 26 */ 27 27 28 #include "ldb_includes.h" 28 #include "replace.h" 29 #include "system/filesys.h" 30 #include "system/time.h" 29 31 #include "ldb_map.h" 30 32 #include "ldb_map_private.h" … … 39 41 const struct ldb_map_context *data = map_get_context(module); 40 42 const char **result; 41 int i, last;43 unsigned int i, last; 42 44 43 45 if (attrs == NULL) … … 82 84 const struct ldb_map_attribute *map; 83 85 const char *name=NULL; 84 int i, j, last;86 unsigned int i, j, last; 85 87 int ret; 86 88 … … 125 127 126 128 switch (map->type) { 127 case MAP_IGNORE:129 case LDB_MAP_IGNORE: 128 130 continue; 129 131 130 case MAP_KEEP:132 case LDB_MAP_KEEP: 131 133 name = attrs[i]; 132 134 goto named; 133 135 134 case MAP_RENAME:135 case MAP_CONVERT:136 case LDB_MAP_RENAME: 137 case LDB_MAP_CONVERT: 136 138 name = map->u.rename.remote_name; 137 139 goto named; 138 140 139 case MAP_GENERATE:141 case LDB_MAP_GENERATE: 140 142 /* Add all remote names of "generate" attrs */ 141 143 for (j = 0; map->u.generate.remote_names[j]; j++) { … … 220 222 const struct ldb_message_element *old) 221 223 { 224 const struct ldb_map_context *data = map_get_context(module); 225 const char *local_attr_name = attr_name; 222 226 struct ldb_message_element *el; 223 int i;227 unsigned int i; 224 228 225 229 el = talloc_zero(mem_ctx, struct ldb_message_element); … … 236 240 } 237 241 238 el->name = talloc_strdup(el, attr_name); 242 for (i = 0; data->attribute_maps[i].local_name; i++) { 243 struct ldb_map_attribute *am = &data->attribute_maps[i]; 244 if ((am->type == LDB_MAP_RENAME && 245 !strcmp(am->u.rename.remote_name, attr_name)) 246 || (am->type == LDB_MAP_CONVERT && 247 !strcmp(am->u.convert.remote_name, attr_name))) { 248 249 local_attr_name = am->local_name; 250 break; 251 } 252 } 253 254 el->name = talloc_strdup(el, local_attr_name); 239 255 if (el->name == NULL) { 240 256 talloc_free(el); … … 282 298 283 299 switch (map->type) { 284 case MAP_IGNORE:285 break; 286 case MAP_CONVERT:300 case LDB_MAP_IGNORE: 301 break; 302 case LDB_MAP_CONVERT: 287 303 remote_name = map->u.convert.remote_name; 288 304 break; 289 case MAP_KEEP:305 case LDB_MAP_KEEP: 290 306 remote_name = attr_name; 291 307 break; 292 case MAP_RENAME:308 case LDB_MAP_RENAME: 293 309 remote_name = map->u.rename.remote_name; 294 310 break; 295 case MAP_GENERATE:311 case LDB_MAP_GENERATE: 296 312 break; 297 313 } 298 314 299 315 switch (map->type) { 300 case MAP_IGNORE:316 case LDB_MAP_IGNORE: 301 317 return LDB_SUCCESS; 302 318 303 case MAP_CONVERT:319 case LDB_MAP_CONVERT: 304 320 if (map->u.convert.convert_remote == NULL) { 305 321 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " … … 310 326 } 311 327 /* fall through */ 312 case MAP_KEEP:313 case MAP_RENAME:328 case LDB_MAP_KEEP: 329 case LDB_MAP_RENAME: 314 330 old = ldb_msg_find_element(remote, remote_name); 315 331 if (old) { … … 320 336 break; 321 337 322 case MAP_GENERATE:338 case LDB_MAP_GENERATE: 323 339 if (map->u.generate.generate_local == NULL) { 324 340 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: " … … 351 367 const struct ldb_map_attribute *map = map_attr_find_local(data, "*"); 352 368 struct ldb_message_element *el=NULL; 353 int i, ret; 369 unsigned int i; 370 int ret; 354 371 355 372 /* Perhaps we have a mapping for "*" */ 356 if (map && map->type == MAP_KEEP) {373 if (map && map->type == LDB_MAP_KEEP) { 357 374 /* We copy everything over, and hope that anything with a 358 375 more specific rule is overwritten */ … … 393 410 static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2) 394 411 { 395 int i, ret; 412 unsigned int i; 413 int ret; 396 414 397 415 for (i = 0; i < msg2->num_elements; i++) { … … 409 427 struct ldb_message *remote) 410 428 { 411 int i, ret; 429 unsigned int i; 430 int ret; 412 431 const char * const *attrs = ac->all_attrs; 413 432 if (!attrs) { … … 521 540 { 522 541 const char **new_attrs; 523 int i, ret; 542 unsigned int i; 543 int ret; 524 544 525 545 if (tree == NULL) { … … 548 568 return 0; 549 569 } 550 551 return -1;552 570 } 553 571 … … 589 607 static int map_subtree_select_local_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) 590 608 { 591 int i, j, ret=0; 609 unsigned int i, j; 610 int ret=0; 592 611 593 612 /* Prepare new tree */ … … 712 731 static int map_subtree_collect_remote_list(struct ldb_module *module, void *mem_ctx, struct ldb_parse_tree **new, const struct ldb_parse_tree *tree) 713 732 { 714 int i, j, ret=0; 733 unsigned int i, j; 734 int ret=0; 715 735 716 736 /* Prepare new tree */ … … 773 793 **new = *tree; 774 794 775 if (map->type == MAP_KEEP) {795 if (map->type == LDB_MAP_KEEP) { 776 796 /* Nothing to do here */ 777 797 return 0; … … 815 835 } 816 836 817 if (map->type == MAP_RENAME) {837 if (map->type == LDB_MAP_RENAME) { 818 838 /* Nothing more to do here, the attribute has been renamed */ 819 839 return 0; … … 898 918 } 899 919 900 if (map->type == MAP_GENERATE) {920 if (map->type == LDB_MAP_GENERATE) { 901 921 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: " 902 922 "Skipping attribute '%s': " … … 1052 1072 const char * const *attrs; 1053 1073 struct ldb_context *ldb; 1054 int i; 1074 unsigned int i; 1075 int ret; 1076 bool matched; 1055 1077 1056 1078 ldb = ldb_module_get_ctx(ac->module); 1057 1079 1058 1080 /* Merged result doesn't match original query, skip */ 1059 if (!ldb_match_msg(ldb, ares->message, 1060 ac->req->op.search.tree, 1061 ac->req->op.search.base, 1062 ac->req->op.search.scope)) { 1081 ret = ldb_match_msg_error(ldb, ares->message, 1082 ac->req->op.search.tree, 1083 ac->req->op.search.base, 1084 ac->req->op.search.scope, 1085 &matched); 1086 if (ret != LDB_SUCCESS) return ret; 1087 if (!matched) { 1063 1088 ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: " 1064 1089 "Skipping record '%s': " … … 1090 1115 1091 1116 /* Search a record. */ 1092 int map_search(struct ldb_module *module, struct ldb_request *req)1117 int ldb_map_search(struct ldb_module *module, struct ldb_request *req) 1093 1118 { 1094 1119 struct ldb_parse_tree *remote_tree; … … 1186 1211 ac, map_remote_search_callback, 1187 1212 req); 1213 LDB_REQ_SET_LOCATION(remote_req); 1188 1214 if (ret != LDB_SUCCESS) { 1189 1215 return LDB_ERR_OPERATIONS_ERROR; … … 1262 1288 } 1263 1289 1264 talloc_free(ares);1290 ac->remote_done_ares = talloc_steal(ac, ares); 1265 1291 1266 1292 ret = map_search_local(ac); … … 1334 1360 1335 1361 case LDB_REPLY_DONE: 1362 /* We don't need the local 'ares', but we will use the remote one from below */ 1336 1363 talloc_free(ares); 1337 1364 … … 1372 1399 * finish operations for this module */ 1373 1400 return ldb_module_done(ac->req, 1374 ac->r _current->remote->controls,1375 ac->r _current->remote->response,1376 ac->r _current->remote->error);1401 ac->remote_done_ares->controls, 1402 ac->remote_done_ares->response, 1403 ac->remote_done_ares->error); 1377 1404 } 1378 1405 -
trunk/server/source4/lib/ldb/ldb_map/ldb_map_private.h
r414 r745 1 #include "ldb_includes.h" 1 #include "replace.h" 2 #include "system/filesys.h" 3 #include "system/time.h" 2 4 3 5 /* A handy macro to report Out of Memory conditions */ … … 38 40 struct map_reply *r_list; 39 41 struct map_reply *r_current; 42 43 /* The response continaing any controls the remote server gave */ 44 struct ldb_reply *remote_done_ares; 40 45 }; 41 46 -
trunk/server/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
r414 r745 256 256 char *ret = NULL; 257 257 char *attr; 258 int i;258 unsigned int i; 259 259 260 260 ldb = ldb_module_get_ctx(module); … … 558 558 559 559 /* 560 * This is a bad hack to support ldap style comparisons w hithin sqlite.560 * This is a bad hack to support ldap style comparisons within sqlite. 561 561 * val is the attribute in the row currently under test 562 562 * func is the desired test "<=" ">=" "~" ":" … … 668 668 struct ldb_message *msg; 669 669 long long eid; 670 int i, ret; 670 unsigned int i; 671 int ret; 671 672 672 673 ac = talloc_get_type(result, struct lsql_context); … … 687 688 * except the first time */ 688 689 if (ac->current_eid != 0) { 689 msg = ldb_msg_canonicalize(ldb, msg); 690 if (!msg) return SQLITE_ABORT; 690 ret = ldb_msg_normalize(ldb, ac->req, msg, &msg); 691 if (ret != LDB_SUCCESS) { 692 return SQLITE_ABORT; 693 } 691 694 692 695 ret = ldb_module_send_entry(ac->req, msg, NULL); 693 696 if (ret != LDB_SUCCESS) { 694 697 ac->callback_failed = true; 698 /* free msg object */ 699 TALLOC_FREE(msg); 695 700 return SQLITE_ABORT; 696 701 } 702 703 /* free msg object */ 704 TALLOC_FREE(msg); 697 705 } 698 706 … … 960 968 /* complete the last message if any */ 961 969 if (ctx->ares) { 962 ctx->ares->message = ldb_msg_canonicalize(ldb, ctx->ares->message); 963 if (ctx->ares->message == NULL) { 970 ret = ldb_msg_normalize(ldb, ctx->ares, 971 ctx->ares->message, 972 &ctx->ares->message); 973 if (ret != LDB_SUCCESS) { 964 974 return LDB_ERR_OPERATIONS_ERROR; 965 975 } … … 987 997 char *errmsg; 988 998 char *query; 989 int i;999 unsigned int i; 990 1000 int ret; 991 1001 … … 1044 1054 const struct ldb_schema_attribute *a; 1045 1055 char *attr; 1046 int j;1056 unsigned int j; 1047 1057 1048 1058 /* Get a case-folded copy of the attribute name */ … … 1053 1063 1054 1064 a = ldb_schema_attribute_by_name(ldb, el->name); 1065 1066 if (el->num_value == 0) { 1067 ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illegal)", 1068 el->name, ldb_dn_get_linearized(msg->dn)); 1069 return LDB_ERR_CONSTRAINT_VIOLATION; 1070 } 1055 1071 1056 1072 /* For each value of the specified attribute name... */ … … 1098 1114 struct ldb_context *ldb; 1099 1115 struct ldb_message *msg = req->op.mod.message; 1100 1116 long long eid; 1101 1117 char *errmsg; 1102 int i;1118 unsigned int i; 1103 1119 int ret; 1104 1120 … … 1124 1140 char *attr; 1125 1141 char *mod; 1126 int j;1142 unsigned int j; 1127 1143 1128 1144 /* Get a case-folded copy of the attribute name */ … … 1137 1153 1138 1154 case LDB_FLAG_MOD_REPLACE: 1155 1156 for (j=0; j<el->num_values; j++) { 1157 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) { 1158 ldb_asprintf_errstring(ldb, "%s: value #%d provided more than once", el->name, j); 1159 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 1160 } 1161 } 1139 1162 1140 1163 /* remove all attributes before adding the replacements */ … … 1160 1183 1161 1184 case LDB_FLAG_MOD_ADD: 1162 #warning "We should throw an error if no value is provided!" 1185 1186 if (el->num_values == 0) { 1187 ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illigal)", 1188 el->name, ldb_dn_get_linearized(msg->dn)); 1189 return LDB_ERR_CONSTRAINT_VIOLATION; 1190 } 1191 1163 1192 /* For each value of the specified attribute name... */ 1164 1193 for (j = 0; j < el->num_values; j++) { … … 1492 1521 default: 1493 1522 /* no other op supported */ 1494 ret = LDB_ERR_ UNWILLING_TO_PERFORM;1523 ret = LDB_ERR_PROTOCOL_ERROR; 1495 1524 } 1496 1525 … … 1510 1539 struct timeval tv; 1511 1540 1512 if ( check_critical_controls(req->controls)) {1541 if (ldb_check_critical_controls(req->controls)) { 1513 1542 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; 1514 1543 } … … 1846 1875 struct ldb_module *module; 1847 1876 struct lsqlite3_private *lsqlite3; 1848 int i, ret; 1877 unsigned int i; 1878 int ret; 1849 1879 1850 1880 module = ldb_module_new(ldb, ldb, "ldb_sqlite3 backend", &lsqlite3_ops); 1851 if (!module) return -1;1881 if (!module) return LDB_ERR_OPERATIONS_ERROR; 1852 1882 1853 1883 lsqlite3 = talloc(module, struct lsqlite3_private); … … 1893 1923 1894 1924 *_module = module; 1895 return 0;1925 return LDB_SUCCESS; 1896 1926 1897 1927 failed: … … 1900 1930 } 1901 1931 talloc_free(lsqlite3); 1902 return -1; 1903 } 1904 1905 const struct ldb_backend_ops ldb_sqlite3_backend_ops = { 1906 .name = "sqlite3", 1907 .connect_fn = lsqlite3_connect 1908 }; 1932 return LDB_ERR_OPERATIONS_ERROR; 1933 } 1934 1935 int ldb_sqlite3_init(const char *version) 1936 { 1937 LDB_MODULE_CHECK_VERSION(version); 1938 return ldb_register_backend("sqlite3", lsqlite3_connect, false); 1939 } -
trunk/server/source4/lib/ldb/ldb_tdb/ldb_cache.c
r414 r745 61 61 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 62 62 struct ldb_message *msg; 63 int i;63 unsigned int i; 64 64 65 65 ldb = ldb_module_get_ctx(module); … … 84 84 static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v) 85 85 { 86 int i;86 unsigned int i; 87 87 unsigned value = 0; 88 88 for (i=0;i<el->num_values;i++) { 89 int j;89 unsigned int j; 90 90 for (j=0;ltdb_valid_attr_flags[j].name;j++) { 91 91 if (strcmp(ltdb_valid_attr_flags[j].name, … … 113 113 struct ldb_message *msg = ltdb->cache->attributes; 114 114 struct ldb_dn *dn; 115 int i, r; 115 unsigned int i; 116 int r; 116 117 117 118 ldb = ldb_module_get_ctx(module); … … 120 121 /* we skip loading the @ATTRIBUTES record when a module is supplying 121 122 its own attribute handling */ 122 return LDB_SUCCESS;123 return 0; 123 124 } 124 125 … … 203 204 ltdb->sequence_number = atof(initial_sequence_number); 204 205 205 msg = talloc(ltdb, struct ldb_message);206 msg = ldb_msg_new(ltdb); 206 207 if (msg == NULL) { 207 208 goto failed; … … 287 288 ltdb->cache = talloc_zero(ltdb, struct ltdb_cache); 288 289 if (ltdb->cache == NULL) goto failed; 289 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message);290 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message);290 ltdb->cache->indexlist = ldb_msg_new(ltdb->cache); 291 ltdb->cache->attributes = ldb_msg_new(ltdb->cache); 291 292 if (ltdb->cache->indexlist == NULL || 292 293 ltdb->cache->attributes == NULL) { … … 295 296 } 296 297 297 baseinfo = talloc(ltdb->cache, struct ldb_message);298 baseinfo = ldb_msg_new(ltdb->cache); 298 299 if (baseinfo == NULL) goto failed; 299 300 300 baseinfo_dn = ldb_dn_new( module, ldb, LTDB_BASEINFO);301 baseinfo_dn = ldb_dn_new(baseinfo, ldb, LTDB_BASEINFO); 301 302 if (baseinfo_dn == NULL) goto failed; 302 303 … … 327 328 328 329 /* Read an interpret database options */ 329 options = talloc(ltdb->cache, struct ldb_message);330 options = ldb_msg_new(ltdb->cache); 330 331 if (options == NULL) goto failed; 331 332 … … 348 349 memset(<db->cache->last_attribute, 0, sizeof(ltdb->cache->last_attribute)); 349 350 350 ltdb_attributes_unload(module);351 352 351 talloc_free(ltdb->cache->indexlist); 353 354 ltdb->cache->indexlist = talloc_zero(ltdb->cache, struct ldb_message); 355 ltdb->cache->attributes = talloc_zero(ltdb->cache, struct ldb_message); 352 ltdb_attributes_unload(module); /* calls internally "talloc_free" */ 353 354 ltdb->cache->indexlist = ldb_msg_new(ltdb->cache); 355 ltdb->cache->attributes = ldb_msg_new(ltdb->cache); 356 356 if (ltdb->cache->indexlist == NULL || 357 357 ltdb->cache->attributes == NULL) { 358 358 goto failed; 359 359 } 360 ltdb->cache->one_level_indexes = false; 361 ltdb->cache->attribute_indexes = false; 360 362 361 363 indexlist_dn = ldb_dn_new(module, ldb, LTDB_INDEXLIST); … … 367 369 } 368 370 371 if (ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXONE) != NULL) { 372 ltdb->cache->one_level_indexes = true; 373 } 374 if (ldb_msg_find_element(ltdb->cache->indexlist, LTDB_IDXATTR) != NULL) { 375 ltdb->cache->attribute_indexes = true; 376 } 377 369 378 if (ltdb_attributes_load(module) == -1) { 370 379 goto failed; … … 374 383 talloc_free(options); 375 384 talloc_free(baseinfo); 376 talloc_free(baseinfo_dn);377 385 talloc_free(indexlist_dn); 378 386 return 0; … … 381 389 talloc_free(options); 382 390 talloc_free(baseinfo); 383 talloc_free(baseinfo_dn);384 391 talloc_free(indexlist_dn); 385 392 return -1; … … 405 412 ldb = ldb_module_get_ctx(module); 406 413 407 msg = talloc(ltdb, struct ldb_message);414 msg = ldb_msg_new(ltdb); 408 415 if (msg == NULL) { 409 416 errno = ENOMEM; … … 413 420 s = talloc_asprintf(msg, "%llu", ltdb->sequence_number+1); 414 421 if (!s) { 422 talloc_free(msg); 415 423 errno = ENOMEM; 416 424 return LDB_ERR_OPERATIONS_ERROR; … … 449 457 s = ldb_timestring(msg, t); 450 458 if (s == NULL) { 459 talloc_free(msg); 451 460 return LDB_ERR_OPERATIONS_ERROR; 452 461 } … … 455 464 val_time.length = strlen(s); 456 465 457 ret = ltdb_modify_internal(module, msg );466 ret = ltdb_modify_internal(module, msg, NULL); 458 467 459 468 talloc_free(msg); … … 472 481 int ltdb_check_at_attributes_values(const struct ldb_val *value) 473 482 { 474 int i;483 unsigned int i; 475 484 476 485 for (i = 0; ltdb_valid_attr_flags[i].name != NULL; i++) { -
trunk/server/source4/lib/ldb/ldb_tdb/ldb_index.c
r414 r745 2 2 ldb database library 3 3 4 Copyright (C) Andrew Tridgell 2004 4 Copyright (C) Andrew Tridgell 2004-2009 5 5 6 6 ** NOTE! The following LGPL license applies to the ldb … … 33 33 34 34 #include "ldb_tdb.h" 35 #include "dlinklist.h" 36 37 /* 38 the idxptr code is a bit unusual. The way it works is to replace 39 @IDX elements in records during a transaction with @IDXPTR 40 elements. The @IDXPTR elements don't contain the actual index entry 41 values, but contain a pointer to a linked list of values. 42 43 This means we are storing pointers in a database, which is normally 44 not allowed, but in this case we are storing them only for the 45 duration of a transaction, and re-writing them into the normal @IDX 46 format at the end of the transaction. That means no other processes 47 are ever exposed to the @IDXPTR values. 48 49 The advantage is that the linked list doesn't cause huge 50 fragmentation during a transaction. Without the @IDXPTR method we 51 often ended up with a ldb that was between 10x and 100x larger then 52 it needs to be due to massive fragmentation caused by re-writing 53 @INDEX records many times during indexing. 54 */ 55 struct ldb_index_pointer { 56 struct ldb_index_pointer *next, *prev; 57 struct ldb_val value; 35 36 struct dn_list { 37 unsigned int count; 38 struct ldb_val *dn; 58 39 }; 59 40 60 41 struct ltdb_idxptr { 61 int num_dns; 62 const char **dn_list; 63 bool repack; 42 struct tdb_context *itdb; 43 int error; 64 44 }; 65 45 66 /* 67 add to the list of DNs that need to be fixed on transaction end 68 */ 69 static int ltdb_idxptr_add(struct ldb_module *module, const struct ldb_message *msg) 70 { 71 void *data = ldb_module_get_private(module); 72 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 73 ltdb->idxptr->dn_list = talloc_realloc(ltdb->idxptr, ltdb->idxptr->dn_list, 74 const char *, ltdb->idxptr->num_dns+1); 75 if (ltdb->idxptr->dn_list == NULL) { 76 ltdb->idxptr->num_dns = 0; 77 return LDB_ERR_OPERATIONS_ERROR; 78 } 79 ltdb->idxptr->dn_list[ltdb->idxptr->num_dns] = 80 talloc_strdup(ltdb->idxptr->dn_list, ldb_dn_get_linearized(msg->dn)); 81 if (ltdb->idxptr->dn_list[ltdb->idxptr->num_dns] == NULL) { 82 return LDB_ERR_OPERATIONS_ERROR; 83 } 84 ltdb->idxptr->num_dns++; 85 return LDB_SUCCESS; 86 } 87 88 /* free an idxptr record */ 89 static int ltdb_free_idxptr(struct ldb_module *module, struct ldb_message_element *el) 90 { 91 struct ldb_val val; 92 struct ldb_index_pointer *ptr; 93 94 if (el->num_values != 1) { 95 return LDB_ERR_OPERATIONS_ERROR; 96 } 97 98 val = el->values[0]; 99 if (val.length != sizeof(void *)) { 100 return LDB_ERR_OPERATIONS_ERROR; 101 } 102 103 ptr = *(struct ldb_index_pointer **)val.data; 104 if (talloc_get_type(ptr, struct ldb_index_pointer) != ptr) { 105 return LDB_ERR_OPERATIONS_ERROR; 106 } 107 108 while (ptr) { 109 struct ldb_index_pointer *tmp = ptr; 110 DLIST_REMOVE(ptr, ptr); 111 talloc_free(tmp); 112 } 113 114 return LDB_SUCCESS; 115 } 116 117 118 /* convert from the IDXPTR format to a ldb_message_element format */ 119 static int ltdb_convert_from_idxptr(struct ldb_module *module, struct ldb_message_element *el) 120 { 121 struct ldb_val val; 122 struct ldb_index_pointer *ptr, *tmp; 123 int i; 124 struct ldb_val *val2; 125 126 if (el->num_values != 1) { 127 return LDB_ERR_OPERATIONS_ERROR; 128 } 129 130 val = el->values[0]; 131 if (val.length != sizeof(void *)) { 132 return LDB_ERR_OPERATIONS_ERROR; 133 } 134 135 ptr = *(struct ldb_index_pointer **)val.data; 136 if (talloc_get_type(ptr, struct ldb_index_pointer) != ptr) { 137 return LDB_ERR_OPERATIONS_ERROR; 138 } 139 140 /* count the length of the list */ 141 for (i=0, tmp = ptr; tmp; tmp=tmp->next) { 142 i++; 143 } 144 145 /* allocate the new values array */ 146 val2 = talloc_realloc(NULL, el->values, struct ldb_val, i); 147 if (val2 == NULL) { 148 return LDB_ERR_OPERATIONS_ERROR; 149 } 150 el->values = val2; 151 el->num_values = i; 152 153 /* populate the values array */ 154 for (i=0, tmp = ptr; tmp; tmp=tmp->next, i++) { 155 el->values[i].length = tmp->value.length; 156 /* we need to over-allocate here as there are still some places 157 in ldb that rely on null termination. */ 158 el->values[i].data = talloc_size(el->values, tmp->value.length+1); 159 if (el->values[i].data == NULL) { 160 return LDB_ERR_OPERATIONS_ERROR; 161 } 162 memcpy(el->values[i].data, tmp->value.data, tmp->value.length); 163 el->values[i].data[tmp->value.length] = 0; 164 } 165 166 /* update the name */ 167 el->name = LTDB_IDX; 168 169 return LDB_SUCCESS; 170 } 171 172 173 /* convert to the IDXPTR format from a ldb_message_element format */ 174 static int ltdb_convert_to_idxptr(struct ldb_module *module, struct ldb_message_element *el) 175 { 176 struct ldb_index_pointer *ptr, *tmp; 177 int i; 178 struct ldb_val *val2; 179 void *data = ldb_module_get_private(module); 180 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 181 182 ptr = NULL; 183 184 for (i=0;i<el->num_values;i++) { 185 tmp = talloc(ltdb->idxptr, struct ldb_index_pointer); 186 if (tmp == NULL) { 187 return LDB_ERR_OPERATIONS_ERROR; 188 } 189 tmp->value = el->values[i]; 190 tmp->value.data = talloc_memdup(tmp, tmp->value.data, tmp->value.length); 191 if (tmp->value.data == NULL) { 192 return LDB_ERR_OPERATIONS_ERROR; 193 } 194 DLIST_ADD(ptr, tmp); 195 } 196 197 /* allocate the new values array */ 198 val2 = talloc_realloc(NULL, el->values, struct ldb_val, 1); 199 if (val2 == NULL) { 200 return LDB_ERR_OPERATIONS_ERROR; 201 } 202 el->values = val2; 203 el->num_values = 1; 204 205 el->values[0].data = talloc_memdup(el->values, &ptr, sizeof(ptr)); 206 el->values[0].length = sizeof(ptr); 207 208 /* update the name */ 209 el->name = LTDB_IDXPTR; 210 211 return LDB_SUCCESS; 212 } 213 46 /* we put a @IDXVERSION attribute on index entries. This 47 allows us to tell if it was written by an older version 48 */ 49 #define LTDB_INDEXING_VERSION 2 214 50 215 51 /* enable the idxptr mode when transactions start */ 216 52 int ltdb_index_transaction_start(struct ldb_module *module) 217 53 { 218 void *data = ldb_module_get_private(module); 219 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 220 ltdb->idxptr = talloc_zero(module, struct ltdb_idxptr); 54 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 55 ltdb->idxptr = talloc_zero(ltdb, struct ltdb_idxptr); 221 56 return LDB_SUCCESS; 222 57 } 223 58 224 /* 225 a wrapper around ltdb_search_dn1() which translates pointer based index records 226 and maps them into normal ldb message structures 227 */ 228 static int ltdb_search_dn1_index(struct ldb_module *module, 229 struct ldb_dn *dn, struct ldb_message *msg) 230 { 231 int ret, i; 59 /* compare two DN entries in a dn_list. Take account of possible 60 * differences in string termination */ 61 static int dn_list_cmp(const struct ldb_val *v1, const struct ldb_val *v2) 62 { 63 if (v1->length > v2->length && v1->data[v2->length] != 0) { 64 return -1; 65 } 66 if (v1->length < v2->length && v2->data[v1->length] != 0) { 67 return 1; 68 } 69 return strncmp((char *)v1->data, (char *)v2->data, v1->length); 70 } 71 72 73 /* 74 find a entry in a dn_list, using a ldb_val. Uses a case sensitive 75 comparison with the dn returns -1 if not found 76 */ 77 static int ltdb_dn_list_find_val(const struct dn_list *list, const struct ldb_val *v) 78 { 79 unsigned int i; 80 for (i=0; i<list->count; i++) { 81 if (dn_list_cmp(&list->dn[i], v) == 0) return i; 82 } 83 return -1; 84 } 85 86 /* 87 find a entry in a dn_list. Uses a case sensitive comparison with the dn 88 returns -1 if not found 89 */ 90 static int ltdb_dn_list_find_str(struct dn_list *list, const char *dn) 91 { 92 struct ldb_val v; 93 v.data = discard_const_p(unsigned char, dn); 94 v.length = strlen(dn); 95 return ltdb_dn_list_find_val(list, &v); 96 } 97 98 /* 99 this is effectively a cast function, but with lots of paranoia 100 checks and also copes with CPUs that are fussy about pointer 101 alignment 102 */ 103 static struct dn_list *ltdb_index_idxptr(struct ldb_module *module, TDB_DATA rec, bool check_parent) 104 { 105 struct dn_list *list; 106 if (rec.dsize != sizeof(void *)) { 107 ldb_asprintf_errstring(ldb_module_get_ctx(module), 108 "Bad data size for idxptr %u", (unsigned)rec.dsize); 109 return NULL; 110 } 111 /* note that we can't just use a cast here, as rec.dptr may 112 not be aligned sufficiently for a pointer. A cast would cause 113 platforms like some ARM CPUs to crash */ 114 memcpy(&list, rec.dptr, sizeof(void *)); 115 list = talloc_get_type(list, struct dn_list); 116 if (list == NULL) { 117 ldb_asprintf_errstring(ldb_module_get_ctx(module), 118 "Bad type '%s' for idxptr", 119 talloc_get_name(list)); 120 return NULL; 121 } 122 if (check_parent && list->dn && talloc_parent(list->dn) != list) { 123 ldb_asprintf_errstring(ldb_module_get_ctx(module), 124 "Bad parent '%s' for idxptr", 125 talloc_get_name(talloc_parent(list->dn))); 126 return NULL; 127 } 128 return list; 129 } 130 131 /* 132 return the @IDX list in an index entry for a dn as a 133 struct dn_list 134 */ 135 static int ltdb_dn_list_load(struct ldb_module *module, 136 struct ldb_dn *dn, struct dn_list *list) 137 { 138 struct ldb_message *msg; 139 int ret; 140 struct ldb_message_element *el; 141 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 142 TDB_DATA rec; 143 struct dn_list *list2; 144 TDB_DATA key; 145 146 list->dn = NULL; 147 list->count = 0; 148 149 /* see if we have any in-memory index entries */ 150 if (ltdb->idxptr == NULL || 151 ltdb->idxptr->itdb == NULL) { 152 goto normal_index; 153 } 154 155 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn)); 156 key.dsize = strlen((char *)key.dptr); 157 158 rec = tdb_fetch(ltdb->idxptr->itdb, key); 159 if (rec.dptr == NULL) { 160 goto normal_index; 161 } 162 163 /* we've found an in-memory index entry */ 164 list2 = ltdb_index_idxptr(module, rec, true); 165 if (list2 == NULL) { 166 free(rec.dptr); 167 return LDB_ERR_OPERATIONS_ERROR; 168 } 169 free(rec.dptr); 170 171 *list = *list2; 172 return LDB_SUCCESS; 173 174 normal_index: 175 msg = ldb_msg_new(list); 176 if (msg == NULL) { 177 return LDB_ERR_OPERATIONS_ERROR; 178 } 179 232 180 ret = ltdb_search_dn1(module, dn, msg); 233 181 if (ret != LDB_SUCCESS) { 182 talloc_free(msg); 234 183 return ret; 235 184 } 236 185 237 /* if this isn't a @INDEX record then don't munge it */ 238 if (strncmp(ldb_dn_get_linearized(msg->dn), LTDB_INDEX ":", strlen(LTDB_INDEX) + 1) != 0) { 239 return LDB_ERR_OPERATIONS_ERROR; 240 } 241 242 for (i=0;i<msg->num_elements;i++) { 243 struct ldb_message_element *el = &msg->elements[i]; 244 if (strcmp(el->name, LTDB_IDXPTR) == 0) { 245 ret = ltdb_convert_from_idxptr(module, el); 246 if (ret != LDB_SUCCESS) { 247 return ret; 248 } 249 } 250 } 251 252 return ret; 253 } 254 255 256 257 /* 258 fixup the idxptr for one DN 259 */ 260 static int ltdb_idxptr_fix_dn(struct ldb_module *module, const char *strdn) 261 { 262 struct ldb_context *ldb; 263 struct ldb_dn *dn; 264 struct ldb_message *msg = ldb_msg_new(module); 186 /* TODO: check indexing version number */ 187 188 el = ldb_msg_find_element(msg, LTDB_IDX); 189 if (!el) { 190 talloc_free(msg); 191 return LDB_SUCCESS; 192 } 193 194 /* we avoid copying the strings by stealing the list */ 195 list->dn = talloc_steal(list, el->values); 196 list->count = el->num_values; 197 198 return LDB_SUCCESS; 199 } 200 201 202 /* 203 save a dn_list into a full @IDX style record 204 */ 205 static int ltdb_dn_list_store_full(struct ldb_module *module, struct ldb_dn *dn, 206 struct dn_list *list) 207 { 208 struct ldb_message *msg; 265 209 int ret; 266 210 267 ldb = ldb_module_get_ctx(module); 268 269 dn = ldb_dn_new(msg, ldb, strdn); 270 if (ltdb_search_dn1_index(module, dn, msg) == LDB_SUCCESS) { 271 ret = ltdb_store(module, msg, TDB_REPLACE); 272 } 211 if (list->count == 0) { 212 ret = ltdb_delete_noindex(module, dn); 213 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 214 return LDB_SUCCESS; 215 } 216 return ret; 217 } 218 219 msg = ldb_msg_new(module); 220 if (!msg) { 221 return ldb_module_oom(module); 222 } 223 224 ret = ldb_msg_add_fmt(msg, LTDB_IDXVERSION, "%u", LTDB_INDEXING_VERSION); 225 if (ret != LDB_SUCCESS) { 226 talloc_free(msg); 227 return ldb_module_oom(module); 228 } 229 230 msg->dn = dn; 231 if (list->count > 0) { 232 struct ldb_message_element *el; 233 234 ret = ldb_msg_add_empty(msg, LTDB_IDX, LDB_FLAG_MOD_ADD, &el); 235 if (ret != LDB_SUCCESS) { 236 talloc_free(msg); 237 return ldb_module_oom(module); 238 } 239 el->values = list->dn; 240 el->num_values = list->count; 241 } 242 243 ret = ltdb_store(module, msg, TDB_REPLACE); 273 244 talloc_free(msg); 274 245 return ret; 275 246 } 276 247 248 /* 249 save a dn_list into the database, in either @IDX or internal format 250 */ 251 static int ltdb_dn_list_store(struct ldb_module *module, struct ldb_dn *dn, 252 struct dn_list *list) 253 { 254 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 255 TDB_DATA rec, key; 256 int ret; 257 struct dn_list *list2; 258 259 if (ltdb->idxptr == NULL) { 260 return ltdb_dn_list_store_full(module, dn, list); 261 } 262 263 if (ltdb->idxptr->itdb == NULL) { 264 ltdb->idxptr->itdb = tdb_open(NULL, 1000, TDB_INTERNAL, O_RDWR, 0); 265 if (ltdb->idxptr->itdb == NULL) { 266 return LDB_ERR_OPERATIONS_ERROR; 267 } 268 } 269 270 key.dptr = discard_const_p(unsigned char, ldb_dn_get_linearized(dn)); 271 key.dsize = strlen((char *)key.dptr); 272 273 rec = tdb_fetch(ltdb->idxptr->itdb, key); 274 if (rec.dptr != NULL) { 275 list2 = ltdb_index_idxptr(module, rec, false); 276 if (list2 == NULL) { 277 free(rec.dptr); 278 return LDB_ERR_OPERATIONS_ERROR; 279 } 280 free(rec.dptr); 281 list2->dn = talloc_steal(list2, list->dn); 282 list2->count = list->count; 283 return LDB_SUCCESS; 284 } 285 286 list2 = talloc(ltdb->idxptr, struct dn_list); 287 if (list2 == NULL) { 288 return LDB_ERR_OPERATIONS_ERROR; 289 } 290 list2->dn = talloc_steal(list2, list->dn); 291 list2->count = list->count; 292 293 rec.dptr = (uint8_t *)&list2; 294 rec.dsize = sizeof(void *); 295 296 ret = tdb_store(ltdb->idxptr->itdb, key, rec, TDB_INSERT); 297 if (ret == -1) { 298 return ltdb_err_map(tdb_error(ltdb->idxptr->itdb)); 299 } 300 return LDB_SUCCESS; 301 } 302 303 /* 304 traverse function for storing the in-memory index entries on disk 305 */ 306 static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) 307 { 308 struct ldb_module *module = state; 309 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 310 struct ldb_dn *dn; 311 struct ldb_context *ldb = ldb_module_get_ctx(module); 312 struct ldb_val v; 313 struct dn_list *list; 314 315 list = ltdb_index_idxptr(module, data, true); 316 if (list == NULL) { 317 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR; 318 return -1; 319 } 320 321 v.data = key.dptr; 322 v.length = strnlen((char *)key.dptr, key.dsize); 323 324 dn = ldb_dn_from_ldb_val(module, ldb, &v); 325 if (dn == NULL) { 326 ldb_asprintf_errstring(ldb, "Failed to parse index key %*.*s as an LDB DN", (int)v.length, (int)v.length, (const char *)v.data); 327 ltdb->idxptr->error = LDB_ERR_OPERATIONS_ERROR; 328 return -1; 329 } 330 331 ltdb->idxptr->error = ltdb_dn_list_store_full(module, dn, list); 332 talloc_free(dn); 333 if (ltdb->idxptr->error != 0) { 334 return -1; 335 } 336 return 0; 337 } 338 277 339 /* cleanup the idxptr mode when transaction commits */ 278 340 int ltdb_index_transaction_commit(struct ldb_module *module) 279 341 { 280 int i; 281 void *data = ldb_module_get_private(module); 282 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 283 284 /* fix all the DNs that we have modified */ 285 if (ltdb->idxptr) { 286 for (i=0;i<ltdb->idxptr->num_dns;i++) { 287 ltdb_idxptr_fix_dn(module, ltdb->idxptr->dn_list[i]); 288 } 289 290 if (ltdb->idxptr->repack) { 291 tdb_repack(ltdb->tdb); 292 } 293 } 294 342 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 343 int ret; 344 345 struct ldb_context *ldb = ldb_module_get_ctx(module); 346 347 ldb_reset_err_string(ldb); 348 349 if (ltdb->idxptr->itdb) { 350 tdb_traverse(ltdb->idxptr->itdb, ltdb_index_traverse_store, module); 351 tdb_close(ltdb->idxptr->itdb); 352 } 353 354 ret = ltdb->idxptr->error; 355 if (ret != LDB_SUCCESS) { 356 if (!ldb_errstring(ldb)) { 357 ldb_set_errstring(ldb, ldb_strerror(ret)); 358 } 359 ldb_asprintf_errstring(ldb, "Failed to store index records in transaction commit: %s", ldb_errstring(ldb)); 360 } 361 362 talloc_free(ltdb->idxptr); 363 ltdb->idxptr = NULL; 364 return ret; 365 } 366 367 /* cleanup the idxptr mode when transaction cancels */ 368 int ltdb_index_transaction_cancel(struct ldb_module *module) 369 { 370 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 371 if (ltdb->idxptr && ltdb->idxptr->itdb) { 372 tdb_close(ltdb->idxptr->itdb); 373 } 295 374 talloc_free(ltdb->idxptr); 296 375 ltdb->idxptr = NULL; … … 298 377 } 299 378 300 /* cleanup the idxptr mode when transaction cancels */301 int ltdb_index_transaction_cancel(struct ldb_module *module)302 {303 void *data = ldb_module_get_private(module);304 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);305 talloc_free(ltdb->idxptr);306 ltdb->idxptr = NULL;307 return LDB_SUCCESS;308 }309 310 311 312 /* a wrapper around ltdb_store() for the index code which313 stores in IDXPTR format when idxptr mode is enabled314 315 WARNING: This modifies the msg which is passed in316 */317 int ltdb_store_idxptr(struct ldb_module *module, const struct ldb_message *msg, int flgs)318 {319 void *data = ldb_module_get_private(module);320 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);321 int ret;322 323 if (ltdb->idxptr) {324 int i;325 struct ldb_message *msg2 = ldb_msg_new(module);326 327 /* free any old pointer */328 ret = ltdb_search_dn1(module, msg->dn, msg2);329 if (ret == 0) {330 for (i=0;i<msg2->num_elements;i++) {331 struct ldb_message_element *el = &msg2->elements[i];332 if (strcmp(el->name, LTDB_IDXPTR) == 0) {333 ret = ltdb_free_idxptr(module, el);334 if (ret != LDB_SUCCESS) {335 return ret;336 }337 }338 }339 }340 talloc_free(msg2);341 342 for (i=0;i<msg->num_elements;i++) {343 struct ldb_message_element *el = &msg->elements[i];344 if (strcmp(el->name, LTDB_IDX) == 0) {345 ret = ltdb_convert_to_idxptr(module, el);346 if (ret != LDB_SUCCESS) {347 return ret;348 }349 }350 }351 352 if (ltdb_idxptr_add(module, msg) != 0) {353 return LDB_ERR_OPERATIONS_ERROR;354 }355 }356 357 ret = ltdb_store(module, msg, flgs);358 return ret;359 }360 361 362 /*363 find an element in a list, using the given comparison function and364 assuming that the list is already sorted using comp_fn365 366 return -1 if not found, or the index of the first occurance of needle if found367 */368 static int ldb_list_find(const void *needle,369 const void *base, size_t nmemb, size_t size,370 comparison_fn_t comp_fn)371 {372 const char *base_p = (const char *)base;373 size_t min_i, max_i, test_i;374 375 if (nmemb == 0) {376 return -1;377 }378 379 min_i = 0;380 max_i = nmemb-1;381 382 while (min_i < max_i) {383 int r;384 385 test_i = (min_i + max_i) / 2;386 /* the following cast looks strange, but is387 correct. The key to understanding it is that base_p388 is a pointer to an array of pointers, so we have to389 dereference it after casting to void **. The strange390 const in the middle gives us the right type of pointer391 after the dereference (tridge) */392 r = comp_fn(needle, *(void * const *)(base_p + (size * test_i)));393 if (r == 0) {394 /* scan back for first element */395 while (test_i > 0 &&396 comp_fn(needle, *(void * const *)(base_p + (size * (test_i-1)))) == 0) {397 test_i--;398 }399 return test_i;400 }401 if (r < 0) {402 if (test_i == 0) {403 return -1;404 }405 max_i = test_i - 1;406 }407 if (r > 0) {408 min_i = test_i + 1;409 }410 }411 412 if (comp_fn(needle, *(void * const *)(base_p + (size * min_i))) == 0) {413 return min_i;414 }415 416 return -1;417 }418 419 struct dn_list {420 unsigned int count;421 char **dn;422 };423 379 424 380 /* 425 381 return the dn key to be used for an index 426 caller frees382 the caller is responsible for freeing 427 383 */ 428 384 static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb, … … 458 414 if (ldb_should_b64_encode(ldb, &v)) { 459 415 char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length); 460 if (!vstr) return NULL; 416 if (!vstr) { 417 talloc_free(attr_folded); 418 return NULL; 419 } 461 420 ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr); 462 421 talloc_free(vstr); … … 476 435 see if a attribute value is in the list of indexed attributes 477 436 */ 478 static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, 479 unsigned int *v_idx, const char *key) 480 { 481 unsigned int i, j; 482 for (i=0;i<msg->num_elements;i++) { 483 if (ldb_attr_cmp(msg->elements[i].name, key) == 0) { 484 const struct ldb_message_element *el = &msg->elements[i]; 485 486 if (attr == NULL) { 487 /* in this case we are just looking to see if key is present, 488 we are not spearching for a specific index */ 489 return 0; 490 } 491 492 for (j=0;j<el->num_values;j++) { 493 if (ldb_attr_cmp((char *)el->values[j].data, attr) == 0) { 494 if (v_idx) { 495 *v_idx = j; 496 } 497 return i; 498 } 499 } 500 } 501 } 502 return -1; 503 } 504 505 /* used in sorting dn lists */ 506 static int list_cmp(const char **s1, const char **s2) 507 { 508 return strcmp(*s1, *s2); 509 } 510 511 /* 512 return a list of dn's that might match a simple indexed search or 437 static bool ltdb_is_indexed(const struct ldb_message *index_list, const char *attr) 438 { 439 unsigned int i; 440 struct ldb_message_element *el; 441 442 el = ldb_msg_find_element(index_list, LTDB_IDXATTR); 443 if (el == NULL) { 444 return false; 445 } 446 447 /* TODO: this is too expensive! At least use a binary search */ 448 for (i=0; i<el->num_values; i++) { 449 if (ldb_attr_cmp((char *)el->values[i].data, attr) == 0) { 450 return true; 451 } 452 } 453 return false; 454 } 455 456 /* 457 in the following logic functions, the return value is treated as 458 follows: 459 460 LDB_SUCCESS: we found some matching index values 461 462 LDB_ERR_NO_SUCH_OBJECT: we know for sure that no object matches 463 464 LDB_ERR_OPERATIONS_ERROR: indexing could not answer the call, 465 we'll need a full search 466 */ 467 468 /* 469 return a list of dn's that might match a simple indexed search (an 470 equality search only) 513 471 */ 514 472 static int ltdb_index_dn_simple(struct ldb_module *module, … … 520 478 struct ldb_dn *dn; 521 479 int ret; 522 unsigned int i, j;523 struct ldb_message *msg;524 480 525 481 ldb = ldb_module_get_ctx(module); … … 530 486 /* if the attribute isn't in the list of indexed attributes then 531 487 this node needs a full search */ 532 if ( ldb_msg_find_idx(index_list, tree->u.equality.attr, NULL, LTDB_IDXATTR) == -1) {488 if (!ltdb_is_indexed(index_list, tree->u.equality.attr)) { 533 489 return LDB_ERR_OPERATIONS_ERROR; 534 490 } … … 539 495 if (!dn) return LDB_ERR_OPERATIONS_ERROR; 540 496 541 msg = talloc(list, struct ldb_message); 542 if (msg == NULL) { 543 return LDB_ERR_OPERATIONS_ERROR; 544 } 545 546 ret = ltdb_search_dn1_index(module, dn, msg); 497 ret = ltdb_dn_list_load(module, dn, list); 547 498 talloc_free(dn); 548 if (ret != LDB_SUCCESS) { 549 return ret; 550 } 551 552 for (i=0;i<msg->num_elements;i++) { 553 struct ldb_message_element *el; 554 555 if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) { 556 continue; 557 } 558 559 el = &msg->elements[i]; 560 561 list->dn = talloc_array(list, char *, el->num_values); 562 if (!list->dn) { 563 talloc_free(msg); 564 return LDB_ERR_OPERATIONS_ERROR; 565 } 566 567 for (j=0;j<el->num_values;j++) { 568 list->dn[list->count] = 569 talloc_strdup(list->dn, (char *)el->values[j].data); 570 if (!list->dn[list->count]) { 571 talloc_free(msg); 572 return LDB_ERR_OPERATIONS_ERROR; 573 } 574 list->count++; 575 } 576 } 577 578 talloc_free(msg); 579 580 if (list->count > 1) { 581 qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t) list_cmp); 582 } 583 584 return LDB_SUCCESS; 585 } 586 587 588 static int list_union(struct ldb_context *, struct dn_list *, const struct dn_list *); 499 return ret; 500 } 501 502 503 static bool list_union(struct ldb_context *, struct dn_list *, const struct dn_list *); 589 504 590 505 /* … … 596 511 struct dn_list *list) 597 512 { 598 struct ldb_context *ldb;599 ldb = ldb_module_get_ctx(module);600 601 513 if (ldb_attr_dn(tree->u.equality.attr) == 0) { 602 list->dn = talloc_array(list, char *, 1);514 list->dn = talloc_array(list, struct ldb_val, 1); 603 515 if (list->dn == NULL) { 604 ldb_ oom(ldb);516 ldb_module_oom(module); 605 517 return LDB_ERR_OPERATIONS_ERROR; 606 518 } 607 list->dn[0] = talloc_strdup(list->dn, (char *)tree->u.equality.value.data); 608 if (list->dn[0] == NULL) { 609 ldb_oom(ldb); 610 return LDB_ERR_OPERATIONS_ERROR; 611 } 519 list->dn[0] = tree->u.equality.value; 612 520 list->count = 1; 613 521 return LDB_SUCCESS; … … 620 528 list intersection 621 529 list = list & list2 622 relies on the lists being sorted 623 */ 624 static int list_intersect(struct ldb_context *ldb, 625 struct dn_list *list, const struct dn_list *list2) 530 */ 531 static bool list_intersect(struct ldb_context *ldb, 532 struct dn_list *list, const struct dn_list *list2) 626 533 { 627 534 struct dn_list *list3; 628 535 unsigned int i; 629 536 630 if (list->count == 0 || list2->count == 0) {537 if (list->count == 0) { 631 538 /* 0 & X == 0 */ 632 return LDB_ERR_NO_SUCH_OBJECT; 633 } 634 635 list3 = talloc(ldb, struct dn_list); 539 return true; 540 } 541 if (list2->count == 0) { 542 /* X & 0 == 0 */ 543 list->count = 0; 544 list->dn = NULL; 545 return true; 546 } 547 548 /* the indexing code is allowed to return a longer list than 549 what really matches, as all results are filtered by the 550 full expression at the end - this shortcut avoids a lot of 551 work in some cases */ 552 if (list->count < 2 && list2->count > 10) { 553 return true; 554 } 555 if (list2->count < 2 && list->count > 10) { 556 list->count = list2->count; 557 list->dn = list2->dn; 558 /* note that list2 may not be the parent of list2->dn, 559 as list2->dn may be owned by ltdb->idxptr. In that 560 case we expect this reparent call to fail, which is 561 OK */ 562 talloc_reparent(list2, list, list2->dn); 563 return true; 564 } 565 566 list3 = talloc_zero(list, struct dn_list); 636 567 if (list3 == NULL) { 637 return LDB_ERR_OPERATIONS_ERROR;638 } 639 640 list3->dn = talloc_array(list3, char *, list->count);568 return false; 569 } 570 571 list3->dn = talloc_array(list3, struct ldb_val, list->count); 641 572 if (!list3->dn) { 642 573 talloc_free(list3); 643 return LDB_ERR_OPERATIONS_ERROR;574 return false; 644 575 } 645 576 list3->count = 0; 646 577 647 578 for (i=0;i<list->count;i++) { 648 if (ldb_list_find(list->dn[i], list2->dn, list2->count, 649 sizeof(char *), (comparison_fn_t)strcmp) != -1) { 650 list3->dn[list3->count] = talloc_move(list3->dn, &list->dn[i]); 579 if (ltdb_dn_list_find_val(list2, &list->dn[i]) != -1) { 580 list3->dn[list3->count] = list->dn[i]; 651 581 list3->count++; 652 } else { 653 talloc_free(list->dn[i]); 654 } 655 } 656 657 talloc_free(list->dn); 658 list->dn = talloc_move(list, &list3->dn); 582 } 583 } 584 585 list->dn = talloc_steal(list, list3->dn); 659 586 list->count = list3->count; 660 587 talloc_free(list3); 661 588 662 return LDB_ERR_NO_SUCH_OBJECT;589 return true; 663 590 } 664 591 … … 667 594 list union 668 595 list = list | list2 669 relies on the lists being sorted 670 */ 671 static int list_union(struct ldb_context *ldb, 672 struct dn_list *list, const struct dn_list *list2) 673 { 674 unsigned int i; 675 char **d; 676 unsigned int count = list->count; 677 678 if (list->count == 0 && list2->count == 0) { 679 /* 0 | 0 == 0 */ 680 return LDB_ERR_NO_SUCH_OBJECT; 681 } 682 683 d = talloc_realloc(list, list->dn, char *, list->count + list2->count); 684 if (!d) { 685 return LDB_ERR_OPERATIONS_ERROR; 686 } 687 list->dn = d; 688 689 for (i=0;i<list2->count;i++) { 690 if (ldb_list_find(list2->dn[i], list->dn, count, 691 sizeof(char *), (comparison_fn_t)strcmp) == -1) { 692 list->dn[list->count] = talloc_strdup(list->dn, list2->dn[i]); 693 if (!list->dn[list->count]) { 694 return LDB_ERR_OPERATIONS_ERROR; 695 } 696 list->count++; 697 } 698 } 699 700 if (list->count != count) { 701 qsort(list->dn, list->count, sizeof(char *), (comparison_fn_t)list_cmp); 702 } 703 704 return LDB_ERR_NO_SUCH_OBJECT; 596 */ 597 static bool list_union(struct ldb_context *ldb, 598 struct dn_list *list, const struct dn_list *list2) 599 { 600 struct ldb_val *dn3; 601 602 if (list2->count == 0) { 603 /* X | 0 == X */ 604 return true; 605 } 606 607 if (list->count == 0) { 608 /* 0 | X == X */ 609 list->count = list2->count; 610 list->dn = list2->dn; 611 /* note that list2 may not be the parent of list2->dn, 612 as list2->dn may be owned by ltdb->idxptr. In that 613 case we expect this reparent call to fail, which is 614 OK */ 615 talloc_reparent(list2, list, list2->dn); 616 return true; 617 } 618 619 dn3 = talloc_array(list, struct ldb_val, list->count + list2->count); 620 if (!dn3) { 621 ldb_oom(ldb); 622 return false; 623 } 624 625 /* we allow for duplicates here, and get rid of them later */ 626 memcpy(dn3, list->dn, sizeof(list->dn[0])*list->count); 627 memcpy(dn3+list->count, list2->dn, sizeof(list2->dn[0])*list2->count); 628 629 list->dn = dn3; 630 list->count += list2->count; 631 632 return true; 705 633 } 706 634 … … 712 640 713 641 /* 714 OR two index results642 process an OR list (a union) 715 643 */ 716 644 static int ltdb_index_dn_or(struct ldb_module *module, … … 721 649 struct ldb_context *ldb; 722 650 unsigned int i; 723 int ret;724 651 725 652 ldb = ldb_module_get_ctx(module); 726 653 727 ret = LDB_ERR_OPERATIONS_ERROR;728 654 list->dn = NULL; 729 655 list->count = 0; 730 656 731 for (i=0; i<tree->u.list.num_elements;i++) {657 for (i=0; i<tree->u.list.num_elements; i++) { 732 658 struct dn_list *list2; 733 int v;734 735 list2 = talloc (module, struct dn_list);659 int ret; 660 661 list2 = talloc_zero(list, struct dn_list); 736 662 if (list2 == NULL) { 737 663 return LDB_ERR_OPERATIONS_ERROR; 738 664 } 739 665 740 v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2); 741 742 if (v == LDB_ERR_NO_SUCH_OBJECT) { 743 /* 0 || X == X */ 744 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { 745 ret = v; 746 } 666 ret = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2); 667 668 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 669 /* X || 0 == X */ 747 670 talloc_free(list2); 748 671 continue; 749 672 } 750 673 751 if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) { 752 /* 1 || X == 1 */ 753 talloc_free(list->dn); 674 if (ret != LDB_SUCCESS) { 675 /* X || * == * */ 754 676 talloc_free(list2); 755 return v; 756 } 757 758 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { 759 ret = LDB_SUCCESS; 760 list->dn = talloc_move(list, &list2->dn); 761 list->count = list2->count; 762 } else { 763 if (list_union(ldb, list, list2) == -1) { 764 talloc_free(list2); 765 return LDB_ERR_OPERATIONS_ERROR; 766 } 767 ret = LDB_SUCCESS; 768 } 769 talloc_free(list2); 677 return ret; 678 } 679 680 if (!list_union(ldb, list, list2)) { 681 talloc_free(list2); 682 return LDB_ERR_OPERATIONS_ERROR; 683 } 770 684 } 771 685 … … 774 688 } 775 689 776 return ret;690 return LDB_SUCCESS; 777 691 } 778 692 … … 810 724 811 725 /* 812 AND two index results726 process an AND expression (intersection) 813 727 */ 814 728 static int ltdb_index_dn_and(struct ldb_module *module, … … 819 733 struct ldb_context *ldb; 820 734 unsigned int i; 821 int ret, pass;735 bool found; 822 736 823 737 ldb = ldb_module_get_ctx(module); 824 738 825 ret = LDB_ERR_OPERATIONS_ERROR;826 739 list->dn = NULL; 827 740 list->count = 0; 828 741 829 for (pass=0;pass<=1;pass++) { 830 /* in the first pass we only look for unique simple 831 equality tests, in the hope of avoiding having to look 832 at any others */ 833 bool only_unique = pass==0?true:false; 834 835 for (i=0;i<tree->u.list.num_elements;i++) { 836 struct dn_list *list2; 837 int v; 838 bool is_unique = false; 839 const struct ldb_parse_tree *subtree = tree->u.list.elements[i]; 840 841 if (subtree->operation == LDB_OP_EQUALITY && 842 ltdb_index_unique(ldb, subtree->u.equality.attr)) { 843 is_unique = true; 844 } 845 if (is_unique != only_unique) continue; 742 /* in the first pass we only look for unique simple 743 equality tests, in the hope of avoiding having to look 744 at any others */ 745 for (i=0; i<tree->u.list.num_elements; i++) { 746 const struct ldb_parse_tree *subtree = tree->u.list.elements[i]; 747 int ret; 748 749 if (subtree->operation != LDB_OP_EQUALITY || 750 !ltdb_index_unique(ldb, subtree->u.equality.attr)) { 751 continue; 752 } 753 754 ret = ltdb_index_dn(module, subtree, index_list, list); 755 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 756 /* 0 && X == 0 */ 757 return LDB_ERR_NO_SUCH_OBJECT; 758 } 759 if (ret == LDB_SUCCESS) { 760 /* a unique index match means we can 761 * stop. Note that we don't care if we return 762 * a few too many objects, due to later 763 * filtering */ 764 return LDB_SUCCESS; 765 } 766 } 767 768 /* now do a full intersection */ 769 found = false; 770 771 for (i=0; i<tree->u.list.num_elements; i++) { 772 const struct ldb_parse_tree *subtree = tree->u.list.elements[i]; 773 struct dn_list *list2; 774 int ret; 775 776 list2 = talloc_zero(list, struct dn_list); 777 if (list2 == NULL) { 778 return ldb_module_oom(module); 779 } 846 780 847 list2 = talloc(module, struct dn_list); 848 if (list2 == NULL) { 849 return LDB_ERR_OPERATIONS_ERROR; 850 } 781 ret = ltdb_index_dn(module, subtree, index_list, list2); 782 783 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 784 /* X && 0 == 0 */ 785 list->dn = NULL; 786 list->count = 0; 787 talloc_free(list2); 788 return LDB_ERR_NO_SUCH_OBJECT; 789 } 790 791 if (ret != LDB_SUCCESS) { 792 /* this didn't adding anything */ 793 talloc_free(list2); 794 continue; 795 } 796 797 if (!found) { 798 talloc_reparent(list2, list, list->dn); 799 list->dn = list2->dn; 800 list->count = list2->count; 801 found = true; 802 } else if (!list_intersect(ldb, list, list2)) { 803 talloc_free(list2); 804 return LDB_ERR_OPERATIONS_ERROR; 805 } 851 806 852 v = ltdb_index_dn(module, subtree, index_list, list2); 853 854 if (v == LDB_ERR_NO_SUCH_OBJECT) { 855 /* 0 && X == 0 */ 856 talloc_free(list->dn); 857 talloc_free(list2); 858 return LDB_ERR_NO_SUCH_OBJECT; 859 } 807 if (list->count == 0) { 808 list->dn = NULL; 809 return LDB_ERR_NO_SUCH_OBJECT; 810 } 860 811 861 if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) { 862 talloc_free(list2); 863 continue; 864 } 865 866 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { 867 ret = LDB_SUCCESS; 868 talloc_free(list->dn); 869 list->dn = talloc_move(list, &list2->dn); 870 list->count = list2->count; 871 } else { 872 if (list_intersect(ldb, list, list2) == -1) { 873 talloc_free(list2); 874 return LDB_ERR_OPERATIONS_ERROR; 875 } 876 } 877 878 talloc_free(list2); 879 880 if (list->count == 0) { 881 talloc_free(list->dn); 882 return LDB_ERR_NO_SUCH_OBJECT; 883 } 884 885 if (list->count == 1) { 886 /* it isn't worth loading the next part of the tree */ 887 return ret; 888 } 812 if (list->count < 2) { 813 /* it isn't worth loading the next part of the tree */ 814 return LDB_SUCCESS; 889 815 } 890 816 } 891 return ret; 817 818 if (!found) { 819 /* none of the attributes were indexed */ 820 return LDB_ERR_OPERATIONS_ERROR; 821 } 822 823 return LDB_SUCCESS; 892 824 } 893 825 894 826 /* 895 AND index results and ONE level special index827 return a list of matching objects using a one-level index 896 828 */ 897 829 static int ltdb_index_dn_one(struct ldb_module *module, … … 900 832 { 901 833 struct ldb_context *ldb; 902 struct dn_list *list2;903 struct ldb_message *msg;904 834 struct ldb_dn *key; 905 835 struct ldb_val val; 906 unsigned int i, j;907 836 int ret; 908 837 909 838 ldb = ldb_module_get_ctx(module); 910 839 911 list2 = talloc_zero(module, struct dn_list); 912 if (list2 == NULL) { 913 return LDB_ERR_OPERATIONS_ERROR; 914 } 915 916 /* the attribute is indexed. Pull the list of DNs that match the 917 search criterion */ 840 /* work out the index key from the parent DN */ 918 841 val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn)); 919 842 val.length = strlen((char *)val.data); 920 843 key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL); 921 844 if (!key) { 922 talloc_free(list2); 923 return LDB_ERR_OPERATIONS_ERROR; 924 } 925 926 msg = talloc(list2, struct ldb_message); 927 if (msg == NULL) { 928 talloc_free(list2); 929 return LDB_ERR_OPERATIONS_ERROR; 930 } 931 932 ret = ltdb_search_dn1_index(module, key, msg); 845 ldb_oom(ldb); 846 return LDB_ERR_OPERATIONS_ERROR; 847 } 848 849 ret = ltdb_dn_list_load(module, key, list); 933 850 talloc_free(key); 934 851 if (ret != LDB_SUCCESS) { … … 936 853 } 937 854 938 for (i = 0; i < msg->num_elements; i++) { 939 struct ldb_message_element *el; 940 941 if (strcmp(msg->elements[i].name, LTDB_IDX) != 0) { 942 continue; 943 } 944 945 el = &msg->elements[i]; 946 947 list2->dn = talloc_array(list2, char *, el->num_values); 948 if (!list2->dn) { 949 talloc_free(list2); 950 return LDB_ERR_OPERATIONS_ERROR; 951 } 952 953 for (j = 0; j < el->num_values; j++) { 954 list2->dn[list2->count] = talloc_strdup(list2->dn, (char *)el->values[j].data); 955 if (!list2->dn[list2->count]) { 956 talloc_free(list2); 957 return LDB_ERR_OPERATIONS_ERROR; 958 } 959 list2->count++; 960 } 961 } 962 963 if (list2->count == 0) { 964 talloc_free(list2); 855 if (list->count == 0) { 965 856 return LDB_ERR_NO_SUCH_OBJECT; 966 857 } 967 968 if (list2->count > 1) {969 qsort(list2->dn, list2->count, sizeof(char *), (comparison_fn_t) list_cmp);970 }971 972 if (list->count > 0) {973 if (list_intersect(ldb, list, list2) == -1) {974 talloc_free(list2);975 return LDB_ERR_OPERATIONS_ERROR;976 }977 978 if (list->count == 0) {979 talloc_free(list->dn);980 talloc_free(list2);981 return LDB_ERR_NO_SUCH_OBJECT;982 }983 } else {984 list->dn = talloc_move(list, &list2->dn);985 list->count = list2->count;986 }987 988 talloc_free(list2);989 858 990 859 return LDB_SUCCESS; … … 1050 919 struct ldb_dn *dn; 1051 920 int ret; 921 bool matched; 1052 922 1053 923 msg = ldb_msg_new(ac); … … 1056 926 } 1057 927 1058 dn = ldb_dn_ new(msg, ldb,dn_list->dn[i]);928 dn = ldb_dn_from_ldb_val(msg, ldb, &dn_list->dn[i]); 1059 929 if (dn == NULL) { 1060 930 talloc_free(msg); … … 1076 946 } 1077 947 1078 if (!ldb_match_msg(ldb, msg, 1079 ac->tree, ac->base, ac->scope)) { 948 ret = ldb_match_msg_error(ldb, msg, 949 ac->tree, ac->base, ac->scope, &matched); 950 if (ret != LDB_SUCCESS) { 951 talloc_free(msg); 952 return ret; 953 } 954 if (!matched) { 1080 955 talloc_free(msg); 1081 956 continue; … … 1092 967 ret = ldb_module_send_entry(ac->req, msg, NULL); 1093 968 if (ret != LDB_SUCCESS) { 969 /* Regardless of success or failure, the msg 970 * is the callbacks responsiblity, and should 971 * not be talloc_free()'ed */ 1094 972 ac->request_terminated = true; 1095 973 return ret; … … 1100 978 1101 979 return LDB_SUCCESS; 980 } 981 982 /* 983 remove any duplicated entries in a indexed result 984 */ 985 static void ltdb_dn_list_remove_duplicates(struct dn_list *list) 986 { 987 unsigned int i, new_count; 988 989 if (list->count < 2) { 990 return; 991 } 992 993 TYPESAFE_QSORT(list->dn, list->count, dn_list_cmp); 994 995 new_count = 1; 996 for (i=1; i<list->count; i++) { 997 if (dn_list_cmp(&list->dn[i], &list->dn[new_count-1]) != 0) { 998 if (new_count != i) { 999 list->dn[new_count] = list->dn[i]; 1000 } 1001 new_count++; 1002 } 1003 } 1004 1005 list->count = new_count; 1102 1006 } 1103 1007 … … 1109 1013 int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count) 1110 1014 { 1111 struct ldb_context *ldb; 1112 void *data = ldb_module_get_private(ac->module); 1113 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 1015 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(ac->module), struct ltdb_private); 1114 1016 struct dn_list *dn_list; 1115 int ret, idxattr, idxone; 1116 1117 ldb = ldb_module_get_ctx(ac->module); 1118 1119 idxattr = idxone = 0; 1120 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXATTR); 1121 if (ret == 0 ) { 1122 idxattr = 1; 1123 } 1124 1125 /* We do one level indexing only if requested */ 1126 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE); 1127 if (ret == 0 ) { 1128 idxone = 1; 1129 } 1130 1131 if ((ac->scope == LDB_SCOPE_ONELEVEL && (idxattr+idxone == 0)) || 1132 (ac->scope == LDB_SCOPE_SUBTREE && idxattr == 0)) { 1133 /* no indexes? must do full search */ 1134 return LDB_ERR_OPERATIONS_ERROR; 1135 } 1136 1137 ret = LDB_ERR_OPERATIONS_ERROR; 1017 int ret; 1018 1019 /* see if indexing is enabled */ 1020 if (!ltdb->cache->attribute_indexes && 1021 !ltdb->cache->one_level_indexes && 1022 ac->scope != LDB_SCOPE_BASE) { 1023 /* fallback to a full search */ 1024 return LDB_ERR_OPERATIONS_ERROR; 1025 } 1138 1026 1139 1027 dn_list = talloc_zero(ac, struct dn_list); 1140 1028 if (dn_list == NULL) { 1141 return LDB_ERR_OPERATIONS_ERROR;1142 } 1143 1144 if (ac->scope == LDB_SCOPE_BASE) {1145 /* with BASE searches only one DN can match */1146 dn_list->dn = talloc_array(dn_list, char *, 1);1029 return ldb_module_oom(ac->module); 1030 } 1031 1032 switch (ac->scope) { 1033 case LDB_SCOPE_BASE: 1034 dn_list->dn = talloc_array(dn_list, struct ldb_val, 1); 1147 1035 if (dn_list->dn == NULL) { 1148 ldb_oom(ldb); 1036 talloc_free(dn_list); 1037 return ldb_module_oom(ac->module); 1038 } 1039 dn_list->dn[0].data = discard_const_p(unsigned char, ldb_dn_get_linearized(ac->base)); 1040 if (dn_list->dn[0].data == NULL) { 1041 talloc_free(dn_list); 1042 return ldb_module_oom(ac->module); 1043 } 1044 dn_list->dn[0].length = strlen((char *)dn_list->dn[0].data); 1045 dn_list->count = 1; 1046 break; 1047 1048 case LDB_SCOPE_ONELEVEL: 1049 if (!ltdb->cache->one_level_indexes) { 1050 talloc_free(dn_list); 1149 1051 return LDB_ERR_OPERATIONS_ERROR; 1150 1052 } 1151 dn_list->dn[0] = ldb_dn_alloc_linearized(dn_list, ac->base); 1152 if (dn_list->dn[0] == NULL) { 1153 ldb_oom(ldb); 1053 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list); 1054 if (ret != LDB_SUCCESS) { 1055 talloc_free(dn_list); 1056 return ret; 1057 } 1058 break; 1059 1060 case LDB_SCOPE_SUBTREE: 1061 case LDB_SCOPE_DEFAULT: 1062 if (!ltdb->cache->attribute_indexes) { 1063 talloc_free(dn_list); 1154 1064 return LDB_ERR_OPERATIONS_ERROR; 1155 1065 } 1156 dn_list->count = 1;1157 ret = LDB_SUCCESS;1158 }1159 1160 if (ac->scope != LDB_SCOPE_BASE && idxattr == 1) {1161 1066 ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list); 1162 } 1163 1164 if (ret == LDB_ERR_OPERATIONS_ERROR && 1165 ac->scope == LDB_SCOPE_ONELEVEL && idxone == 1) { 1166 ret = ltdb_index_dn_one(ac->module, ac->base, dn_list); 1167 } 1168 1169 if (ret == LDB_SUCCESS) { 1170 /* we've got a candidate list - now filter by the full tree 1171 and extract the needed attributes */ 1172 ret = ltdb_index_filter(dn_list, ac, match_count); 1173 } 1174 1067 if (ret != LDB_SUCCESS) { 1068 talloc_free(dn_list); 1069 return ret; 1070 } 1071 ltdb_dn_list_remove_duplicates(dn_list); 1072 break; 1073 } 1074 1075 ret = ltdb_index_filter(dn_list, ac, match_count); 1175 1076 talloc_free(dn_list); 1176 1177 1077 return ret; 1178 }1179 1180 /*1181 add a index element where this is the first indexed DN for this value1182 */1183 static int ltdb_index_add1_new(struct ldb_context *ldb,1184 struct ldb_message *msg,1185 const char *dn)1186 {1187 struct ldb_message_element *el;1188 1189 /* add another entry */1190 el = talloc_realloc(msg, msg->elements,1191 struct ldb_message_element, msg->num_elements+1);1192 if (!el) {1193 return LDB_ERR_OPERATIONS_ERROR;1194 }1195 1196 msg->elements = el;1197 msg->elements[msg->num_elements].name = talloc_strdup(msg->elements, LTDB_IDX);1198 if (!msg->elements[msg->num_elements].name) {1199 return LDB_ERR_OPERATIONS_ERROR;1200 }1201 msg->elements[msg->num_elements].num_values = 0;1202 msg->elements[msg->num_elements].values = talloc(msg->elements, struct ldb_val);1203 if (!msg->elements[msg->num_elements].values) {1204 return LDB_ERR_OPERATIONS_ERROR;1205 }1206 msg->elements[msg->num_elements].values[0].length = strlen(dn);1207 msg->elements[msg->num_elements].values[0].data = discard_const_p(uint8_t, dn);1208 msg->elements[msg->num_elements].num_values = 1;1209 msg->num_elements++;1210 1211 return LDB_SUCCESS;1212 }1213 1214 1215 /*1216 add a index element where this is not the first indexed DN for this1217 value1218 */1219 static int ltdb_index_add1_add(struct ldb_context *ldb,1220 struct ldb_message *msg,1221 int idx,1222 const char *dn,1223 const struct ldb_schema_attribute *a)1224 {1225 struct ldb_val *v2;1226 unsigned int i;1227 1228 /* for multi-valued attributes we can end up with repeats */1229 for (i=0;i<msg->elements[idx].num_values;i++) {1230 if (strcmp(dn, (char *)msg->elements[idx].values[i].data) == 0) {1231 return LDB_SUCCESS;1232 }1233 }1234 1235 if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {1236 return LDB_ERR_ENTRY_ALREADY_EXISTS;1237 }1238 1239 v2 = talloc_realloc(msg->elements, msg->elements[idx].values,1240 struct ldb_val,1241 msg->elements[idx].num_values+1);1242 if (!v2) {1243 return LDB_ERR_OPERATIONS_ERROR;1244 }1245 msg->elements[idx].values = v2;1246 1247 msg->elements[idx].values[msg->elements[idx].num_values].length = strlen(dn);1248 msg->elements[idx].values[msg->elements[idx].num_values].data = discard_const_p(uint8_t, dn);1249 msg->elements[idx].num_values++;1250 1251 return LDB_SUCCESS;1252 1078 } 1253 1079 … … 1259 1085 { 1260 1086 struct ldb_context *ldb; 1261 struct ldb_message *msg;1262 1087 struct ldb_dn *dn_key; 1263 1088 int ret; 1264 unsigned int i;1265 1089 const struct ldb_schema_attribute *a; 1090 struct dn_list *list; 1091 unsigned alloc_len; 1266 1092 1267 1093 ldb = ldb_module_get_ctx(module); 1268 1094 1269 msg = talloc(module, struct ldb_message); 1270 if (msg == NULL) { 1271 errno = ENOMEM; 1095 list = talloc_zero(module, struct dn_list); 1096 if (list == NULL) { 1272 1097 return LDB_ERR_OPERATIONS_ERROR; 1273 1098 } … … 1275 1100 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a); 1276 1101 if (!dn_key) { 1277 talloc_free( msg);1278 return LDB_ERR_OPERATIONS_ERROR; 1279 } 1280 talloc_steal( msg, dn_key);1281 1282 ret = ltdb_ search_dn1_index(module, dn_key, msg);1102 talloc_free(list); 1103 return LDB_ERR_OPERATIONS_ERROR; 1104 } 1105 talloc_steal(list, dn_key); 1106 1107 ret = ltdb_dn_list_load(module, dn_key, list); 1283 1108 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { 1284 talloc_free( msg);1109 talloc_free(list); 1285 1110 return ret; 1286 1111 } 1287 1112 1288 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 1289 msg->dn = dn_key; 1290 msg->num_elements = 0; 1291 msg->elements = NULL; 1292 } 1293 1294 for (i=0;i<msg->num_elements;i++) { 1295 if (strcmp(LTDB_IDX, msg->elements[i].name) == 0) { 1296 break; 1297 } 1298 } 1299 1300 if (i == msg->num_elements) { 1301 ret = ltdb_index_add1_new(ldb, msg, dn); 1302 } else { 1303 ret = ltdb_index_add1_add(ldb, msg, i, dn, a); 1304 } 1305 1306 if (ret == LDB_SUCCESS) { 1307 ret = ltdb_store_idxptr(module, msg, TDB_REPLACE); 1308 } 1309 1310 talloc_free(msg); 1113 if (ltdb_dn_list_find_str(list, dn) != -1) { 1114 talloc_free(list); 1115 return LDB_SUCCESS; 1116 } 1117 1118 if (list->count > 0 && 1119 a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) { 1120 talloc_free(list); 1121 ldb_asprintf_errstring(ldb, __location__ ": unique index violation on %s in %s", 1122 el->name, dn); 1123 return LDB_ERR_ENTRY_ALREADY_EXISTS; 1124 } 1125 1126 /* overallocate the list a bit, to reduce the number of 1127 * realloc trigered copies */ 1128 alloc_len = ((list->count+1)+7) & ~7; 1129 list->dn = talloc_realloc(list, list->dn, struct ldb_val, alloc_len); 1130 if (list->dn == NULL) { 1131 talloc_free(list); 1132 return LDB_ERR_OPERATIONS_ERROR; 1133 } 1134 list->dn[list->count].data = (uint8_t *)talloc_strdup(list->dn, dn); 1135 list->dn[list->count].length = strlen(dn); 1136 list->count++; 1137 1138 ret = ltdb_dn_list_store(module, dn_key, list); 1139 1140 talloc_free(list); 1311 1141 1312 1142 return ret; 1313 1143 } 1314 1144 1315 static int ltdb_index_add0(struct ldb_module *module, const char *dn, 1316 struct ldb_message_element *elements, int num_el) 1317 { 1318 void *data = ldb_module_get_private(module); 1319 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 1320 int ret; 1321 unsigned int i, j; 1145 /* 1146 add index entries for one elements in a message 1147 */ 1148 static int ltdb_index_add_el(struct ldb_module *module, const char *dn, 1149 struct ldb_message_element *el) 1150 { 1151 unsigned int i; 1152 for (i = 0; i < el->num_values; i++) { 1153 int ret = ltdb_index_add1(module, dn, el, i); 1154 if (ret != LDB_SUCCESS) { 1155 return ret; 1156 } 1157 } 1158 1159 return LDB_SUCCESS; 1160 } 1161 1162 /* 1163 add index entries for all elements in a message 1164 */ 1165 static int ltdb_index_add_all(struct ldb_module *module, const char *dn, 1166 struct ldb_message_element *elements, int num_el) 1167 { 1168 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 1169 unsigned int i; 1322 1170 1323 1171 if (dn[0] == '@') { … … 1331 1179 1332 1180 for (i = 0; i < num_el; i++) { 1333 ret = ldb_msg_find_idx(ltdb->cache->indexlist, elements[i].name, 1334 NULL, LTDB_IDXATTR); 1335 if (ret == -1) { 1181 int ret; 1182 if (!ltdb_is_indexed(ltdb->cache->indexlist, elements[i].name)) { 1336 1183 continue; 1337 1184 } 1338 for (j = 0; j < elements[i].num_values; j++) { 1339 ret = ltdb_index_add1(module, dn, &elements[i], j); 1340 if (ret != LDB_SUCCESS) { 1341 return ret; 1342 } 1185 ret = ltdb_index_add_el(module, dn, &elements[i]); 1186 if (ret != LDB_SUCCESS) { 1187 struct ldb_context *ldb = ldb_module_get_ctx(module); 1188 ldb_asprintf_errstring(ldb, 1189 __location__ ": Failed to re-index %s in %s - %s", 1190 elements[i].name, dn, ldb_errstring(ldb)); 1191 return ret; 1343 1192 } 1344 1193 } … … 1347 1196 } 1348 1197 1349 /* 1350 add the index entries for a new record 1351 */ 1352 int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg) 1353 { 1354 const char *dn; 1355 int ret; 1356 1357 dn = ldb_dn_get_linearized(msg->dn); 1358 if (dn == NULL) { 1359 return LDB_ERR_OPERATIONS_ERROR; 1360 } 1361 1362 ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements); 1363 1364 return ret; 1365 } 1366 1367 1368 /* 1369 delete an index entry for one message element 1370 */ 1371 int ltdb_index_del_value(struct ldb_module *module, const char *dn, 1372 struct ldb_message_element *el, int v_idx) 1373 { 1374 struct ldb_context *ldb; 1375 struct ldb_message *msg; 1376 struct ldb_dn *dn_key; 1377 int ret, i; 1378 unsigned int j; 1379 1380 ldb = ldb_module_get_ctx(module); 1381 1382 if (dn[0] == '@') { 1383 return LDB_SUCCESS; 1384 } 1385 1386 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL); 1387 if (!dn_key) { 1388 return LDB_ERR_OPERATIONS_ERROR; 1389 } 1390 1391 msg = talloc(dn_key, struct ldb_message); 1392 if (msg == NULL) { 1393 talloc_free(dn_key); 1394 return LDB_ERR_OPERATIONS_ERROR; 1395 } 1396 1397 ret = ltdb_search_dn1_index(module, dn_key, msg); 1398 if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) { 1399 talloc_free(dn_key); 1400 return ret; 1401 } 1402 1403 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 1404 /* it wasn't indexed. Did we have an earlier error? If we did then 1405 its gone now */ 1406 talloc_free(dn_key); 1407 return LDB_SUCCESS; 1408 } 1409 1410 i = ldb_msg_find_idx(msg, dn, &j, LTDB_IDX); 1411 if (i == -1) { 1412 struct ldb_ldif ldif; 1413 char *ldif_string; 1414 ldif.changetype = LDB_CHANGETYPE_NONE; 1415 ldif.msg = msg; 1416 ldif_string = ldb_ldif_write_string(ldb, NULL, &ldif); 1417 ldb_debug(ldb, LDB_DEBUG_ERROR, 1418 "ERROR: dn %s not found in %s", dn, 1419 ldif_string); 1420 talloc_free(ldif_string); 1421 /* it ain't there. hmmm */ 1422 talloc_free(dn_key); 1423 return LDB_SUCCESS; 1424 } 1425 1426 if (j != msg->elements[i].num_values - 1) { 1427 memmove(&msg->elements[i].values[j], 1428 &msg->elements[i].values[j+1], 1429 (msg->elements[i].num_values-(j+1)) * 1430 sizeof(msg->elements[i].values[0])); 1431 } 1432 msg->elements[i].num_values--; 1433 1434 if (msg->elements[i].num_values == 0) { 1435 ret = ltdb_delete_noindex(module, dn_key); 1436 } else { 1437 ret = ltdb_store_idxptr(module, msg, TDB_REPLACE); 1438 } 1439 1440 talloc_free(dn_key); 1441 1442 return ret; 1443 } 1444 1445 /* 1446 delete the index entries for a record 1447 return -1 on failure 1448 */ 1449 int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg) 1450 { 1451 void *data = ldb_module_get_private(module); 1452 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 1453 int ret; 1454 const char *dn; 1455 unsigned int i, j; 1456 1457 /* find the list of indexed fields */ 1458 if (ltdb->cache->indexlist->num_elements == 0) { 1459 /* no indexed fields */ 1460 return LDB_SUCCESS; 1461 } 1462 1463 if (ldb_dn_is_special(msg->dn)) { 1464 return LDB_SUCCESS; 1465 } 1466 1467 dn = ldb_dn_get_linearized(msg->dn); 1468 if (dn == NULL) { 1469 return LDB_ERR_OPERATIONS_ERROR; 1470 } 1471 1472 for (i = 0; i < msg->num_elements; i++) { 1473 ret = ldb_msg_find_idx(ltdb->cache->indexlist, msg->elements[i].name, 1474 NULL, LTDB_IDXATTR); 1475 if (ret == -1) { 1476 continue; 1477 } 1478 for (j = 0; j < msg->elements[i].num_values; j++) { 1479 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j); 1480 if (ret != LDB_SUCCESS) { 1481 return ret; 1482 } 1483 } 1484 } 1485 1486 return LDB_SUCCESS; 1487 } 1488 1489 /* 1490 handle special index for one level searches 1491 */ 1492 int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add) 1493 { 1494 void *data = ldb_module_get_private(module); 1495 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 1198 1199 /* 1200 insert a one level index for a message 1201 */ 1202 static int ltdb_index_onelevel(struct ldb_module *module, const struct ldb_message *msg, int add) 1203 { 1204 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 1496 1205 struct ldb_message_element el; 1497 1206 struct ldb_val val; … … 1500 1209 int ret; 1501 1210 1502 if (ldb_dn_is_special(msg->dn)) {1503 return LDB_SUCCESS;1504 }1505 1506 1211 /* We index for ONE Level only if requested */ 1507 ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE); 1508 if (ret != 0) { 1212 if (!ltdb->cache->one_level_indexes) { 1509 1213 return LDB_SUCCESS; 1510 1214 } … … 1535 1239 ret = ltdb_index_add1(module, dn, &el, 0); 1536 1240 } else { /* delete */ 1537 ret = ltdb_index_del_value(module, dn, &el, 0);1241 ret = ltdb_index_del_value(module, msg->dn, &el, 0); 1538 1242 } 1539 1243 … … 1543 1247 } 1544 1248 1249 /* 1250 add the index entries for a new element in a record 1251 The caller guarantees that these element values are not yet indexed 1252 */ 1253 int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn, 1254 struct ldb_message_element *el) 1255 { 1256 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 1257 if (ldb_dn_is_special(dn)) { 1258 return LDB_SUCCESS; 1259 } 1260 if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) { 1261 return LDB_SUCCESS; 1262 } 1263 return ltdb_index_add_el(module, ldb_dn_get_linearized(dn), el); 1264 } 1265 1266 /* 1267 add the index entries for a new record 1268 */ 1269 int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg) 1270 { 1271 const char *dn; 1272 int ret; 1273 1274 if (ldb_dn_is_special(msg->dn)) { 1275 return LDB_SUCCESS; 1276 } 1277 1278 dn = ldb_dn_get_linearized(msg->dn); 1279 if (dn == NULL) { 1280 return LDB_ERR_OPERATIONS_ERROR; 1281 } 1282 1283 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements); 1284 if (ret != LDB_SUCCESS) { 1285 return ret; 1286 } 1287 1288 return ltdb_index_onelevel(module, msg, 1); 1289 } 1290 1291 1292 /* 1293 delete an index entry for one message element 1294 */ 1295 int ltdb_index_del_value(struct ldb_module *module, struct ldb_dn *dn, 1296 struct ldb_message_element *el, unsigned int v_idx) 1297 { 1298 struct ldb_context *ldb; 1299 struct ldb_dn *dn_key; 1300 const char *dn_str; 1301 int ret, i; 1302 unsigned int j; 1303 struct dn_list *list; 1304 1305 ldb = ldb_module_get_ctx(module); 1306 1307 dn_str = ldb_dn_get_linearized(dn); 1308 if (dn_str == NULL) { 1309 return LDB_ERR_OPERATIONS_ERROR; 1310 } 1311 1312 if (dn_str[0] == '@') { 1313 return LDB_SUCCESS; 1314 } 1315 1316 dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL); 1317 if (!dn_key) { 1318 return LDB_ERR_OPERATIONS_ERROR; 1319 } 1320 1321 list = talloc_zero(dn_key, struct dn_list); 1322 if (list == NULL) { 1323 talloc_free(dn_key); 1324 return LDB_ERR_OPERATIONS_ERROR; 1325 } 1326 1327 ret = ltdb_dn_list_load(module, dn_key, list); 1328 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 1329 /* it wasn't indexed. Did we have an earlier error? If we did then 1330 its gone now */ 1331 talloc_free(dn_key); 1332 return LDB_SUCCESS; 1333 } 1334 1335 if (ret != LDB_SUCCESS) { 1336 talloc_free(dn_key); 1337 return ret; 1338 } 1339 1340 i = ltdb_dn_list_find_str(list, dn_str); 1341 if (i == -1) { 1342 /* nothing to delete */ 1343 talloc_free(dn_key); 1344 return LDB_SUCCESS; 1345 } 1346 1347 j = (unsigned int) i; 1348 if (j != list->count - 1) { 1349 memmove(&list->dn[j], &list->dn[j+1], sizeof(list->dn[0])*(list->count - (j+1))); 1350 } 1351 list->count--; 1352 list->dn = talloc_realloc(list, list->dn, struct ldb_val, list->count); 1353 1354 ret = ltdb_dn_list_store(module, dn_key, list); 1355 1356 talloc_free(dn_key); 1357 1358 return ret; 1359 } 1360 1361 /* 1362 delete the index entries for a element 1363 return -1 on failure 1364 */ 1365 int ltdb_index_del_element(struct ldb_module *module, struct ldb_dn *dn, 1366 struct ldb_message_element *el) 1367 { 1368 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 1369 const char *dn_str; 1370 int ret; 1371 unsigned int i; 1372 1373 if (!ltdb->cache->attribute_indexes) { 1374 /* no indexed fields */ 1375 return LDB_SUCCESS; 1376 } 1377 1378 dn_str = ldb_dn_get_linearized(dn); 1379 if (dn_str == NULL) { 1380 return LDB_ERR_OPERATIONS_ERROR; 1381 } 1382 1383 if (dn_str[0] == '@') { 1384 return LDB_SUCCESS; 1385 } 1386 1387 if (!ltdb_is_indexed(ltdb->cache->indexlist, el->name)) { 1388 return LDB_SUCCESS; 1389 } 1390 for (i = 0; i < el->num_values; i++) { 1391 ret = ltdb_index_del_value(module, dn, el, i); 1392 if (ret != LDB_SUCCESS) { 1393 return ret; 1394 } 1395 } 1396 1397 return LDB_SUCCESS; 1398 } 1399 1400 /* 1401 delete the index entries for a record 1402 return -1 on failure 1403 */ 1404 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg) 1405 { 1406 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 1407 int ret; 1408 unsigned int i; 1409 1410 if (ldb_dn_is_special(msg->dn)) { 1411 return LDB_SUCCESS; 1412 } 1413 1414 ret = ltdb_index_onelevel(module, msg, 0); 1415 if (ret != LDB_SUCCESS) { 1416 return ret; 1417 } 1418 1419 if (!ltdb->cache->attribute_indexes) { 1420 /* no indexed fields */ 1421 return LDB_SUCCESS; 1422 } 1423 1424 for (i = 0; i < msg->num_elements; i++) { 1425 ret = ltdb_index_del_element(module, msg->dn, &msg->elements[i]); 1426 if (ret != LDB_SUCCESS) { 1427 return ret; 1428 } 1429 } 1430 1431 return LDB_SUCCESS; 1432 } 1433 1545 1434 1546 1435 /* … … 1549 1438 static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) 1550 1439 { 1551 const char *dn = "DN=" LTDB_INDEX ":"; 1552 if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) { 1553 return tdb_delete(tdb, key); 1554 } 1440 struct ldb_module *module = state; 1441 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 1442 const char *dnstr = "DN=" LTDB_INDEX ":"; 1443 struct dn_list list; 1444 struct ldb_dn *dn; 1445 struct ldb_val v; 1446 int ret; 1447 1448 if (strncmp((char *)key.dptr, dnstr, strlen(dnstr)) != 0) { 1449 return 0; 1450 } 1451 /* we need to put a empty list in the internal tdb for this 1452 * index entry */ 1453 list.dn = NULL; 1454 list.count = 0; 1455 1456 /* the offset of 3 is to remove the DN= prefix. */ 1457 v.data = key.dptr + 3; 1458 v.length = strnlen((char *)key.dptr, key.dsize) - 3; 1459 1460 dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v); 1461 ret = ltdb_dn_list_store(module, dn, &list); 1462 if (ret != LDB_SUCCESS) { 1463 ldb_asprintf_errstring(ldb_module_get_ctx(module), 1464 "Unable to store null index for %s\n", 1465 ldb_dn_get_linearized(dn)); 1466 talloc_free(dn); 1467 return -1; 1468 } 1469 talloc_free(dn); 1555 1470 return 0; 1556 1471 } 1557 1472 1473 struct ltdb_reindex_context { 1474 struct ldb_module *module; 1475 int error; 1476 }; 1477 1558 1478 /* 1559 1479 traversal function that adds @INDEX records during a re index … … 1562 1482 { 1563 1483 struct ldb_context *ldb; 1564 struct ldb_module *module = (struct ldb_module *)state; 1484 struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state; 1485 struct ldb_module *module = ctx->module; 1565 1486 struct ldb_message *msg; 1566 1487 const char *dn = NULL; … … 1575 1496 } 1576 1497 1577 msg = talloc(module, struct ldb_message);1498 msg = ldb_msg_new(module); 1578 1499 if (msg == NULL) { 1579 1500 return -1; … … 1583 1504 if (ret != 0) { 1584 1505 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n", 1585 1506 ldb_dn_get_linearized(msg->dn)); 1586 1507 talloc_free(msg); 1587 1508 return -1; … … 1594 1515 /* probably a corrupt record ... darn */ 1595 1516 ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s", 1596 1517 ldb_dn_get_linearized(msg->dn)); 1597 1518 talloc_free(msg); 1598 1519 return 0; … … 1610 1531 } 1611 1532 1612 ret = ltdb_index_one(module, msg, 1); 1613 if (ret == LDB_SUCCESS) { 1614 ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements); 1615 } else { 1533 ret = ltdb_index_onelevel(module, msg, 1); 1534 if (ret != LDB_SUCCESS) { 1616 1535 ldb_debug(ldb, LDB_DEBUG_ERROR, 1617 "Adding special ONE LEVEL index failed (%s)!", 1618 ldb_dn_get_linearized(msg->dn)); 1536 "Adding special ONE LEVEL index failed (%s)!", 1537 ldb_dn_get_linearized(msg->dn)); 1538 talloc_free(msg); 1539 return -1; 1540 } 1541 1542 ret = ltdb_index_add_all(module, dn, msg->elements, msg->num_elements); 1543 1544 if (ret != LDB_SUCCESS) { 1545 ctx->error = ret; 1546 talloc_free(msg); 1547 return -1; 1619 1548 } 1620 1549 1621 1550 talloc_free(msg); 1622 1551 1623 if (ret != LDB_SUCCESS) return -1;1624 1625 1552 return 0; 1626 1553 } … … 1631 1558 int ltdb_reindex(struct ldb_module *module) 1632 1559 { 1633 void *data = ldb_module_get_private(module); 1634 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 1560 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 1635 1561 int ret; 1562 struct ltdb_reindex_context ctx; 1636 1563 1637 1564 if (ltdb_cache_reload(module) != 0) { … … 1639 1566 } 1640 1567 1641 /* first traverse the database deleting any @INDEX records */ 1642 ret = tdb_traverse(ltdb->tdb, delete_index, NULL); 1568 /* first traverse the database deleting any @INDEX records by 1569 * putting NULL entries in the in-memory tdb 1570 */ 1571 ret = tdb_traverse(ltdb->tdb, delete_index, module); 1643 1572 if (ret == -1) { 1644 1573 return LDB_ERR_OPERATIONS_ERROR; … … 1650 1579 } 1651 1580 1581 ctx.module = module; 1582 ctx.error = 0; 1583 1652 1584 /* now traverse adding any indexes for normal LDB records */ 1653 ret = tdb_traverse(ltdb->tdb, re_index, module);1585 ret = tdb_traverse(ltdb->tdb, re_index, &ctx); 1654 1586 if (ret == -1) { 1655 return LDB_ERR_OPERATIONS_ERROR; 1656 } 1657 1658 if (ltdb->idxptr) { 1659 ltdb->idxptr->repack = true; 1587 struct ldb_context *ldb = ldb_module_get_ctx(module); 1588 ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s", ldb_errstring(ldb)); 1589 return LDB_ERR_OPERATIONS_ERROR; 1590 } 1591 1592 if (ctx.error != LDB_SUCCESS) { 1593 struct ldb_context *ldb = ldb_module_get_ctx(module); 1594 ldb_asprintf_errstring(ldb, "reindexing failed: %s", ldb_errstring(ldb)); 1595 return ctx.error; 1660 1596 } 1661 1597 -
trunk/server/source4/lib/ldb/ldb_tdb/ldb_pack.c
r414 r745 59 59 { 60 60 if (el->num_values == 0) return 0; 61 62 if (ldb_attr_cmp(el->name, "dn") == 0) return 0;63 61 64 62 if (ldb_attr_cmp(el->name, "distinguishedName") == 0) return 0; … … 209 207 210 208 if (message->num_elements == 0) { 211 message->elements = NULL;212 209 return 0; 213 210 } -
trunk/server/source4/lib/ldb/ldb_tdb/ldb_search.c
r414 r745 79 79 80 80 elnew->num_values = el->num_values; 81 elnew->flags = el->flags; 81 82 82 83 ret->num_elements++; … … 98 99 el.num_values = 1; 99 100 el.values = &val; 101 el.flags = 0; 100 102 val.data = (uint8_t *)ldb_dn_alloc_linearized(msg, msg->dn); 101 103 val.length = strlen((char *)val.data); … … 146 148 { 147 149 struct ldb_message *ret; 148 int i;150 unsigned int i; 149 151 150 152 ret = talloc(mem_ctx, struct ldb_message); … … 326 328 int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs) 327 329 { 328 int i, keep_all = 0; 330 unsigned int i; 331 int keep_all = 0; 332 struct ldb_message_element *el2; 333 uint32_t num_elements; 329 334 330 335 if (attrs) { … … 353 358 } 354 359 360 el2 = talloc_array(msg, struct ldb_message_element, msg->num_elements); 361 if (el2 == NULL) { 362 return -1; 363 } 364 num_elements = 0; 365 355 366 for (i = 0; i < msg->num_elements; i++) { 356 int j, found; 367 unsigned int j; 368 int found = 0; 357 369 358 for (j = 0 , found = 0; attrs[j]; j++) {370 for (j = 0; attrs[j]; j++) { 359 371 if (ldb_attr_cmp(msg->elements[i].name, attrs[j]) == 0) { 360 372 found = 1; … … 363 375 } 364 376 365 if (!found) { 366 ldb_msg_remove_attr(msg, msg->elements[i].name); 367 i--; 368 } 369 } 377 if (found) { 378 el2[num_elements] = msg->elements[i]; 379 talloc_steal(el2, el2[num_elements].name); 380 talloc_steal(el2, el2[num_elements].values); 381 num_elements++; 382 } 383 } 384 385 talloc_free(msg->elements); 386 msg->elements = talloc_realloc(msg, el2, struct ldb_message_element, msg->num_elements); 387 if (msg->elements == NULL) { 388 return -1; 389 } 390 msg->num_elements = num_elements; 370 391 371 392 return 0; … … 381 402 struct ldb_message *msg; 382 403 int ret; 404 bool matched; 383 405 384 406 ac = talloc_get_type(state, struct ltdb_context); … … 412 434 413 435 /* see if it matches the given expression */ 414 if (!ldb_match_msg(ldb, msg, 415 ac->tree, ac->base, ac->scope)) { 436 ret = ldb_match_msg_error(ldb, msg, 437 ac->tree, ac->base, ac->scope, &matched); 438 if (ret != LDB_SUCCESS) { 439 talloc_free(msg); 440 return -1; 441 } 442 if (!matched) { 416 443 talloc_free(msg); 417 444 return 0; … … 552 579 if ( ! ctx->request_terminated && ret != LDB_SUCCESS) { 553 580 /* Not indexed, so we need to do a full scan */ 554 #if 0 555 /* useful for debugging when slow performance 556 * is caused by unindexed searches */ 557 char *expression = ldb_filter_from_tree(ctx, ctx->tree); 558 printf("FULL SEARCH: %s\n", expression); 559 talloc_free(expression); 560 #endif 581 if (ltdb->warn_unindexed) { 582 /* useful for debugging when slow performance 583 * is caused by unindexed searches */ 584 char *expression = ldb_filter_from_tree(ctx, ctx->tree); 585 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb FULL SEARCH: %s SCOPE: %s DN: %s\n", 586 expression, 587 req->op.search.scope==LDB_SCOPE_BASE?"base": 588 req->op.search.scope==LDB_SCOPE_ONELEVEL?"one": 589 req->op.search.scope==LDB_SCOPE_SUBTREE?"sub":"UNKNOWN", 590 ldb_dn_get_linearized(req->op.search.base)); 591 592 talloc_free(expression); 593 } 561 594 if (match_count != 0) { 562 595 /* the indexing code gave an error … … 568 601 * duplicate entries 569 602 */ 603 ltdb_unlock_read(module); 570 604 return LDB_ERR_OPERATIONS_ERROR; 571 605 } -
trunk/server/source4/lib/ldb/ldb_tdb/ldb_tdb.c
r414 r745 2 2 ldb database library 3 3 4 Copyright (C) Andrew Tridgell 5 Copyright (C) Stefan Metzmacher 6 Copyright (C) Simo Sorce 7 4 Copyright (C) Andrew Tridgell 2004 5 Copyright (C) Stefan Metzmacher 2004 6 Copyright (C) Simo Sorce 2006-2008 7 Copyright (C) Matthias Dieter Wallnöfer 2009-2010 8 8 9 9 ** NOTE! The following LGPL license applies to the ldb … … 37 37 * Modifications: 38 38 * 39 * - description: make the module use async ronous calls39 * - description: make the module use asynchronous calls 40 40 * date: Feb 2006 41 41 * Author: Simo Sorce … … 44 44 * date: Jan 2008 45 45 * Author: Simo Sorce 46 * 47 * - description: fix up memory leaks and small bugs 48 * date: Oct 2009 49 * Author: Matthias Dieter Wallnöfer 46 50 */ 47 51 … … 52 56 map a tdb error code to a ldb error code 53 57 */ 54 staticint ltdb_err_map(enum TDB_ERROR tdb_code)58 int ltdb_err_map(enum TDB_ERROR tdb_code) 55 59 { 56 60 switch (tdb_code) { … … 74 78 case TDB_ERR_RDONLY: 75 79 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; 80 default: 81 break; 76 82 } 77 83 return LDB_ERR_OTHER; … … 85 91 void *data = ldb_module_get_private(module); 86 92 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 87 if (ltdb->in_transaction == 0) { 88 return tdb_lockall_read(ltdb->tdb); 89 } 90 return 0; 93 int ret = 0; 94 95 if (ltdb->in_transaction == 0 && 96 ltdb->read_lock_count == 0) { 97 ret = tdb_lockall_read(ltdb->tdb); 98 } 99 if (ret == 0) { 100 ltdb->read_lock_count++; 101 } 102 return ret; 91 103 } 92 104 … … 98 110 void *data = ldb_module_get_private(module); 99 111 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 100 if (ltdb->in_transaction == 0 ) {112 if (ltdb->in_transaction == 0 && ltdb->read_lock_count == 1) { 101 113 return tdb_unlockall_read(ltdb->tdb); 102 114 } 115 ltdb->read_lock_count--; 103 116 return 0; 104 117 } … … 163 176 */ 164 177 static int ltdb_check_special_dn(struct ldb_module *module, 165 178 const struct ldb_message *msg) 166 179 { 167 180 struct ldb_context *ldb = ldb_module_get_ctx(module); 168 int i, j;181 unsigned int i, j; 169 182 170 183 if (! ldb_dn_is_special(msg->dn) || 171 184 ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) { 172 return 0;185 return LDB_SUCCESS; 173 186 } 174 187 … … 176 189 /* should we check that we deny multivalued attributes ? */ 177 190 for (i = 0; i < msg->num_elements; i++) { 191 if (ldb_attr_cmp(msg->elements[i].name, "distinguishedName") == 0) continue; 192 178 193 for (j = 0; j < msg->elements[i].num_values; j++) { 179 194 if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) { … … 184 199 } 185 200 186 return 0;201 return LDB_SUCCESS; 187 202 } 188 203 … … 195 210 { 196 211 int ret = LDB_SUCCESS; 212 struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); 213 214 /* only allow modifies inside a transaction, otherwise the 215 * ldb is unsafe */ 216 if (ltdb->in_transaction == 0) { 217 ldb_set_errstring(ldb_module_get_ctx(module), "ltdb modify without transaction"); 218 return LDB_ERR_OPERATIONS_ERROR; 219 } 197 220 198 221 if (ldb_dn_is_special(dn) && … … 202 225 } 203 226 227 /* If the modify was to a normal record, or any special except @BASEINFO, update the seq number */ 204 228 if (ret == LDB_SUCCESS && 205 229 !(ldb_dn_is_special(dn) && … … 208 232 } 209 233 234 /* If the modify was to @OPTIONS, reload the cache */ 235 if (ret == LDB_SUCCESS && 236 ldb_dn_is_special(dn) && 237 (ldb_dn_check_special(dn, LTDB_OPTIONS)) ) { 238 ret = ltdb_cache_reload(module); 239 } 240 210 241 return ret; 211 242 } … … 219 250 struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); 220 251 TDB_DATA tdb_key, tdb_data; 221 int ret ;252 int ret = LDB_SUCCESS; 222 253 223 254 tdb_key = ltdb_key(module, msg->dn); 224 if ( !tdb_key.dptr) {255 if (tdb_key.dptr == NULL) { 225 256 return LDB_ERR_OTHER; 226 257 } … … 238 269 } 239 270 240 ret = ltdb_index_add(module, msg);241 if (ret != LDB_SUCCESS) {242 tdb_delete(ltdb->tdb, tdb_key);243 }244 245 271 done: 246 272 talloc_free(tdb_key.dptr); … … 251 277 252 278 279 /* 280 check if a attribute is a single valued, for a given element 281 */ 282 static bool ldb_tdb_single_valued(const struct ldb_schema_attribute *a, 283 struct ldb_message_element *el) 284 { 285 if (!a) return false; 286 if (el != NULL) { 287 if (el->flags & LDB_FLAG_INTERNAL_FORCE_SINGLE_VALUE_CHECK) { 288 /* override from a ldb module, for example 289 used for the description field, which is 290 marked multi-valued in the schema but which 291 should not actually accept multiple 292 values */ 293 return true; 294 } 295 if (el->flags & LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK) { 296 /* override from a ldb module, for example used for 297 deleted linked attribute entries */ 298 return false; 299 } 300 } 301 if (a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { 302 return true; 303 } 304 return false; 305 } 306 253 307 static int ltdb_add_internal(struct ldb_module *module, 254 308 const struct ldb_message *msg) 255 309 { 256 310 struct ldb_context *ldb = ldb_module_get_ctx(module); 257 int ret, i; 258 259 ret = ltdb_check_special_dn(module, msg); 260 if (ret != LDB_SUCCESS) { 261 return ret; 262 } 263 264 if (ltdb_cache_load(module) != 0) { 265 return LDB_ERR_OPERATIONS_ERROR; 266 } 311 int ret = LDB_SUCCESS; 312 unsigned int i; 267 313 268 314 for (i=0;i<msg->num_elements;i++) { … … 271 317 272 318 if (el->num_values == 0) { 273 ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illegal)",319 ldb_asprintf_errstring(ldb, "attribute '%s' on '%s' specified, but with 0 values (illegal)", 274 320 el->name, ldb_dn_get_linearized(msg->dn)); 275 321 return LDB_ERR_CONSTRAINT_VIOLATION; 276 322 } 277 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { 278 if (el->num_values > 1) { 279 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once", 280 el->name, ldb_dn_get_linearized(msg->dn)); 281 return LDB_ERR_CONSTRAINT_VIOLATION; 282 } 323 if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) { 324 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once", 325 el->name, ldb_dn_get_linearized(msg->dn)); 326 return LDB_ERR_CONSTRAINT_VIOLATION; 283 327 } 284 328 } 285 329 286 330 ret = ltdb_store(module, msg, TDB_INSERT); 287 288 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { 289 ldb_asprintf_errstring(ldb, 290 "Entry %s already exists", 291 ldb_dn_get_linearized(msg->dn)); 331 if (ret != LDB_SUCCESS) { 332 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { 333 ldb_asprintf_errstring(ldb, 334 "Entry %s already exists", 335 ldb_dn_get_linearized(msg->dn)); 336 } 292 337 return ret; 293 338 } 294 339 295 if (ret == LDB_SUCCESS) { 296 ret = ltdb_index_one(module, msg, 1); 297 if (ret != LDB_SUCCESS) { 298 return ret; 299 } 300 301 ret = ltdb_modified(module, msg->dn); 302 if (ret != LDB_SUCCESS) { 303 return ret; 304 } 305 } 340 ret = ltdb_index_add_new(module, msg); 341 if (ret != LDB_SUCCESS) { 342 return ret; 343 } 344 345 ret = ltdb_modified(module, msg->dn); 306 346 307 347 return ret; … … 315 355 struct ldb_module *module = ctx->module; 316 356 struct ldb_request *req = ctx->req; 317 int tret; 357 int ret = LDB_SUCCESS; 358 359 ret = ltdb_check_special_dn(module, req->op.add.message); 360 if (ret != LDB_SUCCESS) { 361 return ret; 362 } 318 363 319 364 ldb_request_set_state(req, LDB_ASYNC_PENDING); 320 365 321 tret = ltdb_add_internal(module, req->op.add.message); 322 if (tret != LDB_SUCCESS) { 323 return tret; 324 } 325 326 return LDB_SUCCESS; 366 if (ltdb_cache_load(module) != 0) { 367 return LDB_ERR_OPERATIONS_ERROR; 368 } 369 370 ret = ltdb_add_internal(module, req->op.add.message); 371 372 return ret; 327 373 } 328 374 … … 356 402 { 357 403 struct ldb_message *msg; 358 int ret ;359 360 msg = talloc(module, struct ldb_message);404 int ret = LDB_SUCCESS; 405 406 msg = ldb_msg_new(module); 361 407 if (msg == NULL) { 362 408 return LDB_ERR_OPERATIONS_ERROR; … … 376 422 } 377 423 378 /* remove one level attribute */379 ret = ltdb_index_one(module, msg, 0);380 if (ret != LDB_SUCCESS) {381 goto done;382 }383 384 424 /* remove any indexed attributes */ 385 ret = ltdb_index_del (module, msg);425 ret = ltdb_index_delete(module, msg); 386 426 if (ret != LDB_SUCCESS) { 387 427 goto done; … … 405 445 struct ldb_module *module = ctx->module; 406 446 struct ldb_request *req = ctx->req; 407 int tret;447 int ret = LDB_SUCCESS; 408 448 409 449 ldb_request_set_state(req, LDB_ASYNC_PENDING); … … 413 453 } 414 454 415 tret = ltdb_delete_internal(module, req->op.del.dn); 416 if (tret != LDB_SUCCESS) { 417 return tret; 418 } 419 420 return LDB_SUCCESS; 455 ret = ltdb_delete_internal(module, req->op.del.dn); 456 457 return ret; 421 458 } 422 459 … … 447 484 returns 0 on success, -1 on failure (and sets errno) 448 485 */ 449 static int msg_add_element(struct ldb_context *ldb,450 451 486 static int ltdb_msg_add_element(struct ldb_context *ldb, 487 struct ldb_message *msg, 488 struct ldb_message_element *el) 452 489 { 453 490 struct ldb_message_element *e2; 454 491 unsigned int i; 492 493 if (el->num_values == 0) { 494 /* nothing to do here - we don't add empty elements */ 495 return 0; 496 } 455 497 456 498 e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, … … 467 509 e2->name = el->name; 468 510 e2->flags = el->flags; 469 e2->values = NULL; 470 if (el->num_values != 0) { 471 e2->values = talloc_array(msg->elements, 472 struct ldb_val, el->num_values); 473 if (!e2->values) { 474 errno = ENOMEM; 475 return -1; 476 } 511 e2->values = talloc_array(msg->elements, 512 struct ldb_val, el->num_values); 513 if (!e2->values) { 514 errno = ENOMEM; 515 return -1; 477 516 } 478 517 for (i=0;i<el->num_values;i++) { … … 481 520 e2->num_values = el->num_values; 482 521 483 msg->num_elements++;522 ++msg->num_elements; 484 523 485 524 return 0; … … 493 532 struct ldb_message *msg, const char *name) 494 533 { 495 const char *dn; 496 unsigned int i, j; 497 498 dn = ldb_dn_get_linearized(msg->dn); 499 if (dn == NULL) { 500 return -1; 501 } 502 503 for (i=0;i<msg->num_elements;i++) { 504 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) { 505 for (j=0;j<msg->elements[i].num_values;j++) { 506 ltdb_index_del_value(module, dn, 507 &msg->elements[i], j); 508 } 509 talloc_free(msg->elements[i].values); 510 if (msg->num_elements > (i+1)) { 511 memmove(&msg->elements[i], 512 &msg->elements[i+1], 513 sizeof(struct ldb_message_element)* 514 (msg->num_elements - (i+1))); 515 } 516 msg->num_elements--; 517 i--; 518 msg->elements = talloc_realloc(msg, msg->elements, 519 struct ldb_message_element, 520 msg->num_elements); 521 } 522 } 523 524 return 0; 534 unsigned int i; 535 int ret; 536 struct ldb_message_element *el; 537 538 el = ldb_msg_find_element(msg, name); 539 if (el == NULL) { 540 return LDB_ERR_NO_SUCH_ATTRIBUTE; 541 } 542 i = el - msg->elements; 543 544 ret = ltdb_index_del_element(module, msg->dn, el); 545 if (ret != LDB_SUCCESS) { 546 return ret; 547 } 548 549 talloc_free(el->values); 550 if (msg->num_elements > (i+1)) { 551 memmove(el, el+1, sizeof(*el) * (msg->num_elements - (i+1))); 552 } 553 msg->num_elements--; 554 msg->elements = talloc_realloc(msg, msg->elements, 555 struct ldb_message_element, 556 msg->num_elements); 557 return LDB_SUCCESS; 525 558 } 526 559 … … 528 561 delete all elements matching an attribute name/value 529 562 530 return 0 on success, -1on failure563 return LDB Error on failure 531 564 */ 532 565 static int msg_delete_element(struct ldb_module *module, … … 537 570 struct ldb_context *ldb = ldb_module_get_ctx(module); 538 571 unsigned int i; 539 int found ;572 int found, ret; 540 573 struct ldb_message_element *el; 541 574 const struct ldb_schema_attribute *a; … … 543 576 found = find_element(msg, name); 544 577 if (found == -1) { 545 return -1; 546 } 547 548 el = &msg->elements[found]; 578 return LDB_ERR_NO_SUCH_ATTRIBUTE; 579 } 580 581 i = (unsigned int) found; 582 el = &(msg->elements[i]); 549 583 550 584 a = ldb_schema_attribute_by_name(ldb, el->name); 551 585 552 586 for (i=0;i<el->num_values;i++) { 553 if (a->syntax->comparison_fn(ldb, ldb, 554 &el->values[i], val) == 0) { 587 bool matched; 588 if (a->syntax->operator_fn) { 589 ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a, 590 &el->values[i], val, &matched); 591 if (ret != LDB_SUCCESS) return ret; 592 } else { 593 matched = (a->syntax->comparison_fn(ldb, ldb, 594 &el->values[i], val) == 0); 595 } 596 if (matched) { 597 if (el->num_values == 1) { 598 return msg_delete_attribute(module, ldb, msg, name); 599 } 600 601 ret = ltdb_index_del_value(module, msg->dn, el, i); 602 if (ret != LDB_SUCCESS) { 603 return ret; 604 } 605 555 606 if (i<el->num_values-1) { 556 607 memmove(&el->values[i], &el->values[i+1], … … 559 610 } 560 611 el->num_values--; 561 if (el->num_values == 0) { 562 return msg_delete_attribute(module, ldb, 563 msg, name); 564 } 565 return 0; 612 613 /* per definition we find in a canonicalised message an 614 attribute value only once. So we are finished here */ 615 return LDB_SUCCESS; 566 616 } 567 617 } 568 618 569 return -1; 619 /* Not found */ 620 return LDB_ERR_NO_SUCH_ATTRIBUTE; 570 621 } 571 622 … … 577 628 get away with it, but if we ever have really large attribute lists 578 629 then we'll need to look at this again 630 631 'req' is optional, and is used to specify controls if supplied 579 632 */ 580 633 int ltdb_modify_internal(struct ldb_module *module, 581 const struct ldb_message *msg) 634 const struct ldb_message *msg, 635 struct ldb_request *req) 582 636 { 583 637 struct ldb_context *ldb = ldb_module_get_ctx(module); … … 586 640 TDB_DATA tdb_key, tdb_data; 587 641 struct ldb_message *msg2; 588 unsigned i, j; 589 int ret, idx; 642 unsigned int i, j, k; 643 int ret = LDB_SUCCESS, idx; 644 struct ldb_control *control_permissive = NULL; 645 646 if (req) { 647 control_permissive = ldb_request_get_control(req, 648 LDB_CONTROL_PERMISSIVE_MODIFY_OID); 649 } 590 650 591 651 tdb_key = ltdb_key(module, msg->dn); … … 600 660 } 601 661 602 msg2 = talloc(tdb_key.dptr, struct ldb_message);662 msg2 = ldb_msg_new(tdb_key.dptr); 603 663 if (msg2 == NULL) { 604 talloc_free(tdb_key.dptr); 605 return LDB_ERR_OTHER; 664 free(tdb_data.dptr); 665 ret = LDB_ERR_OTHER; 666 goto done; 606 667 } 607 668 608 669 ret = ltdb_unpack_data(module, &tdb_data, msg2); 670 free(tdb_data.dptr); 609 671 if (ret == -1) { 610 672 ret = LDB_ERR_OTHER; 611 goto failed;673 goto done; 612 674 } 613 675 … … 616 678 } 617 679 618 for (i=0;i<msg->num_elements;i++) { 619 struct ldb_message_element *el = &msg->elements[i]; 620 struct ldb_message_element *el2; 680 for (i=0; i<msg->num_elements; i++) { 681 struct ldb_message_element *el = &msg->elements[i], *el2; 621 682 struct ldb_val *vals; 683 const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name); 622 684 const char *dn; 623 const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name); 685 624 686 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) { 625 626 687 case LDB_FLAG_MOD_ADD: 627 628 /* add this element to the message. fail if it 629 already exists */ 688 689 if (el->num_values == 0) { 690 ldb_asprintf_errstring(ldb, 691 "attribute '%s': attribute on '%s' specified, but with 0 values (illegal)", 692 el->name, ldb_dn_get_linearized(msg2->dn)); 693 ret = LDB_ERR_CONSTRAINT_VIOLATION; 694 goto done; 695 } 696 697 /* make a copy of the array so that a permissive 698 * control can remove duplicates without changing the 699 * original values, but do not copy data as we do not 700 * need to keep it around once the operation is 701 * finished */ 702 if (control_permissive) { 703 el = talloc(msg2, struct ldb_message_element); 704 if (!el) { 705 ret = LDB_ERR_OTHER; 706 goto done; 707 } 708 *el = msg->elements[i]; 709 el->values = talloc_array(el, struct ldb_val, el->num_values); 710 if (el->values == NULL) { 711 ret = LDB_ERR_OTHER; 712 goto done; 713 } 714 for (j = 0; j < el->num_values; j++) { 715 el->values[j] = msg->elements[i].values[j]; 716 } 717 } 718 719 if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) { 720 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once", 721 el->name, ldb_dn_get_linearized(msg2->dn)); 722 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 723 goto done; 724 } 725 726 /* Checks if element already exists */ 630 727 idx = find_element(msg2, el->name); 631 632 if (el->num_values == 0) {633 ldb_asprintf_errstring(ldb, "attribute %s on %s speicified, but with 0 values (illigal)",634 el->name, ldb_dn_get_linearized(msg->dn));635 return LDB_ERR_CONSTRAINT_VIOLATION;636 }637 728 if (idx == -1) { 638 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { 639 if (el->num_values > 1) { 640 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once", 641 el->name, ldb_dn_get_linearized(msg->dn)); 642 return LDB_ERR_CONSTRAINT_VIOLATION; 729 if (ltdb_msg_add_element(ldb, msg2, el) != 0) { 730 ret = LDB_ERR_OTHER; 731 goto done; 732 } 733 ret = ltdb_index_add_element(module, msg2->dn, 734 el); 735 if (ret != LDB_SUCCESS) { 736 goto done; 737 } 738 } else { 739 j = (unsigned int) idx; 740 el2 = &(msg2->elements[j]); 741 742 /* We cannot add another value on a existing one 743 if the attribute is single-valued */ 744 if (ldb_tdb_single_valued(a, el)) { 745 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once", 746 el->name, ldb_dn_get_linearized(msg2->dn)); 747 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 748 goto done; 749 } 750 751 /* Check that values don't exist yet on multi- 752 valued attributes or aren't provided twice */ 753 for (j = 0; j < el->num_values; j++) { 754 if (ldb_msg_find_val(el2, &el->values[j]) != NULL) { 755 if (control_permissive) { 756 /* remove this one as if it was never added */ 757 el->num_values--; 758 for (k = j; k < el->num_values; k++) { 759 el->values[k] = el->values[k + 1]; 760 } 761 j--; /* rewind */ 762 763 continue; 764 } 765 766 ldb_asprintf_errstring(ldb, 767 "attribute '%s': value #%u on '%s' already exists", 768 el->name, j, ldb_dn_get_linearized(msg2->dn)); 769 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 770 goto done; 771 } 772 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) { 773 ldb_asprintf_errstring(ldb, 774 "attribute '%s': value #%u on '%s' provided more than once", 775 el->name, j, ldb_dn_get_linearized(msg2->dn)); 776 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 777 goto done; 643 778 } 644 779 } 645 if (msg_add_element(ldb, msg2, el) != 0) { 780 781 /* Now combine existing and new values to a new 782 attribute record */ 783 vals = talloc_realloc(msg2->elements, 784 el2->values, struct ldb_val, 785 el2->num_values + el->num_values); 786 if (vals == NULL) { 787 ldb_oom(ldb); 646 788 ret = LDB_ERR_OTHER; 647 goto failed;789 goto done; 648 790 } 649 continue; 650 } 651 652 /* If this is an add, then if it already 653 * exists in the object, then we violoate the 654 * single-value rule */ 655 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { 656 return LDB_ERR_CONSTRAINT_VIOLATION; 657 } 658 659 el2 = &msg2->elements[idx]; 660 661 /* An attribute with this name already exists, 662 * add all values if they don't already exist 663 * (check both the other elements to be added, 664 * and those already in the db). */ 665 666 for (j=0;j<el->num_values;j++) { 667 if (ldb_msg_find_val(el2, &el->values[j])) { 668 ldb_asprintf_errstring(ldb, "%s: value #%d already exists", el->name, j); 669 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 670 goto failed; 791 792 for (j=0; j<el->num_values; j++) { 793 vals[el2->num_values + j] = 794 ldb_val_dup(vals, &el->values[j]); 671 795 } 672 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) { 673 ldb_asprintf_errstring(ldb, "%s: value #%d provided more than once", el->name, j); 674 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 675 goto failed; 796 797 el2->values = vals; 798 el2->num_values += el->num_values; 799 800 ret = ltdb_index_add_element(module, msg2->dn, el); 801 if (ret != LDB_SUCCESS) { 802 goto done; 676 803 } 677 804 } 678 805 679 vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val, 680 el2->num_values + el->num_values); 681 682 if (vals == NULL) { 683 ret = LDB_ERR_OTHER; 684 goto failed; 806 break; 807 808 case LDB_FLAG_MOD_REPLACE: 809 810 if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) { 811 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once", 812 el->name, ldb_dn_get_linearized(msg2->dn)); 813 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 814 goto done; 685 815 } 686 816 687 for (j=0;j<el->num_values;j++) { 688 vals[el2->num_values + j] = 689 ldb_val_dup(vals, &el->values[j]); 690 } 691 692 el2->values = vals; 693 el2->num_values += el->num_values; 694 695 break; 696 697 case LDB_FLAG_MOD_REPLACE: 698 if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) { 699 if (el->num_values > 1) { 700 ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once", 701 el->name, ldb_dn_get_linearized(msg->dn)); 702 return LDB_ERR_CONSTRAINT_VIOLATION; 817 /* TODO: This is O(n^2) - replace with more efficient check */ 818 for (j=0; j<el->num_values; j++) { 819 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) { 820 ldb_asprintf_errstring(ldb, 821 "attribute '%s': value #%u on '%s' provided more than once", 822 el->name, j, ldb_dn_get_linearized(msg2->dn)); 823 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 824 goto done; 703 825 } 704 826 } 705 /* replace all elements of this attribute name with the elements 706 listed. The attribute not existing is not an error */ 707 msg_delete_attribute(module, ldb, msg2, el->name); 708 709 for (j=0;j<el->num_values;j++) { 710 if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) { 711 ldb_asprintf_errstring(ldb, "%s: value #%d provided more than once", el->name, j); 712 ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; 713 goto failed; 827 828 /* Checks if element already exists */ 829 idx = find_element(msg2, el->name); 830 if (idx != -1) { 831 j = (unsigned int) idx; 832 el2 = &(msg2->elements[j]); 833 if (ldb_msg_element_compare(el, el2) == 0) { 834 /* we are replacing with the same values */ 835 continue; 836 } 837 838 /* Delete the attribute if it exists in the DB */ 839 if (msg_delete_attribute(module, ldb, msg2, 840 el->name) != 0) { 841 ret = LDB_ERR_OTHER; 842 goto done; 714 843 } 715 844 } 716 845 717 /* add the replacement element, if not empty */ 718 if (el->num_values != 0 && 719 msg_add_element(ldb, msg2, el) != 0) { 846 /* Recreate it with the new values */ 847 if (ltdb_msg_add_element(ldb, msg2, el) != 0) { 720 848 ret = LDB_ERR_OTHER; 721 goto failed;849 goto done; 722 850 } 851 852 ret = ltdb_index_add_element(module, msg2->dn, el); 853 if (ret != LDB_SUCCESS) { 854 goto done; 855 } 856 723 857 break; 724 858 725 859 case LDB_FLAG_MOD_DELETE: 726 727 dn = ldb_dn_get_linearized(msg->dn); 860 dn = ldb_dn_get_linearized(msg2->dn); 728 861 if (dn == NULL) { 729 862 ret = LDB_ERR_OTHER; 730 goto failed;863 goto done; 731 864 } 732 865 733 /* we could be being asked to delete all734 values or just some values */735 866 if (msg->elements[i].num_values == 0) { 736 if (msg_delete_attribute(module, ldb, msg2, 737 msg->elements[i].name) != 0) { 738 ldb_asprintf_errstring(ldb, "No such attribute: %s for delete on %s", msg->elements[i].name, dn); 739 ret = LDB_ERR_NO_SUCH_ATTRIBUTE; 740 goto failed; 867 /* Delete the whole attribute */ 868 ret = msg_delete_attribute(module, ldb, msg2, 869 msg->elements[i].name); 870 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && 871 control_permissive) { 872 ret = LDB_SUCCESS; 873 } else { 874 ldb_asprintf_errstring(ldb, 875 "attribute '%s': no such attribute for delete on '%s'", 876 msg->elements[i].name, dn); 741 877 } 742 break; 743 } 744 for (j=0;j<msg->elements[i].num_values;j++) { 745 if (msg_delete_element(module, 746 msg2, 747 msg->elements[i].name, 748 &msg->elements[i].values[j]) != 0) { 749 ldb_asprintf_errstring(ldb, "No matching attribute value when deleting attribute: %s on %s", msg->elements[i].name, dn); 750 ret = LDB_ERR_NO_SUCH_ATTRIBUTE; 751 goto failed; 878 if (ret != LDB_SUCCESS) { 879 goto done; 752 880 } 753 ret = ltdb_index_del_value(module, dn, &msg->elements[i], j); 754 if (ret != LDB_SUCCESS) { 755 goto failed; 881 } else { 882 /* Delete specified values from an attribute */ 883 for (j=0; j < msg->elements[i].num_values; j++) { 884 ret = msg_delete_element(module, 885 msg2, 886 msg->elements[i].name, 887 &msg->elements[i].values[j]); 888 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE && 889 control_permissive) { 890 ret = LDB_SUCCESS; 891 } else { 892 ldb_asprintf_errstring(ldb, 893 "attribute '%s': no matching attribute value while deleting attribute on '%s'", 894 msg->elements[i].name, dn); 895 } 896 if (ret != LDB_SUCCESS) { 897 goto done; 898 } 756 899 } 757 900 } … … 759 902 default: 760 903 ldb_asprintf_errstring(ldb, 761 "Invalid ldb_modify flags on %s: 0x%x",762 msg->elements[i].name,763 msg->elements[i].flags & LDB_FLAG_MOD_MASK);904 "attribute '%s': invalid modify flags on '%s': 0x%x", 905 msg->elements[i].name, ldb_dn_get_linearized(msg->dn), 906 msg->elements[i].flags & LDB_FLAG_MOD_MASK); 764 907 ret = LDB_ERR_PROTOCOL_ERROR; 765 goto failed;908 goto done; 766 909 } 767 910 } 768 911 769 /* we've made all the mods770 * save the modified record back into the database */771 912 ret = ltdb_store(module, msg2, TDB_MODIFY); 772 913 if (ret != LDB_SUCCESS) { 773 goto failed;774 } 775 776 ret = ltdb_modified(module, msg ->dn);914 goto done; 915 } 916 917 ret = ltdb_modified(module, msg2->dn); 777 918 if (ret != LDB_SUCCESS) { 778 goto failed; 779 } 780 919 goto done; 920 } 921 922 done: 781 923 talloc_free(tdb_key.dptr); 782 free(tdb_data.dptr);783 return ret;784 785 failed:786 talloc_free(tdb_key.dptr);787 free(tdb_data.dptr);788 924 return ret; 789 925 } … … 796 932 struct ldb_module *module = ctx->module; 797 933 struct ldb_request *req = ctx->req; 798 int tret; 934 int ret = LDB_SUCCESS; 935 936 ret = ltdb_check_special_dn(module, req->op.mod.message); 937 if (ret != LDB_SUCCESS) { 938 return ret; 939 } 799 940 800 941 ldb_request_set_state(req, LDB_ASYNC_PENDING); 801 942 802 tret = ltdb_check_special_dn(module, req->op.mod.message);803 if (tret != LDB_SUCCESS) {804 return tret;805 }806 807 943 if (ltdb_cache_load(module) != 0) { 808 944 return LDB_ERR_OPERATIONS_ERROR; 809 945 } 810 946 811 tret = ltdb_modify_internal(module, req->op.mod.message); 812 if (tret != LDB_SUCCESS) { 813 return tret; 814 } 815 816 return LDB_SUCCESS; 947 ret = ltdb_modify_internal(module, req->op.mod.message, req); 948 949 return ret; 817 950 } 818 951 … … 825 958 struct ldb_request *req = ctx->req; 826 959 struct ldb_message *msg; 827 int tret;960 int ret = LDB_SUCCESS; 828 961 829 962 ldb_request_set_state(req, LDB_ASYNC_PENDING); … … 833 966 } 834 967 835 msg = talloc(ctx, struct ldb_message);968 msg = ldb_msg_new(ctx); 836 969 if (msg == NULL) { 837 970 return LDB_ERR_OPERATIONS_ERROR; … … 840 973 /* in case any attribute of the message was indexed, we need 841 974 to fetch the old record */ 842 tret = ltdb_search_dn1(module, req->op.rename.olddn, msg);843 if ( tret != LDB_SUCCESS) {975 ret = ltdb_search_dn1(module, req->op.rename.olddn, msg); 976 if (ret != LDB_SUCCESS) { 844 977 /* not finding the old record is an error */ 845 return tret; 846 } 847 848 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn); 849 if (!msg->dn) { 850 return LDB_ERR_OPERATIONS_ERROR; 978 return ret; 851 979 } 852 980 … … 855 983 * atomic 856 984 */ 857 tret = ltdb_delete_internal(module, req->op.rename.olddn); 858 if (tret != LDB_SUCCESS) { 859 return tret; 860 } 861 862 tret = ltdb_add_internal(module, msg); 863 if (tret != LDB_SUCCESS) { 864 return tret; 865 } 866 867 return LDB_SUCCESS; 985 ret = ltdb_delete_internal(module, msg->dn); 986 if (ret != LDB_SUCCESS) { 987 return ret; 988 } 989 990 msg->dn = ldb_dn_copy(msg, req->op.rename.newdn); 991 if (msg->dn == NULL) { 992 return LDB_ERR_OPERATIONS_ERROR; 993 } 994 995 ret = ltdb_add_internal(module, msg); 996 997 return ret; 868 998 } 869 999 … … 959 1089 struct ldb_module *module = ctx->module; 960 1090 struct ldb_request *req = ctx->req; 961 TALLOC_CTX *tmp_ctx ;1091 TALLOC_CTX *tmp_ctx = NULL; 962 1092 struct ldb_seqnum_request *seq; 963 1093 struct ldb_seqnum_result *res; … … 965 1095 struct ldb_dn *dn; 966 1096 const char *date; 967 int ret ;1097 int ret = LDB_SUCCESS; 968 1098 969 1099 ldb = ldb_module_get_ctx(module); … … 986 1116 goto done; 987 1117 } 1118 988 1119 tmp_ctx = talloc_new(req); 989 1120 if (tmp_ctx == NULL) { … … 993 1124 994 1125 dn = ldb_dn_new(tmp_ctx, ldb, LTDB_BASEINFO); 995 996 msg = talloc(tmp_ctx, struct ldb_message); 1126 if (dn == NULL) { 1127 ret = LDB_ERR_OPERATIONS_ERROR; 1128 goto done; 1129 } 1130 1131 msg = ldb_msg_new(tmp_ctx); 997 1132 if (msg == NULL) { 998 1133 ret = LDB_ERR_OPERATIONS_ERROR; … … 1031 1166 (*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER; 1032 1167 (*ext)->data = talloc_steal(*ext, res); 1033 1034 ret = LDB_SUCCESS;1035 1168 1036 1169 done: … … 1167 1300 default: 1168 1301 /* no other op supported */ 1169 ret = LDB_ERR_ UNWILLING_TO_PERFORM;1302 ret = LDB_ERR_PROTOCOL_ERROR; 1170 1303 } 1171 1304 … … 1197 1330 struct ldb_request *req) 1198 1331 { 1332 struct ldb_control *control_permissive; 1199 1333 struct ldb_context *ldb; 1200 1334 struct tevent_context *ev; … … 1202 1336 struct tevent_timer *te; 1203 1337 struct timeval tv; 1204 1205 if (check_critical_controls(req->controls)) { 1206 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; 1207 } 1338 unsigned int i; 1208 1339 1209 1340 ldb = ldb_module_get_ctx(module); 1341 1342 control_permissive = ldb_request_get_control(req, 1343 LDB_CONTROL_PERMISSIVE_MODIFY_OID); 1344 1345 for (i = 0; req->controls && req->controls[i]; i++) { 1346 if (req->controls[i]->critical && 1347 req->controls[i] != control_permissive) { 1348 ldb_asprintf_errstring(ldb, "Unsupported critical extension %s", 1349 req->controls[i]->oid); 1350 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; 1351 } 1352 } 1210 1353 1211 1354 if (req->starttime == 0 || req->timeout == 0) { … … 1218 1361 ac = talloc_zero(ldb, struct ltdb_context); 1219 1362 if (ac == NULL) { 1220 ldb_ set_errstring(ldb, "Out of Memory");1363 ldb_oom(ldb); 1221 1364 return LDB_ERR_OPERATIONS_ERROR; 1222 1365 } … … 1254 1397 } 1255 1398 1399 static int ltdb_init_rootdse(struct ldb_module *module) 1400 { 1401 struct ldb_context *ldb; 1402 int ret; 1403 1404 ldb = ldb_module_get_ctx(module); 1405 1406 ret = ldb_mod_register_control(module, 1407 LDB_CONTROL_PERMISSIVE_MODIFY_OID); 1408 /* ignore errors on this - we expect it for non-sam databases */ 1409 1410 /* there can be no module beyond the backend, just return */ 1411 return LDB_SUCCESS; 1412 } 1413 1256 1414 static const struct ldb_module_ops ltdb_ops = { 1257 1415 .name = "tdb", 1416 .init_context = ltdb_init_rootdse, 1258 1417 .search = ltdb_handle_request, 1259 1418 .add = ltdb_handle_request, … … 1285 1444 ldb_debug(ldb, LDB_DEBUG_ERROR, 1286 1445 "Invalid tdb URL '%s'", url); 1287 return -1;1446 return LDB_ERR_OPERATIONS_ERROR; 1288 1447 } 1289 1448 path = url+6; … … 1313 1472 if (!ltdb) { 1314 1473 ldb_oom(ldb); 1315 return -1;1474 return LDB_ERR_OPERATIONS_ERROR; 1316 1475 } 1317 1476 … … 1324 1483 "Unable to open tdb '%s'", path); 1325 1484 talloc_free(ltdb); 1326 return -1; 1485 return LDB_ERR_OPERATIONS_ERROR; 1486 } 1487 1488 if (getenv("LDB_WARN_UNINDEXED")) { 1489 ltdb->warn_unindexed = true; 1327 1490 } 1328 1491 … … 1332 1495 if (!module) { 1333 1496 talloc_free(ltdb); 1334 return -1;1497 return LDB_ERR_OPERATIONS_ERROR; 1335 1498 } 1336 1499 ldb_module_set_private(module, ltdb); 1500 talloc_steal(module, ltdb); 1337 1501 1338 1502 if (ltdb_cache_load(module) != 0) { 1339 1503 talloc_free(module); 1340 1504 talloc_free(ltdb); 1341 return -1;1505 return LDB_ERR_OPERATIONS_ERROR; 1342 1506 } 1343 1507 1344 1508 *_module = module; 1345 return 0; 1346 } 1347 1348 const struct ldb_backend_ops ldb_tdb_backend_ops = { 1349 .name = "tdb", 1350 .connect_fn = ltdb_connect 1351 }; 1509 return LDB_SUCCESS; 1510 } 1511 1512 int ldb_tdb_init(const char *version) 1513 { 1514 LDB_MODULE_CHECK_VERSION(version); 1515 return ldb_register_backend("tdb", ltdb_connect, false); 1516 } -
trunk/server/source4/lib/ldb/ldb_tdb/ldb_tdb.h
r414 r745 1 #include "ldb_includes.h" 1 #include "replace.h" 2 #include "system/filesys.h" 3 #include "system/time.h" 2 4 #include "tdb.h" 3 5 #include "ldb_module.h" … … 18 20 struct ldb_message *indexlist; 19 21 struct ldb_message *attributes; 22 bool one_level_indexes; 23 bool attribute_indexes; 20 24 21 25 struct { … … 30 34 struct ltdb_idxptr *idxptr; 31 35 bool prepared_commit; 36 int read_lock_count; 37 38 bool warn_unindexed; 32 39 }; 33 40 … … 59 66 #define LTDB_INDEXLIST "@INDEXLIST" 60 67 #define LTDB_IDX "@IDX" 61 #define LTDB_IDX PTR "@IDXPTR"68 #define LTDB_IDXVERSION "@IDXVERSION" 62 69 #define LTDB_IDXATTR "@IDXATTR" 63 70 #define LTDB_IDXONE "@IDXONE" … … 84 91 85 92 int ltdb_search_indexed(struct ltdb_context *ctx, uint32_t *); 86 int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg); 87 int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg); 88 int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add); 93 int ltdb_index_add_new(struct ldb_module *module, const struct ldb_message *msg); 94 int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg); 95 int ltdb_index_del_element(struct ldb_module *module, struct ldb_dn *dn, 96 struct ldb_message_element *el); 97 int ltdb_index_add_element(struct ldb_module *module, struct ldb_dn *dn, 98 struct ldb_message_element *el); 99 int ltdb_index_del_value(struct ldb_module *module, struct ldb_dn *dn, 100 struct ldb_message_element *el, unsigned int v_idx); 89 101 int ltdb_reindex(struct ldb_module *module); 90 102 int ltdb_index_transaction_start(struct ldb_module *module); … … 123 135 struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn); 124 136 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs); 137 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg, struct ldb_request *req); 125 138 int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn); 126 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg); 127 128 int ltdb_index_del_value(struct ldb_module *module, const char *dn, 129 struct ldb_message_element *el, int v_idx); 139 int ltdb_err_map(enum TDB_ERROR tdb_code); 130 140 131 141 struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, -
trunk/server/source4/lib/ldb/ldb_tdb/ldb_tdb_wrap.c
r414 r745 23 23 24 24 #include "ldb_tdb.h" 25 #include "dlinklist.h" 25 26 26 27 /* … … 43 44 { 44 45 tdb_close(w->tdb); 45 if (w->next) { 46 w->next->prev = w->prev; 47 } 48 if (w->prev) { 49 w->prev->next = w->next; 50 } 51 if (w == tdb_list) { 52 tdb_list = w->next; 53 } 46 DLIST_REMOVE(tdb_list, w); 54 47 return 0; 55 48 } … … 144 137 talloc_set_destructor(w, ltdb_wrap_destructor); 145 138 146 w->next = tdb_list; 147 w->prev = NULL; 148 if (tdb_list) { 149 tdb_list->prev = w; 150 } 151 tdb_list = w; 139 DLIST_ADD(tdb_list, w); 152 140 153 141 return w->tdb; -
trunk/server/source4/lib/ldb/man/ldbadd.1.xml
r414 r745 28 28 <title>DESCRIPTION</title> 29 29 30 <para>ldbadd adds records to an ldb( 7) database. It reads30 <para>ldbadd adds records to an ldb(3) database. It reads 31 31 the ldif(5) files specified on the command line and adds 32 32 the records from these files to the LDB database, which is specified … … 53 53 <term>-H <ldb-url></term> 54 54 <listitem><para> 55 LDB URL to connect to. See ldb( 7) for details.55 LDB URL to connect to. See ldb(3) for details. 56 56 </para></listitem> 57 57 </varlistentry> … … 82 82 <title>SEE ALSO</title> 83 83 84 <para>ldb( 7), ldbmodify, ldbdel, ldif(5)</para>84 <para>ldb(3), ldbmodify, ldbdel, ldif(5)</para> 85 85 86 86 </refsect1> -
trunk/server/source4/lib/ldb/man/ldbdel.1.xml
r414 r745 27 27 <title>DESCRIPTION</title> 28 28 29 <para>ldbdel deletes records from an ldb( 7) database.29 <para>ldbdel deletes records from an ldb(3) database. 30 30 It deletes the records identified by the dn's specified 31 31 on the command-line. </para> … … 51 51 <term>-H <ldb-url></term> 52 52 <listitem><para> 53 LDB URL to connect to. See ldb( 7) for details.53 LDB URL to connect to. See ldb(3) for details. 54 54 </para></listitem> 55 55 </varlistentry> … … 80 80 <title>SEE ALSO</title> 81 81 82 <para>ldb( 7), ldbmodify, ldbadd, ldif(5)</para>82 <para>ldb(3), ldbmodify, ldbadd, ldif(5)</para> 83 83 84 84 </refsect1> -
trunk/server/source4/lib/ldb/man/ldbedit.1.xml
r414 r745 173 173 <title>SEE ALSO</title> 174 174 175 <para>ldb( 7), ldbmodify(1), ldbdel(1), ldif(5), vi(1)</para>175 <para>ldb(3), ldbmodify(1), ldbdel(1), ldif(5), vi(1)</para> 176 176 177 177 </refsect1> -
trunk/server/source4/lib/ldb/man/ldbmodify.1.xml
r414 r745 43 43 <term>-H <ldb-url></term> 44 44 <listitem><para> 45 LDB URL to connect to. See ldb( 7) for details.45 LDB URL to connect to. See ldb(3) for details. 46 46 </para></listitem> 47 47 </varlistentry> … … 70 70 <title>SEE ALSO</title> 71 71 72 <para>ldb( 7), ldbedit</para>72 <para>ldb(3), ldbedit</para> 73 73 74 74 </refsect1> -
trunk/server/source4/lib/ldb/man/ldbrename.1.xml
r414 r745 49 49 <term>-H <ldb-url></term> 50 50 <listitem><para> 51 LDB URL to connect to. See ldb( 7) for details.51 LDB URL to connect to. See ldb(3) for details. 52 52 </para></listitem> 53 53 </varlistentry> … … 84 84 <title>SEE ALSO</title> 85 85 86 <para>ldb( 7), ldbmodify, ldbdel, ldif(5)</para>86 <para>ldb(3), ldbmodify, ldbdel, ldif(5)</para> 87 87 88 88 </refsect1> -
trunk/server/source4/lib/ldb/man/ldbsearch.1.xml
r414 r745 52 52 <term>-H <ldb-url></term> 53 53 <listitem><para> 54 LDB URL to connect to. See ldb( 7) for details.54 LDB URL to connect to. See ldb(3) for details. 55 55 </para></listitem> 56 56 </varlistentry> … … 96 96 <title>SEE ALSO</title> 97 97 98 <para>ldb( 7), ldbedit(1)</para>98 <para>ldb(3), ldbedit(1)</para> 99 99 100 100 </refsect1> -
trunk/server/source4/lib/ldb/modules/asq.c
r414 r745 33 33 */ 34 34 35 #include "replace.h" 36 #include "system/filesys.h" 37 #include "system/time.h" 35 38 #include "ldb_module.h" 36 39 … … 56 59 57 60 struct ldb_request **reqs; 58 int num_reqs;59 int cur_req;61 unsigned int num_reqs; 62 unsigned int cur_req; 60 63 61 64 struct ldb_control **controls; … … 86 89 { 87 90 struct ldb_asq_control *asq; 88 int i;91 unsigned int i; 89 92 90 93 if (ac->controls) { … … 238 241 ac->req); 239 242 if (ret != LDB_SUCCESS) { 240 return LDB_ERR_OPERATIONS_ERROR;243 return ret; 241 244 } 242 245 … … 251 254 struct ldb_dn *dn; 252 255 struct ldb_message_element *el; 253 int ret, i; 256 unsigned int i; 257 int ret; 254 258 255 259 if (ac->base_res == NULL) { … … 293 297 ac->req); 294 298 if (ret != LDB_SUCCESS) { 295 return LDB_ERR_OPERATIONS_ERROR;299 return ret; 296 300 } 297 301 298 302 /* remove the ASQ control itself */ 299 303 control = ldb_request_get_control(ac->req, LDB_CONTROL_ASQ_OID); 300 if (! save_controls(control, ac->reqs[i], &saved_controls)) {304 if (!ldb_save_controls(control, ac->reqs[i], &saved_controls)) { 301 305 return LDB_ERR_OPERATIONS_ERROR; 302 306 } … … 400 404 } 401 405 402 const struct ldb_module_ops ldb_asq_module_ops = {406 static const struct ldb_module_ops ldb_asq_module_ops = { 403 407 .name = "asq", 404 408 .search = asq_search, 405 409 .init_context = asq_init 406 410 }; 411 412 int ldb_asq_init(const char *version) 413 { 414 LDB_MODULE_CHECK_VERSION(version); 415 return ldb_register_module(&ldb_asq_module_ops); 416 } -
trunk/server/source4/lib/ldb/modules/paged_results.c
r414 r745 33 33 */ 34 34 35 #include "ldb_includes.h" 35 #include "replace.h" 36 #include "system/filesys.h" 37 #include "system/time.h" 36 38 #include "ldb_module.h" 37 39 … … 66 68 67 69 struct private_data { 68 69 int next_free_id; 70 unsigned int next_free_id; 70 71 struct results_store *store; 71 72 … … 96 97 { 97 98 struct results_store *newr; 98 int new_id = priv->next_free_id++;99 unsigned int new_id = priv->next_free_id++; 99 100 100 101 /* TODO: we should have a limit on the number of … … 141 142 struct ldb_paged_control *paged; 142 143 struct message_store *msg; 143 int i, num_ctrls, ret; 144 unsigned int i, num_ctrls; 145 int ret; 144 146 145 147 if (ac->store == NULL) { … … 327 329 ac->req = req; 328 330 ac->size = paged_ctrl->size; 331 if (ac->size < 0) { 332 /* apparently some clients send more than 2^31. This 333 violates the ldap standard, but we need to cope */ 334 ac->size = 0x7FFFFFFF; 335 } 329 336 330 337 /* check if it is a continuation search the store */ … … 348 355 paged_search_callback, 349 356 req); 357 if (ret != LDB_SUCCESS) { 358 return ret; 359 } 350 360 351 361 /* save it locally and remove it from the list */ 352 362 /* we do not need to replace them later as we 353 363 * are keeping the original req intact */ 354 if (! save_controls(control, search_req, &saved_controls)) {364 if (!ldb_save_controls(control, search_req, &saved_controls)) { 355 365 return LDB_ERR_OPERATIONS_ERROR; 356 366 } … … 416 426 } 417 427 418 const struct ldb_module_ops ldb_paged_results_module_ops = {428 static const struct ldb_module_ops ldb_paged_results_module_ops = { 419 429 .name = "paged_results", 420 430 .search = paged_search, 421 431 .init_context = paged_request_init 422 432 }; 433 434 int ldb_paged_results_init(const char *version) 435 { 436 LDB_MODULE_CHECK_VERSION(version); 437 return ldb_register_module(&ldb_paged_results_module_ops); 438 } -
trunk/server/source4/lib/ldb/modules/paged_searches.c
r414 r745 34 34 */ 35 35 36 #include "includes.h" 36 #include "replace.h" 37 #include "system/filesys.h" 38 #include "system/time.h" 37 39 #include "ldb_module.h" 38 40 … … 53 55 54 56 char **saved_referrals; 55 int num_referrals;57 unsigned int num_referrals; 56 58 57 59 struct ldb_request *down_req; … … 79 81 return LDB_ERR_OPERATIONS_ERROR; 80 82 } else { 81 /* No cookie rec ived yet, valid to just return the full data set */83 /* No cookie received yet, valid to just return the full data set */ 82 84 83 85 /* we are done */ … … 133 135 struct ldb_reply *ares; 134 136 int ret; 135 int i;137 unsigned int i; 136 138 137 139 for (i = 0; i < ac->num_referrals; i++) { … … 271 273 ps_callback, 272 274 ac->req); 275 LDB_REQ_SET_LOCATION(ac->down_req); 273 276 if (ret != LDB_SUCCESS) { 274 277 return ret; … … 352 355 data, check_supported_paged, 353 356 NULL); 357 LDB_REQ_SET_LOCATION(req); 354 358 if (ret != LDB_SUCCESS) { 355 359 return ret; … … 370 374 } 371 375 372 _PUBLIC_const struct ldb_module_ops ldb_paged_searches_module_ops = {376 static const struct ldb_module_ops ldb_paged_searches_module_ops = { 373 377 .name = "paged_searches", 374 378 .search = ps_search, 375 379 .init_context = ps_init 376 380 }; 381 382 int ldb_paged_searches_init(const char *version) 383 { 384 LDB_MODULE_CHECK_VERSION(version); 385 return ldb_register_module(&ldb_paged_searches_module_ops); 386 } -
trunk/server/source4/lib/ldb/modules/rdn_name.c
r414 r745 2 2 ldb database library 3 3 4 Copyright (C) Andrew Bartlett 2005 4 Copyright (C) Andrew Bartlett 2005-2009 5 5 Copyright (C) Simo Sorce 2006-2008 6 6 … … 37 37 */ 38 38 39 #include "ldb_includes.h" 39 #include "replace.h" 40 #include "system/filesys.h" 41 #include "system/time.h" 40 42 #include "ldb_module.h" 41 43 42 44 struct rename_context { 43 44 45 struct ldb_module *module; 45 46 struct ldb_request *req; … … 47 48 struct ldb_reply *ares; 48 49 }; 49 50 static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)51 {52 int i;53 54 for (i = 0; i < msg->num_elements; i++) {55 if (ldb_attr_cmp(name, msg->elements[i].name) == 0) {56 return &msg->elements[i];57 }58 }59 60 return NULL;61 }62 50 63 51 static int rdn_name_add_callback(struct ldb_request *req, … … 72 60 LDB_ERR_OPERATIONS_ERROR); 73 61 } 62 63 if (ares->type == LDB_REPLY_REFERRAL) { 64 return ldb_module_send_referral(ac->req, ares->referral); 65 } 66 74 67 if (ares->error != LDB_SUCCESS) { 75 68 return ldb_module_done(ac->req, ares->controls, … … 95 88 const struct ldb_schema_attribute *a; 96 89 const char *rdn_name; 90 const struct ldb_val *rdn_val_p; 97 91 struct ldb_val rdn_val; 98 int i, ret; 92 unsigned int i; 93 int ret; 99 94 100 95 ldb = ldb_module_get_ctx(module); 101 ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_add_record");102 96 103 97 /* do not manipulate our control entries */ … … 121 115 rdn_name = ldb_dn_get_rdn_name(msg->dn); 122 116 if (rdn_name == NULL) { 123 talloc_free(ac);124 117 return LDB_ERR_OPERATIONS_ERROR; 125 118 } 126 119 127 rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(msg->dn)); 128 129 /* Perhaps someone above us tried to set this? */ 130 if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) { 131 attribute->num_values = 0; 132 } 133 134 if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) { 135 talloc_free(ac); 136 return LDB_ERR_OPERATIONS_ERROR; 137 } 138 139 attribute = rdn_name_find_attribute(msg, rdn_name); 140 120 rdn_val_p = ldb_dn_get_rdn_val(msg->dn); 121 if (rdn_val_p == NULL) { 122 return LDB_ERR_OPERATIONS_ERROR; 123 } 124 if (rdn_val_p->length == 0) { 125 ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!", 126 ldb_dn_get_linearized(req->op.add.message->dn)); 127 return LDB_ERR_INVALID_DN_SYNTAX; 128 } 129 rdn_val = ldb_val_dup(msg, rdn_val_p); 130 131 /* Perhaps someone above us tried to set this? Then ignore it */ 132 ldb_msg_remove_attr(msg, "name"); 133 134 ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL); 135 if (ret != LDB_SUCCESS) { 136 return ret; 137 } 138 139 a = ldb_schema_attribute_by_name(ldb, rdn_name); 140 if (a == NULL) { 141 return LDB_ERR_OPERATIONS_ERROR; 142 } 143 144 attribute = ldb_msg_find_element(msg, rdn_name); 141 145 if (!attribute) { 142 if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) { 143 talloc_free(ac); 144 return LDB_ERR_OPERATIONS_ERROR; 146 /* add entry with normalised RDN information if possible */ 147 if (a->name != NULL) { 148 ret = ldb_msg_add_value(msg, a->name, &rdn_val, NULL); 149 } else { 150 ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL); 151 } 152 if (ret != LDB_SUCCESS) { 153 return ret; 145 154 } 146 155 } else { 147 a = ldb_schema_attribute_by_name(ldb, rdn_name); 148 156 /* normalise attribute name if possible */ 157 if (a->name != NULL) { 158 attribute->name = a->name; 159 } 160 /* normalise attribute value */ 149 161 for (i = 0; i < attribute->num_values; i++) { 150 ret = a->syntax->comparison_fn(ldb, msg, 151 &rdn_val, &attribute->values[i]); 152 if (ret == 0) { 162 bool matched; 163 if (a->syntax->operator_fn) { 164 ret = a->syntax->operator_fn(ldb, LDB_OP_EQUALITY, a, 165 &rdn_val, &attribute->values[i], &matched); 166 if (ret != LDB_SUCCESS) return ret; 167 } else { 168 matched = (a->syntax->comparison_fn(ldb, msg, 169 &rdn_val, &attribute->values[i]) == 0); 170 } 171 if (matched) { 153 172 /* overwrite so it matches in case */ 154 173 attribute->values[i] = rdn_val; … … 157 176 } 158 177 if (i == attribute->num_values) { 159 char *rdn_errstring = talloc_asprintf(ac, "RDN mismatch on %s: %s (%.*s) should match one of:", 160 ldb_dn_get_linearized(msg->dn), rdn_name, 161 (int)rdn_val.length, (const char *)rdn_val.data); 178 char *rdn_errstring = talloc_asprintf(ac, 179 "RDN mismatch on %s: %s (%.*s) should match one of:", 180 ldb_dn_get_linearized(msg->dn), rdn_name, 181 (int)rdn_val.length, (const char *)rdn_val.data); 162 182 for (i = 0; i < attribute->num_values; i++) { 163 rdn_errstring = talloc_asprintf_append(rdn_errstring, " (%.*s)", 164 (int)attribute->values[i].length, 165 (const char *)attribute->values[i].data); 183 rdn_errstring = talloc_asprintf_append( 184 rdn_errstring, " (%.*s)", 185 (int)attribute->values[i].length, 186 (const char *)attribute->values[i].data); 166 187 } 167 ldb_debug_set(ldb, LDB_DEBUG_FATAL, "%s", rdn_errstring); 168 talloc_free(ac); 188 ldb_set_errstring(ldb, rdn_errstring); 169 189 /* Match AD's error here */ 170 190 return LDB_ERR_INVALID_DN_SYNTAX; … … 197 217 LDB_ERR_OPERATIONS_ERROR); 198 218 } 219 220 if (ares->type == LDB_REPLY_REFERRAL) { 221 return ldb_module_send_referral(ac->req, ares->referral); 222 } 223 199 224 if (ares->error != LDB_SUCCESS) { 200 225 return ldb_module_done(ac->req, ares->controls, … … 219 244 struct ldb_request *mod_req; 220 245 const char *rdn_name; 246 const struct ldb_val *rdn_val_p; 221 247 struct ldb_val rdn_val; 222 248 struct ldb_message *msg; … … 229 255 goto error; 230 256 } 257 258 if (ares->type == LDB_REPLY_REFERRAL) { 259 return ldb_module_send_referral(ac->req, ares->referral); 260 } 261 231 262 if (ares->error != LDB_SUCCESS) { 232 263 return ldb_module_done(ac->req, ares->controls, … … 250 281 goto error; 251 282 } 283 252 284 rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn); 253 285 if (rdn_name == NULL) { 254 286 goto error; 255 287 } 256 257 rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(ac->req->op.rename.newdn)); 258 288 289 rdn_val_p = ldb_dn_get_rdn_val(msg->dn); 290 if (rdn_val_p == NULL) { 291 goto error; 292 } 293 if (rdn_val_p->length == 0) { 294 ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!", 295 ldb_dn_get_linearized(req->op.rename.olddn)); 296 return ldb_module_done(ac->req, NULL, NULL, 297 LDB_ERR_NAMING_VIOLATION); 298 } 299 rdn_val = ldb_val_dup(msg, rdn_val_p); 300 259 301 if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { 260 302 goto error; … … 279 321 talloc_steal(mod_req, msg); 280 322 281 /* do the mod call*/282 return ldb_ request(ldb, mod_req);323 /* go on with the call chain */ 324 return ldb_next_request(ac->module, mod_req); 283 325 284 326 error: 285 return ldb_module_done(ac->req, NULL, NULL, 286 LDB_ERR_OPERATIONS_ERROR); 327 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR); 287 328 } 288 329 … … 295 336 296 337 ldb = ldb_module_get_ctx(module); 297 ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_rename");298 338 299 339 /* do not manipulate our control entries */ … … 321 361 322 362 if (ret != LDB_SUCCESS) { 323 return LDB_ERR_OPERATIONS_ERROR;363 return ret; 324 364 } 325 365 … … 328 368 } 329 369 330 const struct ldb_module_ops ldb_rdn_name_module_ops = { 370 static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) 371 { 372 struct ldb_context *ldb; 373 const struct ldb_val *rdn_val_p; 374 375 ldb = ldb_module_get_ctx(module); 376 377 /* do not manipulate our control entries */ 378 if (ldb_dn_is_special(req->op.mod.message->dn)) { 379 return ldb_next_request(module, req); 380 } 381 382 rdn_val_p = ldb_dn_get_rdn_val(req->op.mod.message->dn); 383 if (rdn_val_p == NULL) { 384 return LDB_ERR_OPERATIONS_ERROR; 385 } 386 if (rdn_val_p->length == 0) { 387 ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!", 388 ldb_dn_get_linearized(req->op.mod.message->dn)); 389 return LDB_ERR_INVALID_DN_SYNTAX; 390 } 391 392 if (ldb_msg_find_element(req->op.mod.message, "distinguishedName")) { 393 ldb_asprintf_errstring(ldb, "Modify of 'distinguishedName' on %s not permitted, must use 'rename' operation instead", 394 ldb_dn_get_linearized(req->op.mod.message->dn)); 395 return LDB_ERR_CONSTRAINT_VIOLATION; 396 } 397 398 if (ldb_msg_find_element(req->op.mod.message, "name")) { 399 ldb_asprintf_errstring(ldb, "Modify of 'name' on %s not permitted, must use 'rename' operation instead", 400 ldb_dn_get_linearized(req->op.mod.message->dn)); 401 return LDB_ERR_NOT_ALLOWED_ON_RDN; 402 } 403 404 if (ldb_msg_find_element(req->op.mod.message, ldb_dn_get_rdn_name(req->op.mod.message->dn))) { 405 ldb_asprintf_errstring(ldb, "Modify of RDN '%s' on %s not permitted, must use 'rename' operation instead", 406 ldb_dn_get_rdn_name(req->op.mod.message->dn), ldb_dn_get_linearized(req->op.mod.message->dn)); 407 return LDB_ERR_NOT_ALLOWED_ON_RDN; 408 } 409 410 /* All OK, they kept their fingers out of the special attributes */ 411 return ldb_next_request(module, req); 412 } 413 414 static int rdn_name_search(struct ldb_module *module, struct ldb_request *req) 415 { 416 struct ldb_context *ldb; 417 const char *rdn_name; 418 const struct ldb_val *rdn_val_p; 419 420 ldb = ldb_module_get_ctx(module); 421 422 /* do not manipulate our control entries */ 423 if (ldb_dn_is_special(req->op.search.base)) { 424 return ldb_next_request(module, req); 425 } 426 427 rdn_name = ldb_dn_get_rdn_name(req->op.search.base); 428 rdn_val_p = ldb_dn_get_rdn_val(req->op.search.base); 429 if ((rdn_name != NULL) && (rdn_val_p == NULL)) { 430 return LDB_ERR_OPERATIONS_ERROR; 431 } 432 if ((rdn_val_p != NULL) && (rdn_val_p->length == 0)) { 433 ldb_asprintf_errstring(ldb, "Empty RDN value on %s not permitted!", 434 ldb_dn_get_linearized(req->op.search.base)); 435 return LDB_ERR_INVALID_DN_SYNTAX; 436 } 437 438 return ldb_next_request(module, req); 439 } 440 441 static const struct ldb_module_ops ldb_rdn_name_module_ops = { 331 442 .name = "rdn_name", 332 443 .add = rdn_name_add, 444 .modify = rdn_name_modify, 333 445 .rename = rdn_name_rename, 446 .search = rdn_name_search 334 447 }; 448 449 int ldb_rdn_name_init(const char *version) 450 { 451 LDB_MODULE_CHECK_VERSION(version); 452 return ldb_register_module(&ldb_rdn_name_module_ops); 453 } -
trunk/server/source4/lib/ldb/modules/skel.c
r414 r745 1 /* 1 /* 2 2 ldb database library 3 3 … … 7 7 ** library. This does NOT imply that all of Samba is released 8 8 ** under the LGPL 9 9 10 10 This library is free software; you can redistribute it and/or 11 11 modify it under the terms of the GNU Lesser General Public … … 32 32 */ 33 33 34 #include "replace.h" 35 #include "system/filesys.h" 36 #include "system/time.h" 34 37 #include "ldb_module.h" 35 38 … … 124 127 } 125 128 126 const struct ldb_module_ops ldb_skel_module_ops = {129 static const struct ldb_module_ops ldb_skel_module_ops = { 127 130 .name = "skel", 128 131 .init_context = skel_init, … … 137 140 .del_transaction = skel_del_trans, 138 141 }; 142 143 int ldb_skel_init(const char *version) 144 { 145 LDB_MODULE_CHECK_VERSION(version); 146 return ldb_register_module(&ldb_skel_module_ops); 147 } -
trunk/server/source4/lib/ldb/modules/sort.c
r414 r745 32 32 */ 33 33 34 #include "replace.h" 35 #include "system/filesys.h" 36 #include "system/time.h" 34 37 #include "ldb_module.h" 35 38 … … 45 48 struct ldb_module *module; 46 49 47 c har *attributeName;48 c har *orderingRule;50 const char *attributeName; 51 const char *orderingRule; 49 52 int reverse; 50 53 … … 52 55 struct ldb_message **msgs; 53 56 char **referrals; 54 int num_msgs;55 int num_refs;57 unsigned int num_msgs; 58 unsigned int num_refs; 56 59 57 60 const struct ldb_schema_attribute *a; … … 63 66 struct ldb_control **controls; 64 67 struct ldb_sort_resp_control *resp; 65 int i;68 unsigned int i; 66 69 67 70 if (*ctrls) { … … 138 141 struct ldb_context *ldb; 139 142 struct ldb_reply *ares; 140 int i, ret; 143 unsigned int i; 144 int ret; 141 145 142 146 ldb = ldb_module_get_ctx(ac->module); … … 145 149 ac->sort_result = 0; 146 150 147 ldb_qsort(ac->msgs, ac->num_msgs, 148 sizeof(struct ldb_message *), 149 ac, (ldb_qsort_cmp_fn_t)sort_compare); 151 LDB_TYPESAFE_QSORT(ac->msgs, ac->num_msgs, ac, sort_compare); 150 152 151 153 if (ac->sort_result != LDB_SUCCESS) { … … 316 318 req); 317 319 if (ret != LDB_SUCCESS) { 318 return LDB_ERR_OPERATIONS_ERROR;320 return ret; 319 321 } 320 322 … … 322 324 /* we do not need to replace them later as we 323 325 * are keeping the original req intact */ 324 if (! save_controls(control, down_req, &saved_controls)) {326 if (!ldb_save_controls(control, down_req, &saved_controls)) { 325 327 return LDB_ERR_OPERATIONS_ERROR; 326 328 } … … 346 348 } 347 349 348 const struct ldb_module_ops ldb_server_sort_module_ops = {350 static const struct ldb_module_ops ldb_server_sort_module_ops = { 349 351 .name = "server_sort", 350 352 .search = server_sort_search, 351 353 .init_context = server_sort_init 352 354 }; 355 356 int ldb_server_sort_init(const char *version) 357 { 358 LDB_MODULE_CHECK_VERSION(version); 359 return ldb_register_module(&ldb_server_sort_module_ops); 360 } -
trunk/server/source4/lib/ldb/nssldb/ldb-nss.c
r414 r745 192 192 size_t bufpos; 193 193 size_t lsize; 194 int i;194 unsigned int i; 195 195 196 196 bufpos = 0; … … 281 281 { 282 282 NSS_STATUS ret; 283 int i;283 unsigned int i; 284 284 285 285 for (i = 0; i < grlist->count; i++) { -
trunk/server/source4/lib/ldb/pyldb.c
r414 r745 6 6 Copyright (C) 2005,2006 Tim Potter <tpot@samba.org> 7 7 Copyright (C) 2006 Simo Sorce <idra@samba.org> 8 Copyright (C) 2007-20 09Jelmer Vernooij <jelmer@samba.org>9 Copyright (C) 2009 Matthias Dieter Wallnöfer10 11 12 13 8 Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org> 9 Copyright (C) 2009-2010 Matthias Dieter Wallnöfer 10 11 ** NOTE! The following LGPL license applies to the ldb 12 ** library. This does NOT imply that all of Samba is released 13 ** under the LGPL 14 14 15 15 This library is free software; you can redistribute it and/or … … 27 27 */ 28 28 29 #include "replace.h" 29 #include <Python.h> 30 #include <pytalloc.h> 30 31 #include "ldb_private.h" 31 #include <Python.h>32 32 #include "pyldb.h" 33 34 void initldb(void); 35 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg); 36 static PyObject *PyExc_LdbError; 37 38 staticforward PyTypeObject PyLdbControl; 39 staticforward PyTypeObject PyLdbResult; 40 staticforward PyTypeObject PyLdbMessage; 41 staticforward PyTypeObject PyLdbModule; 42 staticforward PyTypeObject PyLdbDn; 43 staticforward PyTypeObject PyLdb; 44 staticforward PyTypeObject PyLdbMessageElement; 45 staticforward PyTypeObject PyLdbTree; 46 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx); 47 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod); 48 static struct ldb_message_element *PyObject_AsMessageElement( 49 TALLOC_CTX *mem_ctx, 50 PyObject *set_obj, 51 int flags, 52 const char *attr_name); 33 53 34 54 /* There's no Py_ssize_t in 2.4, apparently */ … … 43 63 #endif 44 64 65 #define SIGN(a) (((a) == 0)?0:((a) < 0?-1:1)) 66 67 68 69 static PyObject *py_ldb_control_str(PyLdbControlObject *self) 70 { 71 if (self->data != NULL) { 72 char* control = ldb_control_to_string(self->mem_ctx, self->data); 73 if (control == NULL) { 74 PyErr_NoMemory(); 75 return NULL; 76 } 77 return PyString_FromString(control); 78 } else { 79 return PyString_FromFormat("ldb control"); 80 } 81 } 82 83 static void py_ldb_control_dealloc(PyLdbControlObject *self) 84 { 85 if (self->mem_ctx != NULL) { 86 talloc_free(self->mem_ctx); 87 } 88 self->ob_type->tp_free(self); 89 } 90 91 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self) 92 { 93 return PyString_FromString(self->data->oid); 94 } 95 96 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self) 97 { 98 return PyBool_FromLong(self->data->critical); 99 } 100 101 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure) 102 { 103 if (PyObject_IsTrue(value)) { 104 self->data->critical = true; 105 } else { 106 self->data->critical = false; 107 } 108 return 0; 109 } 110 111 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 112 { 113 char *data = NULL; 114 const char *array[2]; 115 const char * const kwnames[] = { "ldb", "data", NULL }; 116 struct ldb_control *parsed_controls; 117 PyLdbControlObject *ret; 118 PyObject *py_ldb; 119 TALLOC_CTX *mem_ctx; 120 struct ldb_context *ldb_ctx; 121 122 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os", 123 discard_const_p(char *, kwnames), 124 &py_ldb, &data)) 125 return NULL; 126 127 mem_ctx = talloc_new(NULL); 128 if (mem_ctx == NULL) { 129 PyErr_NoMemory(); 130 return NULL; 131 } 132 133 ldb_ctx = PyLdb_AsLdbContext(py_ldb); 134 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data); 135 136 if (!parsed_controls) { 137 talloc_free(mem_ctx); 138 PyErr_SetString(PyExc_ValueError, "unable to parse control string"); 139 return NULL; 140 } 141 142 ret = PyObject_New(PyLdbControlObject, type); 143 if (ret == NULL) { 144 PyErr_NoMemory(); 145 talloc_free(mem_ctx); 146 return NULL; 147 } 148 149 ret->mem_ctx = mem_ctx; 150 151 ret->data = talloc_steal(mem_ctx, parsed_controls); 152 if (ret->data == NULL) { 153 Py_DECREF(ret); 154 PyErr_NoMemory(); 155 talloc_free(mem_ctx); 156 return NULL; 157 } 158 159 return (PyObject *)ret; 160 } 161 162 static PyGetSetDef py_ldb_control_getset[] = { 163 { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL }, 164 { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL }, 165 { NULL } 166 }; 167 168 static PyTypeObject PyLdbControl = { 169 .tp_name = "ldb.control", 170 .tp_dealloc = (destructor)py_ldb_control_dealloc, 171 .tp_getattro = PyObject_GenericGetAttr, 172 .tp_basicsize = sizeof(PyLdbControlObject), 173 .tp_getset = py_ldb_control_getset, 174 .tp_doc = "LDB control.", 175 .tp_str = (reprfunc)py_ldb_control_str, 176 .tp_new = py_ldb_control_new, 177 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 178 }; 179 45 180 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx) 46 181 { … … 49 184 50 185 PyErr_SetObject(error, 51 Py_BuildValue(discard_const_p(char, "(i,s)"), ret, 52 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx))); 53 } 54 55 static PyObject *PyExc_LdbError; 56 57 PyAPI_DATA(PyTypeObject) PyLdbMessage; 58 PyAPI_DATA(PyTypeObject) PyLdbModule; 59 PyAPI_DATA(PyTypeObject) PyLdbDn; 60 PyAPI_DATA(PyTypeObject) PyLdb; 61 PyAPI_DATA(PyTypeObject) PyLdbMessageElement; 62 PyAPI_DATA(PyTypeObject) PyLdbTree; 63 64 static PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx, 65 struct ldb_message_element *el, 66 struct ldb_val *val) 67 { 68 struct ldb_val new_val; 69 TALLOC_CTX *mem_ctx = talloc_new(NULL); 70 PyObject *ret; 71 72 new_val = *val; 73 74 ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length); 75 76 talloc_free(mem_ctx); 77 78 return ret; 186 Py_BuildValue(discard_const_p(char, "(i,s)"), ret, 187 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx))); 188 } 189 190 static PyObject *PyObject_FromLdbValue(struct ldb_val *val) 191 { 192 return PyString_FromStringAndSize((const char *)val->data, val->length); 79 193 } 80 194 81 195 /** 82 * Obtain a ldb DN from a Python object.196 * Create a Python object from a ldb_result. 83 197 * 84 * @param mem_ctx Memory context 85 * @param object Python object 86 * @param ldb_ctx LDB context 87 * @return Whether or not the conversion succeeded 198 * @param result LDB result to convert 199 * @return Python object with converted result (a list object) 88 200 */ 89 bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, 90 struct ldb_context *ldb_ctx, struct ldb_dn **dn) 91 { 92 struct ldb_dn *odn; 93 94 if (ldb_ctx != NULL && PyString_Check(object)) { 95 odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object)); 96 *dn = odn; 97 return true; 98 } 99 100 if (PyLdbDn_Check(object)) { 101 *dn = PyLdbDn_AsDn(object); 102 return true; 103 } 104 105 PyErr_SetString(PyExc_TypeError, "Expected DN"); 106 return false; 201 static PyObject *PyLdbControl_FromControl(struct ldb_control *control) 202 { 203 TALLOC_CTX *ctl_ctx = talloc_new(NULL); 204 PyLdbControlObject *ctrl; 205 if (ctl_ctx == NULL) { 206 PyErr_NoMemory(); 207 return NULL; 208 } 209 210 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0); 211 if (ctrl == NULL) { 212 PyErr_NoMemory(); 213 return NULL; 214 } 215 ctrl->mem_ctx = ctl_ctx; 216 ctrl->data = talloc_steal(ctrl->mem_ctx, control); 217 if (ctrl->data == NULL) { 218 Py_DECREF(ctrl); 219 PyErr_NoMemory(); 220 return NULL; 221 } 222 return (PyObject*) ctrl; 107 223 } 108 224 … … 115 231 static PyObject *PyLdbResult_FromResult(struct ldb_result *result) 116 232 { 117 PyObject *ret; 118 int i; 233 PyLdbResultObject *ret; 234 PyObject *list, *controls, *referals; 235 Py_ssize_t i; 236 119 237 if (result == NULL) { 120 238 Py_RETURN_NONE; 121 } 122 ret = PyList_New(result->count); 239 } 240 241 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0); 242 if (ret == NULL) { 243 PyErr_NoMemory(); 244 return NULL; 245 } 246 247 list = PyList_New(result->count); 248 if (list == NULL) { 249 PyErr_NoMemory(); 250 Py_DECREF(ret); 251 return NULL; 252 } 253 123 254 for (i = 0; i < result->count; i++) { 124 PyList_SetItem(ret, i, PyLdbMessage_FromMessage(result->msgs[i]) 125 ); 126 } 127 return ret; 255 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i])); 256 } 257 258 ret->mem_ctx = talloc_new(NULL); 259 if (ret->mem_ctx == NULL) { 260 Py_DECREF(list); 261 Py_DECREF(ret); 262 PyErr_NoMemory(); 263 return NULL; 264 } 265 266 ret->msgs = list; 267 268 if (result->controls) { 269 controls = PyList_New(1); 270 if (controls == NULL) { 271 Py_DECREF(ret); 272 PyErr_NoMemory(); 273 return NULL; 274 } 275 for (i=0; result->controls[i]; i++) { 276 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]); 277 if (ctrl == NULL) { 278 Py_DECREF(ret); 279 Py_DECREF(controls); 280 PyErr_NoMemory(); 281 return NULL; 282 } 283 PyList_SetItem(controls, i, ctrl); 284 } 285 } else { 286 /* 287 * No controls so we keep an empty list 288 */ 289 controls = PyList_New(0); 290 if (controls == NULL) { 291 Py_DECREF(ret); 292 PyErr_NoMemory(); 293 return NULL; 294 } 295 } 296 297 ret->controls = controls; 298 299 i = 0; 300 301 while (result->refs && result->refs[i]) { 302 i++; 303 } 304 305 referals = PyList_New(i); 306 if (referals == NULL) { 307 Py_DECREF(ret); 308 PyErr_NoMemory(); 309 return NULL; 310 } 311 312 for (i = 0;result->refs && result->refs[i]; i++) { 313 PyList_SetItem(referals, i, PyString_FromString(result->refs[i])); 314 } 315 ret->referals = referals; 316 return (PyObject *)ret; 128 317 } 129 318 … … 137 326 */ 138 327 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, 139 328 PyObject *obj) 140 329 { 141 330 struct ldb_result *res; 142 int i;331 Py_ssize_t i; 143 332 144 333 if (obj == Py_None) … … 296 485 "S.canonical_ex_str() -> string\n" 297 486 "Canonical version of this DN (like a posix path, with terminating newline)." }, 298 { "check_special", (PyCFunction)py_ldb_dn_is_special, METH_VARARGS,299 NULL },300 487 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS, 301 488 "S.parent() -> dn\n" … … 308 495 "Add a base DN to this DN." }, 309 496 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS, 310 NULL }, 497 "S.check_special(name) -> bool\n\n" 498 "Check if name is a special DN name"}, 311 499 { NULL } 312 500 }; … … 366 554 367 555 ret = ldb_dn_new(mem_ctx, ldb_ctx, str); 368 369 if (ret == NULL || !ldb_dn_validate(ret)) { 556 if (!ldb_dn_validate(ret)) { 370 557 talloc_free(mem_ctx); 371 558 PyErr_SetString(PyExc_ValueError, "unable to parse dn string"); … … 384 571 } 385 572 386 PyObject *PyLdbDn_FromDn(struct ldb_dn *dn)387 {388 PyLdbDnObject *py_ret;389 390 if (dn == NULL) {391 Py_RETURN_NONE;392 }393 394 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);395 if (py_ret == NULL) {396 PyErr_NoMemory();397 return NULL;398 }399 py_ret->mem_ctx = talloc_new(NULL);400 py_ret->dn = talloc_reference(py_ret->mem_ctx, dn);401 return (PyObject *)py_ret;402 }403 404 573 static void py_ldb_dn_dealloc(PyLdbDnObject *self) 405 574 { 406 575 talloc_free(self->mem_ctx); 407 self->ob_type->tp_free(self);408 } 409 410 PyTypeObject PyLdbDn = {411 .tp_name = " Dn",576 PyObject_Del(self); 577 } 578 579 static PyTypeObject PyLdbDn = { 580 .tp_name = "ldb.Dn", 412 581 .tp_methods = py_ldb_dn_methods, 413 582 .tp_str = (reprfunc)py_ldb_dn_get_linearized, … … 418 587 .tp_new = py_ldb_dn_new, 419 588 .tp_dealloc = (destructor)py_ldb_dn_dealloc, 420 .tp_basicsize = sizeof(PyLdb Object),589 .tp_basicsize = sizeof(PyLdbDnObject), 421 590 .tp_flags = Py_TPFLAGS_DEFAULT, 422 591 }; … … 475 644 { 476 645 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self)); 646 Py_RETURN_NONE; 647 } 648 649 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self) 650 { 651 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_prepare_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self)); 477 652 Py_RETURN_NONE; 478 653 } … … 529 704 530 705 static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list, 531 706 const char *paramname) 532 707 { 533 708 const char **ret; 534 int i;709 Py_ssize_t i; 535 710 if (!PyList_Check(list)) { 536 711 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname); … … 538 713 } 539 714 ret = talloc_array(NULL, const char *, PyList_Size(list)+1); 715 if (ret == NULL) { 716 PyErr_NoMemory(); 717 return NULL; 718 } 719 540 720 for (i = 0; i < PyList_Size(list); i++) { 541 721 PyObject *item = PyList_GetItem(list, i); … … 545 725 } 546 726 ret[i] = talloc_strndup(ret, PyString_AsString(item), 547 727 PyString_Size(item)); 548 728 } 549 729 ret[i] = NULL; … … 642 822 { 643 823 PyObject *py_msg; 644 int ret; 645 if (!PyArg_ParseTuple(args, "O", &py_msg)) 646 return NULL; 647 648 if (!PyLdbMessage_Check(py_msg)) { 649 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message"); 650 return NULL; 651 } 652 653 ret = ldb_modify(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg)); 654 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); 655 656 Py_RETURN_NONE; 657 } 658 659 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args) 660 { 661 PyObject *py_msg; 662 int ret; 663 Py_ssize_t dict_pos, msg_pos; 664 struct ldb_message_element *msgel; 665 struct ldb_message *msg; 824 PyObject *py_controls = Py_None; 666 825 struct ldb_context *ldb_ctx; 667 826 struct ldb_request *req; 668 PyObject *key, *value; 669 PyObject *py_controls = Py_None; 827 struct ldb_control **parsed_controls; 828 struct ldb_message *msg; 829 int ret; 670 830 TALLOC_CTX *mem_ctx; 671 struct ldb_control **parsed_controls; 672 673 if (!PyArg_ParseTuple(args, "O|O", &py_msg, &py_controls )) 674 return NULL; 831 832 if (!PyArg_ParseTuple(args, "O|O", &py_msg, &py_controls)) 833 return NULL; 834 835 mem_ctx = talloc_new(NULL); 836 if (mem_ctx == NULL) { 837 PyErr_NoMemory(); 838 return NULL; 839 } 675 840 ldb_ctx = PyLdb_AsLdbContext(self); 676 841 677 mem_ctx = talloc_new(NULL);678 842 if (py_controls == Py_None) { 679 843 parsed_controls = NULL; 680 844 } else { 681 const char **controls = PyList_AsStringList( ldb_ctx, py_controls, "controls");682 parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);845 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 846 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 683 847 talloc_free(controls); 684 848 } 685 if (PyDict_Check(py_msg)) { 686 PyObject *dn_value = PyDict_GetItemString(py_msg, "dn"); 687 msg = ldb_msg_new(mem_ctx); 688 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg)); 689 msg_pos = dict_pos = 0; 690 if (dn_value) { 691 if (!PyObject_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) { 692 PyErr_SetString(PyExc_TypeError, "unable to import dn object"); 693 talloc_free(mem_ctx); 694 return NULL; 695 } 696 if (msg->dn == NULL) { 697 PyErr_SetString(PyExc_TypeError, "dn set but not found"); 698 talloc_free(mem_ctx); 699 return NULL; 700 } 701 } 702 703 while (PyDict_Next(py_msg, &dict_pos, &key, &value)) { 704 char *key_str = PyString_AsString(key); 705 if (strcmp(key_str, "dn") != 0) { 706 msgel = PyObject_AsMessageElement(msg->elements, value, 0, key_str); 707 if (msgel == NULL) { 708 PyErr_SetString(PyExc_TypeError, "unable to import element"); 709 talloc_free(mem_ctx); 710 return NULL; 711 } 712 memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel)); 713 msg_pos++; 714 } 715 } 716 717 if (msg->dn == NULL) { 718 PyErr_SetString(PyExc_TypeError, "no dn set"); 719 talloc_free(mem_ctx); 720 return NULL; 721 } 722 723 msg->num_elements = msg_pos; 724 } else { 725 msg = PyLdbMessage_AsMessage(py_msg); 726 } 727 849 850 if (!PyLdbMessage_Check(py_msg)) { 851 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message"); 852 talloc_free(mem_ctx); 853 return NULL; 854 } 855 msg = PyLdbMessage_AsMessage(py_msg); 856 728 857 ret = ldb_msg_sanity_check(ldb_ctx, msg); 729 730 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));858 if (ret != LDB_SUCCESS) { 859 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 731 860 talloc_free(mem_ctx); 732 861 return NULL; 733 } 734 735 ret = ldb_build_add_req(&req, ldb_ctx, ldb_ctx, 736 msg, 737 parsed_controls, 738 NULL, 739 ldb_op_default_callback, 740 NULL); 741 862 } 863 864 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls, 865 NULL, ldb_op_default_callback, NULL); 742 866 if (ret != LDB_SUCCESS) { 743 867 PyErr_SetString(PyExc_TypeError, "failed to build request"); … … 746 870 } 747 871 748 872 /* do request and autostart a transaction */ 749 873 /* Then let's LDB handle the message error in case of pb as they are meaningful */ 750 874 751 ret = ldb_transaction_start(ldb_ctx); 752 if (ret != LDB_SUCCESS) { 753 talloc_free(req); 875 ret = ldb_transaction_start(ldb_ctx); 876 if (ret != LDB_SUCCESS) { 754 877 talloc_free(mem_ctx); 755 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); 756 } 757 758 ret = ldb_request(ldb_ctx, req); 759 if (ret == LDB_SUCCESS) { 760 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 761 } 762 878 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 879 } 880 881 ret = ldb_request(ldb_ctx, req); 763 882 if (ret == LDB_SUCCESS) { 764 ret = ldb_transaction_commit(ldb_ctx); 765 } else { 766 ldb_transaction_cancel(ldb_ctx); 883 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 884 } 885 886 if (ret == LDB_SUCCESS) { 887 ret = ldb_transaction_commit(ldb_ctx); 888 } else { 889 ldb_transaction_cancel(ldb_ctx); 767 890 if (ldb_ctx->err_string == NULL) { 768 891 /* no error string was setup by the backend */ … … 770 893 } 771 894 } 772 talloc_free(req); 895 773 896 talloc_free(mem_ctx); 774 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); 897 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 898 899 Py_RETURN_NONE; 900 } 901 902 903 /** 904 * Obtain a ldb message from a Python Dictionary object. 905 * 906 * @param mem_ctx Memory context 907 * @param py_obj Python Dictionary object 908 * @param ldb_ctx LDB context 909 * @param mod_flags Flags to be set on every message element 910 * @return ldb_message on success or NULL on failure 911 */ 912 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx, 913 PyObject *py_obj, 914 struct ldb_context *ldb_ctx, 915 unsigned int mod_flags) 916 { 917 struct ldb_message *msg; 918 unsigned int msg_pos = 0; 919 Py_ssize_t dict_pos = 0; 920 PyObject *key, *value; 921 struct ldb_message_element *msg_el; 922 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn"); 923 924 msg = ldb_msg_new(mem_ctx); 925 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj)); 926 927 if (dn_value) { 928 if (!PyObject_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) { 929 PyErr_SetString(PyExc_TypeError, "unable to import dn object"); 930 return NULL; 931 } 932 if (msg->dn == NULL) { 933 PyErr_SetString(PyExc_TypeError, "dn set but not found"); 934 return NULL; 935 } 936 } else { 937 PyErr_SetString(PyExc_TypeError, "no dn set"); 938 return NULL; 939 } 940 941 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) { 942 char *key_str = PyString_AsString(key); 943 if (strcmp(key_str, "dn") != 0) { 944 msg_el = PyObject_AsMessageElement(msg->elements, value, 945 mod_flags, key_str); 946 if (msg_el == NULL) { 947 PyErr_SetString(PyExc_TypeError, "unable to import element"); 948 return NULL; 949 } 950 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el)); 951 msg_pos++; 952 } 953 } 954 955 msg->num_elements = msg_pos; 956 957 return msg; 958 } 959 960 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args) 961 { 962 PyObject *py_obj; 963 int ret; 964 struct ldb_context *ldb_ctx; 965 struct ldb_request *req; 966 struct ldb_message *msg = NULL; 967 PyObject *py_controls = Py_None; 968 TALLOC_CTX *mem_ctx; 969 struct ldb_control **parsed_controls; 970 971 if (!PyArg_ParseTuple(args, "O|O", &py_obj, &py_controls )) 972 return NULL; 973 974 mem_ctx = talloc_new(NULL); 975 if (mem_ctx == NULL) { 976 PyErr_NoMemory(); 977 return NULL; 978 } 979 ldb_ctx = PyLdb_AsLdbContext(self); 980 981 if (py_controls == Py_None) { 982 parsed_controls = NULL; 983 } else { 984 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 985 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 986 talloc_free(controls); 987 } 988 989 if (PyLdbMessage_Check(py_obj)) { 990 msg = PyLdbMessage_AsMessage(py_obj); 991 } else if (PyDict_Check(py_obj)) { 992 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD); 993 } else { 994 PyErr_SetString(PyExc_TypeError, 995 "Dictionary or LdbMessage object expected!"); 996 } 997 998 if (!msg) { 999 /* we should have a PyErr already set */ 1000 talloc_free(mem_ctx); 1001 return NULL; 1002 } 1003 1004 ret = ldb_msg_sanity_check(ldb_ctx, msg); 1005 if (ret != LDB_SUCCESS) { 1006 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1007 talloc_free(mem_ctx); 1008 return NULL; 1009 } 1010 1011 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls, 1012 NULL, ldb_op_default_callback, NULL); 1013 if (ret != LDB_SUCCESS) { 1014 PyErr_SetString(PyExc_TypeError, "failed to build request"); 1015 talloc_free(mem_ctx); 1016 return NULL; 1017 } 1018 1019 /* do request and autostart a transaction */ 1020 /* Then let's LDB handle the message error in case of pb as they are meaningful */ 1021 1022 ret = ldb_transaction_start(ldb_ctx); 1023 if (ret != LDB_SUCCESS) { 1024 talloc_free(mem_ctx); 1025 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1026 } 1027 1028 ret = ldb_request(ldb_ctx, req); 1029 if (ret == LDB_SUCCESS) { 1030 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 1031 } 1032 1033 if (ret == LDB_SUCCESS) { 1034 ret = ldb_transaction_commit(ldb_ctx); 1035 } else { 1036 ldb_transaction_cancel(ldb_ctx); 1037 if (ldb_ctx->err_string == NULL) { 1038 /* no error string was setup by the backend */ 1039 ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret); 1040 } 1041 } 1042 1043 talloc_free(mem_ctx); 1044 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 775 1045 776 1046 Py_RETURN_NONE; … … 782 1052 struct ldb_dn *dn; 783 1053 int ret; 784 struct ldb_context *ldb; 785 if (!PyArg_ParseTuple(args, "O", &py_dn)) 786 return NULL; 787 788 ldb = PyLdb_AsLdbContext(self); 789 790 if (!PyObject_AsDn(NULL, py_dn, ldb, &dn)) 791 return NULL; 792 793 ret = ldb_delete(ldb, dn); 794 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb); 1054 struct ldb_context *ldb_ctx; 1055 struct ldb_request *req; 1056 PyObject *py_controls = Py_None; 1057 TALLOC_CTX *mem_ctx; 1058 struct ldb_control **parsed_controls; 1059 1060 if (!PyArg_ParseTuple(args, "O|O", &py_dn, &py_controls)) 1061 return NULL; 1062 1063 mem_ctx = talloc_new(NULL); 1064 if (mem_ctx == NULL) { 1065 PyErr_NoMemory(); 1066 return NULL; 1067 } 1068 ldb_ctx = PyLdb_AsLdbContext(self); 1069 1070 if (py_controls == Py_None) { 1071 parsed_controls = NULL; 1072 } else { 1073 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 1074 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 1075 talloc_free(controls); 1076 } 1077 1078 if (!PyObject_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) { 1079 talloc_free(mem_ctx); 1080 return NULL; 1081 } 1082 1083 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls, 1084 NULL, ldb_op_default_callback, NULL); 1085 if (ret != LDB_SUCCESS) { 1086 PyErr_SetString(PyExc_TypeError, "failed to build request"); 1087 talloc_free(mem_ctx); 1088 return NULL; 1089 } 1090 1091 /* do request and autostart a transaction */ 1092 /* Then let's LDB handle the message error in case of pb as they are meaningful */ 1093 1094 ret = ldb_transaction_start(ldb_ctx); 1095 if (ret != LDB_SUCCESS) { 1096 talloc_free(mem_ctx); 1097 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1098 } 1099 1100 ret = ldb_request(ldb_ctx, req); 1101 if (ret == LDB_SUCCESS) { 1102 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 1103 } 1104 1105 if (ret == LDB_SUCCESS) { 1106 ret = ldb_transaction_commit(ldb_ctx); 1107 } else { 1108 ldb_transaction_cancel(ldb_ctx); 1109 if (ldb_ctx->err_string == NULL) { 1110 /* no error string was setup by the backend */ 1111 ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret); 1112 } 1113 } 1114 1115 talloc_free(mem_ctx); 1116 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 795 1117 796 1118 Py_RETURN_NONE; … … 804 1126 struct ldb_context *ldb; 805 1127 TALLOC_CTX *mem_ctx; 806 if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2)) 807 return NULL; 1128 PyObject *py_controls = Py_None; 1129 struct ldb_control **parsed_controls; 1130 struct ldb_context *ldb_ctx; 1131 struct ldb_request *req; 1132 1133 ldb_ctx = PyLdb_AsLdbContext(self); 1134 1135 if (!PyArg_ParseTuple(args, "OO|O", &py_dn1, &py_dn2, &py_controls)) 1136 return NULL; 1137 808 1138 809 1139 mem_ctx = talloc_new(NULL); … … 813 1143 } 814 1144 ldb = PyLdb_AsLdbContext(self); 1145 1146 if (py_controls == Py_None) { 1147 parsed_controls = NULL; 1148 } else { 1149 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 1150 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 1151 talloc_free(controls); 1152 } 1153 1154 815 1155 if (!PyObject_AsDn(mem_ctx, py_dn1, ldb, &dn1)) { 816 1156 talloc_free(mem_ctx); … … 823 1163 } 824 1164 825 ret = ldb_rename(ldb, dn1, dn2); 1165 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls, 1166 NULL, ldb_op_default_callback, NULL); 1167 if (ret != LDB_SUCCESS) { 1168 PyErr_SetString(PyExc_TypeError, "failed to build request"); 1169 talloc_free(mem_ctx); 1170 return NULL; 1171 } 1172 1173 /* do request and autostart a transaction */ 1174 /* Then let's LDB handle the message error in case of pb as they are meaningful */ 1175 1176 ret = ldb_transaction_start(ldb_ctx); 1177 if (ret != LDB_SUCCESS) { 1178 talloc_free(mem_ctx); 1179 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1180 } 1181 1182 ret = ldb_request(ldb_ctx, req); 1183 if (ret == LDB_SUCCESS) { 1184 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 1185 } 1186 1187 if (ret == LDB_SUCCESS) { 1188 ret = ldb_transaction_commit(ldb_ctx); 1189 } else { 1190 ldb_transaction_cancel(ldb_ctx); 1191 if (ldb_ctx->err_string == NULL) { 1192 /* no error string was setup by the backend */ 1193 ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret); 1194 } 1195 } 1196 826 1197 talloc_free(mem_ctx); 827 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb );1198 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 828 1199 829 1200 Py_RETURN_NONE; … … 869 1240 870 1241 871 static PyObject *py_ldb_write_ldif(PyLdb MessageObject *self, PyObject *args)1242 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args) 872 1243 { 873 1244 int changetype; … … 938 1309 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args) 939 1310 { 1311 int ldb_ret; 940 1312 PyObject *py_msg_old; 941 1313 PyObject *py_msg_new; 942 1314 struct ldb_message *diff; 1315 struct ldb_context *ldb; 943 1316 PyObject *py_ret; 944 1317 … … 956 1329 } 957 1330 958 diff = ldb_msg_diff(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg_old), PyLdbMessage_AsMessage(py_msg_new)); 959 if (diff == NULL) 960 return NULL; 1331 ldb = PyLdb_AsLdbContext(self); 1332 ldb_ret = ldb_msg_difference(ldb, ldb, 1333 PyLdbMessage_AsMessage(py_msg_old), 1334 PyLdbMessage_AsMessage(py_msg_new), 1335 &diff); 1336 if (ldb_ret != LDB_SUCCESS) { 1337 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff"); 1338 return NULL; 1339 } 961 1340 962 1341 py_ret = PyLdbMessage_FromMessage(diff); 1342 1343 talloc_unlink(ldb, diff); 963 1344 964 1345 return py_ret; … … 1004 1385 { 1005 1386 PyObject *py_base = Py_None; 1006 enum ldb_scopescope = LDB_SCOPE_DEFAULT;1387 int scope = LDB_SCOPE_DEFAULT; 1007 1388 char *expr = NULL; 1008 1389 PyObject *py_attrs = Py_None; … … 1017 1398 struct ldb_dn *base; 1018 1399 PyObject *py_ret; 1019 1400 TALLOC_CTX *mem_ctx; 1401 1402 /* type "int" rather than "enum" for "scope" is intentional */ 1020 1403 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO", 1021 1404 discard_const_p(char *, kwnames), … … 1023 1406 return NULL; 1024 1407 1408 1409 mem_ctx = talloc_new(NULL); 1410 if (mem_ctx == NULL) { 1411 PyErr_NoMemory(); 1412 return NULL; 1413 } 1025 1414 ldb_ctx = PyLdb_AsLdbContext(self); 1026 1415 … … 1028 1417 attrs = NULL; 1029 1418 } else { 1030 attrs = PyList_AsStringList(NULL, py_attrs, "attrs"); 1031 if (attrs == NULL) 1419 attrs = PyList_AsStringList(mem_ctx, py_attrs, "attrs"); 1420 if (attrs == NULL) { 1421 talloc_free(mem_ctx); 1032 1422 return NULL; 1423 } 1033 1424 } 1034 1425 … … 1045 1436 parsed_controls = NULL; 1046 1437 } else { 1047 const char **controls = PyList_AsStringList( ldb_ctx, py_controls, "controls");1048 parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);1438 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 1439 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 1049 1440 talloc_free(controls); 1050 1441 } 1051 1442 1052 res = talloc_zero( ldb_ctx, struct ldb_result);1443 res = talloc_zero(mem_ctx, struct ldb_result); 1053 1444 if (res == NULL) { 1054 1445 PyErr_NoMemory(); 1055 talloc_free( attrs);1056 return NULL; 1057 } 1058 1059 ret = ldb_build_search_req(&req, ldb_ctx, ldb_ctx,1446 talloc_free(mem_ctx); 1447 return NULL; 1448 } 1449 1450 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx, 1060 1451 base, 1061 1452 scope, … … 1067 1458 NULL); 1068 1459 1460 if (ret != LDB_SUCCESS) { 1461 talloc_free(mem_ctx); 1462 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1463 return NULL; 1464 } 1465 1069 1466 talloc_steal(req, attrs); 1070 1071 if (ret != LDB_SUCCESS) {1072 talloc_free(res);1073 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);1074 return NULL;1075 }1076 1467 1077 1468 ret = ldb_request(ldb_ctx, req); … … 1081 1472 } 1082 1473 1083 talloc_free(req);1084 1085 1474 if (ret != LDB_SUCCESS) { 1086 talloc_free( res);1475 talloc_free(mem_ctx); 1087 1476 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1088 1477 return NULL; … … 1091 1480 py_ret = PyLdbResult_FromResult(res); 1092 1481 1093 talloc_free( res);1482 talloc_free(mem_ctx); 1094 1483 1095 1484 return py_ret; … … 1142 1531 } 1143 1532 1533 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args) 1534 { 1535 struct ldb_context *ldb = PyLdb_AsLdbContext(self); 1536 int type, ret; 1537 uint64_t value; 1538 1539 if (!PyArg_ParseTuple(args, "i", &type)) 1540 return NULL; 1541 1542 /* FIXME: More interpretation */ 1543 1544 ret = ldb_sequence_number(ldb, type, &value); 1545 1546 if (ret != LDB_SUCCESS) { 1547 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb); 1548 return NULL; 1549 } 1550 return PyLong_FromLongLong(value); 1551 } 1144 1552 static PyMethodDef py_ldb_methods[] = { 1145 1553 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, … … 1156 1564 "S.transaction_start() -> None\n" 1157 1565 "Start a new transaction." }, 1566 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS, 1567 "S.transaction_prepare_commit() -> None\n" 1568 "prepare to commit a new transaction (2-stage commit)." }, 1158 1569 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, 1159 1570 "S.transaction_commit() -> None\n" … … 1225 1636 "S.modules() -> list\n" 1226 1637 "Return the list of modules on this LDB connection " }, 1638 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS, 1639 "S.sequence_number(type) -> value\n" 1640 "Return the value of the sequence according to the requested type" }, 1227 1641 { NULL }, 1228 1642 }; 1229 1643 1230 PyObject *PyLdbModule_FromModule(struct ldb_module *mod)1644 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod) 1231 1645 { 1232 1646 PyLdbModuleObject *ret; … … 1257 1671 struct ldb_dn *dn; 1258 1672 struct ldb_result *result; 1673 unsigned int count; 1259 1674 int ret; 1260 int count; 1261 1262 if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) 1675 1676 if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) { 1263 1677 return -1; 1264 1265 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, NULL); 1678 } 1679 1680 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, 1681 NULL); 1266 1682 if (ret != LDB_SUCCESS) { 1267 1683 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); … … 1273 1689 talloc_free(result); 1274 1690 1691 if (count > 1) { 1692 PyErr_Format(PyExc_RuntimeError, 1693 "Searching for [%s] dn gave %u results!", 1694 ldb_dn_get_linearized(dn), 1695 count); 1696 return -1; 1697 } 1698 1275 1699 return count; 1276 1700 } … … 1280 1704 }; 1281 1705 1282 PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)1706 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx) 1283 1707 { 1284 1708 PyLdbObject *ret; … … 1300 1724 } 1301 1725 1302 PyTypeObject PyLdb = {1303 .tp_name = " Ldb",1726 static PyTypeObject PyLdb = { 1727 .tp_name = "ldb.Ldb", 1304 1728 .tp_methods = py_ldb_methods, 1305 1729 .tp_repr = (reprfunc)py_ldb_repr, … … 1315 1739 }; 1316 1740 1741 static void py_ldb_result_dealloc(PyLdbResultObject *self) 1742 { 1743 talloc_free(self->mem_ctx); 1744 Py_DECREF(self->msgs); 1745 Py_DECREF(self->referals); 1746 Py_DECREF(self->controls); 1747 self->ob_type->tp_free(self); 1748 } 1749 1750 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure) 1751 { 1752 Py_INCREF(self->msgs); 1753 return self->msgs; 1754 } 1755 1756 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure) 1757 { 1758 Py_INCREF(self->controls); 1759 return self->controls; 1760 } 1761 1762 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure) 1763 { 1764 Py_INCREF(self->referals); 1765 return self->referals; 1766 } 1767 1768 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure) 1769 { 1770 Py_ssize_t size; 1771 if (self->msgs == NULL) { 1772 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context"); 1773 return NULL; 1774 } 1775 size = PyList_Size(self->msgs); 1776 return PyInt_FromLong(size); 1777 } 1778 1779 static PyGetSetDef py_ldb_result_getset[] = { 1780 { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL }, 1781 { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL }, 1782 { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL }, 1783 { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL }, 1784 { NULL } 1785 }; 1786 1787 static PyObject *py_ldb_result_iter(PyLdbResultObject *self) 1788 { 1789 return PyObject_GetIter(self->msgs); 1790 } 1791 1792 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self) 1793 { 1794 return PySequence_Size(self->msgs); 1795 } 1796 1797 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx) 1798 { 1799 return PySequence_GetItem(self->msgs, idx); 1800 } 1801 1802 static PySequenceMethods py_ldb_result_seq = { 1803 .sq_length = (lenfunc)py_ldb_result_len, 1804 .sq_item = (ssizeargfunc)py_ldb_result_find, 1805 }; 1806 1807 static PyObject *py_ldb_result_repr(PyLdbObject *self) 1808 { 1809 return PyString_FromFormat("<ldb result>"); 1810 } 1811 1812 1813 static PyTypeObject PyLdbResult = { 1814 .tp_name = "ldb.Result", 1815 .tp_repr = (reprfunc)py_ldb_result_repr, 1816 .tp_dealloc = (destructor)py_ldb_result_dealloc, 1817 .tp_iter = (getiterfunc)py_ldb_result_iter, 1818 .tp_getset = py_ldb_result_getset, 1819 .tp_getattro = PyObject_GenericGetAttr, 1820 .tp_basicsize = sizeof(PyLdbResultObject), 1821 .tp_as_sequence = &py_ldb_result_seq, 1822 .tp_doc = "LDB result.", 1823 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1824 }; 1825 1317 1826 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self) 1318 1827 { … … 1352 1861 const char * const*attrs; 1353 1862 1863 /* type "int" rather than "enum" for "scope" is intentional */ 1354 1864 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO", 1355 1865 discard_const_p(char *, kwnames), … … 1490 2000 { 1491 2001 talloc_free(self->mem_ctx); 1492 self->ob_type->tp_free(self);1493 } 1494 1495 PyTypeObject PyLdbModule = {1496 .tp_name = " LdbModule",2002 PyObject_Del(self); 2003 } 2004 2005 static PyTypeObject PyLdbModule = { 2006 .tp_name = "ldb.LdbModule", 1497 2007 .tp_methods = py_ldb_module_methods, 1498 2008 .tp_repr = (reprfunc)py_ldb_module_repr, … … 1518 2028 * @return New ldb_message_element, allocated as child of mem_ctx 1519 2029 */ 1520 struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx, 1521 PyObject *set_obj, int flags, 1522 const char *attr_name) 2030 static struct ldb_message_element *PyObject_AsMessageElement( 2031 TALLOC_CTX *mem_ctx, 2032 PyObject *set_obj, 2033 int flags, 2034 const char *attr_name) 1523 2035 { 1524 2036 struct ldb_message_element *me; 1525 2037 1526 if (PyLdbMessageElement_Check(set_obj)) 1527 return talloc_reference(mem_ctx, 1528 PyLdbMessageElement_AsMessageElement(set_obj)); 2038 if (PyLdbMessageElement_Check(set_obj)) { 2039 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj; 2040 /* We have to talloc_reference() the memory context, not the pointer 2041 * which may not actually be it's own context */ 2042 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) { 2043 return PyLdbMessageElement_AsMessageElement(set_obj); 2044 } 2045 return NULL; 2046 } 1529 2047 1530 2048 me = talloc(mem_ctx, struct ldb_message_element); 2049 if (me == NULL) { 2050 PyErr_NoMemory(); 2051 return NULL; 2052 } 1531 2053 1532 2054 me->name = talloc_strdup(me, attr_name); … … 1537 2059 me->values[0].length = PyString_Size(set_obj); 1538 2060 me->values[0].data = talloc_memdup(me, 1539 (uint8_t *)PyString_AsString(set_obj), me->values[0].length );2061 (uint8_t *)PyString_AsString(set_obj), me->values[0].length+1); 1540 2062 } else if (PySequence_Check(set_obj)) { 1541 int i;2063 Py_ssize_t i; 1542 2064 me->num_values = PySequence_Size(set_obj); 1543 2065 me->values = talloc_array(me, struct ldb_val, me->num_values); 1544 2066 for (i = 0; i < me->num_values; i++) { 1545 2067 PyObject *obj = PySequence_GetItem(set_obj, i); 2068 if (!PyString_Check(obj)) { 2069 PyErr_Format(PyExc_TypeError, 2070 "Expected string as element %zd in list", i); 2071 talloc_free(me); 2072 return NULL; 2073 } 1546 2074 1547 2075 me->values[i].length = PyString_Size(obj); 1548 2076 me->values[i].data = talloc_memdup(me, 1549 (uint8_t *)PyString_AsString(obj), me->values[i].length );2077 (uint8_t *)PyString_AsString(obj), me->values[i].length+1); 1550 2078 } 1551 2079 } else { … … 1558 2086 1559 2087 1560 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, 1561 1562 { 1563 int i;2088 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, 2089 struct ldb_message_element *me) 2090 { 2091 Py_ssize_t i; 1564 2092 PyObject *result; 1565 2093 … … 1569 2097 for (i = 0; i < me->num_values; i++) { 1570 2098 PyList_SetItem(result, i, 1571 PyObject_FromLdbValue( ldb_ctx, me,&me->values[i]));2099 PyObject_FromLdbValue(&me->values[i])); 1572 2100 } 1573 2101 … … 1577 2105 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args) 1578 2106 { 1579 int i;1580 if (!PyArg_ParseTuple(args, " i", &i))1581 return NULL; 1582 if (i < 0 || i>= PyLdbMessageElement_AsMessageElement(self)->num_values)2107 unsigned int i; 2108 if (!PyArg_ParseTuple(args, "I", &i)) 2109 return NULL; 2110 if (i >= PyLdbMessageElement_AsMessageElement(self)->num_values) 1583 2111 Py_RETURN_NONE; 1584 2112 1585 return PyObject_FromLdbValue(NULL, PyLdbMessageElement_AsMessageElement(self), 1586 &(PyLdbMessageElement_AsMessageElement(self)->values[i])); 2113 return PyObject_FromLdbValue(&(PyLdbMessageElement_AsMessageElement(self)->values[i])); 1587 2114 } 1588 2115 1589 2116 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args) 1590 2117 { 1591 struct ldb_message_element *el; 1592 1593 el = PyLdbMessageElement_AsMessageElement(self); 2118 struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self); 1594 2119 return PyInt_FromLong(el->flags); 1595 2120 } … … 1636 2161 static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other) 1637 2162 { 1638 return ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self), 1639 PyLdbMessageElement_AsMessageElement(other)); 2163 int ret = ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self), 2164 PyLdbMessageElement_AsMessageElement(other)); 2165 return SIGN(ret); 1640 2166 } 1641 2167 … … 1645 2171 } 1646 2172 1647 PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)2173 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx) 1648 2174 { 1649 2175 PyLdbMessageElementObject *ret; 1650 ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);2176 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement); 1651 2177 if (ret == NULL) { 1652 2178 PyErr_NoMemory(); … … 1684 2210 1685 2211 el = talloc_zero(mem_ctx, struct ldb_message_element); 2212 if (el == NULL) { 2213 PyErr_NoMemory(); 2214 talloc_free(mem_ctx); 2215 return NULL; 2216 } 1686 2217 1687 2218 if (py_elements != NULL) { 1688 int i;2219 Py_ssize_t i; 1689 2220 if (PyString_Check(py_elements)) { 1690 2221 el->num_values = 1; 1691 2222 el->values = talloc_array(el, struct ldb_val, 1); 2223 if (el->values == NULL) { 2224 talloc_free(mem_ctx); 2225 PyErr_NoMemory(); 2226 return NULL; 2227 } 1692 2228 el->values[0].length = PyString_Size(py_elements); 1693 el->values[0].data = talloc_memdup(el ,1694 (uint8_t *)PyString_AsString(py_elements), el->values[0].length );2229 el->values[0].data = talloc_memdup(el->values, 2230 (uint8_t *)PyString_AsString(py_elements), el->values[0].length+1); 1695 2231 } else if (PySequence_Check(py_elements)) { 1696 2232 el->num_values = PySequence_Size(py_elements); 1697 2233 el->values = talloc_array(el, struct ldb_val, el->num_values); 2234 if (el->values == NULL) { 2235 talloc_free(mem_ctx); 2236 PyErr_NoMemory(); 2237 return NULL; 2238 } 1698 2239 for (i = 0; i < el->num_values; i++) { 1699 2240 PyObject *item = PySequence_GetItem(py_elements, i); 2241 if (item == NULL) { 2242 talloc_free(mem_ctx); 2243 return NULL; 2244 } 1700 2245 if (!PyString_Check(item)) { 1701 2246 PyErr_Format(PyExc_TypeError, 1702 "Expected string as element %d in list", 1703 i); 2247 "Expected string as element %zd in list", i); 1704 2248 talloc_free(mem_ctx); 1705 2249 return NULL; 1706 2250 } 1707 2251 el->values[i].length = PyString_Size(item); 1708 el->values[i].data = talloc_memdup(el, 1709 (uint8_t *)PyString_AsString(item), el->values[i].length );2252 el->values[i].data = talloc_memdup(el, 2253 (uint8_t *)PyString_AsString(item), el->values[i].length+1); 1710 2254 } 1711 2255 } else { … … 1720 2264 el->name = talloc_strdup(el, name); 1721 2265 1722 ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);2266 ret = PyObject_New(PyLdbMessageElementObject, type); 1723 2267 if (ret == NULL) { 1724 PyErr_NoMemory();1725 2268 talloc_free(mem_ctx); 1726 2269 return NULL; … … 1735 2278 { 1736 2279 char *element_str = NULL; 1737 int i;2280 Py_ssize_t i; 1738 2281 struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self); 1739 2282 PyObject *ret; … … 1747 2290 } 1748 2291 1749 ret = PyString_FromFormat("MessageElement([%s])", element_str); 1750 1751 talloc_free(element_str); 2292 if (element_str != NULL) { 2293 ret = PyString_FromFormat("MessageElement([%s])", element_str); 2294 talloc_free(element_str); 2295 } else { 2296 ret = PyString_FromString("MessageElement([])"); 2297 } 1752 2298 1753 2299 return ret; … … 1760 2306 if (el->num_values == 1) 1761 2307 return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length); 1762 else 2308 else 1763 2309 Py_RETURN_NONE; 1764 2310 } … … 1767 2313 { 1768 2314 talloc_free(self->mem_ctx); 1769 self->ob_type->tp_free(self);1770 } 1771 1772 PyTypeObject PyLdbMessageElement = {1773 .tp_name = " MessageElement",2315 PyObject_Del(self); 2316 } 2317 2318 static PyTypeObject PyLdbMessageElement = { 2319 .tp_name = "ldb.MessageElement", 1774 2320 .tp_basicsize = sizeof(PyLdbMessageElementObject), 1775 2321 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc, … … 1784 2330 }; 1785 2331 2332 2333 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args) 2334 { 2335 PyObject *py_ldb; 2336 PyObject *py_dict; 2337 PyObject *py_ret; 2338 struct ldb_message *msg; 2339 struct ldb_context *ldb_ctx; 2340 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE; 2341 2342 if (!PyArg_ParseTuple(args, "O!O!|I", 2343 &PyLdb, &py_ldb, &PyDict_Type, &py_dict, 2344 &mod_flags)) { 2345 return NULL; 2346 } 2347 2348 /* mask only flags we are going to use */ 2349 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags); 2350 if (!mod_flags) { 2351 PyErr_SetString(PyExc_ValueError, 2352 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE" 2353 " expected as mod_flag value"); 2354 return NULL; 2355 } 2356 2357 ldb_ctx = PyLdb_AsLdbContext(py_ldb); 2358 2359 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags); 2360 if (!msg) { 2361 return NULL; 2362 } 2363 2364 py_ret = PyLdbMessage_FromMessage(msg); 2365 2366 talloc_unlink(ldb_ctx, msg); 2367 2368 return py_ret; 2369 } 2370 1786 2371 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args) 1787 2372 { … … 1798 2383 { 1799 2384 struct ldb_message *msg = PyLdbMessage_AsMessage(self); 1800 int i, j = 0;2385 Py_ssize_t i, j = 0; 1801 2386 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0)); 1802 2387 if (msg->dn != NULL) { … … 1827 2412 return NULL; 1828 2413 } 1829 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg );2414 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements); 1830 2415 } 1831 2416 … … 1858 2443 { 1859 2444 struct ldb_message *msg = PyLdbMessage_AsMessage(self); 1860 int i, j;2445 Py_ssize_t i, j = 0; 1861 2446 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1)); 1862 j = 0;1863 2447 if (msg->dn != NULL) { 1864 2448 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", PyLdbDn_FromDn(msg->dn))); … … 1866 2450 } 1867 2451 for (i = 0; i < msg->num_elements; i++, j++) { 1868 PyList_SetItem(l, j, Py_BuildValue("(sO)", msg->elements[i].name, PyLdbMessageElement_FromMessageElement(&msg->elements[i], self->msg))); 2452 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements); 2453 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el); 2454 PyList_SetItem(l, j, value); 1869 2455 } 1870 2456 return l; 1871 2457 } 1872 2458 1873 static PyMethodDef py_ldb_msg_methods[] = { 1874 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, NULL }, 1875 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, NULL }, 2459 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self) 2460 { 2461 struct ldb_message *msg = PyLdbMessage_AsMessage(self); 2462 Py_ssize_t i = 0; 2463 PyObject *l = PyList_New(msg->num_elements); 2464 for (i = 0; i < msg->num_elements; i++) { 2465 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements)); 2466 } 2467 return l; 2468 } 2469 2470 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args) 2471 { 2472 struct ldb_message *msg = PyLdbMessage_AsMessage(self); 2473 PyLdbMessageElementObject *py_element; 2474 int ret; 2475 struct ldb_message_element *el; 2476 2477 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element)) 2478 return NULL; 2479 2480 el = talloc_reference(msg, py_element->el); 2481 if (el == NULL) { 2482 PyErr_NoMemory(); 2483 return NULL; 2484 } 2485 2486 ret = ldb_msg_add(msg, el, el->flags); 2487 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL); 2488 2489 Py_RETURN_NONE; 2490 } 2491 2492 static PyMethodDef py_ldb_msg_methods[] = { 2493 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS, 2494 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n" 2495 "Class method to create ldb.Message object from Dictionary.\n" 2496 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."}, 2497 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, 2498 "S.keys() -> list\n\n" 2499 "Return sequence of all attribute names." }, 2500 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, 2501 "S.remove(name)\n\n" 2502 "Remove all entries for attributes with the specified name."}, 1876 2503 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS, NULL }, 1877 2504 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL }, 2505 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL }, 2506 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS, 2507 "S.append(element)\n\n" 2508 "Add an element to this message." }, 1878 2509 { NULL }, 1879 2510 }; … … 1897 2528 return -1; 1898 2529 } 1899 2530 1900 2531 attr_name = PyString_AsString(name); 1901 2532 if (value == NULL) { … … 1904 2535 } else { 1905 2536 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg, 1906 2537 value, 0, attr_name); 1907 2538 if (el == NULL) 1908 2539 return -1; … … 1971 2602 } 1972 2603 1973 PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)2604 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg) 1974 2605 { 1975 2606 PyLdbMessageObject *ret; … … 2021 2652 { 2022 2653 talloc_free(self->mem_ctx); 2023 self->ob_type->tp_free(self); 2024 } 2025 2026 PyTypeObject PyLdbMessage = { 2027 .tp_name = "Message", 2654 PyObject_Del(self); 2655 } 2656 2657 static int py_ldb_msg_compare(PyLdbMessageObject *py_msg1, 2658 PyLdbMessageObject *py_msg2) 2659 { 2660 struct ldb_message *msg1 = PyLdbMessage_AsMessage(py_msg1), 2661 *msg2 = PyLdbMessage_AsMessage(py_msg2); 2662 unsigned int i; 2663 int ret; 2664 2665 if ((msg1->dn != NULL) || (msg2->dn != NULL)) { 2666 ret = ldb_dn_compare(msg1->dn, msg2->dn); 2667 if (ret != 0) { 2668 return SIGN(ret); 2669 } 2670 } 2671 2672 ret = msg1->num_elements - msg2->num_elements; 2673 if (ret != 0) { 2674 return SIGN(ret); 2675 } 2676 2677 for (i = 0; i < msg1->num_elements; i++) { 2678 ret = ldb_msg_element_compare_name(&msg1->elements[i], 2679 &msg2->elements[i]); 2680 if (ret != 0) { 2681 return SIGN(ret); 2682 } 2683 2684 ret = ldb_msg_element_compare(&msg1->elements[i], 2685 &msg2->elements[i]); 2686 if (ret != 0) { 2687 return SIGN(ret); 2688 } 2689 } 2690 2691 return 0; 2692 } 2693 2694 static PyTypeObject PyLdbMessage = { 2695 .tp_name = "ldb.Message", 2028 2696 .tp_methods = py_ldb_msg_methods, 2029 2697 .tp_getset = py_ldb_msg_getset, … … 2035 2703 .tp_flags = Py_TPFLAGS_DEFAULT, 2036 2704 .tp_iter = (getiterfunc)py_ldb_msg_iter, 2705 .tp_compare = (cmpfunc)py_ldb_msg_compare, 2037 2706 }; 2038 2707 2039 PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)2708 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree) 2040 2709 { 2041 2710 PyLdbTreeObject *ret; … … 2055 2724 { 2056 2725 talloc_free(self->mem_ctx); 2057 self->ob_type->tp_free(self);2058 } 2059 2060 PyTypeObject PyLdbTree = {2061 .tp_name = " Tree",2726 PyObject_Del(self); 2727 } 2728 2729 static PyTypeObject PyLdbTree = { 2730 .tp_name = "ldb.Tree", 2062 2731 .tp_basicsize = sizeof(PyLdbTreeObject), 2063 2732 .tp_dealloc = (destructor)py_ldb_tree_dealloc, … … 2367 3036 static PyObject *py_timestring(PyObject *module, PyObject *args) 2368 3037 { 2369 time_t t; 3038 /* most times "time_t" is a signed integer type with 32 or 64 bit: 3039 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */ 3040 long int t_val; 2370 3041 char *tresult; 2371 3042 PyObject *ret; 2372 if (!PyArg_ParseTuple(args, " L", &t))2373 return NULL; 2374 tresult = ldb_timestring(NULL, t);3043 if (!PyArg_ParseTuple(args, "l", &t_val)) 3044 return NULL; 3045 tresult = ldb_timestring(NULL, (time_t) t_val); 2375 3046 ret = PyString_FromString(tresult); 2376 3047 talloc_free(tresult); … … 2435 3106 return; 2436 3107 3108 if (PyType_Ready(&PyLdbResult) < 0) 3109 return; 3110 3111 if (PyType_Ready(&PyLdbControl) < 0) 3112 return; 3113 2437 3114 m = Py_InitModule3("ldb", py_ldb_global_methods, 2438 3115 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server."); … … 2440 3117 return; 2441 3118 3119 PyModule_AddObject(m, "SEQ_HIGHEST_SEQ", PyInt_FromLong(LDB_SEQ_HIGHEST_SEQ)); 3120 PyModule_AddObject(m, "SEQ_HIGHEST_TIMESTAMP", PyInt_FromLong(LDB_SEQ_HIGHEST_TIMESTAMP)); 3121 PyModule_AddObject(m, "SEQ_NEXT", PyInt_FromLong(LDB_SEQ_NEXT)); 2442 3122 PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT)); 2443 3123 PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE)); … … 2494 3174 PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER)); 2495 3175 2496 PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY)); 2497 PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC)); 2498 PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT)); 2499 PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP)); 2500 3176 PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY)); 3177 PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC)); 3178 PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT)); 3179 PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP)); 2501 3180 2502 3181 PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText")); … … 2511 3190 Py_INCREF(&PyLdbMessageElement); 2512 3191 Py_INCREF(&PyLdbTree); 3192 Py_INCREF(&PyLdbResult); 3193 Py_INCREF(&PyLdbControl); 2513 3194 2514 3195 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb); … … 2518 3199 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule); 2519 3200 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree); 2520 } 3201 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl); 3202 3203 PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION)); 3204 } -
trunk/server/source4/lib/ldb/pyldb.h
r414 r745 2 2 Unix SMB/CIFS implementation. 3 3 4 Swiginterface to ldb.4 Python interface to ldb. 5 5 6 6 Copyright (C) 2007-2008 Jelmer Vernooij <jelmer@samba.org> … … 27 27 #define _PYLDB_H_ 28 28 29 #include <Python.h>30 29 #include <talloc.h> 31 30 32 31 typedef struct { 33 32 PyObject_HEAD 33 TALLOC_CTX *mem_ctx; 34 34 struct ldb_context *ldb_ctx; 35 TALLOC_CTX *mem_ctx;36 35 } PyLdbObject; 37 36 38 PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);39 37 #define PyLdb_AsLdbContext(pyobj) ((PyLdbObject *)pyobj)->ldb_ctx 40 38 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb) … … 42 40 typedef struct { 43 41 PyObject_HEAD 42 TALLOC_CTX *mem_ctx; 44 43 struct ldb_dn *dn; 45 TALLOC_CTX *mem_ctx;46 44 } PyLdbDnObject; 47 45 … … 53 51 typedef struct { 54 52 PyObject_HEAD 53 TALLOC_CTX *mem_ctx; 55 54 struct ldb_message *msg; 56 TALLOC_CTX *mem_ctx;57 55 } PyLdbMessageObject; 58 56 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage) … … 61 59 typedef struct { 62 60 PyObject_HEAD 61 TALLOC_CTX *mem_ctx; 63 62 struct ldb_module *mod; 64 TALLOC_CTX *mem_ctx;65 63 } PyLdbModuleObject; 66 PyObject *PyLdbMessage_FromMessage(struct ldb_message *message);67 PyObject *PyLdbModule_FromModule(struct ldb_module *mod);68 64 #define PyLdbModule_AsModule(pyobj) ((PyLdbModuleObject *)pyobj)->mod 69 65 70 66 typedef struct { 71 PyObject_HEAD 67 PyObject_HEAD 68 TALLOC_CTX *mem_ctx; 72 69 struct ldb_message_element *el; 73 TALLOC_CTX *mem_ctx;74 70 } PyLdbMessageElementObject; 75 struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx, PyObject *obj, int flags, const char *name);76 PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *, TALLOC_CTX *mem_ctx);77 71 #define PyLdbMessageElement_AsMessageElement(pyobj) ((PyLdbMessageElementObject *)pyobj)->el 78 72 #define PyLdbMessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement) … … 80 74 typedef struct { 81 75 PyObject_HEAD 76 TALLOC_CTX *mem_ctx; 82 77 struct ldb_parse_tree *tree; 78 } PyLdbTreeObject; 79 #define PyLdbTree_AsTree(pyobj) ((PyLdbTreeObject *)pyobj)->tree 80 81 typedef struct { 82 PyObject_HEAD 83 83 TALLOC_CTX *mem_ctx; 84 } PyLdbTreeObject; 85 PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *); 86 #define PyLdbTree_AsTree(pyobj) ((PyLdbTreeObject *)pyobj)->tree 84 PyObject *msgs; 85 PyObject *referals; 86 PyObject *controls; 87 } PyLdbResultObject; 88 89 typedef struct { 90 PyObject_HEAD 91 TALLOC_CTX *mem_ctx; 92 struct ldb_control *data; 93 } PyLdbControlObject; 87 94 88 95 #define PyErr_LDB_ERROR_IS_ERR_RAISE(err,ret,ldb) \ -
trunk/server/source4/lib/ldb/tests/photo.ldif
r414 r745 2 2 changetype: modify 3 3 add: jpegPhoto 4 jpegPhoto:< file://tests/ tmp/samba4.png4 jpegPhoto:< file://tests/samba4.png 5 5 -
trunk/server/source4/lib/ldb/tests/python/api.py
r414 r745 1 #!/usr/bin/ python1 #!/usr/bin/env python 2 2 # Simple tests for the ldb python bindings. 3 3 # Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org> 4 4 5 import os , sys5 import os 6 6 import unittest 7 7 8 # Required for the standalone LDB build9 sys.path.append("build/lib.linux-i686-2.4")10 11 8 import ldb 12 9 10 13 11 def filename(): 14 return os.tempnam() 12 import tempfile 13 try: 14 dir_prefix = os.path.join(os.environ["SELFTEST_PREFIX"], "tmp") 15 except KeyError: 16 dir_prefix = None 17 return tempfile.mktemp(dir=dir_prefix) 15 18 16 19 class NoContextTests(unittest.TestCase): … … 58 61 59 62 def test_modules_tdb(self): 60 x = ldb.Ldb( "bar.ldb")63 x = ldb.Ldb(filename()) 61 64 self.assertEquals("[<ldb module 'tdb'>]", repr(x.modules())) 62 65 … … 78 81 79 82 def test_search_attr_string(self): 80 l = ldb.Ldb( "foo.tdb")83 l = ldb.Ldb(filename()) 81 84 self.assertRaises(TypeError, l.search, attrs="dc") 82 85 … … 96 99 self.assertRaises(ldb.LdbError, lambda: l.delete(ldb.Dn(l, "dc=foo2"))) 97 100 101 def test_delete_w_unhandled_ctrl(self): 102 l = ldb.Ldb(filename()) 103 m = ldb.Message() 104 m.dn = ldb.Dn(l, "dc=foo1") 105 m["b"] = ["a"] 106 l.add(m) 107 self.assertRaises(ldb.LdbError, lambda: l.delete(m.dn, ["search_options:1:2"])) 108 l.delete(m.dn) 109 98 110 def test_contains(self): 99 l = ldb.Ldb(filename()) 111 name = filename() 112 l = ldb.Ldb(name) 100 113 self.assertFalse(ldb.Dn(l, "dc=foo3") in l) 101 l = ldb.Ldb( filename())114 l = ldb.Ldb(name) 102 115 m = ldb.Message() 103 116 m.dn = ldb.Dn(l, "dc=foo3") … … 209 222 rm = l.search(m.dn)[0] 210 223 self.assertEquals(1, len(rm)) 211 rm = l.search(m.dn, attrs=["bla"]) [0]224 rm = l.search(m.dn, attrs=["bla"]) 212 225 self.assertEquals(0, len(rm)) 213 226 finally: … … 267 280 self.assertEquals(2, len(rm)) 268 281 self.assertEquals(["1234", "456"], list(rm["bla"])) 269 270 # Now create another modify, but switch the flags before we do it282 283 # Now create another modify, but switch the flags before we do it 271 284 m["bla"] = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla") 272 285 m["bla"].set_flags(ldb.FLAG_MOD_DELETE) … … 275 288 self.assertEquals(1, len(rm)) 276 289 self.assertEquals(["1234"], list(rm["bla"])) 277 278 290 finally: 279 291 l.delete(ldb.Dn(l, "dc=add")) … … 316 328 self.assertEquals("foo\0bar", res[0]["displayname"][0]) 317 329 330 def test_no_crash_broken_expr(self): 331 l = ldb.Ldb(filename()) 332 self.assertRaises(ldb.LdbError,lambda: l.search("", ldb.SCOPE_SUBTREE, "&(dc=*)(dn=*)", ["dc"])) 333 318 334 319 335 class DnTests(unittest.TestCase): … … 332 348 y = ldb.Dn(self.ldb, "dc=foo11,bar=bloe") 333 349 self.assertEquals(x, y) 350 y = ldb.Dn(self.ldb, "dc=foo11,bar=blie") 351 self.assertNotEquals(x, y) 334 352 335 353 def test_str(self): … … 356 374 x = ldb.Dn(self.ldb, "@BLA") 357 375 self.assertEquals(None, x.parent()) 358 359 def test_compare(self):360 x = ldb.Dn(self.ldb, "dc=foo17,bar=bloe")361 y = ldb.Dn(self.ldb, "dc=foo17,bar=bloe")362 self.assertEquals(x, y)363 z = ldb.Dn(self.ldb, "dc=foo17,bar=blie")364 self.assertNotEquals(z, y)365 376 366 377 def test_is_valid(self): … … 368 379 self.assertTrue(x.is_valid()) 369 380 x = ldb.Dn(self.ldb, "") 370 # is_valid()'s return values appears to be a side effect of 371 # some other ldb functions. yuck. 372 # self.assertFalse(x.is_valid()) 381 self.assertTrue(x.is_valid()) 373 382 374 383 def test_is_special(self): … … 413 422 ldif = self.ldb.write_ldif(msg[1], ldb.CHANGETYPE_NONE) 414 423 self.assertEquals("dn: foo=bar\n\n", ldif) 415 424 416 425 def test_parse_ldif_more(self): 417 426 msgs = self.ldb.parse_ldif("dn: foo=bar\n\n\ndn: bar=bar") … … 441 450 def test_iter_items(self): 442 451 self.assertEquals(0, len(self.msg.items())) 443 self.msg.dn = ldb.Dn(ldb.Ldb( "foo.tdb"), "dc=foo28")452 self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "dc=foo28") 444 453 self.assertEquals(1, len(self.msg.items())) 445 454 446 455 def test_repr(self): 447 self.msg.dn = ldb.Dn(ldb.Ldb( "foo.tdb"), "dc=foo29")456 self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "dc=foo29") 448 457 self.msg["dc"] = "foo" 449 458 self.assertEquals("Message({'dn': Dn('dc=foo29'), 'dc': MessageElement(['foo'])})", repr(self.msg)) … … 457 466 def test_del(self): 458 467 del self.msg["foo"] 468 469 def test_add(self): 470 self.msg.add(ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla")) 471 472 def test_elements_empty(self): 473 self.assertEquals([], self.msg.elements()) 474 475 def test_elements(self): 476 el = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla") 477 self.msg.add(el) 478 self.assertEquals([el], self.msg.elements()) 459 479 460 480 def test_add_value(self): … … 476 496 477 497 def test_keys(self): 478 self.msg.dn = ldb.Dn(ldb.Ldb( "foo.tdb"), "@BASEINFO")498 self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "@BASEINFO") 479 499 self.msg["foo"] = ["bla"] 480 500 self.msg["bar"] = ["bla"] … … 486 506 487 507 def test_get_dn(self): 488 self.msg.dn = ldb.Dn(ldb.Ldb( "foo.tdb"), "@BASEINFO")508 self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "@BASEINFO") 489 509 self.assertEquals("@BASEINFO", self.msg.get("dn").__str__()) 490 510 491 511 def test_get_invalid(self): 492 self.msg.dn = ldb.Dn(ldb.Ldb( "foo.tdb"), "@BASEINFO")512 self.msg.dn = ldb.Dn(ldb.Ldb(filename()), "@BASEINFO") 493 513 self.assertRaises(TypeError, self.msg.get, 42) 494 514 … … 510 530 self.assertEquals(1, len(msgdiff)) 511 531 532 def test_equal_empty(self): 533 msg1 = ldb.Message() 534 msg2 = ldb.Message() 535 self.assertEquals(msg1, msg2) 536 537 def test_equal_simplel(self): 538 db = ldb.Ldb(filename()) 539 msg1 = ldb.Message() 540 msg1.dn = ldb.Dn(db, "foo=bar") 541 msg2 = ldb.Message() 542 msg2.dn = ldb.Dn(db, "foo=bar") 543 self.assertEquals(msg1, msg2) 544 msg1['foo'] = 'bar' 545 msg2['foo'] = 'bar' 546 self.assertEquals(msg1, msg2) 547 msg2['foo'] = 'blie' 548 self.assertNotEquals(msg1, msg2) 549 msg2['foo'] = 'blie' 550 551 def test_from_dict(self): 552 rec = {"dn": "dc=fromdict", 553 "a1": ["a1-val1", "a1-val1"]} 554 l = ldb.Ldb() 555 # check different types of input Flags 556 for flags in [ldb.FLAG_MOD_ADD, ldb.FLAG_MOD_REPLACE, ldb.FLAG_MOD_DELETE]: 557 m = ldb.Message.from_dict(l, rec, flags) 558 self.assertEquals(rec["a1"], list(m["a1"])) 559 self.assertEquals(flags, m["a1"].flags()) 560 # check input params 561 self.assertRaises(TypeError, ldb.Message.from_dict, dict(), rec, ldb.FLAG_MOD_REPLACE) 562 self.assertRaises(TypeError, ldb.Message.from_dict, l, list(), ldb.FLAG_MOD_REPLACE) 563 self.assertRaises(ValueError, ldb.Message.from_dict, l, rec, 0) 564 # Message.from_dict expects dictionary with 'dn' 565 err_rec = {"a1": ["a1-val1", "a1-val1"]} 566 self.assertRaises(TypeError, ldb.Message.from_dict, l, err_rec, ldb.FLAG_MOD_REPLACE) 567 512 568 513 569 … … 552 608 self.assertEquals(y, x) 553 609 610 def test_extended(self): 611 el = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla") 612 self.assertEquals("MessageElement(['456'])", repr(el)) 613 554 614 555 615 class ModuleTests(unittest.TestCase): … … 572 632 return self.next.search(*args, **kwargs) 573 633 634 def request(self, *args, **kwargs): 635 pass 636 637 name = filename() 574 638 ldb.register_module(ExampleModule) 575 if os.path.exists( "usemodule.ldb"):576 os.unlink( "usemodule.ldb")577 l = ldb.Ldb( "usemodule.ldb")639 if os.path.exists(name): 640 os.unlink(name) 641 l = ldb.Ldb(name) 578 642 l.add({"dn": "@MODULES", "@LIST": "bla"}) 579 643 self.assertEquals([], ops) 580 l = ldb.Ldb( "usemodule.ldb")644 l = ldb.Ldb(name) 581 645 self.assertEquals(["init"], ops) 646 647 class LdbResultTests(unittest.TestCase): 648 649 def setUp(self): 650 name = filename() 651 self.name = name 652 if os.path.exists(name): 653 os.unlink(name) 654 self.l = ldb.Ldb(name) 655 self.l.add({"dn": "DC=SAMBA,DC=ORG", "name": "samba.org"}) 656 self.l.add({"dn": "OU=ADMIN,DC=SAMBA,DC=ORG", "name": "Admins"}) 657 self.l.add({"dn": "OU=USERS,DC=SAMBA,DC=ORG", "name": "Users"}) 658 self.l.add({"dn": "OU=OU1,DC=SAMBA,DC=ORG", "name": "OU #1"}) 659 self.l.add({"dn": "OU=OU2,DC=SAMBA,DC=ORG", "name": "OU #2"}) 660 self.l.add({"dn": "OU=OU3,DC=SAMBA,DC=ORG", "name": "OU #3"}) 661 self.l.add({"dn": "OU=OU4,DC=SAMBA,DC=ORG", "name": "OU #4"}) 662 self.l.add({"dn": "OU=OU5,DC=SAMBA,DC=ORG", "name": "OU #5"}) 663 self.l.add({"dn": "OU=OU6,DC=SAMBA,DC=ORG", "name": "OU #6"}) 664 self.l.add({"dn": "OU=OU7,DC=SAMBA,DC=ORG", "name": "OU #7"}) 665 self.l.add({"dn": "OU=OU8,DC=SAMBA,DC=ORG", "name": "OU #8"}) 666 self.l.add({"dn": "OU=OU9,DC=SAMBA,DC=ORG", "name": "OU #9"}) 667 self.l.add({"dn": "OU=OU10,DC=SAMBA,DC=ORG", "name": "OU #10"}) 668 669 def tearDown(self): 670 if os.path.exists(self.name): 671 os.unlink(self.name) 672 673 def test_return_type(self): 674 res = self.l.search() 675 self.assertEquals(str(res), "<ldb result>") 676 677 def test_get_msgs(self): 678 res = self.l.search() 679 list = res.msgs 680 681 def test_get_controls(self): 682 res = self.l.search() 683 list = res.controls 684 685 def test_get_referals(self): 686 res = self.l.search() 687 list = res.referals 688 689 def test_iter_msgs(self): 690 found = False 691 for l in self.l.search().msgs: 692 if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG": 693 found = True 694 self.assertTrue(found) 695 696 def test_iter_msgs_count(self): 697 self.assertTrue(self.l.search().count > 0) 698 # 13 objects has been added to the DC=SAMBA, DC=ORG 699 self.assertEqual(self.l.search(base="DC=SAMBA,DC=ORG").count, 13) 700 701 def test_iter_controls(self): 702 res = self.l.search().controls 703 it = iter(res) 704 705 def test_create_control(self): 706 self.assertRaises(ValueError, ldb.Control, self.l, "tatayoyo:0") 707 c = ldb.Control(self.l, "relax:1") 708 self.assertEquals(c.critical, True) 709 self.assertEquals(c.oid, "1.3.6.1.4.1.4203.666.5.12") 710 711 def test_iter_refs(self): 712 res = self.l.search().referals 713 it = iter(res) 714 715 def test_iter_as_sequence_msgs(self): 716 found = False 717 res = self.l.search().msgs 718 719 for i in range(0, len(res)): 720 l = res[i] 721 if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG": 722 found = True 723 self.assertTrue(found) 724 725 def test_iter_as_sequence(self): 726 found = False 727 res = self.l.search() 728 729 for i in range(0, len(res)): 730 l = res[i] 731 if str(l.dn) == "OU=OU10,DC=SAMBA,DC=ORG": 732 found = True 733 self.assertTrue(found) 734 735 class VersionTests(unittest.TestCase): 736 737 def test_version(self): 738 self.assertTrue(isinstance(ldb.__version__, str)) 582 739 583 740 -
trunk/server/source4/lib/ldb/tests/sample_module.c
r414 r745 22 22 */ 23 23 24 #include "replace.h" 25 #include "system/filesys.h" 26 #include "system/time.h" 24 27 #include "ldb_module.h" 25 28 26 int sample_add(struct ldb_module *mod, struct ldb_request *req)29 static int sample_add(struct ldb_module *mod, struct ldb_request *req) 27 30 { 31 struct ldb_control *control; 32 28 33 ldb_msg_add_fmt(req->op.add.message, "touchedBy", "sample"); 29 34 30 return ldb_next_request(mod, req); 35 /* check if there's a relax control */ 36 control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID); 37 if (control == NULL) { 38 /* not found go on */ 39 return ldb_next_request(mod, req); 40 } else { 41 return LDB_ERR_UNWILLING_TO_PERFORM; 42 } 31 43 } 32 44 33 const struct ldb_module_ops ldb_sample_module_ops = { 45 static int sample_modify(struct ldb_module *mod, struct ldb_request *req) 46 { 47 struct ldb_control *control; 48 49 /* check if there's a relax control */ 50 control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID); 51 if (control == NULL) { 52 /* not found go on */ 53 return ldb_next_request(mod, req); 54 } else { 55 return LDB_ERR_UNWILLING_TO_PERFORM; 56 } 57 } 58 59 60 static struct ldb_module_ops ldb_sample_module_ops = { 34 61 .name = "sample", 35 62 .add = sample_add, 63 .del = sample_modify, 64 .modify = sample_modify, 36 65 }; 66 67 int ldb_sample_init(const char *version) 68 { 69 LDB_MODULE_CHECK_VERSION(version); 70 return ldb_register_module(&ldb_sample_module_ops); 71 } -
trunk/server/source4/lib/ldb/tests/test-generic.sh
r414 r745 45 45 } 46 46 47 echo " testing indexed search"47 echo "Testing indexed search" 48 48 $VALGRIND ldbsearch$EXEEXT '(uid=uham)' || exit 1 49 49 $VALGRIND ldbsearch$EXEEXT '(&(objectclass=person)(objectclass=person)(objectclass=top))' || exit 1 … … 82 82 83 83 echo "Testing binary file attribute value" 84 mkdir -p tests/tmp85 cp $LDBDIR/tests/samba4.png tests/tmp/samba4.png86 84 $VALGRIND ldbmodify$EXEEXT $LDBDIR/tests/photo.ldif || exit 1 87 85 count=`$VALGRIND ldbsearch$EXEEXT '(cn=Hampster Ursula)' jpegPhoto | grep '^dn' | wc -l` … … 90 88 exit 1 91 89 fi 92 rm -f tests/tmp/samba4.png93 90 94 91 echo "*TODO* Testing UTF8 upper lower case searches !!" -
trunk/server/source4/lib/ldb/tests/test-schema.sh
r414 r745 20 20 $VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-3.ldif || exit 1 21 21 $VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-4.ldif 22 if [ "$?" = ="0" ]; then22 if [ "$?" = "0" ]; then 23 23 echo "test failed!" 24 24 exit 1 25 25 fi 26 26 $VALGRIND bin/ldbmodify $LDBDIR/tests/schema-tests/schema-mod-test-5.ldif 27 if [ "$?" = ="0" ]; then27 if [ "$?" = "0" ]; then 28 28 echo "test failed!" 29 29 exit 1 -
trunk/server/source4/lib/ldb/tests/test-tdb.sh
r414 r745 30 30 31 31 . $LDBDIR/tests/test-tdb-features.sh 32 33 . $LDBDIR/tests/test-controls.sh -
trunk/server/source4/lib/ldb/tests/test.ldif
r414 r745 410 410 facsimiletelephonenumber: +1 313 555 9700 411 411 telephonenumber: +1 313 555 5331 412 413 dn: cn=Fred Bassett,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST 414 objectclass: OpenLDAPperson 415 cn: Fred Bassett 416 sn: Bassett 417 uid: Bassett, Fred -
trunk/server/source4/lib/ldb/tools/cmdline.c
r414 r745 22 22 */ 23 23 24 #include "ldb_includes.h" 24 #include "replace.h" 25 #include "system/filesys.h" 26 #include "system/time.h" 25 27 #include "ldb.h" 28 #include "ldb_module.h" 26 29 #include "tools/cmdline.h" 27 30 28 #if (_SAMBA_BUILD_ >= 4)29 #include "includes.h"30 #include "lib/cmdline/popt_common.h"31 #include "lib/ldb-samba/ldif_handlers.h"32 #include "auth/gensec/gensec.h"33 #include "auth/auth.h"34 #include "ldb_wrap.h"35 #include "param/param.h"36 #endif37 38 31 static struct ldb_cmdline options; /* needs to be static for older compilers */ 39 32 40 static struct poptOption popt_options[] = { 33 enum ldb_cmdline_options { CMDLINE_RELAX=1 }; 34 35 static struct poptOption builtin_popt_options[] = { 41 36 POPT_AUTOHELP 42 37 { "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" }, … … 54 49 { "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL }, 55 50 { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL }, 56 { "input", 'I', POPT_ARG_STRING, &options.input, 0, "Input File", "Input" },57 { "output", 'O', POPT_ARG_STRING, &options.output, 0, "Output File", "Output" },58 51 { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" }, 59 52 { "controls", 0, POPT_ARG_STRING, NULL, 'c', "controls", NULL }, 60 53 { "show-binary", 0, POPT_ARG_NONE, &options.show_binary, 0, "display binary LDIF", NULL }, 61 #if (_SAMBA_BUILD_ >= 4) 62 POPT_COMMON_SAMBA 63 POPT_COMMON_CREDENTIALS 64 POPT_COMMON_CONNECTION 65 POPT_COMMON_VERSION 66 #endif 54 { "paged", 0, POPT_ARG_NONE, NULL, 'P', "use a paged search", NULL }, 55 { "show-deleted", 0, POPT_ARG_NONE, NULL, 'D', "show deleted objects", NULL }, 56 { "show-recycled", 0, POPT_ARG_NONE, NULL, 'R', "show recycled objects", NULL }, 57 { "show-deactivated-link", 0, POPT_ARG_NONE, NULL, 'd', "show deactivated links", NULL }, 58 { "reveal", 0, POPT_ARG_NONE, NULL, 'r', "reveal ldb internals", NULL }, 59 { "relax", 0, POPT_ARG_NONE, NULL, CMDLINE_RELAX, "pass relax control", NULL }, 60 { "cross-ncs", 0, POPT_ARG_NONE, NULL, 'N', "search across NC boundaries", NULL }, 61 { "extended-dn", 0, POPT_ARG_NONE, NULL, 'E', "show extended DNs", NULL }, 67 62 { NULL } 68 63 }; 69 64 70 void ldb_cmdline_help( const char *cmdname, FILE *f)65 void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f) 71 66 { 72 67 poptContext pc; 73 pc = poptGetContext(cmdname, 0, NULL, popt_options, 68 struct poptOption **popt_options = ldb_module_popt_options(ldb); 69 pc = poptGetContext(cmdname, 0, NULL, *popt_options, 74 70 POPT_CONTEXT_KEEP_FIRST); 75 71 poptPrintHelp(pc, f, 0); 72 } 73 74 /* 75 add a control to the options structure 76 */ 77 static bool add_control(TALLOC_CTX *mem_ctx, const char *control) 78 { 79 unsigned int i; 80 81 /* count how many controls we already have */ 82 for (i=0; options.controls && options.controls[i]; i++) ; 83 84 options.controls = talloc_realloc(mem_ctx, options.controls, const char *, i + 2); 85 if (options.controls == NULL) { 86 return false; 87 } 88 options.controls[i] = control; 89 options.controls[i+1] = NULL; 90 return true; 76 91 } 77 92 … … 81 96 struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, 82 97 int argc, const char **argv, 83 void (*usage)( void))98 void (*usage)(struct ldb_context *)) 84 99 { 85 100 struct ldb_cmdline *ret=NULL; 86 101 poptContext pc; 87 #if (_SAMBA_BUILD_ >= 4)88 int r;89 #endif90 102 int num_options = 0; 91 103 int opt; 92 104 int flags = 0; 93 94 #if (_SAMBA_BUILD_ >= 4) 95 r = ldb_register_samba_handlers(ldb); 96 if (r != 0) { 97 goto failed; 98 } 99 100 #endif 105 int rc; 106 struct poptOption **popt_options; 107 108 /* make the ldb utilities line buffered */ 109 setlinebuf(stdout); 101 110 102 111 ret = talloc_zero(ldb, struct ldb_cmdline); … … 122 131 options.scope = LDB_SCOPE_DEFAULT; 123 132 124 pc = poptGetContext(argv[0], argc, argv, popt_options, 133 popt_options = ldb_module_popt_options(ldb); 134 (*popt_options) = builtin_popt_options; 135 136 rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_OPTIONS); 137 if (rc != LDB_SUCCESS) { 138 fprintf(stderr, "ldb: failed to run command line hooks : %s\n", ldb_strerror(rc)); 139 goto failed; 140 } 141 142 pc = poptGetContext(argv[0], argc, argv, *popt_options, 125 143 POPT_CONTEXT_KEEP_FIRST); 126 144 … … 160 178 case 'c': { 161 179 const char *cs = poptGetOptArg(pc); 162 const char *p, *q; 163 int cc; 164 165 for (p = cs, cc = 1; (q = strchr(p, ',')); cc++, p = q + 1) ; 166 167 options.controls = talloc_array(ret, char *, cc + 1); 168 if (options.controls == NULL) { 169 fprintf(stderr, "Out of memory!\n"); 170 goto failed; 171 } 172 for (p = cs, cc = 0; p != NULL; cc++) { 173 const char *t; 180 const char *p; 181 182 for (p = cs; p != NULL; ) { 183 const char *t, *c; 174 184 175 185 t = strchr(p, ','); 176 186 if (t == NULL) { 177 options.controls[cc]= talloc_strdup(options.controls, p);187 c = talloc_strdup(options.controls, p); 178 188 p = NULL; 179 189 } else { 180 options.controls[cc]= talloc_strndup(options.controls, p, t-p);190 c = talloc_strndup(options.controls, p, t-p); 181 191 p = t + 1; 182 192 } 183 } 184 options.controls[cc] = NULL; 193 if (c == NULL || !add_control(ret, c)) { 194 fprintf(stderr, __location__ ": out of memory\n"); 195 goto failed; 196 } 197 } 185 198 186 199 break; 187 200 } 201 case 'P': 202 if (!add_control(ret, "paged_results:1:1024")) { 203 fprintf(stderr, __location__ ": out of memory\n"); 204 goto failed; 205 } 206 break; 207 case 'D': 208 if (!add_control(ret, "show_deleted:1")) { 209 fprintf(stderr, __location__ ": out of memory\n"); 210 goto failed; 211 } 212 break; 213 case 'R': 214 if (!add_control(ret, "show_recycled:0")) { 215 fprintf(stderr, __location__ ": out of memory\n"); 216 goto failed; 217 } 218 break; 219 case 'd': 220 if (!add_control(ret, "show_deactivated_link:0")) { 221 fprintf(stderr, __location__ ": out of memory\n"); 222 goto failed; 223 } 224 break; 225 case 'r': 226 if (!add_control(ret, "reveal_internals:0")) { 227 fprintf(stderr, __location__ ": out of memory\n"); 228 goto failed; 229 } 230 break; 231 case CMDLINE_RELAX: 232 if (!add_control(ret, "relax:0")) { 233 fprintf(stderr, __location__ ": out of memory\n"); 234 goto failed; 235 } 236 break; 237 case 'N': 238 if (!add_control(ret, "search_options:1:2")) { 239 fprintf(stderr, __location__ ": out of memory\n"); 240 goto failed; 241 } 242 break; 243 case 'E': 244 if (!add_control(ret, "extended_dn:1:1")) { 245 fprintf(stderr, __location__ ": out of memory\n"); 246 goto failed; 247 } 248 break; 188 249 default: 189 250 fprintf(stderr, "Invalid option %s: %s\n", 190 251 poptBadOption(pc, 0), poptStrerror(opt)); 191 if (usage) usage( );252 if (usage) usage(ldb); 192 253 goto failed; 193 254 } … … 206 267 if (ret->url == NULL) { 207 268 fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n"); 208 if (usage) usage( );269 if (usage) usage(ldb); 209 270 goto failed; 210 271 } … … 226 287 } 227 288 228 #if (_SAMBA_BUILD_ >= 4)229 /* Must be after we have processed command line options */230 gensec_init(cmdline_lp_ctx);231 232 if (ldb_set_opaque(ldb, "sessionInfo", system_session(ldb, cmdline_lp_ctx))) {233 goto failed;234 }235 if (ldb_set_opaque(ldb, "credentials", cmdline_credentials)) {236 goto failed;237 }238 if (ldb_set_opaque(ldb, "loadparm", cmdline_lp_ctx)) {239 goto failed;240 }241 242 ldb_set_utf8_fns(ldb, NULL, wrap_casefold);243 #endif244 245 289 if (options.modules_path != NULL) { 246 290 ldb_set_modules_dir(ldb, options.modules_path); 247 } else if (getenv("LDB_MODULES_PATH") != NULL) { 248 ldb_set_modules_dir(ldb, getenv("LDB_MODULES_PATH")); 291 } 292 293 rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_PRECONNECT); 294 if (rc != LDB_SUCCESS) { 295 fprintf(stderr, "ldb: failed to run preconnect hooks : %s\n", ldb_strerror(rc)); 296 goto failed; 249 297 } 250 298 … … 256 304 } 257 305 306 rc = ldb_modules_hook(ldb, LDB_MODULE_HOOK_CMDLINE_POSTCONNECT); 307 if (rc != LDB_SUCCESS) { 308 fprintf(stderr, "ldb: failed to run post connect hooks : %s\n", ldb_strerror(rc)); 309 goto failed; 310 } 311 258 312 return ret; 259 313 260 314 failed: 261 315 talloc_free(ret); 262 exit( 1);316 exit(LDB_ERR_OPERATIONS_ERROR); 263 317 return NULL; 264 318 } … … 274 328 int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request) 275 329 { 276 int i, j;277 330 unsigned int i, j; 331 int ret = 0; 278 332 279 333 if (reply == NULL || request == NULL) return -1; -
trunk/server/source4/lib/ldb/tools/cmdline.h
r414 r745 42 42 int num_searches; 43 43 const char *sasl_mechanism; 44 const char *input; 45 const char *output; 46 char **controls; 44 const char **controls; 47 45 int show_binary; 48 46 int tracing; 49 47 }; 50 48 51 struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv, 52 void (*usage)(void)); 49 struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, 50 const char **argv, 51 void (*usage)(struct ldb_context *)); 53 52 54 53 55 54 int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request); 56 void ldb_cmdline_help( const char *cmdname, FILE *f);55 void ldb_cmdline_help(struct ldb_context *ldb, const char *cmdname, FILE *f); 57 56 -
trunk/server/source4/lib/ldb/tools/ldbadd.c
r414 r745 1 /* 1 /* 2 2 ldb database library 3 3 … … 7 7 ** library. This does NOT imply that all of Samba is released 8 8 ** under the LGPL 9 9 10 10 This library is free software; you can redistribute it and/or 11 11 modify it under the terms of the GNU Lesser General Public … … 34 34 #include "ldb.h" 35 35 #include "tools/cmdline.h" 36 #include "ldbutil.h" 36 37 37 static int failures; 38 static unsigned int failures; 39 static struct ldb_cmdline *options; 38 40 39 static void usage( void)41 static void usage(struct ldb_context *ldb) 40 42 { 41 printf("Usage: ldbadd <options> <ldif...>\n"); 43 printf("Usage: ldbadd <options> <ldif...>\n"); 42 44 printf("Adds records to a ldb, reading ldif the specified list of files\n\n"); 43 ldb_cmdline_help( "ldbadd", stdout);44 exit( 1);45 ldb_cmdline_help(ldb, "ldbadd", stdout); 46 exit(LDB_ERR_OPERATIONS_ERROR); 45 47 } 46 48 … … 49 51 add records from an opened file 50 52 */ 51 static int process_file(struct ldb_context *ldb, FILE *f, int *count)53 static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) 52 54 { 53 55 struct ldb_ldif *ldif; 54 56 int ret = LDB_SUCCESS; 57 struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); 58 if (options->controls != NULL && req_ctrls== NULL) { 59 printf("parsing controls failed: %s\n", ldb_errstring(ldb)); 60 return LDB_ERR_OPERATIONS_ERROR; 61 } 62 55 63 56 64 while ((ldif = ldb_ldif_read_file(ldb, f))) { … … 61 69 } 62 70 63 ldif->msg = ldb_msg_canonicalize(ldb, ldif->msg); 71 ret = ldb_msg_normalize(ldb, ldif, ldif->msg, &ldif->msg); 72 if (ret != LDB_SUCCESS) { 73 fprintf(stderr, 74 "ERR: Message canonicalize failed - %s\n", 75 ldb_strerror(ret)); 76 failures++; 77 ldb_ldif_read_free(ldb, ldif); 78 continue; 79 } 64 80 65 ret = ldb_add (ldb, ldif->msg);81 ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls); 66 82 if (ret != LDB_SUCCESS) { 67 fprintf(stderr, "ERR: \"%s\" on DN %s\n", 68 ldb_errstring(ldb), ldb_dn_get_linearized(ldif->msg->dn)); 83 fprintf(stderr, "ERR: %s : \"%s\" on DN %s\n", 84 ldb_strerror(ret), ldb_errstring(ldb), 85 ldb_dn_get_linearized(ldif->msg->dn)); 69 86 failures++; 70 87 } else { 71 88 (*count)++; 89 if (options->verbose) { 90 printf("Added %s\n", ldb_dn_get_linearized(ldif->msg->dn)); 91 } 72 92 } 73 93 ldb_ldif_read_free(ldb, ldif); … … 82 102 { 83 103 struct ldb_context *ldb; 84 int i, ret=0, count=0; 85 struct ldb_cmdline *options; 104 unsigned int i, count = 0; 105 int ret = LDB_SUCCESS; 106 TALLOC_CTX *mem_ctx = talloc_new(NULL); 86 107 87 ldb = ldb_init(NULL, NULL); 108 ldb = ldb_init(mem_ctx, NULL); 109 if (ldb == NULL) { 110 return LDB_ERR_OPERATIONS_ERROR; 111 } 88 112 89 113 options = ldb_cmdline_process(ldb, argc, argv, usage); 90 114 91 if (ldb_transaction_start(ldb) != 0) { 115 ret = ldb_transaction_start(ldb); 116 if (ret != LDB_SUCCESS) { 92 117 printf("Failed to start transaction: %s\n", ldb_errstring(ldb)); 93 exit(1);118 return ret; 94 119 } 95 120 … … 103 128 if (!f) { 104 129 perror(fname); 105 exit(1);130 return LDB_ERR_OPERATIONS_ERROR; 106 131 } 107 132 ret = process_file(ldb, f, &count); … … 111 136 112 137 if (count != 0) { 113 if (ldb_transaction_commit(ldb) != 0) { 138 ret = ldb_transaction_commit(ldb); 139 if (ret != LDB_SUCCESS) { 114 140 printf("Failed to commit transaction: %s\n", ldb_errstring(ldb)); 115 exit(1);141 return ret; 116 142 } 117 143 } else { … … 119 145 } 120 146 121 talloc_free( ldb);147 talloc_free(mem_ctx); 122 148 123 printf("Added % d records with %dfailures\n", count, failures);124 149 printf("Added %u records with %u failures\n", count, failures); 150 125 151 return ret; 126 152 } -
trunk/server/source4/lib/ldb/tools/ldbdel.c
r414 r745 32 32 */ 33 33 34 #include "replace.h" 34 35 #include "ldb.h" 35 36 #include "tools/cmdline.h" 37 #include "ldbutil.h" 36 38 37 static int ldb_delete_recursive(struct ldb_context *ldb, struct ldb_dn *dn)39 static int dn_cmp(struct ldb_message **msg1, struct ldb_message **msg2) 38 40 { 39 int ret, i, total=0; 41 return ldb_dn_compare((*msg1)->dn, (*msg2)->dn); 42 } 43 44 static int ldb_delete_recursive(struct ldb_context *ldb, struct ldb_dn *dn,struct ldb_control **req_ctrls) 45 { 46 int ret; 47 unsigned int i, total=0; 40 48 const char *attrs[] = { NULL }; 41 49 struct ldb_result *res; 42 50 43 51 ret = ldb_search(ldb, ldb, &res, dn, LDB_SCOPE_SUBTREE, attrs, "distinguishedName=*"); 44 if (ret != LDB_SUCCESS) return -1; 52 if (ret != LDB_SUCCESS) return ret; 53 54 /* sort the DNs, deepest first */ 55 TYPESAFE_QSORT(res->msgs, res->count, dn_cmp); 45 56 46 57 for (i = 0; i < res->count; i++) { 47 if (ldb_delete (ldb, res->msgs[i]->dn) == 0) {58 if (ldb_delete_ctrl(ldb, res->msgs[i]->dn,req_ctrls) == LDB_SUCCESS) { 48 59 total++; 60 } else { 61 printf("Failed to delete '%s' - %s\n", 62 ldb_dn_get_linearized(res->msgs[i]->dn), 63 ldb_errstring(ldb)); 49 64 } 50 65 } … … 53 68 54 69 if (total == 0) { 55 return -1;70 return LDB_ERR_OPERATIONS_ERROR; 56 71 } 57 printf("Deleted % drecords\n", total);58 return 0;72 printf("Deleted %u records\n", total); 73 return LDB_SUCCESS; 59 74 } 60 75 61 static void usage( void)76 static void usage(struct ldb_context *ldb) 62 77 { 63 78 printf("Usage: ldbdel <options> <DN...>\n"); 64 79 printf("Deletes records from a ldb\n\n"); 65 ldb_cmdline_help( "ldbdel", stdout);66 exit( 1);80 ldb_cmdline_help(ldb, "ldbdel", stdout); 81 exit(LDB_ERR_OPERATIONS_ERROR); 67 82 } 68 83 69 84 int main(int argc, const char **argv) 70 85 { 86 struct ldb_control **req_ctrls; 87 struct ldb_cmdline *options; 71 88 struct ldb_context *ldb; 72 89 int ret = 0, i; 73 struct ldb_cmdline *options;90 TALLOC_CTX *mem_ctx = talloc_new(NULL); 74 91 75 ldb = ldb_init(NULL, NULL); 92 ldb = ldb_init(mem_ctx, NULL); 93 if (ldb == NULL) { 94 return LDB_ERR_OPERATIONS_ERROR; 95 } 76 96 77 97 options = ldb_cmdline_process(ldb, argc, argv, usage); 78 98 79 99 if (options->argc < 1) { 80 usage(); 81 exit(1); 100 usage(ldb); 101 } 102 103 req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); 104 if (options->controls != NULL && req_ctrls== NULL) { 105 printf("parsing controls failed: %s\n", ldb_errstring(ldb)); 106 return LDB_ERR_OPERATIONS_ERROR; 82 107 } 83 108 … … 86 111 87 112 dn = ldb_dn_new(ldb, ldb, options->argv[i]); 88 if ( ! ldb_dn_validate(dn)) { 89 printf("Invalid DN format\n"); 90 exit(1); 113 if (dn == NULL) { 114 return LDB_ERR_OPERATIONS_ERROR; 91 115 } 92 116 if (options->recursive) { 93 ret = ldb_delete_recursive(ldb, dn );117 ret = ldb_delete_recursive(ldb, dn,req_ctrls); 94 118 } else { 95 ret = ldb_delete (ldb, dn);96 if (ret == 0) {119 ret = ldb_delete_ctrl(ldb, dn,req_ctrls); 120 if (ret == LDB_SUCCESS) { 97 121 printf("Deleted 1 record\n"); 98 122 } 99 123 } 100 if (ret != 0) { 101 printf("delete of '%s' failed - %s\n", 102 ldb_dn_get_linearized(dn), 103 ldb_errstring(ldb)); 124 if (ret != LDB_SUCCESS) { 125 printf("delete of '%s' failed - (%s) %s\n", 126 ldb_dn_get_linearized(dn), 127 ldb_strerror(ret), 128 ldb_errstring(ldb)); 104 129 } 105 130 } 106 131 107 talloc_free( ldb);132 talloc_free(mem_ctx); 108 133 109 134 return ret; -
trunk/server/source4/lib/ldb/tools/ldbedit.c
r414 r745 1 /* 1 /* 2 2 ldb database library 3 3 … … 7 7 ** library. This does NOT imply that all of Samba is released 8 8 ** under the LGPL 9 9 10 10 This library is free software; you can redistribute it and/or 11 11 modify it under the terms of the GNU Lesser General Public … … 31 31 * Author: Andrew Tridgell 32 32 */ 33 #include "ldb_includes.h" 33 34 #include "replace.h" 35 #include "system/filesys.h" 36 #include "system/time.h" 37 #include "system/filesys.h" 34 38 #include "ldb.h" 35 39 #include "tools/cmdline.h" 40 #include "tools/ldbutil.h" 36 41 37 42 static struct ldb_cmdline *options; 38 43 39 44 /* 40 debug routine 41 */ 42 static void ldif_write_msg(struct ldb_context *ldb, 43 FILE *f, 45 debug routine 46 */ 47 static void ldif_write_msg(struct ldb_context *ldb, 48 FILE *f, 44 49 enum ldb_changetype changetype, 45 50 struct ldb_message *msg) … … 55 60 returns the number of modified elements 56 61 */ 57 static int modify_record(struct ldb_context *ldb, 62 static int modify_record(struct ldb_context *ldb, 58 63 struct ldb_message *msg1, 59 struct ldb_message *msg2) 60 { 64 struct ldb_message *msg2, 65 struct ldb_control **req_ctrls) 66 { 67 int ret; 61 68 struct ldb_message *mod; 62 69 63 mod = ldb_msg_diff(ldb, msg1, msg2); 64 if (mod == NULL) { 70 if (ldb_msg_difference(ldb, ldb, msg1, msg2, &mod) != LDB_SUCCESS) { 65 71 fprintf(stderr, "Failed to calculate message differences\n"); 66 72 return -1; 67 73 } 68 74 69 if (mod->num_elements == 0) { 70 return 0; 75 ret = mod->num_elements; 76 if (ret == 0) { 77 goto done; 71 78 } 72 79 … … 75 82 } 76 83 77 if (ldb_modify (ldb, mod) != 0) {78 fprintf(stderr, "failed to modify %s - %s\n", 84 if (ldb_modify_ctrl(ldb, mod, req_ctrls) != LDB_SUCCESS) { 85 fprintf(stderr, "failed to modify %s - %s\n", 79 86 ldb_dn_get_linearized(msg1->dn), ldb_errstring(ldb)); 80 return -1; 81 } 82 83 return mod->num_elements; 87 ret = -1; 88 goto done; 89 } 90 91 done: 92 talloc_free(mod); 93 return ret; 84 94 } 85 95 … … 89 99 static struct ldb_message *msg_find(struct ldb_context *ldb, 90 100 struct ldb_message **msgs, 91 int count,101 unsigned int count, 92 102 struct ldb_dn *dn) 93 103 { 94 int i;104 unsigned int i; 95 105 for (i=0;i<count;i++) { 96 106 if (ldb_dn_compare(dn, msgs[i]->dn) == 0) { … … 105 115 */ 106 116 static int merge_edits(struct ldb_context *ldb, 107 struct ldb_message **msgs1, int count1,108 struct ldb_message **msgs2, int count2)109 { 110 int i;117 struct ldb_message **msgs1, unsigned int count1, 118 struct ldb_message **msgs2, unsigned int count2) 119 { 120 unsigned int i; 111 121 struct ldb_message *msg; 112 int ret = 0; 113 int adds=0, modifies=0, deletes=0; 114 115 if (ldb_transaction_start(ldb) != 0) { 122 int ret; 123 unsigned int adds=0, modifies=0, deletes=0; 124 struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); 125 if (options->controls != NULL && req_ctrls == NULL) { 126 fprintf(stderr, "parsing controls failed: %s\n", ldb_errstring(ldb)); 127 return -1; 128 } 129 130 if (ldb_transaction_start(ldb) != LDB_SUCCESS) { 116 131 fprintf(stderr, "Failed to start transaction: %s\n", ldb_errstring(ldb)); 117 132 return -1; … … 125 140 ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]); 126 141 } 127 if (ldb_add (ldb, msgs2[i]) != 0) {142 if (ldb_add_ctrl(ldb, msgs2[i], req_ctrls) != LDB_SUCCESS) { 128 143 fprintf(stderr, "failed to add %s - %s\n", 129 144 ldb_dn_get_linearized(msgs2[i]->dn), … … 134 149 adds++; 135 150 } else { 136 if (modify_record(ldb, msg, msgs2[i]) > 0) { 137 modifies++; 151 ret = modify_record(ldb, msg, msgs2[i], req_ctrls); 152 if (ret != -1) { 153 modifies += (unsigned int) ret; 154 } else { 155 return -1; 138 156 } 139 157 } … … 147 165 ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]); 148 166 } 149 if (ldb_delete (ldb, msgs1[i]->dn) != 0) {167 if (ldb_delete_ctrl(ldb, msgs1[i]->dn, req_ctrls) != LDB_SUCCESS) { 150 168 fprintf(stderr, "failed to delete %s - %s\n", 151 169 ldb_dn_get_linearized(msgs1[i]->dn), … … 158 176 } 159 177 160 if (ldb_transaction_commit(ldb) != 0) {178 if (ldb_transaction_commit(ldb) != LDB_SUCCESS) { 161 179 fprintf(stderr, "Failed to commit transaction: %s\n", ldb_errstring(ldb)); 162 180 return -1; 163 181 } 164 182 165 printf("# % d adds %d modifies %ddeletes\n", adds, modifies, deletes);166 167 return ret;183 printf("# %u adds %u modifies %u deletes\n", adds, modifies, deletes); 184 185 return 0; 168 186 } 169 187 … … 171 189 save a set of messages as ldif to a file 172 190 */ 173 static int save_ldif(struct ldb_context *ldb, 174 FILE *f, struct ldb_message **msgs, int count)175 { 176 int i;177 178 fprintf(f, "# editing % drecords\n", count);191 static int save_ldif(struct ldb_context *ldb, 192 FILE *f, struct ldb_message **msgs, unsigned int count) 193 { 194 unsigned int i; 195 196 fprintf(f, "# editing %u records\n", count); 179 197 180 198 for (i=0;i<count;i++) { 181 199 struct ldb_ldif ldif; 182 fprintf(f, "# record % d\n", i+1);200 fprintf(f, "# record %u\n", i+1); 183 201 184 202 ldif.changetype = LDB_CHANGETYPE_NONE; … … 195 213 edit the ldb search results in msgs using the user selected editor 196 214 */ 197 static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int count1,198 const char *editor)215 static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, 216 unsigned int count1, const char *editor) 199 217 { 200 218 int fd, ret; … … 204 222 struct ldb_ldif *ldif; 205 223 struct ldb_message **msgs2 = NULL; 206 int count2 = 0;224 unsigned int count2 = 0; 207 225 208 226 /* write out the original set of messages to a temporary … … 270 288 } 271 289 272 static void usage( void)290 static void usage(struct ldb_context *ldb) 273 291 { 274 292 printf("Usage: ldbedit <options> <expression> <attributes ...>\n"); 275 ldb_cmdline_help( "ldbedit", stdout);276 exit( 1);293 ldb_cmdline_help(ldb, "ldbedit", stdout); 294 exit(LDB_ERR_OPERATIONS_ERROR); 277 295 } 278 296 … … 285 303 const char *expression = "(|(objectClass=*)(distinguishedName=*))"; 286 304 const char * const * attrs = NULL; 287 288 ldb = ldb_init(NULL, NULL); 305 TALLOC_CTX *mem_ctx = talloc_new(NULL); 306 struct ldb_control **req_ctrls; 307 308 ldb = ldb_init(mem_ctx, NULL); 309 if (ldb == NULL) { 310 return LDB_ERR_OPERATIONS_ERROR; 311 } 289 312 290 313 options = ldb_cmdline_process(ldb, argc, argv, usage); 291 314 292 315 /* the check for '=' is for compatibility with ldapsearch */ 293 if (options->argc > 0 && 316 if (options->argc > 0 && 294 317 strchr(options->argv[0], '=')) { 295 318 expression = options->argv[0]; … … 304 327 if (options->basedn != NULL) { 305 328 basedn = ldb_dn_new(ldb, ldb, options->basedn); 306 if ( ! ldb_dn_validate(basedn)) { 307 printf("Invalid Base DN format\n"); 308 exit(1); 309 } 310 } 311 312 ret = ldb_search(ldb, ldb, &result, basedn, options->scope, attrs, "%s", expression); 329 if (basedn == NULL) { 330 return LDB_ERR_OPERATIONS_ERROR; 331 } 332 } 333 334 req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); 335 if (options->controls != NULL && req_ctrls== NULL) { 336 printf("parsing controls failed: %s\n", ldb_errstring(ldb)); 337 return LDB_ERR_OPERATIONS_ERROR; 338 } 339 340 ret = ldb_search_ctrl(ldb, ldb, &result, basedn, options->scope, attrs, req_ctrls, "%s", expression); 313 341 if (ret != LDB_SUCCESS) { 314 342 printf("search failed - %s\n", ldb_errstring(ldb)); 315 exit(1);343 return ret; 316 344 } 317 345 318 346 if (result->count == 0) { 319 347 printf("no matching records - cannot edit\n"); 320 return 0; 321 } 322 323 do_edit(ldb, result->msgs, result->count, options->editor); 324 325 if (result) { 326 ret = talloc_free(result); 327 if (ret == -1) { 328 fprintf(stderr, "talloc_free failed\n"); 329 exit(1); 330 } 331 } 332 333 talloc_free(ldb); 334 return 0; 335 } 348 talloc_free(mem_ctx); 349 return LDB_SUCCESS; 350 } 351 352 ret = do_edit(ldb, result->msgs, result->count, options->editor); 353 354 talloc_free(mem_ctx); 355 356 return ret == 0 ? LDB_SUCCESS : LDB_ERR_OPERATIONS_ERROR; 357 } -
trunk/server/source4/lib/ldb/tools/ldbmodify.c
r414 r745 34 34 #include "ldb.h" 35 35 #include "tools/cmdline.h" 36 #include "ldbutil.h" 36 37 37 static int failures; 38 static unsigned int failures; 39 static struct ldb_cmdline *options; 38 40 39 static void usage( void)41 static void usage(struct ldb_context *ldb) 40 42 { 41 43 printf("Usage: ldbmodify <options> <ldif...>\n"); 42 44 printf("Modifies a ldb based upon ldif change records\n\n"); 43 ldb_cmdline_help( "ldbmodify", stdout);44 exit( 1);45 ldb_cmdline_help(ldb, "ldbmodify", stdout); 46 exit(LDB_ERR_OPERATIONS_ERROR); 45 47 } 46 48 … … 48 50 process modifies for one file 49 51 */ 50 static int process_file(struct ldb_context *ldb, FILE *f, int *count)52 static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count) 51 53 { 52 54 struct ldb_ldif *ldif; 53 55 int ret = LDB_SUCCESS; 54 56 struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls); 57 58 if (options->controls != NULL && req_ctrls== NULL) { 59 printf("parsing controls failed: %s\n", ldb_errstring(ldb)); 60 exit(LDB_ERR_OPERATIONS_ERROR); 61 } 62 55 63 while ((ldif = ldb_ldif_read_file(ldb, f))) { 56 64 switch (ldif->changetype) { 57 65 case LDB_CHANGETYPE_NONE: 58 66 case LDB_CHANGETYPE_ADD: 59 ret = ldb_add (ldb, ldif->msg);67 ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls); 60 68 break; 61 69 case LDB_CHANGETYPE_DELETE: 62 ret = ldb_delete (ldb, ldif->msg->dn);70 ret = ldb_delete_ctrl(ldb, ldif->msg->dn,req_ctrls); 63 71 break; 64 72 case LDB_CHANGETYPE_MODIFY: 65 ret = ldb_modify (ldb, ldif->msg);73 ret = ldb_modify_ctrl(ldb, ldif->msg,req_ctrls); 66 74 break; 67 75 } 68 76 if (ret != LDB_SUCCESS) { 69 fprintf(stderr, "ERR: \"%s\" on DN %s\n", 77 fprintf(stderr, "ERR: (%s) \"%s\" on DN %s\n", 78 ldb_strerror(ret), 70 79 ldb_errstring(ldb), ldb_dn_get_linearized(ldif->msg->dn)); 71 80 failures++; 72 81 } else { 73 82 (*count)++; 83 if (options->verbose) { 84 printf("Modified %s\n", ldb_dn_get_linearized(ldif->msg->dn)); 85 } 74 86 } 75 87 ldb_ldif_read_free(ldb, ldif); … … 82 94 { 83 95 struct ldb_context *ldb; 84 int count=0;85 int i, ret=LDB_SUCCESS;86 struct ldb_cmdline *options;96 unsigned int i, count = 0; 97 int ret = LDB_SUCCESS; 98 TALLOC_CTX *mem_ctx = talloc_new(NULL); 87 99 88 ldb = ldb_init(NULL, NULL); 100 ldb = ldb_init(mem_ctx, NULL); 101 if (ldb == NULL) { 102 return LDB_ERR_OPERATIONS_ERROR; 103 } 89 104 90 105 options = ldb_cmdline_process(ldb, argc, argv, usage); … … 99 114 if (!f) { 100 115 perror(fname); 101 exit(1);116 return LDB_ERR_OPERATIONS_ERROR; 102 117 } 103 118 ret = process_file(ldb, f, &count); … … 106 121 } 107 122 108 talloc_free( ldb);123 talloc_free(mem_ctx); 109 124 110 printf("Modified % d records with %dfailures\n", count, failures);125 printf("Modified %u records with %u failures\n", count, failures); 111 126 112 127 return ret; -
trunk/server/source4/lib/ldb/tools/ldbrename.c
r414 r745 37 37 #include "tools/cmdline.h" 38 38 39 static void usage( void)39 static void usage(struct ldb_context *ldb) 40 40 { 41 41 printf("Usage: ldbrename [<options>] <olddn> <newdn>\n"); 42 42 printf("Renames records in a ldb\n\n"); 43 ldb_cmdline_help( "ldbmodify", stdout);44 exit( 1);43 ldb_cmdline_help(ldb, "ldbmodify", stdout); 44 exit(LDB_ERR_OPERATIONS_ERROR); 45 45 } 46 46 … … 52 52 struct ldb_cmdline *options; 53 53 struct ldb_dn *dn1, *dn2; 54 TALLOC_CTX *mem_ctx = talloc_new(NULL); 54 55 55 ldb = ldb_init(NULL, NULL); 56 ldb = ldb_init(mem_ctx, NULL); 57 if (ldb == NULL) { 58 return LDB_ERR_OPERATIONS_ERROR; 59 } 56 60 57 61 options = ldb_cmdline_process(ldb, argc, argv, usage); 58 62 59 63 if (options->argc < 2) { 60 usage( );64 usage(ldb); 61 65 } 62 66 63 67 dn1 = ldb_dn_new(ldb, ldb, options->argv[0]); 64 68 dn2 = ldb_dn_new(ldb, ldb, options->argv[1]); 65 66 if ( ! ldb_dn_validate(dn1)) { 67 printf("Invalid DN1: %s\n", options->argv[0]); 68 return -1; 69 } 70 if ( ! ldb_dn_validate(dn2)) { 71 printf("Invalid DN2: %s\n", options->argv[1]); 72 return -1; 69 if ((dn1 == NULL) || (dn2 == NULL)) { 70 return LDB_ERR_OPERATIONS_ERROR; 73 71 } 74 72 75 73 ret = ldb_rename(ldb, dn1, dn2); 76 if (ret == 0) {74 if (ret == LDB_SUCCESS) { 77 75 printf("Renamed 1 record\n"); 78 76 } else { … … 81 79 } 82 80 83 talloc_free( ldb);81 talloc_free(mem_ctx); 84 82 85 83 return ret; -
trunk/server/source4/lib/ldb/tools/ldbsearch.c
r414 r745 32 32 */ 33 33 34 #include "ldb_includes.h" 34 #include "replace.h" 35 #include "system/filesys.h" 36 #include "system/time.h" 35 37 #include "ldb.h" 36 38 #include "tools/cmdline.h" 37 39 38 static void usage( void)40 static void usage(struct ldb_context *ldb) 39 41 { 40 42 printf("Usage: ldbsearch <options> <expression> <attrs...>\n"); 41 ldb_cmdline_help( "ldbsearch", stdout);42 exit( 1);43 ldb_cmdline_help(ldb, "ldbsearch", stdout); 44 exit(LDB_ERR_OPERATIONS_ERROR); 43 45 } 44 46 … … 55 57 56 58 int sort; 57 int num_stored;59 unsigned int num_stored; 58 60 struct ldb_message **store; 59 int refs_stored;61 unsigned int refs_stored; 60 62 char **refs_store; 61 63 62 int entries;63 int refs;64 65 int pending;64 unsigned int entries; 65 unsigned int refs; 66 67 unsigned int pending; 66 68 int status; 67 69 }; … … 132 134 { 133 135 struct search_context *sctx; 134 int ret ;136 int ret = LDB_SUCCESS; 135 137 136 138 sctx = talloc_get_type(req->context, struct search_context); … … 173 175 174 176 talloc_free(ares); 175 if (ret ) {177 if (ret != LDB_SUCCESS) { 176 178 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR); 177 179 } … … 192 194 req = NULL; 193 195 194 sctx = talloc (ldb, struct search_context);195 if (!sctx) return -1;196 sctx = talloc_zero(ldb, struct search_context); 197 if (!sctx) return LDB_ERR_OPERATIONS_ERROR; 196 198 197 199 sctx->ldb = ldb; 198 200 sctx->sort = options->sorted; 199 sctx->num_stored = 0;200 sctx->refs_stored = 0;201 sctx->store = NULL;202 201 sctx->req_ctrls = ldb_parse_control_strings(ldb, sctx, (const char **)options->controls); 203 202 if (options->controls != NULL && sctx->req_ctrls== NULL) { 204 203 printf("parsing controls failed: %s\n", ldb_errstring(ldb)); 205 return -1; 206 } 207 sctx->entries = 0; 208 sctx->refs = 0; 204 return LDB_ERR_OPERATIONS_ERROR; 205 } 209 206 210 207 if (basedn == NULL) { … … 225 222 talloc_free(sctx); 226 223 printf("allocating request failed: %s\n", ldb_errstring(ldb)); 227 return -1;224 return ret; 228 225 } 229 226 … … 233 230 if (ret != LDB_SUCCESS) { 234 231 printf("search failed - %s\n", ldb_errstring(ldb)); 235 return -1;232 return ret; 236 233 } 237 234 238 235 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 239 236 if (ret != LDB_SUCCESS) { 240 237 printf("search error - %s\n", ldb_errstring(ldb)); 241 return -1;238 return ret; 242 239 } 243 240 … … 246 243 247 244 if (sctx->sort && (sctx->num_stored != 0 || sctx->refs != 0)) { 248 int i;245 unsigned int i; 249 246 250 247 if (sctx->num_stored) { 251 ldb_qsort(sctx->store, sctx->num_stored, sizeof(struct ldb_message *), 252 ldb, (ldb_qsort_cmp_fn_t)do_compare_msg); 248 LDB_TYPESAFE_QSORT(sctx->store, sctx->num_stored, ldb, do_compare_msg); 253 249 } 254 250 for (i = 0; i < sctx->num_stored; i++) { … … 261 257 } 262 258 263 printf("# returned % d records\n# %d entries\n# %dreferrals\n",259 printf("# returned %u records\n# %u entries\n# %u referrals\n", 264 260 sctx->entries + sctx->refs, sctx->entries, sctx->refs); 265 261 … … 267 263 talloc_free(req); 268 264 269 return 0;265 return LDB_SUCCESS; 270 266 } 271 267 … … 278 274 int ret = -1; 279 275 const char *expression = "(|(objectClass=*)(distinguishedName=*))"; 280 281 ldb = ldb_init(NULL, NULL); 276 TALLOC_CTX *mem_ctx = talloc_new(NULL); 277 278 ldb = ldb_init(mem_ctx, NULL); 282 279 if (ldb == NULL) { 283 return -1;280 return LDB_ERR_OPERATIONS_ERROR; 284 281 } 285 282 … … 301 298 if (options->basedn != NULL) { 302 299 basedn = ldb_dn_new(ldb, ldb, options->basedn); 303 if ( ! ldb_dn_validate(basedn)) { 304 fprintf(stderr, "Invalid Base DN format\n"); 305 exit(1); 300 if (basedn == NULL) { 301 return LDB_ERR_OPERATIONS_ERROR; 306 302 } 307 303 } … … 310 306 char line[1024]; 311 307 while (fgets(line, sizeof(line), stdin)) { 312 if (do_search(ldb, basedn, options, line, attrs) == -1) { 313 ret = -1; 314 } 308 ret = do_search(ldb, basedn, options, line, attrs); 315 309 } 316 310 } else { … … 318 312 } 319 313 320 talloc_free(ldb); 314 talloc_free(mem_ctx); 315 321 316 return ret; 322 317 } -
trunk/server/source4/lib/ldb/tools/ldbtest.c
r414 r745 32 32 */ 33 33 34 #include "ldb_includes.h" 34 #include "replace.h" 35 #include "system/filesys.h" 36 #include "system/time.h" 35 37 #include "ldb.h" 36 38 #include "tools/cmdline.h" 37 39 38 static struct time valtp1,tp2;40 static struct timespec tp1,tp2; 39 41 static struct ldb_cmdline *options; 40 42 41 43 static void _start_timer(void) 42 44 { 43 gettimeofday(&tp1,NULL); 45 if (clock_gettime(CUSTOM_CLOCK_MONOTONIC, &tp1) != 0) { 46 clock_gettime(CLOCK_REALTIME, &tp1); 47 } 44 48 } 45 49 46 50 static double _end_timer(void) 47 51 { 48 gettimeofday(&tp2,NULL); 52 if (clock_gettime(CUSTOM_CLOCK_MONOTONIC, &tp2) != 0) { 53 clock_gettime(CLOCK_REALTIME, &tp2); 54 } 49 55 return((tp2.tv_sec - tp1.tv_sec) + 50 (tp2.tv_ usec - tp1.tv_usec)*1.0e-6);56 (tp2.tv_nsec - tp1.tv_nsec)*1.0e-9); 51 57 } 52 58 53 59 static void add_records(struct ldb_context *ldb, 54 60 struct ldb_dn *basedn, 55 int count)61 unsigned int count) 56 62 { 57 63 struct ldb_message msg; 58 int i;64 unsigned int i; 59 65 60 66 #if 0 61 67 if (ldb_lock(ldb, "transaction") != 0) { 62 68 printf("transaction lock failed\n"); 63 exit( 1);69 exit(LDB_ERR_OPERATIONS_ERROR); 64 70 } 65 71 #endif … … 123 129 if (ldb_add(ldb, &msg) != 0) { 124 130 printf("Add of %s failed - %s\n", name, ldb_errstring(ldb)); 125 exit( 1);131 exit(LDB_ERR_OPERATIONS_ERROR); 126 132 } 127 133 … … 134 140 if (ldb_unlock(ldb, "transaction") != 0) { 135 141 printf("transaction unlock failed\n"); 136 exit( 1);142 exit(LDB_ERR_OPERATIONS_ERROR); 137 143 } 138 144 #endif … … 142 148 static void modify_records(struct ldb_context *ldb, 143 149 struct ldb_dn *basedn, 144 int count)150 unsigned int count) 145 151 { 146 152 struct ldb_message msg; 147 int i;153 unsigned int i; 148 154 149 155 for (i=0;i<count;i++) { … … 180 186 if (ldb_modify(ldb, &msg) != 0) { 181 187 printf("Modify of %s failed - %s\n", name, ldb_errstring(ldb)); 182 exit( 1);188 exit(LDB_ERR_OPERATIONS_ERROR); 183 189 } 184 190 … … 195 201 static void delete_records(struct ldb_context *ldb, 196 202 struct ldb_dn *basedn, 197 int count)198 { 199 int i;203 unsigned int count) 204 { 205 unsigned int i; 200 206 201 207 for (i=0;i<count;i++) { … … 210 216 if (ldb_delete(ldb, dn) != 0) { 211 217 printf("Delete of %s failed - %s\n", ldb_dn_get_linearized(dn), ldb_errstring(ldb)); 212 exit( 1);218 exit(LDB_ERR_OPERATIONS_ERROR); 213 219 } 214 220 talloc_free(name); … … 218 224 } 219 225 220 static void search_uid(struct ldb_context *ldb, struct ldb_dn *basedn, int nrecords, int nsearches) 221 { 222 int i; 226 static void search_uid(struct ldb_context *ldb, struct ldb_dn *basedn, 227 unsigned int nrecords, unsigned int nsearches) 228 { 229 unsigned int i; 223 230 224 231 for (i=0;i<nsearches;i++) { … … 233 240 if (ret != LDB_SUCCESS || (uid < nrecords && res->count != 1)) { 234 241 printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb)); 235 exit( 1);242 exit(LDB_ERR_OPERATIONS_ERROR); 236 243 } 237 244 238 245 if (uid >= nrecords && res->count > 0) { 239 246 printf("Found %s !? - %d\n", expr, ret); 240 exit( 1);247 exit(LDB_ERR_OPERATIONS_ERROR); 241 248 } 242 249 243 printf(" testing uid %d/%d - %d \r", i, uid, res->count);250 printf("Testing uid %d/%d - %d \r", i, uid, res->count); 244 251 fflush(stdout); 245 252 … … 251 258 } 252 259 253 static void start_test(struct ldb_context *ldb, int nrecords, int nsearches) 260 static void start_test(struct ldb_context *ldb, unsigned int nrecords, 261 unsigned int nsearches) 254 262 { 255 263 struct ldb_dn *basedn; … … 257 265 basedn = ldb_dn_new(ldb, ldb, options->basedn); 258 266 if ( ! ldb_dn_validate(basedn)) { 259 printf("Invalid base DN \n");260 exit( 1);267 printf("Invalid base DN format\n"); 268 exit(LDB_ERR_INVALID_DN_SYNTAX); 261 269 } 262 270 … … 323 331 if (ldb_add(*ldb, msg) != 0) { 324 332 printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb)); 325 exit( 1);333 exit(LDB_ERR_OPERATIONS_ERROR); 326 334 } 327 335 … … 338 346 if (ldb_add(*ldb, msg) != 0) { 339 347 printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb)); 340 exit( 1);348 exit(LDB_ERR_OPERATIONS_ERROR); 341 349 } 342 350 343 351 if (talloc_free(*ldb) != 0) { 344 352 printf("failed to free/close ldb database"); 345 exit( 1);353 exit(LDB_ERR_OPERATIONS_ERROR); 346 354 } 347 355 … … 351 359 if (ret != 0) { 352 360 printf("failed to connect to %s\n", options->url); 353 exit( 1);361 exit(LDB_ERR_OPERATIONS_ERROR); 354 362 } 355 363 356 364 basedn = ldb_dn_new(*ldb, *ldb, options->basedn); 365 msg->dn = basedn; 366 ldb_dn_add_child_fmt(msg->dn, "cn=test"); 357 367 358 368 ret = ldb_search(*ldb, *ldb, &res, basedn, LDB_SCOPE_SUBTREE, NULL, "uid=test"); 359 369 if (ret != LDB_SUCCESS) { 360 370 printf("Search with (uid=test) filter failed!\n"); 361 exit( 1);371 exit(LDB_ERR_OPERATIONS_ERROR); 362 372 } 363 373 if(res->count != 1) { 364 374 printf("Should have found 1 record - found %d\n", res->count); 365 exit( 1);375 exit(LDB_ERR_OPERATIONS_ERROR); 366 376 } 367 377 … … 371 381 ldb_delete(*ldb, indexlist) != 0) { 372 382 printf("cleanup failed - %s\n", ldb_errstring(*ldb)); 373 exit( 1);383 exit(LDB_ERR_OPERATIONS_ERROR); 374 384 } 375 385 … … 378 388 379 389 380 static void usage( void)390 static void usage(struct ldb_context *ldb) 381 391 { 382 392 printf("Usage: ldbtest <options>\n"); … … 387 397 printf("\n"); 388 398 printf("tests ldb API\n\n"); 389 exit( 1);399 exit(LDB_ERR_OPERATIONS_ERROR); 390 400 } 391 401 … … 396 406 397 407 ldb = ldb_init(mem_ctx, NULL); 408 if (ldb == NULL) { 409 return LDB_ERR_OPERATIONS_ERROR; 410 } 398 411 399 412 options = ldb_cmdline_process(ldb, argc, argv, usage); … … 410 423 options->num_records, options->num_searches); 411 424 412 start_test(ldb, options->num_records, options->num_searches); 425 start_test(ldb, 426 (unsigned int) options->num_records, 427 (unsigned int) options->num_searches); 413 428 414 429 start_test_index(&ldb); … … 416 431 talloc_free(mem_ctx); 417 432 418 return 0;419 } 433 return LDB_SUCCESS; 434 } -
trunk/server/source4/lib/ldb/web/index.html
r414 r745 51 51 <h2>Discussion and bug reports</h2> 52 52 53 ldb does not currently have its own mailing list or bug tracking54 system. For now, please use the <a 55 href="https://lists.samba.org/mailman/listinfo/samba-technical">samba-technical</a>56 mailing list or the <a href="https://lists.samba.org/mailman/listinfo/ldb">ldb</a>57 mailing list, and the <a href="http://bugzilla.samba.org/">Sambabugzilla</a> bug tracking system.53 ldb does not have its own mailing list or bug tracking system. Please 54 use 55 the <a href="https://lists.samba.org/mailman/listinfo/samba-technical">samba-technical</a> 56 mailing list, and the <a href="http://bugzilla.samba.org/">Samba 57 bugzilla</a> bug tracking system. 58 58 59 59 <h2>Download</h2> 60 60 61 You can download the latest release either via rsync or thtough git.<br> 62 <br> 63 To fetch via git see the following guide:<br> 61 You can download the latest release here:<br> 62 <a href="http://samba.org/ftp/pub/ldb">http://samba.org/ftp/pub/ldb</a> 63 64 Alternatively, you can fetch via git. See the following guide:<br> 64 65 <a href="http://wiki.samba.org/index.php/Using_Git_for_Samba_Development">Using Git for Samba Development</a><br> 65 Once you have cloned the tree switch to the v4-0-test branch and cd into the source/lib/ldb directory.<br>66 <br>67 To fetch via rsync use these commands:68 69 <pre>70 rsync -Pavz samba.org::ftp/unpacked/ldb .71 rsync -Pavz samba.org::ftp/unpacked/tdb .72 rsync -Pavz samba.org::ftp/unpacked/talloc .73 rsync -Pavz samba.org::ftp/unpacked/libreplace .74 </pre>75 76 and build in ldb. It will find the other libraries in the directory77 above automatically.78 66 79 67 <hr> -
trunk/server/source4/lib/messaging/irpc.h
r414 r745 25 25 #include "lib/messaging/messaging.h" 26 26 #include "librpc/gen_ndr/irpc.h" 27 #include "librpc/gen_ndr/server_id.h"28 27 29 28 /* … … 36 35 struct ndr_pull *ndr; 37 36 bool defer_reply; 37 bool no_reply; 38 38 struct messaging_context *msg_ctx; 39 39 struct irpc_list *irpc; … … 43 43 44 44 /* don't allow calls to take too long */ 45 #define IRPC_CALL_TIMEOUT 10 45 #define IRPC_CALL_TIMEOUT 10 46 /* wait for the calls as long as it takes */ 47 #define IRPC_CALL_TIMEOUT_INF 0 46 48 47 49 … … 55 57 (irpc_function_t)function, private_data) 56 58 57 /* make a irpc call */ 58 #define IRPC_CALL(msg_ctx, server_id, pipename, funcname, ptr, ctx) \ 59 irpc_call(msg_ctx, server_id, &ndr_table_ ## pipename, NDR_ ## funcname, ptr, ctx) 60 61 #define IRPC_CALL_SEND(msg_ctx, server_id, pipename, funcname, ptr, ctx) \ 62 irpc_call_send(msg_ctx, server_id, &ndr_table_ ## pipename, NDR_ ## funcname, ptr, ctx) 63 64 65 /* 66 a pending irpc call 67 */ 68 struct irpc_request { 69 struct messaging_context *msg_ctx; 70 const struct ndr_interface_table *table; 71 int callnum; 72 int callid; 73 void *r; 74 NTSTATUS status; 75 bool done; 76 bool reject_free; 77 TALLOC_CTX *mem_ctx; 78 struct { 79 void (*fn)(struct irpc_request *); 80 void *private_data; 81 } async; 82 }; 83 84 struct loadparm_context; 85 86 typedef void (*msg_callback_t)(struct messaging_context *msg, void *private_data, 87 uint32_t msg_type, 88 struct server_id server_id, DATA_BLOB *data); 89 90 NTSTATUS messaging_send(struct messaging_context *msg, struct server_id server, 91 uint32_t msg_type, DATA_BLOB *data); 92 NTSTATUS messaging_register(struct messaging_context *msg, void *private_data, 93 uint32_t msg_type, 94 msg_callback_t fn); 95 NTSTATUS messaging_register_tmp(struct messaging_context *msg, void *private_data, 96 msg_callback_t fn, uint32_t *msg_type); 97 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, 98 const char *dir, 99 struct server_id server_id, 100 struct smb_iconv_convenience *iconv_convenience, 101 struct tevent_context *ev); 102 struct messaging_context *messaging_client_init(TALLOC_CTX *mem_ctx, 103 const char *dir, 104 struct smb_iconv_convenience *iconv_convenience, 105 struct tevent_context *ev); 106 NTSTATUS messaging_send_ptr(struct messaging_context *msg, struct server_id server, 107 uint32_t msg_type, void *ptr); 108 void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void *private_data); 109 110 111 59 struct ndr_interface_table; 112 60 113 61 NTSTATUS irpc_register(struct messaging_context *msg_ctx, 114 62 const struct ndr_interface_table *table, 115 63 int call, irpc_function_t fn, void *private_data); 116 struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx, 117 struct server_id server_id, 118 const struct ndr_interface_table *table, 119 int callnum, void *r, TALLOC_CTX *ctx); 120 NTSTATUS irpc_call_recv(struct irpc_request *irpc); 121 NTSTATUS irpc_call(struct messaging_context *msg_ctx, 122 struct server_id server_id, 123 const struct ndr_interface_table *table, 124 int callnum, void *r, TALLOC_CTX *ctx); 64 65 struct dcerpc_binding_handle *irpc_binding_handle(TALLOC_CTX *mem_ctx, 66 struct messaging_context *msg_ctx, 67 struct server_id server_id, 68 const struct ndr_interface_table *table); 69 struct dcerpc_binding_handle *irpc_binding_handle_by_name(TALLOC_CTX *mem_ctx, 70 struct messaging_context *msg_ctx, 71 const char *dest_task, 72 const struct ndr_interface_table *table); 73 void irpc_binding_handle_add_security_token(struct dcerpc_binding_handle *h, 74 struct security_token *token); 125 75 126 76 NTSTATUS irpc_add_name(struct messaging_context *msg_ctx, const char *name); … … 128 78 void irpc_remove_name(struct messaging_context *msg_ctx, const char *name); 129 79 NTSTATUS irpc_send_reply(struct irpc_message *m, NTSTATUS status); 130 struct server_id messaging_get_server_id(struct messaging_context *msg_ctx);131 80 132 81 #endif -
trunk/server/source4/lib/messaging/messaging.c
r414 r745 28 28 #include "librpc/gen_ndr/ndr_irpc.h" 29 29 #include "lib/messaging/irpc.h" 30 #include " tdb_wrap.h"30 #include "lib/util/tdb_wrap.h" 31 31 #include "../lib/util/unix_privs.h" 32 32 #include "librpc/rpc/dcerpc.h" 33 #include "../tdb/include/tdb.h"33 #include <tdb.h> 34 34 #include "../lib/util/util_tdb.h" 35 35 #include "cluster/cluster.h" 36 #include "../lib/util/tevent_ntstatus.h" 36 37 37 38 /* change the message version with any incompatible changes in the protocol */ 38 39 #define MESSAGING_VERSION 1 40 41 /* 42 a pending irpc call 43 */ 44 struct irpc_request { 45 struct messaging_context *msg_ctx; 46 int callid; 47 struct { 48 void (*handler)(struct irpc_request *irpc, struct irpc_message *m); 49 void *private_data; 50 } incoming; 51 }; 39 52 40 53 struct messaging_context { … … 48 61 struct messaging_rec *pending; 49 62 struct messaging_rec *retry_queue; 50 struct smb_iconv_convenience *iconv_convenience;51 63 struct irpc_list *irpc; 52 64 struct idr_context *idr; … … 99 111 { 100 112 DEBUG(1,("INFO: Received PING message from server %u.%u [%.*s]\n", 101 (u int_t)src.node, (uint_t)src.id, (int)data->length,113 (unsigned int)src.node, (unsigned int)src.id, (int)data->length, 102 114 data->data?(const char *)data->data:"")); 103 115 messaging_send(msg, src, MSG_PONG, data); … … 120 132 static char *messaging_path(struct messaging_context *msg, struct server_id server_id) 121 133 { 122 return talloc_asprintf(msg, "%s/msg.%s", msg->base_path, 123 cluster_id_string(msg, server_id)); 134 TALLOC_CTX *tmp_ctx = talloc_new(msg); 135 const char *id = cluster_id_string(tmp_ctx, server_id); 136 char *s; 137 if (id == NULL) { 138 return NULL; 139 } 140 s = talloc_asprintf(msg, "%s/msg.%s", msg->base_path, id); 141 talloc_steal(s, tmp_ctx); 142 return s; 124 143 } 125 144 … … 262 281 rec->retries = 0; 263 282 if (!NT_STATUS_IS_OK(status)) { 283 TALLOC_CTX *tmp_ctx = talloc_new(msg); 264 284 DEBUG(1,("messaging: Lost message from %s to %s of type %u - %s\n", 265 cluster_id_string( debug_ctx(), rec->header->from),266 cluster_id_string( debug_ctx(), rec->header->to),285 cluster_id_string(tmp_ctx, rec->header->from), 286 cluster_id_string(tmp_ctx, rec->header->to), 267 287 rec->header->msg_type, 268 288 nt_errstr(status))); 289 talloc_free(tmp_ctx); 269 290 } 270 291 DLIST_REMOVE(msg->pending, rec); … … 441 462 */ 442 463 NTSTATUS messaging_send(struct messaging_context *msg, struct server_id server, 443 uint32_t msg_type, DATA_BLOB *data)464 uint32_t msg_type, const DATA_BLOB *data) 444 465 { 445 466 struct messaging_rec *rec; … … 536 557 const char *dir, 537 558 struct server_id server_id, 538 struct smb_iconv_convenience *iconv_convenience,539 559 struct tevent_context *ev) 540 560 { … … 565 585 msg->path = messaging_path(msg, server_id); 566 586 msg->server_id = server_id; 567 msg->iconv_convenience = iconv_convenience;568 587 msg->idr = idr_init(msg); 569 588 msg->dispatch_tree = idr_init(msg); … … 600 619 msg->event.fde = event_add_fd(ev, msg, socket_get_fd(msg->sock), 601 620 EVENT_FD_READ, messaging_handler, msg); 621 tevent_fd_set_auto_close(msg->event.fde); 602 622 603 623 talloc_set_destructor(msg, messaging_destructor); … … 615 635 struct messaging_context *messaging_client_init(TALLOC_CTX *mem_ctx, 616 636 const char *dir, 617 struct smb_iconv_convenience *iconv_convenience,618 637 struct tevent_context *ev) 619 638 { … … 621 640 ZERO_STRUCT(id); 622 641 id.id = random() % 0x10000000; 623 return messaging_init(mem_ctx, dir, id, iconv_convenience,ev);642 return messaging_init(mem_ctx, dir, id, ev); 624 643 } 625 644 /* … … 673 692 { 674 693 struct irpc_request *irpc; 675 enum ndr_err_code ndr_err;676 694 677 695 irpc = (struct irpc_request *)idr_find(msg_ctx->idr, m->header.callid); 678 696 if (irpc == NULL) return; 679 697 680 /* parse the reply data */ 681 ndr_err = irpc->table->calls[irpc->callnum].ndr_pull(m->ndr, NDR_OUT, irpc->r); 682 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 683 irpc->status = m->header.status; 684 talloc_steal(irpc->mem_ctx, m); 685 } else { 686 irpc->status = ndr_map_error2ntstatus(ndr_err); 687 talloc_steal(irpc, m); 688 } 689 irpc->done = true; 690 if (irpc->async.fn) { 691 irpc->async.fn(irpc); 692 } 698 irpc->incoming.handler(irpc, m); 693 699 } 694 700 … … 705 711 706 712 /* setup the reply */ 707 push = ndr_push_init_ctx(m->ndr , m->msg_ctx->iconv_convenience);713 push = ndr_push_init_ctx(m->ndr); 708 714 if (push == NULL) { 709 715 status = NT_STATUS_NO_MEMORY; … … 712 718 713 719 m->header.flags |= IRPC_FLAG_REPLY; 720 m->header.creds.token= NULL; 714 721 715 722 /* construct the packet */ … … 764 771 if (r == NULL) goto failed; 765 772 773 m->ndr->flags |= LIBNDR_FLAG_REF_ALLOC; 774 766 775 /* parse the request data */ 767 776 ndr_err = i->table->calls[i->callnum].ndr_pull(m->ndr, NDR_IN, r); … … 771 780 m->private_data= i->private_data; 772 781 m->defer_reply = false; 782 m->no_reply = false; 773 783 m->msg_ctx = msg_ctx; 774 784 m->irpc = i; … … 778 788 m->header.status = i->fn(m, r); 779 789 790 if (m->no_reply) { 791 /* the server function won't ever be replying to this request */ 792 talloc_free(m); 793 return; 794 } 795 780 796 if (m->defer_reply) { 781 797 /* the server function has asked to defer the reply to later */ … … 805 821 m->from = src; 806 822 807 m->ndr = ndr_pull_init_blob(packet, m , msg_ctx->iconv_convenience);823 m->ndr = ndr_pull_init_blob(packet, m); 808 824 if (m->ndr == NULL) goto failed; 809 825 … … 835 851 } 836 852 837 if (irpc->reject_free) {838 return -1;839 }840 853 return 0; 841 }842 843 /*844 timeout a irpc request845 */846 static void irpc_timeout(struct tevent_context *ev, struct tevent_timer *te,847 struct timeval t, void *private_data)848 {849 struct irpc_request *irpc = talloc_get_type(private_data, struct irpc_request);850 irpc->status = NT_STATUS_IO_TIMEOUT;851 irpc->done = true;852 if (irpc->async.fn) {853 irpc->async.fn(irpc);854 }855 }856 857 858 /*859 make a irpc call - async send860 */861 struct irpc_request *irpc_call_send(struct messaging_context *msg_ctx,862 struct server_id server_id,863 const struct ndr_interface_table *table,864 int callnum, void *r, TALLOC_CTX *ctx)865 {866 struct irpc_header header;867 struct ndr_push *ndr;868 NTSTATUS status;869 DATA_BLOB packet;870 struct irpc_request *irpc;871 enum ndr_err_code ndr_err;872 873 irpc = talloc(msg_ctx, struct irpc_request);874 if (irpc == NULL) goto failed;875 876 irpc->msg_ctx = msg_ctx;877 irpc->table = table;878 irpc->callnum = callnum;879 irpc->callid = idr_get_new(msg_ctx->idr, irpc, UINT16_MAX);880 if (irpc->callid == -1) goto failed;881 irpc->r = r;882 irpc->done = false;883 irpc->async.fn = NULL;884 irpc->mem_ctx = ctx;885 irpc->reject_free = false;886 887 talloc_set_destructor(irpc, irpc_destructor);888 889 /* setup the header */890 header.uuid = table->syntax_id.uuid;891 892 header.if_version = table->syntax_id.if_version;893 header.callid = irpc->callid;894 header.callnum = callnum;895 header.flags = 0;896 header.status = NT_STATUS_OK;897 898 /* construct the irpc packet */899 ndr = ndr_push_init_ctx(irpc, msg_ctx->iconv_convenience);900 if (ndr == NULL) goto failed;901 902 ndr_err = ndr_push_irpc_header(ndr, NDR_SCALARS|NDR_BUFFERS, &header);903 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;904 905 ndr_err = table->calls[callnum].ndr_push(ndr, NDR_IN, r);906 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;907 908 /* and send it */909 packet = ndr_push_blob(ndr);910 status = messaging_send(msg_ctx, server_id, MSG_IRPC, &packet);911 if (!NT_STATUS_IS_OK(status)) goto failed;912 913 event_add_timed(msg_ctx->event.ev, irpc,914 timeval_current_ofs(IRPC_CALL_TIMEOUT, 0),915 irpc_timeout, irpc);916 917 talloc_free(ndr);918 return irpc;919 920 failed:921 talloc_free(irpc);922 return NULL;923 }924 925 /*926 wait for a irpc reply927 */928 NTSTATUS irpc_call_recv(struct irpc_request *irpc)929 {930 NTSTATUS status;931 932 NT_STATUS_HAVE_NO_MEMORY(irpc);933 934 irpc->reject_free = true;935 936 while (!irpc->done) {937 if (event_loop_once(irpc->msg_ctx->event.ev) != 0) {938 return NT_STATUS_CONNECTION_DISCONNECTED;939 }940 }941 942 irpc->reject_free = false;943 944 status = irpc->status;945 talloc_free(irpc);946 return status;947 }948 949 /*950 perform a synchronous irpc request951 */952 NTSTATUS irpc_call(struct messaging_context *msg_ctx,953 struct server_id server_id,954 const struct ndr_interface_table *table,955 int callnum, void *r,956 TALLOC_CTX *mem_ctx)957 {958 struct irpc_request *irpc = irpc_call_send(msg_ctx, server_id,959 table, callnum, r, mem_ctx);960 return irpc_call_recv(irpc);961 854 } 962 855 … … 1117 1010 return msg_ctx->server_id; 1118 1011 } 1012 1013 struct irpc_bh_state { 1014 struct messaging_context *msg_ctx; 1015 struct server_id server_id; 1016 const struct ndr_interface_table *table; 1017 uint32_t timeout; 1018 struct security_token *token; 1019 }; 1020 1021 static bool irpc_bh_is_connected(struct dcerpc_binding_handle *h) 1022 { 1023 struct irpc_bh_state *hs = dcerpc_binding_handle_data(h, 1024 struct irpc_bh_state); 1025 1026 if (!hs->msg_ctx) { 1027 return false; 1028 } 1029 1030 return true; 1031 } 1032 1033 static uint32_t irpc_bh_set_timeout(struct dcerpc_binding_handle *h, 1034 uint32_t timeout) 1035 { 1036 struct irpc_bh_state *hs = dcerpc_binding_handle_data(h, 1037 struct irpc_bh_state); 1038 uint32_t old = hs->timeout; 1039 1040 hs->timeout = timeout; 1041 1042 return old; 1043 } 1044 1045 struct irpc_bh_raw_call_state { 1046 struct irpc_request *irpc; 1047 uint32_t opnum; 1048 DATA_BLOB in_data; 1049 DATA_BLOB in_packet; 1050 DATA_BLOB out_data; 1051 }; 1052 1053 static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc, 1054 struct irpc_message *m); 1055 1056 static struct tevent_req *irpc_bh_raw_call_send(TALLOC_CTX *mem_ctx, 1057 struct tevent_context *ev, 1058 struct dcerpc_binding_handle *h, 1059 const struct GUID *object, 1060 uint32_t opnum, 1061 uint32_t in_flags, 1062 const uint8_t *in_data, 1063 size_t in_length) 1064 { 1065 struct irpc_bh_state *hs = 1066 dcerpc_binding_handle_data(h, 1067 struct irpc_bh_state); 1068 struct tevent_req *req; 1069 struct irpc_bh_raw_call_state *state; 1070 bool ok; 1071 struct irpc_header header; 1072 struct ndr_push *ndr; 1073 NTSTATUS status; 1074 enum ndr_err_code ndr_err; 1075 1076 req = tevent_req_create(mem_ctx, &state, 1077 struct irpc_bh_raw_call_state); 1078 if (req == NULL) { 1079 return NULL; 1080 } 1081 state->opnum = opnum; 1082 state->in_data.data = discard_const_p(uint8_t, in_data); 1083 state->in_data.length = in_length; 1084 1085 ok = irpc_bh_is_connected(h); 1086 if (!ok) { 1087 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION); 1088 return tevent_req_post(req, ev); 1089 } 1090 1091 state->irpc = talloc_zero(state, struct irpc_request); 1092 if (tevent_req_nomem(state->irpc, req)) { 1093 return tevent_req_post(req, ev); 1094 } 1095 1096 state->irpc->msg_ctx = hs->msg_ctx; 1097 state->irpc->callid = idr_get_new(hs->msg_ctx->idr, 1098 state->irpc, UINT16_MAX); 1099 if (state->irpc->callid == -1) { 1100 tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES); 1101 return tevent_req_post(req, ev); 1102 } 1103 state->irpc->incoming.handler = irpc_bh_raw_call_incoming_handler; 1104 state->irpc->incoming.private_data = req; 1105 1106 talloc_set_destructor(state->irpc, irpc_destructor); 1107 1108 /* setup the header */ 1109 header.uuid = hs->table->syntax_id.uuid; 1110 1111 header.if_version = hs->table->syntax_id.if_version; 1112 header.callid = state->irpc->callid; 1113 header.callnum = state->opnum; 1114 header.flags = 0; 1115 header.status = NT_STATUS_OK; 1116 header.creds.token= hs->token; 1117 1118 /* construct the irpc packet */ 1119 ndr = ndr_push_init_ctx(state->irpc); 1120 if (tevent_req_nomem(ndr, req)) { 1121 return tevent_req_post(req, ev); 1122 } 1123 1124 ndr_err = ndr_push_irpc_header(ndr, NDR_SCALARS|NDR_BUFFERS, &header); 1125 status = ndr_map_error2ntstatus(ndr_err); 1126 if (!NT_STATUS_IS_OK(status)) { 1127 tevent_req_nterror(req, status); 1128 return tevent_req_post(req, ev); 1129 } 1130 1131 ndr_err = ndr_push_bytes(ndr, in_data, in_length); 1132 status = ndr_map_error2ntstatus(ndr_err); 1133 if (!NT_STATUS_IS_OK(status)) { 1134 tevent_req_nterror(req, status); 1135 return tevent_req_post(req, ev); 1136 } 1137 1138 /* and send it */ 1139 state->in_packet = ndr_push_blob(ndr); 1140 status = messaging_send(hs->msg_ctx, hs->server_id, 1141 MSG_IRPC, &state->in_packet); 1142 if (!NT_STATUS_IS_OK(status)) { 1143 tevent_req_nterror(req, status); 1144 return tevent_req_post(req, ev); 1145 } 1146 1147 if (hs->timeout != IRPC_CALL_TIMEOUT_INF) { 1148 /* set timeout-callback in case caller wants that */ 1149 ok = tevent_req_set_endtime(req, ev, timeval_current_ofs(hs->timeout, 0)); 1150 if (!ok) { 1151 return tevent_req_post(req, ev); 1152 } 1153 } 1154 1155 return req; 1156 } 1157 1158 static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc, 1159 struct irpc_message *m) 1160 { 1161 struct tevent_req *req = 1162 talloc_get_type_abort(irpc->incoming.private_data, 1163 struct tevent_req); 1164 struct irpc_bh_raw_call_state *state = 1165 tevent_req_data(req, 1166 struct irpc_bh_raw_call_state); 1167 1168 talloc_steal(state, m); 1169 1170 if (!NT_STATUS_IS_OK(m->header.status)) { 1171 tevent_req_nterror(req, m->header.status); 1172 return; 1173 } 1174 1175 state->out_data = data_blob_talloc(state, 1176 m->ndr->data + m->ndr->offset, 1177 m->ndr->data_size - m->ndr->offset); 1178 if ((m->ndr->data_size - m->ndr->offset) > 0 && !state->out_data.data) { 1179 tevent_req_nomem(NULL, req); 1180 return; 1181 } 1182 1183 tevent_req_done(req); 1184 } 1185 1186 static NTSTATUS irpc_bh_raw_call_recv(struct tevent_req *req, 1187 TALLOC_CTX *mem_ctx, 1188 uint8_t **out_data, 1189 size_t *out_length, 1190 uint32_t *out_flags) 1191 { 1192 struct irpc_bh_raw_call_state *state = 1193 tevent_req_data(req, 1194 struct irpc_bh_raw_call_state); 1195 NTSTATUS status; 1196 1197 if (tevent_req_is_nterror(req, &status)) { 1198 tevent_req_received(req); 1199 return status; 1200 } 1201 1202 *out_data = talloc_move(mem_ctx, &state->out_data.data); 1203 *out_length = state->out_data.length; 1204 *out_flags = 0; 1205 tevent_req_received(req); 1206 return NT_STATUS_OK; 1207 } 1208 1209 struct irpc_bh_disconnect_state { 1210 uint8_t _dummy; 1211 }; 1212 1213 static struct tevent_req *irpc_bh_disconnect_send(TALLOC_CTX *mem_ctx, 1214 struct tevent_context *ev, 1215 struct dcerpc_binding_handle *h) 1216 { 1217 struct irpc_bh_state *hs = dcerpc_binding_handle_data(h, 1218 struct irpc_bh_state); 1219 struct tevent_req *req; 1220 struct irpc_bh_disconnect_state *state; 1221 bool ok; 1222 1223 req = tevent_req_create(mem_ctx, &state, 1224 struct irpc_bh_disconnect_state); 1225 if (req == NULL) { 1226 return NULL; 1227 } 1228 1229 ok = irpc_bh_is_connected(h); 1230 if (!ok) { 1231 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION); 1232 return tevent_req_post(req, ev); 1233 } 1234 1235 hs->msg_ctx = NULL; 1236 1237 tevent_req_done(req); 1238 return tevent_req_post(req, ev); 1239 } 1240 1241 static NTSTATUS irpc_bh_disconnect_recv(struct tevent_req *req) 1242 { 1243 NTSTATUS status; 1244 1245 if (tevent_req_is_nterror(req, &status)) { 1246 tevent_req_received(req); 1247 return status; 1248 } 1249 1250 tevent_req_received(req); 1251 return NT_STATUS_OK; 1252 } 1253 1254 static bool irpc_bh_ref_alloc(struct dcerpc_binding_handle *h) 1255 { 1256 return true; 1257 } 1258 1259 static const struct dcerpc_binding_handle_ops irpc_bh_ops = { 1260 .name = "wbint", 1261 .is_connected = irpc_bh_is_connected, 1262 .set_timeout = irpc_bh_set_timeout, 1263 .raw_call_send = irpc_bh_raw_call_send, 1264 .raw_call_recv = irpc_bh_raw_call_recv, 1265 .disconnect_send = irpc_bh_disconnect_send, 1266 .disconnect_recv = irpc_bh_disconnect_recv, 1267 1268 .ref_alloc = irpc_bh_ref_alloc, 1269 }; 1270 1271 /* initialise a irpc binding handle */ 1272 struct dcerpc_binding_handle *irpc_binding_handle(TALLOC_CTX *mem_ctx, 1273 struct messaging_context *msg_ctx, 1274 struct server_id server_id, 1275 const struct ndr_interface_table *table) 1276 { 1277 struct dcerpc_binding_handle *h; 1278 struct irpc_bh_state *hs; 1279 1280 h = dcerpc_binding_handle_create(mem_ctx, 1281 &irpc_bh_ops, 1282 NULL, 1283 table, 1284 &hs, 1285 struct irpc_bh_state, 1286 __location__); 1287 if (h == NULL) { 1288 return NULL; 1289 } 1290 hs->msg_ctx = msg_ctx; 1291 hs->server_id = server_id; 1292 hs->table = table; 1293 hs->timeout = IRPC_CALL_TIMEOUT; 1294 1295 dcerpc_binding_handle_set_sync_ev(h, msg_ctx->event.ev); 1296 1297 return h; 1298 } 1299 1300 struct dcerpc_binding_handle *irpc_binding_handle_by_name(TALLOC_CTX *mem_ctx, 1301 struct messaging_context *msg_ctx, 1302 const char *dest_task, 1303 const struct ndr_interface_table *table) 1304 { 1305 struct dcerpc_binding_handle *h; 1306 struct server_id *sids; 1307 struct server_id sid; 1308 1309 /* find the server task */ 1310 sids = irpc_servers_byname(msg_ctx, mem_ctx, dest_task); 1311 if (sids == NULL) { 1312 errno = EADDRNOTAVAIL; 1313 return NULL; 1314 } 1315 if (sids[0].id == 0) { 1316 talloc_free(sids); 1317 errno = EADDRNOTAVAIL; 1318 return NULL; 1319 } 1320 sid = sids[0]; 1321 talloc_free(sids); 1322 1323 h = irpc_binding_handle(mem_ctx, msg_ctx, 1324 sid, table); 1325 if (h == NULL) { 1326 return NULL; 1327 } 1328 1329 return h; 1330 } 1331 1332 void irpc_binding_handle_add_security_token(struct dcerpc_binding_handle *h, 1333 struct security_token *token) 1334 { 1335 struct irpc_bh_state *hs = 1336 dcerpc_binding_handle_data(h, 1337 struct irpc_bh_state); 1338 1339 hs->token = token; 1340 } -
trunk/server/source4/lib/messaging/messaging.h
r414 r745 22 22 #define _MESSAGES_H_ 23 23 24 #include "librpc/gen_ndr/server_id4.h" 25 24 26 struct messaging_context; 25 27 … … 33 35 #define MSG_PVFS_NOTIFY 7 34 36 #define MSG_NTVFS_OPLOCK_BREAK 8 37 #define MSG_DREPL_ALLOCATE_RID 9 35 38 36 39 /* temporary messaging endpoints are allocated above this line */ … … 40 43 #define SAMBA_PARENT_TASKID 0 41 44 45 typedef void (*msg_callback_t)(struct messaging_context *msg, void *private_data, 46 uint32_t msg_type, 47 struct server_id server_id, DATA_BLOB *data); 48 49 NTSTATUS messaging_send(struct messaging_context *msg, struct server_id server, 50 uint32_t msg_type, const DATA_BLOB *data); 51 NTSTATUS messaging_register(struct messaging_context *msg, void *private_data, 52 uint32_t msg_type, 53 msg_callback_t fn); 54 NTSTATUS messaging_register_tmp(struct messaging_context *msg, void *private_data, 55 msg_callback_t fn, uint32_t *msg_type); 56 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, 57 const char *dir, 58 struct server_id server_id, 59 struct tevent_context *ev); 60 struct messaging_context *messaging_client_init(TALLOC_CTX *mem_ctx, 61 const char *dir, 62 struct tevent_context *ev); 63 NTSTATUS messaging_send_ptr(struct messaging_context *msg, struct server_id server, 64 uint32_t msg_type, void *ptr); 65 void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void *private_data); 66 struct server_id messaging_get_server_id(struct messaging_context *msg_ctx); 67 42 68 #endif -
trunk/server/source4/lib/messaging/pymessaging.c
r414 r745 20 20 */ 21 21 22 #include <Python.h> 22 23 #include "includes.h" 23 #include <Python.h>24 24 #include "scripting/python/modules.h" 25 25 #include "libcli/util/pyerrors.h" 26 #include "librpc/rpc/pyrpc .h"27 #include "lib /messaging/irpc.h"26 #include "librpc/rpc/pyrpc_util.h" 27 #include "librpc/ndr/libndr.h" 28 28 #include "lib/messaging/messaging.h" 29 29 #include "lib/events/events.h" … … 31 31 #include "param/param.h" 32 32 #include "param/pyparam.h" 33 34 #ifndef Py_RETURN_NONE 35 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None 36 #endif 37 38 PyAPI_DATA(PyTypeObject) messaging_Type; 39 PyAPI_DATA(PyTypeObject) irpc_ClientConnectionType; 40 41 /* FIXME: This prototype should be in py_irpc.h, or shared otherwise */ 42 extern const struct PyNdrRpcMethodDef py_ndr_irpc_methods[]; 33 #include "librpc/rpc/dcerpc.h" 34 #include "librpc/gen_ndr/server_id4.h" 35 36 void initmessaging(void); 37 38 extern PyTypeObject messaging_Type; 43 39 44 40 static bool server_id_from_py(PyObject *object, struct server_id *server_id) … … 66 62 } messaging_Object; 67 63 68 PyObject *py_messaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)64 static PyObject *py_messaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs) 69 65 { 70 66 struct tevent_context *ev; … … 88 84 89 85 if (messaging_path == NULL) { 90 messaging_path = lp _messaging_path(ret->mem_ctx,86 messaging_path = lpcfg_messaging_path(ret->mem_ctx, 91 87 py_default_loadparm_context(ret->mem_ctx)); 92 88 } else { … … 103 99 messaging_path, 104 100 server_id, 105 py_iconv_convenience(ret->mem_ctx),106 101 ev); 107 102 } else { 108 103 ret->msg_ctx = messaging_client_init(ret->mem_ctx, 109 104 messaging_path, 110 py_iconv_convenience(ret->mem_ctx),111 105 ev); 112 106 } … … 125 119 messaging_Object *iface = (messaging_Object *)self; 126 120 talloc_free(iface->msg_ctx); 127 PyObject_Del(self);121 self->ob_type->tp_free(self); 128 122 } 129 123 … … 139 133 int length; 140 134 141 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ois# |:send",135 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ois#:send", 142 136 discard_const_p(char *, kwnames), &target, &msg_type, &data.data, &length)) { 137 143 138 return NULL; 144 139 } … … 146 141 data.length = length; 147 142 148 if (!server_id_from_py(target, &server)) 143 if (!server_id_from_py(target, &server)) 149 144 return NULL; 150 145 … … 177 172 const char *kwnames[] = { "callback", "msg_type", NULL }; 178 173 179 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i: send",174 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:register", 180 175 discard_const_p(char *, kwnames), &callback, &msg_type)) { 181 176 return NULL; … … 208 203 const char *kwnames[] = { "callback", "msg_type", NULL }; 209 204 210 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i: send",205 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:deregister", 211 206 discard_const_p(char *, kwnames), &callback, &msg_type)) { 212 207 return NULL; … … 216 211 217 212 Py_DECREF(callback); 218 219 Py_RETURN_NONE;220 }221 222 static PyObject *py_messaging_add_name(PyObject *self, PyObject *args, PyObject *kwargs)223 {224 messaging_Object *iface = (messaging_Object *)self;225 NTSTATUS status;226 char *name;227 const char *kwnames[] = { "name", NULL };228 229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|:send",230 discard_const_p(char *, kwnames), &name)) {231 return NULL;232 }233 234 status = irpc_add_name(iface->msg_ctx, name);235 if (NT_STATUS_IS_ERR(status)) {236 PyErr_SetNTSTATUS(status);237 return NULL;238 }239 240 Py_RETURN_NONE;241 }242 243 244 static PyObject *py_messaging_remove_name(PyObject *self, PyObject *args, PyObject *kwargs)245 {246 messaging_Object *iface = (messaging_Object *)self;247 char *name;248 const char *kwnames[] = { "name", NULL };249 250 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|:send",251 discard_const_p(char *, kwnames), &name)) {252 return NULL;253 }254 255 irpc_remove_name(iface->msg_ctx, name);256 213 257 214 Py_RETURN_NONE; … … 265 222 { "deregister", (PyCFunction)py_messaging_deregister, METH_VARARGS|METH_KEYWORDS, 266 223 "S.deregister(callback, msg_type) -> None\nDeregister a message handler" }, 267 { "add_name", (PyCFunction)py_messaging_add_name, METH_VARARGS|METH_KEYWORDS, "S.add_name(name) -> None\nListen on another name" },268 { "remove_name", (PyCFunction)py_messaging_remove_name, METH_VARARGS|METH_KEYWORDS, "S.remove_name(name) -> None\nStop listening on a name" },269 224 { NULL, NULL, 0, NULL } 270 225 }; … … 288 243 PyTypeObject messaging_Type = { 289 244 PyObject_HEAD_INIT(NULL) 0, 290 .tp_name = " irpc.Messaging",245 .tp_name = "messaging.Messaging", 291 246 .tp_basicsize = sizeof(messaging_Object), 292 247 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, … … 300 255 }; 301 256 302 303 /*304 state of a irpc 'connection'305 */306 typedef struct {307 PyObject_HEAD308 const char *server_name;309 struct server_id *dest_ids;310 struct messaging_context *msg_ctx;311 TALLOC_CTX *mem_ctx;312 } irpc_ClientConnectionObject;313 314 /*315 setup a context for talking to a irpc server316 example:317 status = irpc.connect("smb_server");318 */319 320 PyObject *py_irpc_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)321 {322 struct tevent_context *ev;323 const char *kwnames[] = { "server", "own_id", "messaging_path", NULL };324 char *server;325 const char *messaging_path = NULL;326 PyObject *own_id = Py_None;327 irpc_ClientConnectionObject *ret;328 329 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oz:connect",330 discard_const_p(char *, kwnames), &server, &own_id, &messaging_path)) {331 return NULL;332 }333 334 ret = PyObject_New(irpc_ClientConnectionObject, &irpc_ClientConnectionType);335 if (ret == NULL)336 return NULL;337 338 ret->mem_ctx = talloc_new(NULL);339 340 ret->server_name = server;341 342 ev = s4_event_context_init(ret->mem_ctx);343 344 if (messaging_path == NULL) {345 messaging_path = lp_messaging_path(ret->mem_ctx,346 py_default_loadparm_context(ret->mem_ctx));347 } else {348 messaging_path = talloc_strdup(ret->mem_ctx, messaging_path);349 }350 351 if (own_id != Py_None) {352 struct server_id server_id;353 354 if (!server_id_from_py(own_id, &server_id))355 return NULL;356 357 ret->msg_ctx = messaging_init(ret->mem_ctx,358 messaging_path,359 server_id,360 py_iconv_convenience(ret->mem_ctx),361 ev);362 } else {363 ret->msg_ctx = messaging_client_init(ret->mem_ctx,364 messaging_path,365 py_iconv_convenience(ret->mem_ctx),366 ev);367 }368 369 if (ret->msg_ctx == NULL) {370 PyErr_SetString(PyExc_RuntimeError, "irpc_connect unable to create a messaging context");371 talloc_free(ret->mem_ctx);372 return NULL;373 }374 375 ret->dest_ids = irpc_servers_byname(ret->msg_ctx, ret->mem_ctx, ret->server_name);376 if (ret->dest_ids == NULL || ret->dest_ids[0].id == 0) {377 talloc_free(ret->mem_ctx);378 PyErr_SetNTSTATUS(NT_STATUS_OBJECT_NAME_NOT_FOUND);379 return NULL;380 } else {381 return (PyObject *)ret;382 }383 }384 385 typedef struct {386 PyObject_HEAD387 struct irpc_request **reqs;388 int count;389 int current;390 TALLOC_CTX *mem_ctx;391 py_data_unpack_fn unpack_fn;392 } irpc_ResultObject;393 394 395 static PyObject *irpc_result_next(irpc_ResultObject *iterator)396 {397 NTSTATUS status;398 399 if (iterator->current >= iterator->count) {400 PyErr_SetString(PyExc_StopIteration, "No more results");401 return NULL;402 }403 404 status = irpc_call_recv(iterator->reqs[iterator->current]);405 iterator->current++;406 if (!NT_STATUS_IS_OK(status)) {407 PyErr_SetNTSTATUS(status);408 return NULL;409 }410 411 return iterator->unpack_fn(iterator->reqs[iterator->current-1]->r);412 }413 414 static PyObject *irpc_result_len(irpc_ResultObject *self)415 {416 return PyLong_FromLong(self->count);417 }418 419 static PyMethodDef irpc_result_methods[] = {420 { "__len__", (PyCFunction)irpc_result_len, METH_NOARGS,421 "Number of elements returned"},422 { NULL }423 };424 425 static void irpc_result_dealloc(PyObject *self)426 {427 talloc_free(((irpc_ResultObject *)self)->mem_ctx);428 PyObject_Del(self);429 }430 431 PyTypeObject irpc_ResultIteratorType = {432 PyObject_HEAD_INIT(NULL) 0,433 .tp_name = "irpc.ResultIterator",434 .tp_basicsize = sizeof(irpc_ResultObject),435 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,436 .tp_iternext = (iternextfunc)irpc_result_next,437 .tp_iter = PyObject_SelfIter,438 .tp_methods = irpc_result_methods,439 .tp_dealloc = irpc_result_dealloc,440 };441 442 static PyObject *py_irpc_call(irpc_ClientConnectionObject *p, struct PyNdrRpcMethodDef *method_def, PyObject *args, PyObject *kwargs)443 {444 void *ptr;445 struct irpc_request **reqs;446 int i, count;447 NTSTATUS status;448 TALLOC_CTX *mem_ctx = talloc_new(NULL);449 irpc_ResultObject *ret;450 451 /* allocate the C structure */452 ptr = talloc_zero_size(mem_ctx, method_def->table->calls[method_def->opnum].struct_size);453 if (ptr == NULL) {454 status = NT_STATUS_NO_MEMORY;455 goto done;456 }457 458 /* convert the mpr object into a C structure */459 if (!method_def->pack_in_data(args, kwargs, ptr)) {460 talloc_free(mem_ctx);461 return NULL;462 }463 464 for (count=0;p->dest_ids[count].id;count++) /* noop */ ;465 466 /* we need to make a call per server */467 reqs = talloc_array(mem_ctx, struct irpc_request *, count);468 if (reqs == NULL) {469 status = NT_STATUS_NO_MEMORY;470 goto done;471 }472 473 /* make the actual calls */474 for (i=0;i<count;i++) {475 reqs[i] = irpc_call_send(p->msg_ctx, p->dest_ids[i],476 method_def->table, method_def->opnum, ptr, ptr);477 if (reqs[i] == NULL) {478 status = NT_STATUS_NO_MEMORY;479 goto done;480 }481 talloc_steal(reqs, reqs[i]);482 }483 484 ret = PyObject_New(irpc_ResultObject, &irpc_ResultIteratorType);485 ret->mem_ctx = mem_ctx;486 ret->reqs = reqs;487 ret->count = count;488 ret->current = 0;489 ret->unpack_fn = method_def->unpack_out_data;490 491 return (PyObject *)ret;492 done:493 talloc_free(mem_ctx);494 PyErr_SetNTSTATUS(status);495 return NULL;496 }497 498 static PyObject *py_irpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs)499 {500 irpc_ClientConnectionObject *iface = (irpc_ClientConnectionObject *)self;501 struct PyNdrRpcMethodDef *md = wrapped;502 503 return py_irpc_call(iface, md, args, kwargs);504 }505 506 static void py_irpc_dealloc(PyObject *self)507 {508 irpc_ClientConnectionObject *iface = (irpc_ClientConnectionObject *)self;509 talloc_free(iface->mem_ctx);510 PyObject_Del(self);511 }512 513 PyTypeObject irpc_ClientConnectionType = {514 PyObject_HEAD_INIT(NULL) 0,515 .tp_name = "irpc.ClientConnection",516 .tp_basicsize = sizeof(irpc_ClientConnectionObject),517 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,518 .tp_new = py_irpc_connect,519 .tp_dealloc = py_irpc_dealloc,520 .tp_doc = "ClientConnection(server, own_id=None, messaging_path=None)\n" \521 "Create a new IRPC client connection to communicate with the servers in the specified path.\n" \522 "If no path is specified, the default path from smb.conf will be used."523 };524 525 static bool irpc_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpcMethodDef *mds)526 {527 int i;528 for (i = 0; mds[i].name; i++) {529 PyObject *ret;530 struct wrapperbase *wb = calloc(sizeof(struct wrapperbase), 1);531 532 wb->name = discard_const_p(char, mds[i].name);533 wb->flags = PyWrapperFlag_KEYWORDS;534 wb->wrapper = (wrapperfunc)py_irpc_call_wrapper;535 wb->doc = discard_const_p(char, mds[i].doc);536 537 ret = PyDescr_NewWrapper(ifacetype, wb, discard_const_p(void, &mds[i]));538 539 PyDict_SetItemString(ifacetype->tp_dict, mds[i].name,540 (PyObject *)ret);541 }542 543 return true;544 }545 546 257 void initmessaging(void) 547 258 { 548 259 PyObject *mod; 549 PyObject *dep_irpc;550 551 dep_irpc = PyImport_ImportModule("samba.dcerpc.irpc");552 if (dep_irpc == NULL)553 return;554 555 if (PyType_Ready(&irpc_ClientConnectionType) < 0)556 return;557 260 558 261 if (PyType_Ready(&messaging_Type) < 0) 559 return;560 561 if (PyType_Ready(&irpc_ResultIteratorType) < 0)562 return;563 564 if (!irpc_AddNdrRpcMethods(&irpc_ClientConnectionType, py_ndr_irpc_methods))565 262 return; 566 263 … … 569 266 return; 570 267 571 Py_INCREF((PyObject *)&irpc_ClientConnectionType);572 PyModule_AddObject(mod, "ClientConnection", (PyObject *)&irpc_ClientConnectionType);573 574 268 Py_INCREF((PyObject *)&messaging_Type); 575 269 PyModule_AddObject(mod, "Messaging", (PyObject *)&messaging_Type); -
trunk/server/source4/lib/messaging/tests/irpc.c
r414 r745 24 24 #include "lib/messaging/irpc.h" 25 25 #include "librpc/gen_ndr/ndr_echo.h" 26 #include "librpc/gen_ndr/ndr_echo_c.h" 26 27 #include "torture/torture.h" 27 28 #include "cluster/cluster.h" … … 58 59 { 59 60 struct irpc_message *irpc = talloc_get_type(private_data, struct irpc_message); 60 struct echo_EchoData *r = irpc->data;61 r->out.out_data = talloc_memdup(r, r->in.in_data, r->in.len);61 struct echo_EchoData *r = (struct echo_EchoData *)irpc->data; 62 r->out.out_data = (uint8_t *)talloc_memdup(r, r->in.in_data, r->in.len); 62 63 if (r->out.out_data == NULL) { 63 64 irpc_send_reply(irpc, NT_STATUS_NO_MEMORY); … … 89 90 const struct irpc_test_data *data = (const struct irpc_test_data *)_data; 90 91 uint32_t value = *(const uint32_t *)_value; 92 struct dcerpc_binding_handle *irpc_handle; 93 94 irpc_handle = irpc_binding_handle(test, data->msg_ctx1, 95 cluster_id(0, MSG_ID2), 96 &ndr_table_rpcecho); 97 torture_assert(test, irpc_handle, "no memory"); 91 98 92 99 /* make the call */ … … 94 101 95 102 test_debug = true; 96 status = IRPC_CALL(data->msg_ctx1, cluster_id(0, MSG_ID2), 97 rpcecho, ECHO_ADDONE, &r, test); 103 status = dcerpc_echo_AddOne_r(irpc_handle, test, &r); 98 104 test_debug = false; 99 105 torture_assert_ntstatus_ok(test, status, "AddOne failed"); … … 118 124 const struct irpc_test_data *data = (const struct irpc_test_data *)tcase_data; 119 125 TALLOC_CTX *mem_ctx = tctx; 126 struct dcerpc_binding_handle *irpc_handle; 127 128 irpc_handle = irpc_binding_handle(mem_ctx, data->msg_ctx1, 129 cluster_id(0, MSG_ID2), 130 &ndr_table_rpcecho); 131 torture_assert(tctx, irpc_handle, "no memory"); 120 132 121 133 /* make the call */ … … 123 135 r.in.len = strlen((char *)r.in.in_data); 124 136 125 status = IRPC_CALL(data->msg_ctx1, cluster_id(0, MSG_ID2), 126 rpcecho, ECHO_ECHODATA, &r, 127 mem_ctx); 137 status = dcerpc_echo_EchoData_r(irpc_handle, mem_ctx, &r); 128 138 torture_assert_ntstatus_ok(tctx, status, "EchoData failed"); 129 139 … … 142 152 } 143 153 144 145 static void irpc_callback(struct irpc_request *irpc) 146 { 147 struct echo_AddOne *r = (struct echo_AddOne *)irpc->r; 148 int *pong_count = (int *)irpc->async.private_data; 149 NTSTATUS status = irpc_call_recv(irpc); 154 struct irpc_callback_state { 155 struct echo_AddOne r; 156 int *pong_count; 157 }; 158 159 static void irpc_callback(struct tevent_req *subreq) 160 { 161 struct irpc_callback_state *s = 162 tevent_req_callback_data(subreq, 163 struct irpc_callback_state); 164 NTSTATUS status; 165 166 status = dcerpc_echo_AddOne_r_recv(subreq, s); 167 TALLOC_FREE(subreq); 150 168 if (!NT_STATUS_IS_OK(status)) { 151 169 printf("irpc call failed - %s\n", nt_errstr(status)); 152 170 } 153 if (* r->out.out_data != r->in.in_data + 1) {171 if (*s->r.out.out_data != s->r.in.in_data + 1) { 154 172 printf("AddOne wrong answer - %u + 1 = %u should be %u\n", 155 r->in.in_data, *r->out.out_data, r->in.in_data+1);156 } 157 (* pong_count)++;173 s->r.in.in_data, *s->r.out.out_data, s->r.in.in_data+1); 174 } 175 (*s->pong_count)++; 158 176 } 159 177 … … 169 187 const struct irpc_test_data *data = (const struct irpc_test_data *)tcase_data; 170 188 struct timeval tv; 171 struct echo_AddOne r;172 189 TALLOC_CTX *mem_ctx = tctx; 173 190 int timelimit = torture_setting_int(tctx, "timelimit", 10); 191 struct dcerpc_binding_handle *irpc_handle; 192 193 irpc_handle = irpc_binding_handle(mem_ctx, data->msg_ctx1, 194 cluster_id(0, MSG_ID2), 195 &ndr_table_rpcecho); 196 torture_assert(tctx, irpc_handle, "no memory"); 174 197 175 198 tv = timeval_current(); 176 177 r.in.in_data = 0;178 199 179 200 torture_comment(tctx, "Sending echo for %d seconds\n", timelimit); 180 201 while (timeval_elapsed(&tv) < timelimit) { 181 struct irpc_request *irpc; 182 183 irpc = IRPC_CALL_SEND(data->msg_ctx1, cluster_id(0, MSG_ID2), 184 rpcecho, ECHO_ADDONE, 185 &r, mem_ctx); 186 torture_assert(tctx, irpc != NULL, "AddOne send failed"); 187 188 irpc->async.fn = irpc_callback; 189 irpc->async.private_data = &pong_count; 202 struct tevent_req *subreq; 203 struct irpc_callback_state *s; 204 205 s = talloc_zero(mem_ctx, struct irpc_callback_state); 206 torture_assert(tctx, s != NULL, "no mem"); 207 208 s->pong_count = &pong_count; 209 210 subreq = dcerpc_echo_AddOne_r_send(mem_ctx, 211 tctx->ev, 212 irpc_handle, 213 &s->r); 214 torture_assert(tctx, subreq != NULL, "AddOne send failed"); 215 216 tevent_req_set_callback(subreq, irpc_callback, s); 190 217 191 218 ping_count++; … … 216 243 *_data = data = talloc(tctx, struct irpc_test_data); 217 244 218 lp _set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");245 lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp"); 219 246 220 247 data->ev = tctx->ev; 221 248 torture_assert(tctx, data->msg_ctx1 = 222 249 messaging_init(tctx, 223 lp _messaging_path(tctx, tctx->lp_ctx),250 lpcfg_messaging_path(tctx, tctx->lp_ctx), 224 251 cluster_id(0, MSG_ID1), 225 lp_iconv_convenience(tctx->lp_ctx),226 252 data->ev), 227 253 "Failed to init first messaging context"); … … 229 255 torture_assert(tctx, data->msg_ctx2 = 230 256 messaging_init(tctx, 231 lp _messaging_path(tctx, tctx->lp_ctx),257 lpcfg_messaging_path(tctx, tctx->lp_ctx), 232 258 cluster_id(0, MSG_ID2), 233 lp_iconv_convenience(tctx->lp_ctx),234 259 data->ev), 235 260 "Failed to init second messaging context"); … … 247 272 struct torture_suite *torture_local_irpc(TALLOC_CTX *mem_ctx) 248 273 { 249 struct torture_suite *suite = torture_suite_create(mem_ctx, " IRPC");274 struct torture_suite *suite = torture_suite_create(mem_ctx, "irpc"); 250 275 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "irpc"); 251 276 int i; -
trunk/server/source4/lib/messaging/tests/messaging.c
r414 r745 68 68 uint32_t msg_ping, msg_exit; 69 69 70 lp _set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");70 lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp"); 71 71 72 72 ev = tctx->ev; 73 73 74 74 msg_server_ctx = messaging_init(tctx, 75 lp_messaging_path(tctx, tctx->lp_ctx), 76 cluster_id(0, 1), 77 lp_iconv_convenience(tctx->lp_ctx), 75 lpcfg_messaging_path(tctx, tctx->lp_ctx), cluster_id(0, 1), 78 76 ev); 79 77 … … 84 82 85 83 msg_client_ctx = messaging_init(tctx, 86 lp _messaging_path(tctx, tctx->lp_ctx),84 lpcfg_messaging_path(tctx, tctx->lp_ctx), 87 85 cluster_id(0, 2), 88 lp_iconv_convenience(tctx->lp_ctx),89 86 ev); 90 87 … … 140 137 struct torture_suite *torture_local_messaging(TALLOC_CTX *mem_ctx) 141 138 { 142 struct torture_suite *s = torture_suite_create(mem_ctx, " MESSAGING");139 struct torture_suite *s = torture_suite_create(mem_ctx, "messaging"); 143 140 torture_suite_add_simple_test(s, "ping_speed", test_ping_speed); 144 141 return s; -
trunk/server/source4/lib/registry/dir.c
r414 r745 41 41 42 42 path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name); 43 W_ERROR_HAVE_NO_MEMORY(path); 43 44 ret = mkdir(path, 0700); 44 45 if (ret == 0) { 45 46 struct dir_key *key = talloc(mem_ctx, struct dir_key); 47 W_ERROR_HAVE_NO_MEMORY(key); 46 48 key->key.ops = ®_backend_dir; 47 49 key->path = talloc_steal(key, path); … … 77 79 78 80 path = talloc_asprintf(name, "%s/%s", name, e->d_name); 79 if (!path) 80 return WERR_NOMEM; 81 W_ERROR_HAVE_NO_MEMORY(path); 81 82 82 83 stat(path, &stbuf); … … 109 110 } 110 111 111 static WERROR reg_dir_del_key(const struct hive_key *k, const char *name) 112 static WERROR reg_dir_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *k, 113 const char *name) 112 114 { 113 115 struct dir_key *dk = talloc_get_type(k, struct dir_key); 114 char *child = talloc_asprintf(NULL, "%s/%s", dk->path, name);116 char *child; 115 117 WERROR ret; 118 119 child = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name); 120 W_ERROR_HAVE_NO_MEMORY(child); 116 121 117 122 ret = reg_dir_delete_recursive(child); … … 137 142 138 143 fullpath = talloc_asprintf(mem_ctx, "%s/%s", p->path, name); 144 W_ERROR_HAVE_NO_MEMORY(fullpath); 139 145 140 146 d = opendir(fullpath); … … 142 148 DEBUG(3,("Unable to open '%s': %s\n", fullpath, 143 149 strerror(errno))); 150 talloc_free(fullpath); 144 151 return WERR_BADFILE; 145 152 } … … 160 167 struct dirent *e; 161 168 const struct dir_key *dk = talloc_get_type(k, struct dir_key); 162 int i = 0;169 unsigned int i = 0; 163 170 DIR *d; 164 171 … … 174 181 175 182 /* Check if file is a directory */ 176 asprintf(&thispath, "%s/%s", dk->path, e->d_name); 183 thispath = talloc_asprintf(mem_ctx, "%s/%s", dk->path, 184 e->d_name); 185 W_ERROR_HAVE_NO_MEMORY(thispath); 177 186 stat(thispath, &stbuf); 178 187 179 188 if (!S_ISDIR(stbuf.st_mode)) { 180 SAFE_FREE(thispath);189 talloc_free(thispath); 181 190 continue; 182 191 } … … 185 194 struct stat st; 186 195 *name = talloc_strdup(mem_ctx, e->d_name); 196 W_ERROR_HAVE_NO_MEMORY(*name); 187 197 *classname = NULL; 188 198 stat(thispath, &st); 189 199 unix_to_nt_time(last_mod_time, st.st_mtime); 190 SAFE_FREE(thispath);200 talloc_free(thispath); 191 201 closedir(d); 192 202 return WERR_OK; … … 194 204 i++; 195 205 196 SAFE_FREE(thispath);206 talloc_free(thispath); 197 207 } 198 208 } … … 212 222 213 223 dk = talloc(parent_ctx, struct dir_key); 224 W_ERROR_HAVE_NO_MEMORY(dk); 214 225 dk->key.ops = ®_backend_dir; 215 226 dk->path = talloc_strdup(dk, location); … … 271 282 char *path = talloc_asprintf(ctx, "%s/%s", 272 283 dk->path, e->d_name); 284 W_ERROR_HAVE_NO_MEMORY(path); 273 285 274 286 if (stat(path, &st) < 0) { 275 287 DEBUG(0, ("Error statting %s: %s\n", path, 276 288 strerror(errno))); 289 talloc_free(path); 277 290 continue; 278 291 } … … 309 322 { 310 323 const struct dir_key *dk = talloc_get_type(key, struct dir_key); 311 char *path = talloc_asprintf(dk, "%s/%s", dk->path, name); 312 313 if (!file_save(path, data.data, data.length)) 324 char *path; 325 bool ret; 326 327 path = talloc_asprintf(dk, "%s/%s", dk->path, name); 328 W_ERROR_HAVE_NO_MEMORY(path); 329 330 ret = file_save(path, data.data, data.length); 331 332 talloc_free(path); 333 334 if (!ret) { 314 335 return WERR_GENERAL_FAILURE; 336 } 315 337 316 338 /* FIXME: Type */ … … 324 346 { 325 347 const struct dir_key *dk = talloc_get_type(key, struct dir_key); 326 char *path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);348 char *path; 327 349 size_t size; 328 350 char *contents; 329 351 352 path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name); 353 W_ERROR_HAVE_NO_MEMORY(path); 354 330 355 contents = file_load(path, &size, 0, mem_ctx); 356 331 357 talloc_free(path); 358 332 359 if (contents == NULL) 333 360 return WERR_BADFILE; … … 343 370 344 371 static WERROR reg_dir_enum_value(TALLOC_CTX *mem_ctx, 345 struct hive_key *key, int idx,372 struct hive_key *key, uint32_t idx, 346 373 const char **name, 347 374 uint32_t *type, DATA_BLOB *data) … … 350 377 DIR *d; 351 378 struct dirent *e; 352 int i;379 unsigned int i; 353 380 354 381 d = opendir(dk->path); … … 365 392 366 393 if (i == idx) { 367 if (name != NULL) 394 if (name != NULL) { 368 395 *name = talloc_strdup(mem_ctx, e->d_name); 396 W_ERROR_HAVE_NO_MEMORY(*name); 397 } 369 398 W_ERROR_NOT_OK_RETURN(reg_dir_get_value(mem_ctx, key, 370 399 *name, type, … … 381 410 382 411 383 static WERROR reg_dir_del_value (struct hive_key *key, const char *name) 412 static WERROR reg_dir_del_value(TALLOC_CTX *mem_ctx, 413 struct hive_key *key, const char *name) 384 414 { 385 415 const struct dir_key *dk = talloc_get_type(key, struct dir_key); 386 char *path = talloc_asprintf(key, "%s/%s", dk->path, name); 387 if (unlink(path) < 0) { 388 talloc_free(path); 416 char *path; 417 int ret; 418 419 path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name); 420 W_ERROR_HAVE_NO_MEMORY(path); 421 422 ret = unlink(path); 423 424 talloc_free(path); 425 426 if (ret < 0) { 389 427 if (errno == ENOENT) 390 428 return WERR_BADFILE; 391 429 return WERR_GENERAL_FAILURE; 392 430 } 393 talloc_free(path);394 431 395 432 return WERR_OK; -
trunk/server/source4/lib/registry/hive.c
r414 r745 55 55 if (!strncmp(peek, "regf", 4)) { 56 56 close(fd); 57 return reg_open_regf_file(parent_ctx, location, lp_iconv_convenience(lp_ctx),root);57 return reg_open_regf_file(parent_ctx, location, root); 58 58 } else if (!strncmp(peek, "TDB file", 8)) { 59 59 close(fd); … … 92 92 } 93 93 94 _PUBLIC_ WERROR hive_key_del(const struct hive_key *key, const char *name) 94 _PUBLIC_ WERROR hive_key_del(TALLOC_CTX *mem_ctx, const struct hive_key *key, 95 const char *name) 95 96 { 96 return key->ops->del_key( key, name);97 return key->ops->del_key(mem_ctx, key, name); 97 98 } 98 99 … … 164 165 } 165 166 166 WERROR hive_key_del_value(struct hive_key *key, const char *name) 167 WERROR hive_key_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key, 168 const char *name) 167 169 { 168 170 if (key->ops->delete_value == NULL) 169 171 return WERR_NOT_SUPPORTED; 170 172 171 return key->ops->delete_value( key, name);173 return key->ops->delete_value(mem_ctx, key, name); 172 174 } 173 175 -
trunk/server/source4/lib/registry/interface.c
r414 r745 45 45 _PUBLIC_ const char *reg_get_predef_name(uint32_t hkey) 46 46 { 47 int i;47 unsigned int i; 48 48 for (i = 0; reg_predefined_keys[i].name; i++) { 49 49 if (reg_predefined_keys[i].handle == hkey) … … 59 59 struct registry_key **key) 60 60 { 61 int i;61 unsigned int i; 62 62 63 63 for (i = 0; reg_predefined_keys[i].name; i++) { … … 151 151 _PUBLIC_ WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, 152 152 const struct registry_key *key, 153 int idx, const char **name,153 uint32_t idx, const char **name, 154 154 const char **keyclass, 155 155 NTTIME *last_changed_time) … … 186 186 * Delete a key. 187 187 */ 188 _PUBLIC_ WERROR reg_key_del(struct registry_key *parent, const char *name) 188 _PUBLIC_ WERROR reg_key_del(TALLOC_CTX *mem_ctx, struct registry_key *parent, 189 const char *name) 189 190 { 190 191 if (parent == NULL) … … 194 195 return WERR_NOT_SUPPORTED; 195 196 196 return parent->context->ops->delete_key( parent, name);197 return parent->context->ops->delete_key(mem_ctx, parent, name); 197 198 } 198 199 … … 202 203 _PUBLIC_ WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, 203 204 struct registry_key *parent, 204 const char * name, const char *key_class,205 const char *path, const char *key_class, 205 206 struct security_descriptor *desc, 206 207 struct registry_key **newkey) … … 215 216 } 216 217 217 return parent->context->ops->create_key(mem_ctx, parent, name,218 return parent->context->ops->create_key(mem_ctx, parent, path, 218 219 key_class, desc, newkey); 219 220 } … … 258 259 * Delete a value. 259 260 */ 260 _PUBLIC_ WERROR reg_del_value(struct registry_key *key, const char *valname) 261 _PUBLIC_ WERROR reg_del_value(TALLOC_CTX *mem_ctx, struct registry_key *key, 262 const char *valname) 261 263 { 262 264 if (key == NULL) … … 266 268 return WERR_NOT_SUPPORTED; 267 269 268 return key->context->ops->delete_value( key, valname);270 return key->context->ops->delete_value(mem_ctx, key, valname); 269 271 } 270 272 -
trunk/server/source4/lib/registry/ldb.c
r414 r745 3 3 Registry interface 4 4 Copyright (C) 2004-2007, Jelmer Vernooij, jelmer@samba.org 5 Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de5 Copyright (C) 2008-2010, Matthias Dieter Wallnöfer, mdw@samba.org 6 6 7 7 This program is free software; you can redistribute it and/or modify … … 21 21 #include "includes.h" 22 22 #include "registry.h" 23 #include "lib/ldb/include/ldb.h"24 #include "lib/ldb/include/ldb_errors.h"23 #include <ldb.h> 24 #include <ldb_errors.h> 25 25 #include "ldb_wrap.h" 26 26 #include "librpc/gen_ndr/winreg.h" … … 35 35 struct ldb_dn *dn; 36 36 struct ldb_message **subkeys, **values; 37 int subkey_count, value_count; 37 unsigned int subkey_count, value_count; 38 const char *classname; 38 39 }; 39 40 40 static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, 41 static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx, 41 42 struct ldb_message *msg, 42 43 const char **name, uint32_t *type, … … 46 47 uint32_t value_type; 47 48 48 if (name != NULL) 49 if (name != NULL) { 49 50 *name = talloc_strdup(mem_ctx, 50 51 ldb_msg_find_attr_as_string(msg, "value", 51 NULL)); 52 "")); 53 } 52 54 53 55 value_type = ldb_msg_find_attr_as_uint(msg, "type", 0); 54 *type = value_type; 56 *type = value_type; 55 57 56 58 val = ldb_msg_find_ldb_val(msg, "data"); … … 60 62 case REG_SZ: 61 63 case REG_EXPAND_SZ: 62 if (val != NULL) 64 if (val != NULL) { 65 /* The data should be provided as UTF16 string */ 63 66 convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16, 64 65 66 else {67 val->data, val->length, 68 (void **)&data->data, &data->length, false); 69 } else { 67 70 data->data = NULL; 68 71 data->length = 0; … … 70 73 break; 71 74 72 case REG_BINARY: 73 if (val != NULL) 74 *data = data_blob_talloc(mem_ctx, val->data, val->length); 75 else { 75 case REG_DWORD: 76 case REG_DWORD_BIG_ENDIAN: 77 if (val != NULL) { 78 /* The data is a plain DWORD */ 79 uint32_t tmp = strtoul((char *)val->data, NULL, 0); 80 data->data = talloc_size(mem_ctx, sizeof(uint32_t)); 81 if (data->data != NULL) { 82 SIVAL(data->data, 0, tmp); 83 } 84 data->length = sizeof(uint32_t); 85 } else { 76 86 data->data = NULL; 77 87 data->length = 0; … … 79 89 break; 80 90 81 case REG_DWORD: { 82 uint32_t tmp = strtoul((char *)val->data, NULL, 0); 83 *data = data_blob_talloc(mem_ctx, &tmp, 4); 91 case REG_QWORD: 92 if (val != NULL) { 93 /* The data is a plain QWORD */ 94 uint64_t tmp = strtoull((char *)val->data, NULL, 0); 95 data->data = talloc_size(mem_ctx, sizeof(uint64_t)); 96 if (data->data != NULL) { 97 SBVAL(data->data, 0, tmp); 98 } 99 data->length = sizeof(uint64_t); 100 } else { 101 data->data = NULL; 102 data->length = 0; 84 103 } 85 104 break; 86 105 106 case REG_BINARY: 87 107 default: 88 *data = data_blob_talloc(mem_ctx, val->data, val->length); 108 if (val != NULL) { 109 data->data = talloc_memdup(mem_ctx, val->data, 110 val->length); 111 data->length = val->length; 112 } else { 113 data->data = NULL; 114 data->length = 0; 115 } 89 116 break; 90 117 } … … 96 123 uint32_t type, DATA_BLOB data) 97 124 { 98 struct ldb_val val; 99 struct ldb_message *msg = talloc_zero(mem_ctx, struct ldb_message); 100 char *type_s; 101 102 ldb_msg_add_string(msg, "value", talloc_strdup(mem_ctx, name)); 125 struct ldb_message *msg; 126 char *name_dup, *type_str; 127 int ret; 128 129 msg = talloc_zero(mem_ctx, struct ldb_message); 130 if (msg == NULL) { 131 return NULL; 132 } 133 134 name_dup = talloc_strdup(msg, name); 135 if (name_dup == NULL) { 136 talloc_free(msg); 137 return NULL; 138 } 139 140 ret = ldb_msg_add_string(msg, "value", name_dup); 141 if (ret != LDB_SUCCESS) { 142 talloc_free(msg); 143 return NULL; 144 } 103 145 104 146 switch (type) { 105 147 case REG_SZ: 106 148 case REG_EXPAND_SZ: 107 if (data.data[0] != '\0') { 108 convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, 109 (void *)data.data, 110 data.length, 111 (void **)&val.data, &val.length, false); 112 ldb_msg_add_value(msg, "data", &val, NULL); 149 if ((data.length > 0) && (data.data != NULL)) { 150 struct ldb_val *val; 151 bool ret2 = false; 152 153 val = talloc_zero(msg, struct ldb_val); 154 if (val == NULL) { 155 talloc_free(msg); 156 return NULL; 157 } 158 159 /* The data is provided as UTF16 string */ 160 ret2 = convert_string_talloc(mem_ctx, CH_UTF16, CH_UTF8, 161 (void *)data.data, data.length, 162 (void **)&val->data, &val->length, 163 false); 164 if (ret2) { 165 ret = ldb_msg_add_value(msg, "data", val, NULL); 166 } else { 167 /* workaround for non-standard data */ 168 ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); 169 } 113 170 } else { 114 ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL);171 ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); 115 172 } 116 173 break; 117 174 175 case REG_DWORD: 176 case REG_DWORD_BIG_ENDIAN: 177 if ((data.length > 0) && (data.data != NULL)) { 178 if (data.length == sizeof(uint32_t)) { 179 char *conv_str; 180 181 conv_str = talloc_asprintf(msg, "0x%8.8x", 182 IVAL(data.data, 0)); 183 if (conv_str == NULL) { 184 talloc_free(msg); 185 return NULL; 186 } 187 ret = ldb_msg_add_string(msg, "data", conv_str); 188 } else { 189 /* workaround for non-standard data */ 190 talloc_free(msg); 191 return NULL; 192 } 193 } else { 194 ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); 195 } 196 break; 197 198 case REG_QWORD: 199 if ((data.length > 0) && (data.data != NULL)) { 200 if (data.length == sizeof(uint64_t)) { 201 char *conv_str; 202 203 conv_str = talloc_asprintf(msg, "0x%16.16llx", 204 (unsigned long long)BVAL(data.data, 0)); 205 if (conv_str == NULL) { 206 talloc_free(msg); 207 return NULL; 208 } 209 ret = ldb_msg_add_string(msg, "data", conv_str); 210 } else { 211 /* workaround for non-standard data */ 212 talloc_free(msg); 213 return NULL; 214 215 } 216 } else { 217 ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); 218 } 219 break; 220 118 221 case REG_BINARY: 119 if (data.length > 0) 120 ldb_msg_add_value(msg, "data", &data, NULL); 121 else 122 ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); 222 default: 223 if ((data.length > 0) && (data.data != NULL)) { 224 ret = ldb_msg_add_value(msg, "data", &data, NULL); 225 } else { 226 ret = ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); 227 } 123 228 break; 124 125 case REG_DWORD: 126 ldb_msg_add_string(msg, "data", 127 talloc_asprintf(mem_ctx, "0x%x", 128 IVAL(data.data, 0))); 129 break; 130 default: 131 ldb_msg_add_value(msg, "data", &data, NULL); 132 } 133 134 135 type_s = talloc_asprintf(mem_ctx, "%u", type); 136 ldb_msg_add_string(msg, "type", type_s); 229 } 230 231 if (ret != LDB_SUCCESS) { 232 talloc_free(msg); 233 return NULL; 234 } 235 236 type_str = talloc_asprintf(mem_ctx, "%u", type); 237 if (type_str == NULL) { 238 talloc_free(msg); 239 return NULL; 240 } 241 242 ret = ldb_msg_add_string(msg, "type", type_str); 243 if (ret != LDB_SUCCESS) { 244 talloc_free(msg); 245 return NULL; 246 } 137 247 138 248 return msg; … … 167 277 const char *path, const char *add) 168 278 { 169 TALLOC_CTX *local_ctx;170 279 struct ldb_dn *ret; 171 char *mypath = talloc_strdup(mem_ctx, path);280 char *mypath; 172 281 char *begin; 173 282 struct ldb_key_data *kd = talloc_get_type(from, struct ldb_key_data); 174 283 struct ldb_context *ldb = kd->ldb; 175 284 176 local_ctx = talloc_new(mem_ctx); 177 178 if (add) { 179 ret = ldb_dn_new(mem_ctx, ldb, add); 180 } else { 181 ret = ldb_dn_new(mem_ctx, ldb, NULL); 182 } 285 mypath = talloc_strdup(mem_ctx, path); 286 if (mypath == NULL) { 287 return NULL; 288 } 289 290 ret = ldb_dn_new(mem_ctx, ldb, add); 183 291 if (!ldb_dn_validate(ret)) { 184 292 talloc_free(ret); 185 talloc_free(local_ctx);186 293 return NULL; 187 294 } 188 295 189 while (mypath) { 190 char *keyname; 191 192 begin = strrchr(mypath, '\\'); 193 194 if (begin) keyname = begin + 1; 195 else keyname = mypath; 196 197 if(strlen(keyname)) { 198 if (!ldb_dn_add_base_fmt(ret, "key=%s", 199 reg_ldb_escape(local_ctx, 200 keyname))) 201 { 202 talloc_free(local_ctx); 203 return NULL; 204 } 205 } 206 207 if(begin) { 296 if (!ldb_dn_add_base(ret, kd->dn)) { 297 talloc_free(ret); 298 return NULL; 299 } 300 301 while (mypath[0] != '\0') { 302 begin = strchr(mypath, '\\'); 303 if (begin != NULL) { 208 304 *begin = '\0'; 305 } 306 307 if (!ldb_dn_add_child_fmt(ret, "key=%s", 308 reg_ldb_escape(mem_ctx, mypath))) { 309 talloc_free(ret); 310 return NULL; 311 } 312 313 if (begin != NULL) { 314 mypath = begin + 1; 209 315 } else { 210 316 break; 211 317 } 212 318 } 213 214 ldb_dn_add_base(ret, kd->dn);215 216 talloc_free(local_ctx);217 319 218 320 return ret; … … 225 327 int ret; 226 328 227 ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL, NULL, "(key=*)");228 329 ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL, 330 NULL, "(key=*)"); 229 331 if (ret != LDB_SUCCESS) { 230 332 DEBUG(0, ("Error getting subkeys for '%s': %s\n", … … 248 350 ret = ldb_search(c, c, &res, kd->dn, LDB_SCOPE_ONELEVEL, 249 351 NULL, "(value=*)"); 250 251 352 if (ret != LDB_SUCCESS) { 252 353 DEBUG(0, ("Error getting values for '%s': %s\n", … … 269 370 NTTIME *last_mod_time) 270 371 { 271 struct ldb_message_element *el;272 372 struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data); 273 373 274 374 /* Initialization */ 275 375 if (name != NULL) 276 376 *name = NULL; 277 377 if (classname != NULL) 278 *classname = NULL; /* TODO: Store properly */378 *classname = NULL; 279 379 if (last_mod_time != NULL) 280 380 *last_mod_time = 0; /* TODO: we need to add this to the … … 289 389 return WERR_NO_MORE_ITEMS; 290 390 291 el = ldb_msg_find_element(kd->subkeys[idx], "key");292 SMB_ASSERT(el != NULL);293 SMB_ASSERT(el->num_values != 0);294 295 391 if (name != NULL) 296 *name = talloc_strdup(mem_ctx, (char *)el->values[0].data); 297 298 return WERR_OK; 299 } 300 301 static WERROR ldb_get_default_value(TALLOC_CTX *mem_ctx, struct hive_key *k, 302 const char **name, uint32_t *data_type, 303 DATA_BLOB *data) 392 *name = talloc_strdup(mem_ctx, 393 ldb_msg_find_attr_as_string(kd->subkeys[idx], "key", NULL)); 394 if (classname != NULL) 395 *classname = talloc_strdup(mem_ctx, 396 ldb_msg_find_attr_as_string(kd->subkeys[idx], "classname", NULL)); 397 398 return WERR_OK; 399 } 400 401 static WERROR ldb_get_default_value(TALLOC_CTX *mem_ctx, 402 const struct hive_key *k, 403 const char **name, uint32_t *data_type, 404 DATA_BLOB *data) 304 405 { 305 406 struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data); … … 309 410 int ret; 310 411 311 ret = ldb_search(c, mem_ctx, &res, kd->dn, LDB_SCOPE_BASE, attrs, " %s", "");412 ret = ldb_search(c, mem_ctx, &res, kd->dn, LDB_SCOPE_BASE, attrs, "(dn=*)"); 312 413 313 414 if (ret != LDB_SUCCESS) { … … 317 418 } 318 419 319 if (res->count == 0 || res->msgs[0]->num_elements == 0) 420 if (res->count == 0 || res->msgs[0]->num_elements == 0) { 421 talloc_free(res); 320 422 return WERR_BADFILE; 321 322 reg_ldb_unpack_value(mem_ctx, 323 res->msgs[0], name, data_type, data); 423 } 424 425 if ((data_type != NULL) && (data != NULL)) { 426 reg_ldb_unpack_value(mem_ctx, res->msgs[0], name, data_type, 427 data); 428 } 324 429 325 430 talloc_free(res); … … 329 434 330 435 static WERROR ldb_get_value_by_id(TALLOC_CTX *mem_ctx, struct hive_key *k, 331 int idx, const char **name,436 uint32_t idx, const char **name, 332 437 uint32_t *data_type, DATA_BLOB *data) 333 438 { 334 439 struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data); 335 440 336 /* if default value exists, give it back */441 /* if the default value exists, give it back */ 337 442 if (W_ERROR_IS_OK(ldb_get_default_value(mem_ctx, k, name, data_type, 338 443 data))) { … … 361 466 { 362 467 struct ldb_key_data *kd = talloc_get_type(k, struct ldb_key_data); 363 struct ldb_context *c = kd->ldb; 364 struct ldb_result *res; 365 int ret; 366 char *query; 367 368 if (strlen(name) == 0) { 369 /* default value */ 468 const char *res_name; 469 uint32_t idx; 470 471 /* the default value was requested, give it back */ 472 if (name[0] == '\0') { 370 473 return ldb_get_default_value(mem_ctx, k, NULL, data_type, data); 371 } else { 372 /* normal value */ 373 query = talloc_asprintf(mem_ctx, "(value=%s)", name); 374 ret = ldb_search(c, mem_ctx, &res, kd->dn, LDB_SCOPE_ONELEVEL, NULL, "%s", query); 375 talloc_free(query); 376 377 if (ret != LDB_SUCCESS) { 378 DEBUG(0, ("Error getting values for '%s': %s\n", 379 ldb_dn_get_linearized(kd->dn), ldb_errstring(c))); 380 return WERR_FOOBAR; 381 } 382 383 if (res->count == 0) 384 return WERR_BADFILE; 385 386 reg_ldb_unpack_value(mem_ctx, res->msgs[0], NULL, data_type, data); 387 388 talloc_free(res); 389 } 390 391 return WERR_OK; 474 } 475 476 /* Do the search if necessary */ 477 if (kd->values == NULL) { 478 W_ERROR_NOT_OK_RETURN(cache_values(kd)); 479 } 480 481 for (idx = 0; idx < kd->value_count; idx++) { 482 res_name = ldb_msg_find_attr_as_string(kd->values[idx], "value", 483 ""); 484 if (ldb_attr_cmp(name, res_name) == 0) { 485 reg_ldb_unpack_value(mem_ctx, kd->values[idx], NULL, 486 data_type, data); 487 return WERR_OK; 488 } 489 } 490 491 return WERR_BADFILE; 392 492 } 393 493 … … 396 496 { 397 497 struct ldb_result *res; 398 struct ldb_dn *ld ap_path;498 struct ldb_dn *ldb_path; 399 499 int ret; 400 500 struct ldb_key_data *newkd; … … 402 502 struct ldb_context *c = kd->ldb; 403 503 404 ldap_path = reg_path_to_ldb(mem_ctx, h, name, NULL); 405 406 ret = ldb_search(c, mem_ctx, &res, ldap_path, LDB_SCOPE_BASE, NULL, "(key=*)"); 504 ldb_path = reg_path_to_ldb(mem_ctx, h, name, NULL); 505 W_ERROR_HAVE_NO_MEMORY(ldb_path); 506 507 ret = ldb_search(c, mem_ctx, &res, ldb_path, LDB_SCOPE_BASE, NULL, "(key=*)"); 407 508 408 509 if (ret != LDB_SUCCESS) { 409 510 DEBUG(3, ("Error opening key '%s': %s\n", 410 ldb_dn_get_linearized(ld ap_path), ldb_errstring(c)));511 ldb_dn_get_linearized(ldb_path), ldb_errstring(c))); 411 512 return WERR_FOOBAR; 412 513 } else if (res->count == 0) { 413 514 DEBUG(3, ("Key '%s' not found\n", 414 ldb_dn_get_linearized(ld ap_path)));515 ldb_dn_get_linearized(ldb_path))); 415 516 talloc_free(res); 416 517 return WERR_BADFILE; … … 418 519 419 520 newkd = talloc_zero(mem_ctx, struct ldb_key_data); 521 W_ERROR_HAVE_NO_MEMORY(newkd); 420 522 newkd->key.ops = ®_backend_ldb; 421 523 newkd->ldb = talloc_reference(newkd, kd->ldb); 422 newkd->dn = ldb_dn_copy(mem_ctx, res->msgs[0]->dn); 524 newkd->dn = ldb_dn_copy(newkd, res->msgs[0]->dn); 525 newkd->classname = talloc_steal(newkd, 526 ldb_msg_find_attr_as_string(res->msgs[0], "classname", NULL)); 527 528 talloc_free(res); 423 529 424 530 *key = (struct hive_key *)newkd; … … 442 548 443 549 wrap = ldb_wrap_connect(parent_ctx, ev_ctx, lp_ctx, 444 location, session_info, credentials, 0 , NULL);550 location, session_info, credentials, 0); 445 551 446 552 if (wrap == NULL) { … … 477 583 { 478 584 struct ldb_key_data *parentkd = discard_const_p(struct ldb_key_data, parent); 585 struct ldb_dn *ldb_path; 479 586 struct ldb_message *msg; 480 587 struct ldb_key_data *newkd; 481 588 int ret; 482 589 590 ldb_path = reg_path_to_ldb(mem_ctx, parent, name, NULL); 591 W_ERROR_HAVE_NO_MEMORY(ldb_path); 592 483 593 msg = ldb_msg_new(mem_ctx); 484 485 msg->dn = reg_path_to_ldb(msg, parent, name, NULL); 486 487 ldb_msg_add_string(msg, "key", talloc_strdup(mem_ctx, name)); 488 if (classname != NULL) 489 ldb_msg_add_string(msg, "classname", 490 talloc_strdup(mem_ctx, classname)); 594 W_ERROR_HAVE_NO_MEMORY(msg); 595 596 msg->dn = ldb_path; 597 598 ldb_msg_add_string(msg, "key", name); 599 if (classname != NULL) { 600 ldb_msg_add_string(msg, "classname", classname); 601 } 491 602 492 603 ret = ldb_add(parentkd->ldb, msg); 604 605 talloc_free(msg); 606 493 607 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { 494 608 return WERR_ALREADY_EXISTS; … … 500 614 } 501 615 502 DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized( msg->dn)));616 DEBUG(2, ("key added: %s\n", ldb_dn_get_linearized(ldb_path))); 503 617 504 618 newkd = talloc_zero(mem_ctx, struct ldb_key_data); 619 W_ERROR_HAVE_NO_MEMORY(newkd); 505 620 newkd->ldb = talloc_reference(newkd, parentkd->ldb); 506 621 newkd->key.ops = ®_backend_ldb; 507 newkd->dn = talloc_steal(newkd, msg->dn); 622 newkd->dn = talloc_steal(newkd, ldb_path); 623 newkd->classname = talloc_steal(newkd, classname); 508 624 509 625 *newkey = (struct hive_key *)newkd; … … 516 632 } 517 633 518 static WERROR ldb_del_value (struct hive_key *key, const char *child) 634 static WERROR ldb_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key, 635 const char *child) 519 636 { 520 637 int ret; 521 638 struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data); 522 TALLOC_CTX *mem_ctx;523 639 struct ldb_message *msg; 524 640 struct ldb_dn *childdn; 525 641 526 if ( strlen(child) == 0) {642 if (child[0] == '\0') { 527 643 /* default value */ 528 mem_ctx = talloc_init("ldb_del_value");529 530 644 msg = talloc_zero(mem_ctx, struct ldb_message); 645 W_ERROR_HAVE_NO_MEMORY(msg); 531 646 msg->dn = ldb_dn_copy(msg, kd->dn); 647 W_ERROR_HAVE_NO_MEMORY(msg->dn); 532 648 ldb_msg_add_empty(msg, "data", LDB_FLAG_MOD_DELETE, NULL); 533 649 ldb_msg_add_empty(msg, "type", LDB_FLAG_MOD_DELETE, NULL); 534 650 535 651 ret = ldb_modify(kd->ldb, msg); 652 653 talloc_free(msg); 654 536 655 if (ret != LDB_SUCCESS) { 537 656 DEBUG(1, ("ldb_del_value: %s\n", ldb_errstring(kd->ldb))); 538 talloc_free(mem_ctx);539 657 return WERR_FOOBAR; 540 658 } 541 542 talloc_free(mem_ctx);543 659 } else { 544 660 /* normal value */ … … 570 686 } 571 687 572 static WERROR ldb_del_key(const struct hive_key *key, const char *name) 573 { 574 int i, ret; 688 static WERROR ldb_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *key, 689 const char *name) 690 { 691 unsigned int i; 692 int ret; 575 693 struct ldb_key_data *parentkd = talloc_get_type(key, struct ldb_key_data); 576 struct ldb_dn *ldap_path; 577 TALLOC_CTX *mem_ctx = talloc_init("ldb_del_key"); 694 struct ldb_dn *ldb_path; 578 695 struct ldb_context *c = parentkd->ldb; 579 696 struct ldb_result *res_keys; … … 585 702 werr = ldb_open_key(mem_ctx, key, name, &hk); 586 703 if (!W_ERROR_IS_OK(werr)) { 587 talloc_free(mem_ctx);588 704 return werr; 589 705 } 590 706 591 ldap_path = reg_path_to_ldb(mem_ctx, key, name, NULL); 592 if (!ldap_path) { 593 talloc_free(mem_ctx); 594 return WERR_FOOBAR; 595 } 707 ldb_path = reg_path_to_ldb(mem_ctx, key, name, NULL); 708 W_ERROR_HAVE_NO_MEMORY(ldb_path); 596 709 597 710 /* Search for subkeys */ 598 ret = ldb_search(c, mem_ctx, &res_keys, ld ap_path, LDB_SCOPE_ONELEVEL,711 ret = ldb_search(c, mem_ctx, &res_keys, ldb_path, LDB_SCOPE_ONELEVEL, 599 712 NULL, "(key=*)"); 600 713 601 714 if (ret != LDB_SUCCESS) { 602 715 DEBUG(0, ("Error getting subkeys for '%s': %s\n", 603 ldb_dn_get_linearized(ldap_path), ldb_errstring(c))); 604 talloc_free(mem_ctx); 716 ldb_dn_get_linearized(ldb_path), ldb_errstring(c))); 605 717 return WERR_FOOBAR; 606 718 } 607 719 608 720 /* Search for values */ 609 ret = ldb_search(c, mem_ctx, &res_vals, ld ap_path, LDB_SCOPE_ONELEVEL,721 ret = ldb_search(c, mem_ctx, &res_vals, ldb_path, LDB_SCOPE_ONELEVEL, 610 722 NULL, "(value=*)"); 611 723 612 724 if (ret != LDB_SUCCESS) { 613 725 DEBUG(0, ("Error getting values for '%s': %s\n", 614 ldb_dn_get_linearized(ldap_path), ldb_errstring(c))); 615 talloc_free(mem_ctx); 726 ldb_dn_get_linearized(ldb_path), ldb_errstring(c))); 616 727 return WERR_FOOBAR; 617 728 } … … 622 733 if (ret != LDB_SUCCESS) { 623 734 DEBUG(0, ("ldb_transaction_start: %s\n", ldb_errstring(c))); 624 talloc_free(mem_ctx);625 735 return WERR_FOOBAR; 626 736 } … … 631 741 for (i = 0; i < res_keys->count; i++) 632 742 { 633 werr = ldb_del_key(hk, ldb_msg_find_attr_as_string( 743 werr = ldb_del_key(mem_ctx, hk, 744 ldb_msg_find_attr_as_string( 634 745 res_keys->msgs[i], 635 746 "key", NULL)); 636 747 if (!W_ERROR_IS_OK(werr)) { 637 748 ret = ldb_transaction_cancel(c); 638 talloc_free(mem_ctx);639 749 return werr; 640 750 } … … 644 754 for (i = 0; i < res_vals->count; i++) 645 755 { 646 werr = ldb_del_value(hk, ldb_msg_find_attr_as_string( 756 werr = ldb_del_value(mem_ctx, hk, 757 ldb_msg_find_attr_as_string( 647 758 res_vals->msgs[i], 648 759 "value", NULL)); 649 760 if (!W_ERROR_IS_OK(werr)) { 650 761 ret = ldb_transaction_cancel(c); 651 talloc_free(mem_ctx);652 762 return werr; 653 763 } 654 764 } 655 765 } 766 talloc_free(res_keys); 767 talloc_free(res_vals); 656 768 657 769 /* Delete the key itself */ 658 ret = ldb_delete(c, ld ap_path);770 ret = ldb_delete(c, ldb_path); 659 771 660 772 if (ret != LDB_SUCCESS) … … 662 774 DEBUG(1, ("ldb_del_key: %s\n", ldb_errstring(c))); 663 775 ret = ldb_transaction_cancel(c); 664 talloc_free(mem_ctx);665 776 return WERR_FOOBAR; 666 777 } … … 673 784 DEBUG(0, ("ldb_transaction_commit: %s\n", ldb_errstring(c))); 674 785 ret = ldb_transaction_cancel(c); 675 talloc_free(mem_ctx); 676 return WERR_FOOBAR; 677 } 678 679 talloc_free(mem_ctx); 786 return WERR_FOOBAR; 787 } 680 788 681 789 /* reset cache */ … … 692 800 struct ldb_message *msg; 693 801 struct ldb_key_data *kd = talloc_get_type(parent, struct ldb_key_data); 802 unsigned int i; 694 803 int ret; 695 804 TALLOC_CTX *mem_ctx = talloc_init("ldb_set_value"); 696 805 697 806 msg = reg_ldb_pack_value(kd->ldb, mem_ctx, name, type, data); 807 W_ERROR_HAVE_NO_MEMORY(msg); 808 698 809 msg->dn = ldb_dn_copy(msg, kd->dn); 699 700 if (strlen(name) > 0) { 810 W_ERROR_HAVE_NO_MEMORY(msg->dn); 811 812 if (name[0] != '\0') { 701 813 /* For a default value, we add/overwrite the attributes to/of the hive. 702 For a normal value, we create new childs. */814 For a normal value, we create a new child. */ 703 815 if (!ldb_dn_add_child_fmt(msg->dn, "value=%s", 704 816 reg_ldb_escape(mem_ctx, name))) … … 709 821 } 710 822 711 ret = ldb_add(kd->ldb, msg); 712 if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { 713 int i; 714 for (i = 0; i < msg->num_elements; i++) { 715 if (msg->elements[i].flags != LDB_FLAG_MOD_DELETE) 716 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; 717 } 718 ret = ldb_modify(kd->ldb, msg); 719 } 823 /* Try first a "modify" and if this doesn't work do try an "add" */ 824 for (i = 0; i < msg->num_elements; i++) { 825 if (msg->elements[i].flags != LDB_FLAG_MOD_DELETE) { 826 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; 827 } 828 } 829 ret = ldb_modify(kd->ldb, msg); 830 if (ret == LDB_ERR_NO_SUCH_OBJECT) { 831 i = 0; 832 while (i < msg->num_elements) { 833 if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) == LDB_FLAG_MOD_DELETE) { 834 ldb_msg_remove_element(msg, &msg->elements[i]); 835 } else { 836 ++i; 837 } 838 } 839 ret = ldb_add(kd->ldb, msg); 840 } 841 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) { 842 /* ignore this -> the value didn't exist and also now doesn't */ 843 ret = LDB_SUCCESS; 844 } 845 846 talloc_free(msg); 720 847 721 848 if (ret != LDB_SUCCESS) { … … 744 871 { 745 872 struct ldb_key_data *kd = talloc_get_type(key, struct ldb_key_data); 873 uint32_t default_value_type = REG_NONE; 874 DATA_BLOB default_value = { NULL, 0 }; 875 WERROR werr; 746 876 747 877 /* Initialization */ … … 761 891 *max_valbufsize = 0; 762 892 893 /* We need this to get the default value (if it exists) for counting 894 * the values under the key and for finding out the longest value buffer 895 * size. If no default value exists the DATA_BLOB "default_value" will 896 * remain { NULL, 0 }. */ 897 werr = ldb_get_default_value(mem_ctx, key, NULL, &default_value_type, 898 &default_value); 899 if ((!W_ERROR_IS_OK(werr)) && (!W_ERROR_EQUAL(werr, WERR_BADFILE))) { 900 return werr; 901 } 902 763 903 if (kd->subkeys == NULL) { 764 904 W_ERROR_NOT_OK_RETURN(cache_subkeys(kd)); 765 905 } 766 767 906 if (kd->values == NULL) { 768 907 W_ERROR_NOT_OK_RETURN(cache_values(kd)); 769 908 } 770 909 910 if (classname != NULL) { 911 *classname = kd->classname; 912 } 913 771 914 if (num_subkeys != NULL) { 772 915 *num_subkeys = kd->subkey_count; … … 774 917 if (num_values != NULL) { 775 918 *num_values = kd->value_count; 919 /* also consider the default value if it exists */ 920 if (default_value.data != NULL) { 921 ++(*num_values); 922 } 776 923 } 777 924 778 925 779 926 if (max_subkeynamelen != NULL) { 780 int i;927 unsigned int i; 781 928 struct ldb_message_element *el; 782 783 *max_subkeynamelen = 0;784 929 785 930 for (i = 0; i < kd->subkey_count; i++) { … … 790 935 791 936 if (max_valnamelen != NULL || max_valbufsize != NULL) { 792 int i;937 unsigned int i; 793 938 struct ldb_message_element *el; 794 939 W_ERROR_NOT_OK_RETURN(cache_values(kd)); 795 940 796 if (max_valbufsize != NULL)797 *max_valbufsize = 0;798 799 if (max_valnamelen != NULL)800 *max_valnamelen = 0;941 /* also consider the default value if it exists */ 942 if ((max_valbufsize != NULL) && (default_value.data != NULL)) { 943 *max_valbufsize = MAX(*max_valbufsize, 944 default_value.length); 945 } 801 946 802 947 for (i = 0; i < kd->value_count; i++) { … … 809 954 uint32_t data_type; 810 955 DATA_BLOB data; 811 reg_ldb_unpack_value(mem_ctx, 812 kd->values[i], NULL, 956 reg_ldb_unpack_value(mem_ctx, 957 kd->values[i], NULL, 813 958 &data_type, &data); 814 959 *max_valbufsize = MAX(*max_valbufsize, data.length); … … 817 962 } 818 963 } 964 965 talloc_free(default_value.data); 819 966 820 967 return WERR_OK; -
trunk/server/source4/lib/registry/local.c
r414 r745 58 58 59 59 local_key = talloc(ctx, struct local_key); 60 local_key->hive_key = talloc_steal(local_key, hive); 61 local_key->global.context = talloc_reference(local_key, ctx); 62 local_key->path = parent_path; 60 if (local_key != NULL) { 61 local_key->hive_key = talloc_reference(local_key, hive); 62 local_key->global.context = talloc_reference(local_key, ctx); 63 local_key->path = parent_path; 64 } 63 65 64 66 return (struct registry_key *)local_key; … … 71 73 struct registry_key **result) 72 74 { 73 char *orig = talloc_strdup(mem_ctx, path), 74 *curbegin = orig, 75 *curend = strchr(orig, '\\'); 75 char *orig, *curbegin, *curend; 76 76 struct local_key *local_parent = talloc_get_type(parent, 77 77 struct local_key); … … 81 81 int el; 82 82 83 if (path == NULL) { 84 return WERR_INVALID_PARAM; 85 } 86 87 orig = talloc_strdup(mem_ctx, path); 88 W_ERROR_HAVE_NO_MEMORY(orig); 89 curbegin = orig; 90 curend = strchr(orig, '\\'); 91 83 92 if (local_parent->path.elements != NULL) { 84 93 elements = talloc_array(mem_ctx, const char *, 85 94 str_list_length(local_parent->path.elements) + 1); 95 W_ERROR_HAVE_NO_MEMORY(elements); 86 96 for (el = 0; local_parent->path.elements[el] != NULL; el++) { 87 97 elements[el] = talloc_reference(elements, … … 98 108 *curend = '\0'; 99 109 elements = talloc_realloc(mem_ctx, elements, const char *, el+2); 110 W_ERROR_HAVE_NO_MEMORY(elements); 100 111 elements[el] = talloc_strdup(elements, curbegin); 112 W_ERROR_HAVE_NO_MEMORY(elements[el]); 101 113 el++; 102 114 elements[el] = NULL; … … 159 171 160 172 static WERROR local_create_key(TALLOC_CTX *mem_ctx, 161 struct registry_key *parent _key,162 const char * name,173 struct registry_key *parent, 174 const char *path, 163 175 const char *key_class, 164 176 struct security_descriptor *security, 165 struct registry_key **key) 166 { 167 struct local_key *local_parent; 168 struct hive_key *hivekey; 169 const char **elements; 170 int i; 171 const char *last_part; 172 173 last_part = strrchr(name, '\\'); 174 if (last_part == NULL) { 175 last_part = name; 176 local_parent = (struct local_key *)parent_key; 177 struct registry_key **result) 178 { 179 char *orig, *curbegin, *curend; 180 struct local_key *local_parent = talloc_get_type(parent, 181 struct local_key); 182 struct hive_key *curkey = local_parent->hive_key; 183 WERROR error; 184 const char **elements = NULL; 185 int el; 186 187 if (path == NULL) { 188 return WERR_INVALID_PARAM; 189 } 190 191 orig = talloc_strdup(mem_ctx, path); 192 W_ERROR_HAVE_NO_MEMORY(orig); 193 curbegin = orig; 194 curend = strchr(orig, '\\'); 195 196 if (local_parent->path.elements != NULL) { 197 elements = talloc_array(mem_ctx, const char *, 198 str_list_length(local_parent->path.elements) + 1); 199 W_ERROR_HAVE_NO_MEMORY(elements); 200 for (el = 0; local_parent->path.elements[el] != NULL; el++) { 201 elements[el] = talloc_reference(elements, 202 local_parent->path.elements[el]); 203 } 204 elements[el] = NULL; 177 205 } else { 178 W_ERROR_NOT_OK_RETURN(reg_open_key(mem_ctx, parent_key, 179 talloc_strndup(mem_ctx, name, last_part-name), 180 (struct registry_key **)&local_parent)); 181 last_part++; 182 } 183 184 W_ERROR_NOT_OK_RETURN(hive_key_add_name(mem_ctx, local_parent->hive_key, 185 last_part, key_class, security, 186 &hivekey)); 187 188 if (local_parent->path.elements != NULL) { 189 elements = talloc_array(hivekey, const char *, 190 str_list_length(local_parent->path.elements)+2); 191 for (i = 0; local_parent->path.elements[i] != NULL; i++) { 192 elements[i] = talloc_reference(elements, 193 local_parent->path.elements[i]); 194 } 195 } else { 196 elements = talloc_array(hivekey, const char *, 2); 197 i = 0; 198 } 199 200 elements[i] = talloc_strdup(elements, name); 201 elements[i+1] = NULL; 202 203 *key = reg_import_hive_key(local_parent->global.context, hivekey, 204 local_parent->path.predefined_key, 205 elements); 206 elements = NULL; 207 el = 0; 208 } 209 210 while (curbegin != NULL && *curbegin) { 211 if (curend != NULL) 212 *curend = '\0'; 213 elements = talloc_realloc(mem_ctx, elements, const char *, el+2); 214 W_ERROR_HAVE_NO_MEMORY(elements); 215 elements[el] = talloc_strdup(elements, curbegin); 216 W_ERROR_HAVE_NO_MEMORY(elements[el]); 217 el++; 218 elements[el] = NULL; 219 error = hive_get_key_by_name(mem_ctx, curkey, 220 curbegin, &curkey); 221 if (W_ERROR_EQUAL(error, WERR_BADFILE)) { 222 error = hive_key_add_name(mem_ctx, curkey, curbegin, 223 key_class, security, 224 &curkey); 225 } 226 if (!W_ERROR_IS_OK(error)) { 227 DEBUG(2, ("Open/Creation of key %s failed: %s\n", 228 curbegin, win_errstr(error))); 229 talloc_free(orig); 230 return error; 231 } 232 if (curend == NULL) 233 break; 234 curbegin = curend + 1; 235 curend = strchr(curbegin, '\\'); 236 } 237 talloc_free(orig); 238 239 *result = reg_import_hive_key(local_parent->global.context, curkey, 240 local_parent->path.predefined_key, 241 talloc_steal(curkey, elements)); 206 242 207 243 return WERR_OK; … … 212 248 { 213 249 struct local_key *local = (struct local_key *)key; 250 251 if (name == NULL) { 252 return WERR_INVALID_PARAM; 253 } 214 254 215 255 return hive_key_set_value(local->hive_key, name, type, data); … … 221 261 { 222 262 const struct local_key *local = (const struct local_key *)key; 263 264 if (name == NULL) { 265 return WERR_INVALID_PARAM; 266 } 223 267 224 268 return hive_get_value(mem_ctx, local->hive_key, name, type, data); … … 237 281 } 238 282 239 static WERROR local_delete_key(struct registry_key *key, const char *name) 240 { 241 const struct local_key *local = (const struct local_key *)key; 242 243 return hive_key_del(local->hive_key, name); 244 } 245 246 static WERROR local_delete_value(struct registry_key *key, const char *name) 247 { 248 const struct local_key *local = (const struct local_key *)key; 249 250 return hive_key_del_value(local->hive_key, name); 283 static WERROR local_delete_key(TALLOC_CTX *mem_ctx, struct registry_key *key, 284 const char *name) 285 { 286 const struct local_key *local = (const struct local_key *)key; 287 288 if (name == NULL) { 289 return WERR_INVALID_PARAM; 290 } 291 292 return hive_key_del(mem_ctx, local->hive_key, name); 293 } 294 295 static WERROR local_delete_value(TALLOC_CTX *mem_ctx, struct registry_key *key, 296 const char *name) 297 { 298 const struct local_key *local = (const struct local_key *)key; 299 300 if (name == NULL) { 301 return WERR_INVALID_PARAM; 302 } 303 304 return hive_key_del_value(mem_ctx, local->hive_key, name); 251 305 } 252 306 … … 328 382 struct registry_local *reg_local = talloc_get_type(rctx, 329 383 struct registry_local); 330 struct mountpoint *mp = talloc(rctx, struct mountpoint); 331 int i = 0; 332 384 struct mountpoint *mp; 385 unsigned int i = 0; 386 387 mp = talloc(rctx, struct mountpoint); 388 W_ERROR_HAVE_NO_MEMORY(mp); 333 389 mp->path.predefined_key = key_id; 334 390 mp->prev = mp->next = NULL; … … 337 393 mp->path.elements = talloc_array(mp, const char *, 338 394 str_list_length(elements)); 395 W_ERROR_HAVE_NO_MEMORY(mp->path.elements); 339 396 for (i = 0; elements[i] != NULL; i++) { 340 397 mp->path.elements[i] = talloc_reference(mp->path.elements, -
trunk/server/source4/lib/registry/man/regdiff.1.xml
r414 r745 1 1 <?xml version="1.0" encoding="iso-8859-1"?> 2 <!DOCTYPE refentry PUBLIC "-// Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> 3 3 <refentry id="regdiff.1"> 4 4 -
trunk/server/source4/lib/registry/man/regpatch.1.xml
r414 r745 1 1 <?xml version="1.0" encoding="iso-8859-1"?> 2 <!DOCTYPE refentry PUBLIC "-// Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> 3 3 <refentry id="regpatch.1"> 4 4 -
trunk/server/source4/lib/registry/man/regshell.1.xml
r414 r745 1 1 <?xml version="1.0" encoding="iso-8859-1"?> 2 <!DOCTYPE refentry PUBLIC "-// Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> 3 3 <refentry id="regshell.1"> 4 4 -
trunk/server/source4/lib/registry/man/regtree.1.xml
r414 r745 1 1 <?xml version="1.0" encoding="iso-8859-1"?> 2 <!DOCTYPE refentry PUBLIC "-// Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> 3 3 <refentry id="regtree.1"> 4 4 -
trunk/server/source4/lib/registry/patchfile.c
r414 r745 5 5 Copyright (C) Jelmer Vernooij 2004-2007 6 6 Copyright (C) Wilco Baan Hofman 2006 7 Copyright (C) Matthias Dieter Wallnöfer 2008 7 Copyright (C) Matthias Dieter Wallnöfer 2008-2010 8 8 9 9 This program is free software; you can redistribute it and/or modify … … 27 27 28 28 _PUBLIC_ WERROR reg_preg_diff_load(int fd, 29 struct smb_iconv_convenience *iconv_convenience,30 29 const struct reg_diff_callbacks *callbacks, 31 30 void *callback_data); 32 31 33 32 _PUBLIC_ WERROR reg_dotreg_diff_load(int fd, 34 struct smb_iconv_convenience *iconv_convenience,35 33 const struct reg_diff_callbacks *callbacks, 36 34 void *callback_data); … … 45 43 void *callback_data) 46 44 { 47 int i;45 unsigned int i; 48 46 struct registry_key *t1 = NULL, *t2 = NULL; 49 47 char *tmppath; … … 87 85 88 86 if (!W_ERROR_IS_OK(error2) && !W_ERROR_EQUAL(error2, WERR_BADFILE)) { 89 DEBUG(0, ("Error occur ed while getting subkey by name: %s\n",87 DEBUG(0, ("Error occurred while getting subkey by name: %s\n", 90 88 win_errstr(error2))); 91 89 talloc_free(mem_ctx); … … 96 94 /* didn't have such a subkey and therefore add a del diff */ 97 95 tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1); 96 if (tmppath == NULL) { 97 DEBUG(0, ("Out of memory\n")); 98 talloc_free(mem_ctx); 99 return WERR_NOMEM; 100 } 98 101 if (!W_ERROR_IS_OK(error2)) 99 102 callbacks->del_key(callback_data, tmppath); … … 102 105 error1 = reg_open_key(mem_ctx, oldkey, keyname1, &t1); 103 106 if (!W_ERROR_IS_OK(error1)) { 104 DEBUG(0, ("Error occur ed while getting subkey by name: %s\n",107 DEBUG(0, ("Error occurred while getting subkey by name: %s\n", 105 108 win_errstr(error1))); 106 109 talloc_free(mem_ctx); … … 155 158 } 156 159 157 /* oldkey didn't have such a subkey, add a dd diff */160 /* oldkey didn't have such a subkey, add a add diff */ 158 161 tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1); 162 if (tmppath == NULL) { 163 DEBUG(0, ("Out of memory\n")); 164 talloc_free(mem_ctx); 165 return WERR_NOMEM; 166 } 159 167 callbacks->add_key(callback_data, tmppath); 160 168 … … 162 170 error1 = reg_open_key(mem_ctx, newkey, keyname1, &t2); 163 171 if (!W_ERROR_IS_OK(error1)) { 164 DEBUG(0, ("Error occur ed while getting subkey by name: %s\n",172 DEBUG(0, ("Error occurred while getting subkey by name: %s\n", 165 173 win_errstr(error1))); 166 174 talloc_free(mem_ctx); … … 176 184 const char *name; 177 185 uint32_t type1, type2; 178 DATA_BLOB contents1 , contents2;186 DATA_BLOB contents1 = { NULL, 0 }, contents2 = { NULL, 0 }; 179 187 180 188 error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, … … 203 211 204 212 if (W_ERROR_IS_OK(error2) 205 && (data_blob_cmp(&contents1, &contents2) == 0) 206 && (type1 == type2)) 213 && (data_blob_cmp(&contents1, &contents2) == 0) 214 && (type1 == type2)) { 215 talloc_free(discard_const_p(char, name)); 216 talloc_free(contents1.data); 217 talloc_free(contents2.data); 207 218 continue; 219 } 208 220 209 221 callbacks->set_value(callback_data, path, name, 210 222 type1, contents1); 223 224 talloc_free(discard_const_p(char, name)); 225 talloc_free(contents1.data); 226 talloc_free(contents2.data); 211 227 } 212 228 … … 215 231 const char *name; 216 232 uint32_t type; 217 DATA_BLOB contents ;233 DATA_BLOB contents = { NULL, 0 }; 218 234 219 235 error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &name, … … 232 248 error2 = WERR_BADFILE; 233 249 234 if (W_ERROR_IS_OK(error2)) 250 if (W_ERROR_IS_OK(error2)) { 251 talloc_free(discard_const_p(char, name)); 252 talloc_free(contents.data); 235 253 continue; 254 } 236 255 237 256 if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) { … … 243 262 244 263 callbacks->del_value(callback_data, path, name); 264 265 talloc_free(discard_const_p(char, name)); 266 talloc_free(contents.data); 245 267 } 246 268 … … 257 279 void *callback_data) 258 280 { 259 int i;281 unsigned int i; 260 282 WERROR error; 261 283 … … 281 303 } 282 304 305 /* if "r1" is NULL (old hive) and "r2" isn't (new hive) then 306 * the hive doesn't exist yet and we have to generate an add 307 * diff */ 308 if ((r1 == NULL) && (r2 != NULL)) { 309 callbacks->add_key(callback_data, 310 reg_predefined_keys[i].name); 311 } 312 /* if "r1" isn't NULL (old hive) and "r2" is (new hive) then 313 * the hive shouldn't exist anymore and we have to generate a 314 * del diff */ 315 if ((r1 != NULL) && (r2 == NULL)) { 316 callbacks->del_key(callback_data, 317 reg_predefined_keys[i].name); 318 } 319 283 320 error = reg_generate_diff_key(r1, r2, 284 321 reg_predefined_keys[i].name, callbacks, … … 300 337 */ 301 338 _PUBLIC_ WERROR reg_diff_load(const char *filename, 302 struct smb_iconv_convenience *iconv_convenience,303 339 const struct reg_diff_callbacks *callbacks, 304 340 void *callback_data) … … 334 370 if (strncmp(hdr, "PReg", 4) == 0) { 335 371 /* Must be a GPO Registry.pol file */ 336 return reg_preg_diff_load(fd, iconv_convenience,callbacks, callback_data);372 return reg_preg_diff_load(fd, callbacks, callback_data); 337 373 } else { 338 374 /* Must be a normal .REG file */ 339 return reg_dotreg_diff_load(fd, iconv_convenience,callbacks, callback_data);375 return reg_dotreg_diff_load(fd, callbacks, callback_data); 340 376 } 341 377 } … … 353 389 /* Recursively create the path */ 354 390 buf = talloc_strdup(ctx, key_name); 391 W_ERROR_HAVE_NO_MEMORY(buf); 355 392 buf_ptr = buf; 356 393 … … 367 404 } 368 405 *buf_ptr++ = '\\'; 369 } 370 } 406 talloc_free(tmp); 407 } 408 } 409 410 talloc_free(buf); 371 411 372 412 /* Add the key */ … … 379 419 return error; 380 420 } 421 talloc_free(tmp); 422 381 423 return WERR_OK; 382 424 } … … 388 430 /* We can't proof here for success, because a common superkey could */ 389 431 /* have been deleted before the subkey's (diff order). This removed */ 390 /* therefore all child srecursively and the "WERR_BADFILE" result is */432 /* therefore all children recursively and the "WERR_BADFILE" result is */ 391 433 /* expected. */ 392 434 … … 420 462 } 421 463 464 talloc_free(tmp); 465 422 466 return WERR_OK; 423 467 } … … 438 482 } 439 483 440 error = reg_del_value( tmp, value_name);484 error = reg_del_value(ctx, tmp, value_name); 441 485 if (!W_ERROR_IS_OK(error)) { 442 486 DEBUG(0, ("Error deleting value '%s'\n", value_name)); … … 444 488 } 445 489 490 talloc_free(tmp); 446 491 447 492 return WERR_OK; … … 453 498 struct registry_key *key; 454 499 WERROR error; 455 const char *value_name;500 const char *value_name; 456 501 457 502 error = reg_open_key_abs(ctx, ctx, key_name, &key); … … 467 512 while (W_ERROR_IS_OK(reg_key_get_value_by_index( 468 513 ctx, key, 0, &value_name, NULL, NULL))) { 469 error = reg_del_value( key, value_name);514 error = reg_del_value(ctx, key, value_name); 470 515 if (!W_ERROR_IS_OK(error)) { 471 516 DEBUG(0, ("Error deleting value '%s'\n", value_name)); 472 517 return error; 473 518 } 474 } 519 talloc_free(discard_const_p(char, value_name)); 520 } 521 522 talloc_free(key); 475 523 476 524 return WERR_OK; … … 481 529 */ 482 530 _PUBLIC_ WERROR reg_diff_apply(struct registry_context *ctx, 483 struct smb_iconv_convenience *iconv_convenience,484 531 const char *filename) 485 532 { … … 493 540 callbacks.done = NULL; 494 541 495 return reg_diff_load(filename, iconv_convenience, 496 &callbacks, ctx); 497 } 542 return reg_diff_load(filename, &callbacks, ctx); 543 } -
trunk/server/source4/lib/registry/patchfile_dotreg.c
r414 r745 4 4 5 5 Copyright (C) Jelmer Vernooij 2004-2007 6 Copyright (C) Wilco Baan Hofman 2006-20 086 Copyright (C) Wilco Baan Hofman 2006-2010 7 7 8 8 This program is free software; you can redistribute it and/or modify … … 21 21 */ 22 22 23 /* FIXME Newer .REG files, created by Windows XP and above use unicode UCS-2 */ 23 /* FIXME: 24 * - Newer .REG files, created by Windows XP and above use unicode UCS-2 25 * - @="" constructions should write value with empty name. 26 */ 24 27 25 28 #include "includes.h" … … 36 39 struct dotreg_data { 37 40 int fd; 38 struct smb_iconv_convenience *iconv_convenience;39 41 }; 42 43 /* 44 * This is basically a copy of data_blob_hex_string_upper, but with comma's 45 * between the bytes in hex. 46 */ 47 static char *dotreg_data_blob_hex_string(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob) 48 { 49 size_t i; 50 char *hex_string; 51 52 hex_string = talloc_array(mem_ctx, char, (blob->length*3)+1); 53 if (!hex_string) { 54 return NULL; 55 } 56 57 for (i = 0; i < blob->length; i++) 58 slprintf(&hex_string[i*3], 4, "%02X,", blob->data[i]); 59 60 /* Remove last comma and NULL-terminate the string */ 61 hex_string[(blob->length*3)-1] = '\0'; 62 return hex_string; 63 } 64 65 /* 66 * This is basically a copy of reg_val_data_string, except that this function 67 * has no 0x for dwords, everything else is regarded as binary, and binary 68 * strings are represented with bytes comma-separated. 69 */ 70 static char *reg_val_dotreg_string(TALLOC_CTX *mem_ctx, uint32_t type, 71 const DATA_BLOB data) 72 { 73 char *ret = NULL; 74 75 if (data.length == 0) 76 return talloc_strdup(mem_ctx, ""); 77 78 switch (type) { 79 case REG_EXPAND_SZ: 80 case REG_SZ: 81 convert_string_talloc(mem_ctx, 82 CH_UTF16, CH_UNIX, data.data, data.length, 83 (void **)&ret, NULL, false); 84 break; 85 case REG_DWORD: 86 case REG_DWORD_BIG_ENDIAN: 87 SMB_ASSERT(data.length == sizeof(uint32_t)); 88 ret = talloc_asprintf(mem_ctx, "%08x", 89 IVAL(data.data, 0)); 90 break; 91 default: /* default means treat as binary */ 92 case REG_BINARY: 93 ret = dotreg_data_blob_hex_string(mem_ctx, &data); 94 break; 95 } 96 97 return ret; 98 } 40 99 41 100 static WERROR reg_dotreg_diff_add_key(void *_data, const char *key_name) … … 62 121 { 63 122 struct dotreg_data *data = (struct dotreg_data *)_data; 64 65 fdprintf(data->fd, "\"%s\"=%s:%s\n", 66 value_name, str_regtype(value_type), 67 reg_val_data_string(NULL, data->iconv_convenience, value_type, value)); 123 char *data_string = reg_val_dotreg_string(NULL, 124 value_type, value); 125 char *data_incl_type; 126 127 W_ERROR_HAVE_NO_MEMORY(data_string); 128 129 switch (value_type) { 130 case REG_SZ: 131 data_incl_type = talloc_asprintf(data_string, "\"%s\"", 132 data_string); 133 break; 134 case REG_DWORD: 135 data_incl_type = talloc_asprintf(data_string, 136 "dword:%s", data_string); 137 break; 138 case REG_BINARY: 139 data_incl_type = talloc_asprintf(data_string, "hex:%s", 140 data_string); 141 break; 142 default: 143 data_incl_type = talloc_asprintf(data_string, "hex(%x):%s", 144 value_type, data_string); 145 break; 146 } 147 148 if (value_name[0] == '\0') { 149 fdprintf(data->fd, "@=%s\n", data_incl_type); 150 } else { 151 fdprintf(data->fd, "\"%s\"=%s\n", 152 value_name, data_incl_type); 153 } 154 155 talloc_free(data_string); 68 156 69 157 return WERR_OK; … … 100 188 */ 101 189 _PUBLIC_ WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename, 102 struct smb_iconv_convenience *iconv_convenience,103 190 struct reg_diff_callbacks **callbacks, 104 191 void **callback_data) … … 108 195 data = talloc_zero(ctx, struct dotreg_data); 109 196 *callback_data = data; 110 111 data->iconv_convenience = iconv_convenience;112 197 113 198 if (filename) { … … 139 224 */ 140 225 _PUBLIC_ WERROR reg_dotreg_diff_load(int fd, 141 struct smb_iconv_convenience *iconv_convenience,142 226 const struct reg_diff_callbacks *callbacks, 143 227 void *callback_data) … … 148 232 WERROR error; 149 233 uint32_t value_type; 150 DATA_BLOB value; 234 DATA_BLOB data; 235 bool result; 236 char *type_str = NULL; 237 char *data_str; 238 char *value; 239 bool continue_next_line = 0; 151 240 152 241 line = afdgets(fd, mem_ctx, 0); … … 159 248 160 249 while ((line = afdgets(fd, mem_ctx, 0))) { 250 /* Remove '\r' if it's a Windows text file */ 251 if (line[strlen(line)-1] == '\r') { 252 line[strlen(line)-1] = '\0'; 253 } 254 161 255 /* Ignore comments and empty lines */ 162 256 if (strlen(line) == 0 || line[0] == ';') { … … 172 266 /* Start of key */ 173 267 if (line[0] == '[') { 174 p = strchr_m(line, ']'); 175 if (p[strlen(p)-1] != ']') { 176 DEBUG(0, ("Missing ']'\n")); 177 return WERR_GENERAL_FAILURE; 178 } 268 if (line[strlen(line)-1] != ']') { 269 DEBUG(0, ("Missing ']' on line: %s\n", line)); 270 talloc_free(line); 271 continue; 272 } 273 179 274 /* Deleting key */ 180 275 if (line[1] == '-') { 181 276 curkey = talloc_strndup(line, line+2, strlen(line)-3); 277 W_ERROR_HAVE_NO_MEMORY(curkey); 182 278 183 279 error = callbacks->del_key(callback_data, 184 280 curkey); 281 185 282 if (!W_ERROR_IS_OK(error)) { 186 283 DEBUG(0,("Error deleting key %s\n", … … 195 292 } 196 293 curkey = talloc_strndup(mem_ctx, line+1, strlen(line)-2); 294 W_ERROR_HAVE_NO_MEMORY(curkey); 197 295 198 296 error = callbacks->add_key(callback_data, curkey); … … 208 306 209 307 /* Deleting/Changing value */ 210 p = strchr_m(line, '='); 211 if (p == NULL) { 212 DEBUG(0, ("Malformed line\n")); 213 talloc_free(line); 214 continue; 215 } 216 217 *p = '\0'; p++; 218 219 if (curkey == NULL) { 220 DEBUG(0, ("Value change without key\n")); 221 talloc_free(line); 222 continue; 223 } 224 225 /* Delete value */ 226 if (strcmp(p, "-") == 0) { 227 error = callbacks->del_value(callback_data, 228 curkey, line); 229 if (!W_ERROR_IS_OK(error)) { 230 DEBUG(0, ("Error deleting value %s in key %s\n", 231 line, curkey)); 232 talloc_free(mem_ctx); 233 return error; 234 } 235 236 talloc_free(line); 237 continue; 238 } 239 240 q = strchr_m(p, ':'); 241 if (q) { 242 *q = '\0'; 243 q++; 244 } 245 246 reg_string_to_val(line, iconv_convenience, 247 q?p:"REG_SZ", q?q:p, 248 &value_type, &value); 249 250 error = callbacks->set_value(callback_data, curkey, line, 251 value_type, value); 308 if (continue_next_line) { 309 continue_next_line = 0; 310 311 /* Continued data start with two whitespaces */ 312 if (line[0] != ' ' || line[1] != ' ') { 313 DEBUG(0, ("Malformed line: %s\n", line)); 314 talloc_free(line); 315 continue; 316 } 317 p = line + 2; 318 319 /* Continue again if line ends with a backslash */ 320 if (line[strlen(line)-1] == '\\') { 321 line[strlen(line)-1] = '\0'; 322 continue_next_line = 1; 323 data_str = talloc_strdup_append(data_str, p); 324 talloc_free(line); 325 continue; 326 } 327 data_str = talloc_strdup_append(data_str, p); 328 } else { 329 p = strchr_m(line, '='); 330 if (p == NULL) { 331 DEBUG(0, ("Malformed line: %s\n", line)); 332 talloc_free(line); 333 continue; 334 } 335 336 *p = '\0'; p++; 337 338 339 if (curkey == NULL) { 340 DEBUG(0, ("Value change without key\n")); 341 talloc_free(line); 342 continue; 343 } 344 345 /* Values should be double-quoted */ 346 if (line[0] != '"') { 347 DEBUG(0, ("Malformed line\n")); 348 talloc_free(line); 349 continue; 350 } 351 352 /* Chop of the quotes and store as value */ 353 value = talloc_strndup(mem_ctx, line+1,strlen(line)-2); 354 355 /* Delete value */ 356 if (p[0] == '-') { 357 error = callbacks->del_value(callback_data, 358 curkey, value); 359 360 /* Ignore if key does not exist (WERR_BADFILE) 361 * Consistent with Windows behaviour */ 362 if (!W_ERROR_IS_OK(error) && 363 !W_ERROR_EQUAL(error, WERR_BADFILE)) { 364 DEBUG(0, ("Error deleting value %s in key %s\n", 365 value, curkey)); 366 talloc_free(mem_ctx); 367 return error; 368 } 369 370 talloc_free(line); 371 talloc_free(value); 372 continue; 373 } 374 375 /* Do not look for colons in strings */ 376 if (p[0] == '"') { 377 q = NULL; 378 data_str = talloc_strndup(mem_ctx, p+1,strlen(p)-2); 379 } else { 380 /* Split the value type from the data */ 381 q = strchr_m(p, ':'); 382 if (q) { 383 *q = '\0'; 384 q++; 385 type_str = talloc_strdup(mem_ctx, p); 386 data_str = talloc_strdup(mem_ctx, q); 387 } else { 388 data_str = talloc_strdup(mem_ctx, p); 389 } 390 } 391 392 /* Backslash before the CRLF means continue on next line */ 393 if (data_str[strlen(data_str)-1] == '\\') { 394 data_str[strlen(data_str)-1] = '\0'; 395 talloc_free(line); 396 continue_next_line = 1; 397 continue; 398 } 399 } 400 DEBUG(9, ("About to write %s with type %s, length %ld: %s\n", value, type_str, (long) strlen(data_str), data_str)); 401 result = reg_string_to_val(value, 402 type_str?type_str:"REG_SZ", data_str, 403 &value_type, &data); 404 if (!result) { 405 DEBUG(0, ("Error converting string to value for line:\n%s\n", 406 line)); 407 return WERR_GENERAL_FAILURE; 408 } 409 410 error = callbacks->set_value(callback_data, curkey, value, 411 value_type, data); 252 412 if (!W_ERROR_IS_OK(error)) { 253 413 DEBUG(0, ("Error setting value for %s in %s\n", 254 line, curkey));414 value, curkey)); 255 415 talloc_free(mem_ctx); 256 416 return error; 257 417 } 258 418 419 /* Clean up buffers */ 420 if (type_str != NULL) { 421 talloc_free(type_str); 422 type_str = NULL; 423 } 424 talloc_free(data_str); 425 talloc_free(value); 259 426 talloc_free(line); 260 427 } … … 262 429 close(fd); 263 430 264 return WERR_OK; 265 } 431 talloc_free(mem_ctx); 432 433 return WERR_OK; 434 } -
trunk/server/source4/lib/registry/patchfile_preg.c
r414 r745 34 34 uint16_t v; 35 35 36 if (read(fd, &v, 2) < 2) {36 if (read(fd, &v, sizeof(uint16_t)) < sizeof(uint16_t)) { 37 37 return WERR_GENERAL_FAILURE; 38 38 } … … 42 42 static WERROR preg_write_utf16(int fd, const char *string) 43 43 { 44 codepoint_t v; 45 uint16_t i; 46 size_t size; 44 uint16_t v; 45 size_t i, size; 47 46 48 47 for (i = 0; i < strlen(string); i+=size) { 49 48 v = next_codepoint(&string[i], &size); 50 if (write(fd, &v, 2) < 2) {49 if (write(fd, &v, sizeof(uint16_t)) < sizeof(uint16_t)) { 51 50 return WERR_GENERAL_FAILURE; 52 51 } … … 89 88 char *parent_name; 90 89 DATA_BLOB blob; 91 92 parent_name = talloc_strndup(data->ctx, key_name, strrchr(key_name, '\\')-key_name); 93 blob.data = (uint8_t *)talloc_strndup(data->ctx, key_name+(strrchr(key_name, '\\')-key_name)+1, 94 strlen(key_name)-(strrchr(key_name, '\\')-key_name)); 90 WERROR werr; 91 92 parent_name = talloc_strndup(data->ctx, key_name, 93 strrchr(key_name, '\\')-key_name); 94 W_ERROR_HAVE_NO_MEMORY(parent_name); 95 blob.data = (uint8_t*)talloc_strndup(data->ctx, 96 key_name+(strrchr(key_name, '\\')-key_name)+1, 97 strlen(key_name)-(strrchr(key_name, '\\')-key_name)); 98 W_ERROR_HAVE_NO_MEMORY(blob.data); 95 99 blob.length = strlen((char *)blob.data)+1; 96 100 97 101 98 102 /* FIXME: These values should be accumulated to be written at done(). */ 99 return reg_preg_diff_set_value(data, parent_name, "**DeleteKeys", REG_SZ, blob); 103 werr = reg_preg_diff_set_value(data, parent_name, "**DeleteKeys", 104 REG_SZ, blob); 105 106 talloc_free(parent_name); 107 talloc_free(blob.data); 108 109 return werr; 100 110 } 101 111 … … 106 116 char *val; 107 117 DATA_BLOB blob; 118 WERROR werr; 108 119 109 120 val = talloc_asprintf(data->ctx, "**Del.%s", value_name); 110 121 W_ERROR_HAVE_NO_MEMORY(val); 111 122 blob.data = (uint8_t *)talloc(data->ctx, uint32_t); 112 *(uint32_t *)blob.data = 0; 113 blob.length = 4; 114 return reg_preg_diff_set_value(data, key_name, val, REG_DWORD, blob); 123 W_ERROR_HAVE_NO_MEMORY(blob.data); 124 SIVAL(blob.data, 0, 0); 125 blob.length = sizeof(uint32_t); 126 127 werr = reg_preg_diff_set_value(data, key_name, val, REG_DWORD, blob); 128 129 talloc_free(val); 130 talloc_free(blob.data); 131 132 return werr; 115 133 } 116 134 … … 119 137 struct preg_data *data = (struct preg_data *)_data; 120 138 DATA_BLOB blob; 139 WERROR werr; 121 140 122 141 blob.data = (uint8_t *)talloc(data->ctx, uint32_t); 123 *(uint32_t *)blob.data = 0; 124 blob.length = 4; 125 126 return reg_preg_diff_set_value(data, key_name, "**DelVals.", REG_DWORD, blob); 142 W_ERROR_HAVE_NO_MEMORY(blob.data); 143 SIVAL(blob.data, 0, 0); 144 blob.length = sizeof(uint32_t); 145 146 werr = reg_preg_diff_set_value(data, key_name, "**DelVals.", REG_DWORD, 147 blob); 148 149 talloc_free(blob.data); 150 151 return werr; 127 152 } 128 153 … … 140 165 */ 141 166 _PUBLIC_ WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename, 142 struct smb_iconv_convenience *ic,143 167 struct reg_diff_callbacks **callbacks, 144 168 void **callback_data) … … 165 189 166 190 strncpy(preg_header.hdr, "PReg", 4); 167 SIVAL(&preg_header , 4, 1);168 write(data->fd, (uint8_t *)&preg_header, 8);191 SIVAL(&preg_header.version, 0, 1); 192 write(data->fd, (uint8_t *)&preg_header, sizeof(preg_header)); 169 193 170 194 data->ctx = ctx; … … 185 209 */ 186 210 _PUBLIC_ WERROR reg_preg_diff_load(int fd, 187 struct smb_iconv_convenience *iconv_convenience,188 211 const struct reg_diff_callbacks *callbacks, 189 212 void *callback_data) … … 206 229 207 230 /* Read first 8 bytes (the header) */ 208 if (read(fd, &preg_header, 8) != 8) {231 if (read(fd, &preg_header, sizeof(preg_header)) != sizeof(preg_header)) { 209 232 DEBUG(0, ("Could not read PReg file: %s\n", 210 233 strerror(errno))); … … 255 278 256 279 /* Get the type */ 257 if (read(fd, &value_type, 4) < 4) {280 if (read(fd, &value_type, sizeof(uint32_t)) < sizeof(uint32_t)) { 258 281 DEBUG(0, ("Error while reading PReg\n")); 259 282 ret = WERR_GENERAL_FAILURE; … … 270 293 goto cleanup; 271 294 } 295 272 296 /* Get data length */ 273 if (read(fd, &length, 4) < 4) {297 if (read(fd, &length, sizeof(uint32_t)) < sizeof(uint32_t)) { 274 298 DEBUG(0, ("Error while reading PReg\n")); 275 299 ret = WERR_GENERAL_FAILURE; 276 300 goto cleanup; 277 301 } 302 length = IVAL(&length, 0); 303 278 304 /* Read past delimiter */ 279 305 buf_ptr = buf; … … 284 310 goto cleanup; 285 311 } 312 286 313 /* Get the data */ 287 314 buf_ptr = buf; -
trunk/server/source4/lib/registry/pyregistry.c
r414 r745 3 3 Samba utility functions 4 4 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 5 Copyright (C) Wilco Baan Hofman <wilco@baanhofman.nl> 2010 5 6 6 7 This program is free software; you can redistribute it and/or modify … … 18 19 */ 19 20 21 #include <Python.h> 20 22 #include "includes.h" 21 #include <tevent.h>22 #include <Python.h>23 23 #include "libcli/util/pyerrors.h" 24 24 #include "lib/registry/registry.h" 25 #include " scripting/python/modules.h" /* for py_iconv_convenience() */26 #include <pytalloc.h>25 #include "lib/talloc/pytalloc.h" 26 #include "lib/events/events.h" 27 27 #include "auth/credentials/pycredentials.h" 28 28 #include "param/pyparam.h" 29 29 30 #ifndef Py_RETURN_NONE 31 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None 32 #endif 33 34 PyAPI_DATA(PyTypeObject) PyRegistryKey; 35 PyAPI_DATA(PyTypeObject) PyRegistry; 36 PyAPI_DATA(PyTypeObject) PyHiveKey; 30 extern PyTypeObject PyRegistryKey; 31 extern PyTypeObject PyRegistry; 32 extern PyTypeObject PyHiveKey; 37 33 38 34 /*#define PyRegistryKey_AsRegistryKey(obj) py_talloc_get_type(obj, struct registry_key)*/ … … 96 92 return NULL; 97 93 98 result = reg_diff_apply(ctx, py_iconv_convenience(NULL),filename);94 result = reg_diff_apply(ctx, filename); 99 95 PyErr_WERROR_IS_ERR_RAISE(result); 100 96 … … 164 160 .tp_new = registry_new, 165 161 .tp_basicsize = sizeof(py_talloc_Object), 166 .tp_dealloc = py_talloc_dealloc,167 162 .tp_flags = Py_TPFLAGS_DEFAULT, 168 163 }; … … 177 172 return NULL; 178 173 179 result = hive_key_del( key, name);174 result = hive_key_del(NULL, key, name); 180 175 181 176 PyErr_WERROR_IS_ERR_RAISE(result); … … 204 199 return NULL; 205 200 206 result = hive_key_del_value( key, name);201 result = hive_key_del_value(NULL, key, name); 207 202 208 203 PyErr_WERROR_IS_ERR_RAISE(result); … … 225 220 result = hive_key_set_value(key, name, type, value); 226 221 else 227 result = hive_key_del_value( key, name);222 result = hive_key_del_value(NULL, key, name); 228 223 229 224 PyErr_WERROR_IS_ERR_RAISE(result); … … 244 239 }; 245 240 246 static PyObject *hive_open(PyTypeObject *type, PyObject *args, PyObject *kwargs) 247 { 248 /* reg_open_hive */ 241 static PyObject *hive_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { 249 242 Py_RETURN_NONE; 243 } 244 245 static PyObject *py_open_hive(PyTypeObject *type, PyObject *args, PyObject *kwargs) 246 { 247 const char *kwnames[] = { "location", "lp_ctx", "session_info", "credentials", NULL }; 248 WERROR result; 249 struct loadparm_context *lp_ctx; 250 PyObject *py_lp_ctx, *py_session_info, *py_credentials; 251 struct auth_session_info *session_info; 252 struct cli_credentials *credentials; 253 char *location; 254 struct hive_key *hive_key; 255 TALLOC_CTX *mem_ctx; 256 257 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOO", 258 discard_const_p(char *, kwnames), 259 &location, 260 &py_lp_ctx, &py_session_info, 261 &py_credentials)) 262 return NULL; 263 264 mem_ctx = talloc_new(NULL); 265 if (mem_ctx == NULL) { 266 PyErr_NoMemory(); 267 return NULL; 268 } 269 270 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx); 271 if (lp_ctx == NULL) { 272 PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); 273 talloc_free(mem_ctx); 274 return NULL; 275 } 276 277 credentials = cli_credentials_from_py_object(py_credentials); 278 if (credentials == NULL) { 279 PyErr_SetString(PyExc_TypeError, "Expected credentials"); 280 talloc_free(mem_ctx); 281 return NULL; 282 } 283 session_info = NULL; 284 285 result = reg_open_hive(NULL, location, session_info, credentials, 286 tevent_context_init(NULL), 287 lp_ctx, &hive_key); 288 talloc_free(mem_ctx); 289 PyErr_WERROR_IS_ERR_RAISE(result); 290 291 return py_talloc_steal(&PyHiveKey, hive_key); 250 292 } 251 293 … … 253 295 .tp_name = "HiveKey", 254 296 .tp_methods = hive_key_methods, 255 .tp_new = hive_ open,297 .tp_new = hive_new, 256 298 .tp_basicsize = sizeof(py_talloc_Object), 257 .tp_dealloc = py_talloc_dealloc,258 299 .tp_flags = Py_TPFLAGS_DEFAULT, 259 300 }; … … 262 303 .tp_name = "RegistryKey", 263 304 .tp_basicsize = sizeof(py_talloc_Object), 264 .tp_dealloc = py_talloc_dealloc,265 305 .tp_flags = Py_TPFLAGS_DEFAULT, 266 306 }; … … 271 311 struct registry_context *reg_ctx; 272 312 WERROR result; 273 313 struct loadparm_context *lp_ctx; 274 314 PyObject *py_lp_ctx, *py_session_info, *py_credentials; 275 315 struct auth_session_info *session_info; 276 struct cli_credentials *credentials; 277 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO", discard_const_p(char *, kwnames), 278 &py_lp_ctx, &py_session_info, &py_credentials)) 279 return NULL; 280 281 lp_ctx = lp_from_py_object(py_lp_ctx); 282 if (lp_ctx == NULL) { 316 struct cli_credentials *credentials; 317 TALLOC_CTX *mem_ctx; 318 319 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO", 320 discard_const_p(char *, kwnames), 321 &py_lp_ctx, &py_session_info, 322 &py_credentials)) 323 return NULL; 324 325 mem_ctx = talloc_new(NULL); 326 if (mem_ctx == NULL) { 327 PyErr_NoMemory(); 328 return NULL; 329 } 330 331 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx); 332 if (lp_ctx == NULL) { 283 333 PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); 284 return NULL; 285 } 334 talloc_free(mem_ctx); 335 return NULL; 336 } 286 337 287 338 credentials = cli_credentials_from_py_object(py_credentials); 288 339 if (credentials == NULL) { 289 340 PyErr_SetString(PyExc_TypeError, "Expected credentials"); 341 talloc_free(mem_ctx); 290 342 return NULL; 291 343 } … … 295 347 result = reg_open_samba(NULL, ®_ctx, NULL, 296 348 lp_ctx, session_info, credentials); 349 talloc_free(mem_ctx); 297 350 if (!W_ERROR_IS_OK(result)) { 298 351 PyErr_SetWERROR(result); 299 352 return NULL; 300 353 } 301 354 302 355 return py_talloc_steal(&PyRegistry, reg_ctx); 303 356 } … … 339 392 WERROR result; 340 393 char *location; 341 342 394 struct loadparm_context *lp_ctx; 395 struct cli_credentials *credentials; 343 396 struct hive_key *key; 344 397 struct auth_session_info *session_info; 398 TALLOC_CTX *mem_ctx; 345 399 346 400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOO", 347 discard_const_p(char *, kwnames), 348 &location, 349 &py_session_info, &py_credentials, 350 &py_lp_ctx)) 351 return NULL; 352 353 lp_ctx = lp_from_py_object(py_lp_ctx); 354 if (lp_ctx == NULL) { 401 discard_const_p(char *, kwnames), 402 &location, &py_session_info, 403 &py_credentials, &py_lp_ctx)) 404 return NULL; 405 406 mem_ctx = talloc_new(NULL); 407 if (mem_ctx == NULL) { 408 PyErr_NoMemory(); 409 return NULL; 410 } 411 412 lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx); 413 if (lp_ctx == NULL) { 355 414 PyErr_SetString(PyExc_TypeError, "Expected loadparm context"); 356 return NULL; 357 } 415 talloc_free(mem_ctx); 416 return NULL; 417 } 358 418 359 419 credentials = cli_credentials_from_py_object(py_credentials); 360 420 if (credentials == NULL) { 361 421 PyErr_SetString(PyExc_TypeError, "Expected credentials"); 422 talloc_free(mem_ctx); 362 423 return NULL; 363 424 } … … 366 427 367 428 result = reg_open_ldb_file(NULL, location, session_info, credentials, 368 tevent_context_init(NULL), lp_ctx, &key); 429 s4_event_context_init(NULL), lp_ctx, &key); 430 talloc_free(mem_ctx); 369 431 PyErr_WERROR_IS_ERR_RAISE(result); 370 432 … … 401 463 { "create_directory", py_create_directory, METH_VARARGS, "create_dir(location) -> key" }, 402 464 { "open_ldb", (PyCFunction)py_open_ldb_file, METH_VARARGS|METH_KEYWORDS, "open_ldb(location, session_info=None, credentials=None, loadparm_context=None) -> key" }, 465 { "open_hive", (PyCFunction)py_open_hive, METH_VARARGS|METH_KEYWORDS, "open_hive(location, session_info=None, credentials=None, loadparm_context=None) -> key" }, 403 466 { "str_regtype", py_str_regtype, METH_VARARGS, "str_regtype(int) -> str" }, 404 467 { "get_predef_name", py_get_predef_name, METH_VARARGS, "get_predef_name(hkey) -> str" }, … … 409 472 { 410 473 PyObject *m; 474 PyTypeObject *talloc_type = PyTalloc_GetObjectType(); 475 476 if (talloc_type == NULL) 477 return; 478 479 PyHiveKey.tp_base = talloc_type; 480 PyRegistry.tp_base = talloc_type; 481 PyRegistryKey.tp_base = talloc_type; 411 482 412 483 if (PyType_Ready(&PyHiveKey) < 0) -
trunk/server/source4/lib/registry/regf.c
r414 r745 3 3 Registry backend for REGF files 4 4 Copyright (C) 2005-2007 Jelmer Vernooij, jelmer@samba.org 5 Copyright (C) 2006 Wilco Baan Hofman, wilco@baanhofman.nl5 Copyright (C) 2006-2010 Wilco Baan Hofman, wilco@baanhofman.nl 6 6 7 7 This program is free software; you can redistribute it and/or modify … … 50 50 struct hbin_block **hbins; 51 51 struct regf_hdr *header; 52 struct smb_iconv_convenience *iconv_convenience;52 time_t last_write; 53 53 }; 54 54 55 static WERROR regf_save_hbin(struct regf_data *data );55 static WERROR regf_save_hbin(struct regf_data *data, bool flush); 56 56 57 57 struct regf_key_data { … … 65 65 uint32_t offset, uint32_t *rel_offset) 66 66 { 67 int i;67 unsigned int i; 68 68 69 69 for (i = 0; data->hbins[i]; i++) { … … 87 87 { 88 88 uint32_t checksum = 0, x; 89 int i;89 unsigned int i; 90 90 91 91 for (i = 0; i < 0x01FB; i+= 4) { … … 112 112 113 113 if (hbin == NULL) { 114 DEBUG(1, ("Can't find HBIN containing0x%04x\n", offset));114 DEBUG(1, ("Can't find HBIN at 0x%04x\n", offset)); 115 115 return ret; 116 116 } … … 135 135 TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p) 136 136 { 137 struct tdr_pull *pull = tdr_pull_init(regf , regf->iconv_convenience);137 struct tdr_pull *pull = tdr_pull_init(regf); 138 138 139 139 pull->data = hbin_get(regf, offset); … … 160 160 { 161 161 DATA_BLOB ret; 162 uint32_t rel_offset = -1; /* Relative offset ! */162 uint32_t rel_offset = (uint32_t) -1; /* Relative offset ! */ 163 163 struct hbin_block *hbin = NULL; 164 int i;164 unsigned int i; 165 165 166 166 *offset = 0; … … 218 218 DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n", 219 219 size)); 220 221 /* Add extra hbin block */ 220 222 data->hbins = talloc_realloc(data, data->hbins, 221 223 struct hbin_block *, i+2); … … 226 228 data->hbins[i+1] = NULL; 227 229 230 /* Set hbin data */ 228 231 hbin->HBIN_ID = talloc_strdup(hbin, "hbin"); 229 232 hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next); 230 233 hbin->offset_to_next = 0x1000; 231 234 hbin->unknown[0] = 0; 232 hbin->unknown[ 0] = 0;235 hbin->unknown[1] = 0; 233 236 unix_to_nt_time(&hbin->last_change, time(NULL)); 234 237 hbin->block_size = hbin->offset_to_next; 235 238 hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20); 236 239 /* Update the regf header */ 240 data->header->last_block += hbin->offset_to_next; 241 242 /* Set the next block to it's proper size and set the 243 * rel_offset for this block */ 244 SIVAL(hbin->data, size, hbin->block_size - size - 0x20); 237 245 rel_offset = 0x0; 238 SIVAL(hbin->data, size, hbin->block_size - size - 0x20);239 246 } 240 247 … … 262 269 memcpy(dest.data, blob.data, blob.length); 263 270 271 /* Make sure that we have no tailing garbage in the block */ 272 if (dest.length > blob.length) { 273 memset(dest.data + blob.length, 0, dest.length - blob.length); 274 } 275 264 276 return ret; 265 277 } … … 268 280 tdr_push_fn_t push_fn, void *p) 269 281 { 270 struct tdr_push *push = tdr_push_init(data , data->iconv_convenience);282 struct tdr_push *push = tdr_push_init(data); 271 283 uint32_t ret; 272 284 … … 311 323 312 324 /* If the next block is free, merge into big free block */ 313 if (rel_offset + size < hbin->offset_to_next ) {325 if (rel_offset + size < hbin->offset_to_next - 0x20) { 314 326 next_size = IVALS(hbin->data, rel_offset+size); 315 327 if (next_size > 0) { … … 336 348 int32_t needed_size; 337 349 int32_t possible_size; 338 int i;350 unsigned int i; 339 351 340 352 SMB_ASSERT(orig_offset > 0); … … 395 407 uint32_t orig_offset, void *p) 396 408 { 397 struct tdr_push *push = tdr_push_init(regf , regf->iconv_convenience);409 struct tdr_push *push = tdr_push_init(regf); 398 410 uint32_t ret; 399 411 … … 451 463 (char*)data.data, 452 464 private_data->nk->clsname_length); 465 W_ERROR_HAVE_NO_MEMORY(*classname); 453 466 } else 454 467 *classname = NULL; … … 485 498 if (!hbin_get_tdr(regf, offset, nk, 486 499 (tdr_pull_fn_t)tdr_pull_nk_block, nk)) { 487 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));500 DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n", offset)); 488 501 return NULL; 489 502 } … … 500 513 501 514 static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key, 502 int idx, const char **name,515 uint32_t idx, const char **name, 503 516 uint32_t *data_type, DATA_BLOB *data) 504 517 { … … 515 528 tmp = hbin_get(regf, private_data->nk->values_offset); 516 529 if (!tmp.data) { 517 DEBUG(0, ("Unable to find value list\n")); 530 DEBUG(0, ("Unable to find value list at 0x%x\n", 531 private_data->nk->values_offset)); 518 532 return WERR_GENERAL_FAILURE; 519 533 } … … 530 544 if (!hbin_get_tdr(regf, vk_offset, vk, 531 545 (tdr_pull_fn_t)tdr_pull_vk_block, vk)) { 532 DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));546 DEBUG(0, ("Unable to get VK block at 0x%x\n", vk_offset)); 533 547 talloc_free(vk); 534 548 return WERR_GENERAL_FAILURE; … … 536 550 537 551 /* FIXME: name character set ?*/ 538 if (name != NULL) 552 if (name != NULL) { 539 553 *name = talloc_strndup(ctx, vk->data_name, vk->name_length); 554 W_ERROR_HAVE_NO_MEMORY(*name); 555 } 540 556 541 557 if (data_type != NULL) … … 543 559 544 560 if (vk->data_length & 0x80000000) { 545 vk->data_length &=~0x80000000; 546 data->data = (uint8_t *)talloc_memdup(ctx, (uint8_t *)&vk->data_offset, vk->data_length); 547 data->length = vk->data_length; 561 /* this is data of type "REG_DWORD" or "REG_DWORD_BIG_ENDIAN" */ 562 data->data = talloc_size(ctx, sizeof(uint32_t)); 563 W_ERROR_HAVE_NO_MEMORY(data->data); 564 SIVAL(data->data, 0, vk->data_offset); 565 data->length = sizeof(uint32_t); 548 566 } else { 549 567 *data = hbin_get(regf, vk->data_offset); … … 563 581 uint32_t *type, DATA_BLOB *data) 564 582 { 565 int i;583 unsigned int i; 566 584 const char *vname; 567 585 WERROR error; … … 598 616 return WERR_NO_MORE_ITEMS; 599 617 618 /* Make sure that we don't crash if the key is empty */ 619 if (nk->subkeys_offset == -1) { 620 return WERR_NO_MORE_ITEMS; 621 } 622 600 623 data = hbin_get(private_data->hive, nk->subkeys_offset); 601 624 if (!data.data) { 602 DEBUG(0, ("Unable to find subkey list\n")); 625 DEBUG(0, ("Unable to find subkey list at 0x%x\n", 626 nk->subkeys_offset)); 603 627 return WERR_GENERAL_FAILURE; 604 628 } … … 606 630 if (!strncmp((char *)data.data, "li", 2)) { 607 631 struct li_block li; 608 struct tdr_pull *pull = tdr_pull_init(private_data->hive , private_data->hive->iconv_convenience);632 struct tdr_pull *pull = tdr_pull_init(private_data->hive); 609 633 610 634 DEBUG(10, ("Subkeys in LI list\n")); … … 627 651 } else if (!strncmp((char *)data.data, "lf", 2)) { 628 652 struct lf_block lf; 629 struct tdr_pull *pull = tdr_pull_init(private_data->hive , private_data->hive->iconv_convenience);653 struct tdr_pull *pull = tdr_pull_init(private_data->hive); 630 654 631 655 DEBUG(10, ("Subkeys in LF list\n")); … … 648 672 } else if (!strncmp((char *)data.data, "lh", 2)) { 649 673 struct lh_block lh; 650 struct tdr_pull *pull = tdr_pull_init(private_data->hive , private_data->hive->iconv_convenience);674 struct tdr_pull *pull = tdr_pull_init(private_data->hive); 651 675 652 676 DEBUG(10, ("Subkeys in LH list\n")); … … 668 692 } else if (!strncmp((char *)data.data, "ri", 2)) { 669 693 struct ri_block ri; 670 struct tdr_pull *pull = tdr_pull_init(ctx , private_data->hive->iconv_convenience);694 struct tdr_pull *pull = tdr_pull_init(ctx); 671 695 uint16_t i; 672 696 uint16_t sublist_count = 0; … … 769 793 (char*)db.data, 770 794 ret->nk->clsname_length); 795 W_ERROR_HAVE_NO_MEMORY(*classname); 771 796 } else 772 797 *classname = NULL; … … 801 826 } 802 827 803 pull = tdr_pull_init(ctx , private_data->hive->iconv_convenience);828 pull = tdr_pull_init(ctx); 804 829 805 830 pull->data = subkey_data; … … 836 861 uint32_t key_off = 0; 837 862 863 /* Make sure that we don't crash if the key is empty */ 864 if (nk->subkeys_offset == -1) { 865 return WERR_BADFILE; 866 } 867 838 868 data = hbin_get(private_data->hive, nk->subkeys_offset); 839 869 if (!data.data) { … … 844 874 if (!strncmp((char *)data.data, "li", 2)) { 845 875 struct li_block li; 846 struct tdr_pull *pull = tdr_pull_init(ctx , private_data->hive->iconv_convenience);876 struct tdr_pull *pull = tdr_pull_init(ctx); 847 877 uint16_t i; 848 878 … … 875 905 } else if (!strncmp((char *)data.data, "lf", 2)) { 876 906 struct lf_block lf; 877 struct tdr_pull *pull = tdr_pull_init(ctx , private_data->hive->iconv_convenience);907 struct tdr_pull *pull = tdr_pull_init(ctx); 878 908 uint16_t i; 879 909 … … 910 940 } else if (!strncmp((char *)data.data, "lh", 2)) { 911 941 struct lh_block lh; 912 struct tdr_pull *pull = tdr_pull_init(ctx , private_data->hive->iconv_convenience);942 struct tdr_pull *pull = tdr_pull_init(ctx); 913 943 uint16_t i; 914 944 uint32_t hash; … … 947 977 } else if (!strncmp((char *)data.data, "ri", 2)) { 948 978 struct ri_block ri; 949 struct tdr_pull *pull = tdr_pull_init(ctx , private_data->hive->iconv_convenience);979 struct tdr_pull *pull = tdr_pull_init(ctx); 950 980 uint16_t i, j; 951 981 … … 1052 1082 1053 1083 /* Push the security descriptor to a blob */ 1054 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL,1084 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, 1055 1085 sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { 1056 1086 DEBUG(0, ("Unable to push security descriptor\n")); … … 1205 1235 data.data = sk.sec_desc; 1206 1236 data.length = sk.rec_size; 1207 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, NULL,*sd,1237 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, *sd, 1208 1238 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) { 1209 1239 DEBUG(0, ("Error parsing security descriptor\n")); … … 1289 1319 1290 1320 if (!strncmp((char *)data.data, "li", 2)) { 1291 struct tdr_pull *pull = tdr_pull_init(regf , regf->iconv_convenience);1321 struct tdr_pull *pull = tdr_pull_init(regf); 1292 1322 struct li_block li; 1323 struct nk_block sub_nk; 1324 int32_t i, j; 1293 1325 1294 1326 pull->data = data; … … 1307 1339 } 1308 1340 1341 /* 1342 * Find the position to store the pointer 1343 * Extensive testing reveils that at least on windows 7 subkeys 1344 * *MUST* be stored in alphabetical order 1345 */ 1346 for (i = 0; i < li.key_count; i++) { 1347 /* Get the nk */ 1348 hbin_get_tdr(regf, li.nk_offset[i], regf, 1349 (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk); 1350 if (strcasecmp(name, sub_nk.key_name) < 0) { 1351 break; 1352 } 1353 } 1354 1309 1355 li.nk_offset = talloc_realloc(regf, li.nk_offset, 1310 1356 uint32_t, li.key_count+1); 1311 1357 W_ERROR_HAVE_NO_MEMORY(li.nk_offset); 1312 li.nk_offset[li.key_count] = key_offset; 1358 1359 /* Move everything behind this offset */ 1360 for (j = li.key_count - 1; j >= i; j--) { 1361 li.nk_offset[j+1] = li.nk_offset[j]; 1362 } 1363 1364 li.nk_offset[i] = key_offset; 1313 1365 li.key_count++; 1314 1366 *ret = hbin_store_tdr_resize(regf, … … 1318 1370 talloc_free(li.nk_offset); 1319 1371 } else if (!strncmp((char *)data.data, "lf", 2)) { 1320 struct tdr_pull *pull = tdr_pull_init(regf , regf->iconv_convenience);1372 struct tdr_pull *pull = tdr_pull_init(regf); 1321 1373 struct lf_block lf; 1374 struct nk_block sub_nk; 1375 int32_t i, j; 1322 1376 1323 1377 pull->data = data; … … 1331 1385 SMB_ASSERT(!strncmp(lf.header, "lf", 2)); 1332 1386 1387 /* 1388 * Find the position to store the hash record 1389 * Extensive testing reveils that at least on windows 7 subkeys 1390 * *MUST* be stored in alphabetical order 1391 */ 1392 for (i = 0; i < lf.key_count; i++) { 1393 /* Get the nk */ 1394 hbin_get_tdr(regf, lf.hr[i].nk_offset, regf, 1395 (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk); 1396 if (strcasecmp(name, sub_nk.key_name) < 0) { 1397 break; 1398 } 1399 } 1400 1333 1401 lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, 1334 1402 lf.key_count+1); 1335 1403 W_ERROR_HAVE_NO_MEMORY(lf.hr); 1336 lf.hr[lf.key_count].nk_offset = key_offset; 1337 lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4); 1404 1405 /* Move everything behind this hash record */ 1406 for (j = lf.key_count - 1; j >= i; j--) { 1407 lf.hr[j+1] = lf.hr[j]; 1408 } 1409 1410 lf.hr[i].nk_offset = key_offset; 1411 lf.hr[i].hash = talloc_strndup(lf.hr, name, 4); 1338 1412 W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash); 1339 1413 lf.key_count++; … … 1344 1418 talloc_free(lf.hr); 1345 1419 } else if (!strncmp((char *)data.data, "lh", 2)) { 1346 struct tdr_pull *pull = tdr_pull_init(regf , regf->iconv_convenience);1420 struct tdr_pull *pull = tdr_pull_init(regf); 1347 1421 struct lh_block lh; 1422 struct nk_block sub_nk; 1423 int32_t i, j; 1348 1424 1349 1425 pull->data = data; … … 1357 1433 SMB_ASSERT(!strncmp(lh.header, "lh", 2)); 1358 1434 1435 /* 1436 * Find the position to store the hash record 1437 * Extensive testing reveils that at least on windows 7 subkeys 1438 * *MUST* be stored in alphabetical order 1439 */ 1440 for (i = 0; i < lh.key_count; i++) { 1441 /* Get the nk */ 1442 hbin_get_tdr(regf, lh.hr[i].nk_offset, regf, 1443 (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk); 1444 if (strcasecmp(name, sub_nk.key_name) < 0) { 1445 break; 1446 } 1447 } 1448 1359 1449 lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash, 1360 1450 lh.key_count+1); 1361 1451 W_ERROR_HAVE_NO_MEMORY(lh.hr); 1362 lh.hr[lh.key_count].nk_offset = key_offset; 1363 lh.hr[lh.key_count].base37 = regf_create_lh_hash(name); 1452 1453 /* Move everything behind this hash record */ 1454 for (j = lh.key_count - 1; j >= i; j--) { 1455 lh.hr[j+1] = lh.hr[j]; 1456 } 1457 1458 lh.hr[i].nk_offset = key_offset; 1459 lh.hr[i].base37 = regf_create_lh_hash(name); 1364 1460 lh.key_count++; 1365 1461 *ret = hbin_store_tdr_resize(regf, … … 1393 1489 if (strncmp((char *)data.data, "li", 2) == 0) { 1394 1490 struct li_block li; 1395 struct tdr_pull *pull = tdr_pull_init(regf , regf->iconv_convenience);1491 struct tdr_pull *pull = tdr_pull_init(regf); 1396 1492 uint16_t i; 1397 1493 bool found_offset = false; … … 1437 1533 } else if (strncmp((char *)data.data, "lf", 2) == 0) { 1438 1534 struct lf_block lf; 1439 struct tdr_pull *pull = tdr_pull_init(regf , regf->iconv_convenience);1535 struct tdr_pull *pull = tdr_pull_init(regf); 1440 1536 uint16_t i; 1441 1537 bool found_offset = false; … … 1483 1579 } else if (strncmp((char *)data.data, "lh", 2) == 0) { 1484 1580 struct lh_block lh; 1485 struct tdr_pull *pull = tdr_pull_init(regf , regf->iconv_convenience);1581 struct tdr_pull *pull = tdr_pull_init(regf); 1486 1582 uint16_t i; 1487 1583 bool found_offset = false; … … 1538 1634 } 1539 1635 1540 static WERROR regf_del_value (struct hive_key *key, const char *name) 1636 static WERROR regf_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key, 1637 const char *name) 1541 1638 { 1542 1639 struct regf_key_data *private_data = (struct regf_key_data *)key; … … 1547 1644 bool found_offset = false; 1548 1645 DATA_BLOB values; 1549 u int32_t i;1646 unsigned int i; 1550 1647 1551 1648 if (nk->values_offset == -1) { … … 1592 1689 private_data->offset, nk); 1593 1690 1594 return regf_save_hbin(private_data->hive); 1595 } 1596 1597 1598 static WERROR regf_del_key(const struct hive_key *parent, const char *name) 1691 return regf_save_hbin(private_data->hive, 0); 1692 } 1693 1694 1695 static WERROR regf_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent, 1696 const char *name) 1599 1697 { 1600 1698 const struct regf_key_data *private_data = … … 1623 1721 char *sk_name; 1624 1722 struct hive_key *sk = (struct hive_key *)key; 1625 int i = key->nk->num_subkeys;1723 unsigned int i = key->nk->num_subkeys; 1626 1724 while (i--) { 1627 1725 /* Get subkey information. */ … … 1635 1733 1636 1734 /* Delete subkey. */ 1637 error = regf_del_key( sk, sk_name);1735 error = regf_del_key(NULL, sk, sk_name); 1638 1736 if (!W_ERROR_IS_OK(error)) { 1639 1737 DEBUG(0, ("Can't delete key '%s'.\n", sk_name)); … … 1649 1747 struct hive_key *sk = (struct hive_key *)key; 1650 1748 DATA_BLOB data; 1651 int i = key->nk->num_values;1749 unsigned int i = key->nk->num_values; 1652 1750 while (i--) { 1653 1751 /* Get value information. */ … … 1661 1759 1662 1760 /* Delete value. */ 1663 error = regf_del_value( sk, val_name);1761 error = regf_del_value(NULL, sk, val_name); 1664 1762 if (!W_ERROR_IS_OK(error)) { 1665 1763 DEBUG(0, ("Can't delete value '%s'.\n", val_name)); … … 1690 1788 hbin_free(private_data->hive, key->offset); 1691 1789 1692 return regf_save_hbin(private_data->hive );1790 return regf_save_hbin(private_data->hive, 0); 1693 1791 } 1694 1792 … … 1717 1815 nk.num_values = 0; 1718 1816 nk.values_offset = -1; 1719 memset(nk.unk3, 0, 5);1817 memset(nk.unk3, 0, sizeof(nk.unk3)); 1720 1818 nk.clsname_offset = -1; /* FIXME: fill in */ 1721 1819 nk.clsname_length = 0; … … 1728 1826 if (!hbin_get_tdr(regf, regf->header->data_offset, root, 1729 1827 (tdr_pull_fn_t)tdr_pull_nk_block, root)) { 1730 DEBUG(0, ("Unable to find HBIN data for offset %d\n",1828 DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n", 1731 1829 regf->header->data_offset)); 1732 1830 return WERR_GENERAL_FAILURE; … … 1753 1851 *ret = (struct hive_key *)regf_get_key(ctx, regf, offset); 1754 1852 1755 return regf_save_hbin(private_data->hive); 1853 DEBUG(9, ("Storing key %s\n", name)); 1854 return regf_save_hbin(private_data->hive, 0); 1756 1855 } 1757 1856 … … 1764 1863 struct vk_block vk; 1765 1864 uint32_t i; 1766 uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1;1865 uint32_t tmp_vk_offset, vk_offset, old_vk_offset = (uint32_t) -1; 1767 1866 DATA_BLOB values; 1768 1867 … … 1778 1877 (tdr_pull_fn_t)tdr_pull_vk_block, 1779 1878 &vk)) { 1780 DEBUG(0, ("Unable to get VK block at %d\n",1879 DEBUG(0, ("Unable to get VK block at 0x%x\n", 1781 1880 tmp_vk_offset)); 1782 1881 return WERR_GENERAL_FAILURE; … … 1787 1886 } 1788 1887 } 1789 /* Free data, if any */ 1790 if (!(vk.data_length & 0x80000000)) { 1791 hbin_free(regf, vk.data_offset); 1792 } 1793 } 1888 } 1889 1890 /* If it's new, create the vk struct, if it's old, free the old data. */ 1794 1891 if (old_vk_offset == -1) { 1795 1892 vk.header = "vk"; … … 1802 1899 vk.flag = 0; 1803 1900 } 1804 } 1901 } else { 1902 /* Free data, if any */ 1903 if (!(vk.data_length & 0x80000000)) { 1904 hbin_free(regf, vk.data_offset); 1905 } 1906 } 1907 1805 1908 /* Set the type and data */ 1806 1909 vk.data_length = data.length; 1807 1910 vk.data_type = type; 1808 if (type == REG_DWORD) { 1911 if ((type == REG_DWORD) || (type == REG_DWORD_BIG_ENDIAN)) { 1912 if (vk.data_length != sizeof(uint32_t)) { 1913 DEBUG(0, ("DWORD or DWORD_BIG_ENDIAN value with size other than 4 byte!\n")); 1914 return WERR_NOT_SUPPORTED; 1915 } 1809 1916 vk.data_length |= 0x80000000; 1810 vk.data_offset = *(uint32_t *)data.data;1917 vk.data_offset = IVAL(data.data, 0); 1811 1918 } else { 1812 1919 /* Store data somewhere */ … … 1864 1971 (tdr_push_fn_t) tdr_push_nk_block, 1865 1972 private_data->offset, nk); 1866 return regf_save_hbin(private_data->hive );1867 } 1868 1869 static WERROR regf_save_hbin(struct regf_data *regf )1870 { 1871 struct tdr_push *push = tdr_push_init(regf , regf->iconv_convenience);1872 int i;1973 return regf_save_hbin(private_data->hive, 0); 1974 } 1975 1976 static WERROR regf_save_hbin(struct regf_data *regf, bool flush) 1977 { 1978 struct tdr_push *push = tdr_push_init(regf); 1979 unsigned int i; 1873 1980 1874 1981 W_ERROR_HAVE_NO_MEMORY(push); 1982 1983 /* Only write once every 5 seconds, or when flush is set */ 1984 if (!flush && regf->last_write + 5 >= time(NULL)) { 1985 return WERR_OK; 1986 } 1987 1988 regf->last_write = time(NULL); 1875 1989 1876 1990 if (lseek(regf->fd, 0, SEEK_SET) == -1) { … … 1887 2001 talloc_free(push); 1888 2002 1889 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,2003 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, 1890 2004 (tdr_push_fn_t)tdr_push_regf_hdr, 1891 2005 regf->header))) { … … 1900 2014 1901 2015 for (i = 0; regf->hbins[i]; i++) { 1902 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,2016 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, 1903 2017 (tdr_push_fn_t)tdr_push_hbin_block, 1904 2018 regf->hbins[i]))) { … … 1912 2026 1913 2027 WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, 1914 struct smb_iconv_convenience *iconv_convenience,1915 2028 const char *location, 1916 2029 int minor_version, struct hive_key **key) … … 1926 2039 1927 2040 regf = (struct regf_data *)talloc_zero(NULL, struct regf_data); 1928 1929 regf->iconv_convenience = iconv_convenience;1930 2041 1931 2042 W_ERROR_HAVE_NO_MEMORY(regf); … … 1963 2074 1964 2075 nk.header = "nk"; 1965 nk.type = REG_ SUB_KEY;2076 nk.type = REG_ROOT_KEY; 1966 2077 unix_to_nt_time(&nk.last_change, time(NULL)); 1967 2078 nk.uk1 = 0; … … 1997 2108 1998 2109 /* Push the security descriptor to a blob */ 1999 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL,2110 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, 2000 2111 sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { 2001 2112 DEBUG(0, ("Unable to push security descriptor\n")); … … 2028 2139 regf->header->data_offset); 2029 2140 2030 error = regf_save_hbin(regf );2141 error = regf_save_hbin(regf, 1); 2031 2142 if (!W_ERROR_IS_OK(error)) { 2032 2143 return error; … … 2034 2145 2035 2146 /* We can drop our own reference now that *key will have created one */ 2036 talloc_ free(regf);2147 talloc_unlink(NULL, regf); 2037 2148 2038 2149 return WERR_OK; 2039 2150 } 2040 2151 2152 static WERROR regf_flush_key(struct hive_key *key) 2153 { 2154 struct regf_key_data *private_data = (struct regf_key_data *)key; 2155 struct regf_data *regf = private_data->hive; 2156 WERROR error; 2157 2158 error = regf_save_hbin(regf, 1); 2159 if (!W_ERROR_IS_OK(error)) { 2160 DEBUG(0, ("Failed to flush regf to disk\n")); 2161 return error; 2162 } 2163 2164 return WERR_OK; 2165 } 2166 2167 static int regf_destruct(struct regf_data *regf) 2168 { 2169 WERROR error; 2170 2171 /* Write to disk */ 2172 error = regf_save_hbin(regf, 1); 2173 if (!W_ERROR_IS_OK(error)) { 2174 DEBUG(0, ("Failed to flush registry to disk\n")); 2175 return -1; 2176 } 2177 2178 /* Close file descriptor */ 2179 close(regf->fd); 2180 2181 return 0; 2182 } 2183 2041 2184 WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location, 2042 struct smb_iconv_convenience *iconv_convenience, structhive_key **key)2185 struct hive_key **key) 2043 2186 { 2044 2187 struct regf_data *regf; 2045 2188 struct regf_hdr *regf_hdr; 2046 2189 struct tdr_pull *pull; 2047 int i;2190 unsigned int i; 2048 2191 2049 2192 regf = (struct regf_data *)talloc_zero(parent_ctx, struct regf_data); 2050 2051 regf->iconv_convenience = iconv_convenience;2052 2053 2193 W_ERROR_HAVE_NO_MEMORY(regf); 2194 2195 talloc_set_destructor(regf, regf_destruct); 2054 2196 2055 2197 DEBUG(5, ("Attempting to load registry file\n")); … … 2065 2207 } 2066 2208 2067 pull = tdr_pull_init(regf , regf->iconv_convenience);2209 pull = tdr_pull_init(regf); 2068 2210 2069 2211 pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, 0, regf); … … 2163 2305 .del_key = regf_del_key, 2164 2306 .delete_value = regf_del_value, 2307 .flush_key = regf_flush_key 2165 2308 }; -
trunk/server/source4/lib/registry/regf.idl
r414 r745 25 25 [noprint] struct regf_version { 26 26 [value(1)] uint32 major; 27 [value(3)]uint32 minor;27 uint32 minor; 28 28 [value(0)] uint32 release; 29 29 [value(1)] uint32 build; … … 75 75 76 76 [noprint] enum reg_key_type { 77 REG_ROOT_KEY = 0x2 0,78 REG_SUB_KEY = 0x2 C,77 REG_ROOT_KEY = 0x2C, 78 REG_SUB_KEY = 0x20, 79 79 REG_SYM_LINK = 0x10 80 80 }; -
trunk/server/source4/lib/registry/registry.h
r414 r745 24 24 struct registry_context; 25 25 struct loadparm_context; 26 struct smb_iconv_convenience;27 26 28 27 #include <talloc.h> … … 71 70 */ 72 71 WERROR (*add_key) (TALLOC_CTX *ctx, 73 const struct hive_key *parent_key, const char * name,72 const struct hive_key *parent_key, const char *path, 74 73 const char *classname, 75 74 struct security_descriptor *desc, … … 78 77 * Remove an existing key. 79 78 */ 80 WERROR (*del_key) (const struct hive_key *key, const char *name); 79 WERROR (*del_key) (TALLOC_CTX *mem_ctx, 80 const struct hive_key *key, const char *name); 81 81 82 82 /** … … 89 89 */ 90 90 WERROR (*enum_value) (TALLOC_CTX *mem_ctx, 91 struct hive_key *key, int idx,91 struct hive_key *key, uint32_t idx, 92 92 const char **name, uint32_t *type, 93 93 DATA_BLOB *data); … … 109 109 * Remove a value. 110 110 */ 111 WERROR (*delete_value) (struct hive_key *key, const char *name); 111 WERROR (*delete_value) (TALLOC_CTX *mem_ctx, 112 struct hive_key *key, const char *name); 112 113 113 114 /* Security Descriptors */ … … 167 168 struct security_descriptor *desc, 168 169 struct hive_key **key); 169 WERROR hive_key_del(const struct hive_key *key, const char *name); 170 WERROR hive_key_del(TALLOC_CTX *mem_ctx, 171 const struct hive_key *key, const char *name); 170 172 WERROR hive_get_key_by_name(TALLOC_CTX *mem_ctx, 171 173 const struct hive_key *key, const char *name, … … 194 196 const struct security_descriptor *security); 195 197 196 WERROR hive_key_del_value(struct hive_key *key, const char *name); 198 WERROR hive_key_del_value(TALLOC_CTX *mem_ctx, 199 struct hive_key *key, const char *name); 197 200 198 201 WERROR hive_key_flush(struct hive_key *key); … … 203 206 const char *location, struct hive_key **key); 204 207 WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, 205 const char *location, struct smb_iconv_convenience *iconv_convenience, 206 struct hive_key **key); 208 const char *location, struct hive_key **key); 207 209 WERROR reg_open_ldb_file(TALLOC_CTX *parent_ctx, const char *location, 208 210 struct auth_session_info *session_info, … … 216 218 const char *location, struct hive_key **key); 217 219 WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, 218 struct smb_iconv_convenience *iconv_convenience,219 220 const char *location, 220 221 int major_version, … … 305 306 struct registry_key **key); 306 307 307 WERROR (*delete_key) (struct registry_key *key, const char *name); 308 309 WERROR (*delete_value) (struct registry_key *key, const char *name); 308 WERROR (*delete_key) (TALLOC_CTX *mem_ctx, 309 struct registry_key *key, const char *name); 310 311 WERROR (*delete_value) (TALLOC_CTX *mem_ctx, 312 struct registry_key *key, const char *name); 310 313 311 314 WERROR (*enum_key) (TALLOC_CTX *mem_ctx, … … 412 415 WERROR reg_key_get_subkey_by_index(TALLOC_CTX *mem_ctx, 413 416 const struct registry_key *key, 414 int idx,417 uint32_t idx, 415 418 const char **name, 416 419 const char **classname, … … 425 428 uint32_t *type, 426 429 DATA_BLOB *data); 427 WERROR reg_key_del(struct registry_key *parent, const char *name); 430 WERROR reg_key_del(TALLOC_CTX *mem_ctx, 431 struct registry_key *parent, const char *name); 428 432 WERROR reg_key_add_name(TALLOC_CTX *mem_ctx, 429 433 struct registry_key *parent, const char *name, … … 435 439 WERROR reg_get_sec_desc(TALLOC_CTX *ctx, const struct registry_key *key, 436 440 struct security_descriptor **secdesc); 437 WERROR reg_del_value(struct registry_key *key, const char *valname); 441 WERROR reg_del_value(TALLOC_CTX *mem_ctx, 442 struct registry_key *key, const char *valname); 438 443 WERROR reg_key_flush(struct registry_key *key); 439 444 WERROR reg_create_key(TALLOC_CTX *mem_ctx, … … 446 451 /* Utility functions */ 447 452 const char *str_regtype(int type); 448 char *reg_val_data_string(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, uint32_t type, const DATA_BLOB data); 449 char *reg_val_description(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, const char *name, 453 bool push_reg_sz(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char *s); 454 bool push_reg_multi_sz(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, const char **a); 455 bool pull_reg_sz(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, const char **s); 456 bool pull_reg_multi_sz(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, const char ***a); 457 int regtype_by_string(const char *str); 458 char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, const DATA_BLOB data); 459 char *reg_val_description(TALLOC_CTX *mem_ctx, const char *name, 450 460 uint32_t type, const DATA_BLOB data); 451 bool reg_string_to_val(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience,const char *type_str,461 bool reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, 452 462 const char *data_str, uint32_t *type, DATA_BLOB *data); 453 463 WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle, … … 486 496 487 497 WERROR reg_diff_apply(struct registry_context *ctx, 488 struct smb_iconv_convenience *ic,const char *filename);498 const char *filename); 489 499 490 500 WERROR reg_generate_diff(struct registry_context *ctx1, … … 493 503 void *callback_data); 494 504 WERROR reg_dotreg_diff_save(TALLOC_CTX *ctx, const char *filename, 495 struct smb_iconv_convenience *iconv_convenience,496 505 struct reg_diff_callbacks **callbacks, 497 506 void **callback_data); 498 507 WERROR reg_preg_diff_save(TALLOC_CTX *ctx, const char *filename, 499 struct smb_iconv_convenience *ic,500 508 struct reg_diff_callbacks **callbacks, 501 509 void **callback_data); … … 506 514 void *callback_data); 507 515 WERROR reg_diff_load(const char *filename, 508 struct smb_iconv_convenience *iconv_convenience,509 516 const struct reg_diff_callbacks *callbacks, 510 517 void *callback_data); 511 518 512 519 WERROR reg_dotreg_diff_load(int fd, 513 struct smb_iconv_convenience *iconv_convenience,514 520 const struct reg_diff_callbacks *callbacks, 515 521 void *callback_data); 516 522 517 523 WERROR reg_preg_diff_load(int fd, 518 struct smb_iconv_convenience *iconv_convenience,519 524 const struct reg_diff_callbacks *callbacks, 520 525 void *callback_data); -
trunk/server/source4/lib/registry/registry.pc.in
r414 r745 8 8 Requires: talloc 9 9 Requires.private: ldb 10 Version: 0.0.111 Libs: -L${libdir} -lregistry10 Version: @PACKAGE_VERSION@ 11 Libs: @LIB_RPATH@ -L${libdir} -lregistry 12 12 Cflags: -I${includedir} -DHAVE_IMMEDIATE_STRUCTURES=1 -
trunk/server/source4/lib/registry/rpc.c
r414 r745 28 28 struct registry_key key; 29 29 struct policy_handle pol; 30 struct dcerpc_pipe *pipe; 31 30 struct dcerpc_binding_handle *binding_handle; 32 31 const char* classname; 33 32 uint32_t num_subkeys; … … 44 43 struct registry_context context; 45 44 struct dcerpc_pipe *pipe; 45 struct dcerpc_binding_handle *binding_handle; 46 46 }; 47 47 … … 52 52 */ 53 53 54 #define openhive(u) static WERROR open_ ## u(struct dcerpc_ pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \54 #define openhive(u) static WERROR open_ ## u(struct dcerpc_binding_handle *b, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \ 55 55 { \ 56 56 struct winreg_Open ## u r; \ … … 62 62 r.out.handle = hnd;\ 63 63 \ 64 status = dcerpc_winreg_Open ## u (p, mem_ctx, &r); \64 status = dcerpc_winreg_Open ## u ## _r(b, mem_ctx, &r); \ 65 65 \ 66 66 if (!NT_STATUS_IS_OK(status)) { \ … … 82 82 static struct { 83 83 uint32_t hkey; 84 WERROR (*open) (struct dcerpc_ pipe *p, TALLOC_CTX *,84 WERROR (*open) (struct dcerpc_binding_handle *b, TALLOC_CTX *, 85 85 struct policy_handle *h); 86 86 } known_hives[] = { … … 118 118 119 119 mykeydata = talloc_zero(ctx, struct rpc_key); 120 W_ERROR_HAVE_NO_MEMORY(mykeydata); 120 121 mykeydata->key.context = ctx; 121 mykeydata-> pipe = talloc_reference(mykeydata, rctx->pipe);122 mykeydata->binding_handle = rctx->binding_handle; 122 123 mykeydata->num_values = -1; 123 124 mykeydata->num_subkeys = -1; 124 125 *k = (struct registry_key *)mykeydata; 125 return known_hives[n].open(mykeydata-> pipe, mykeydata, &(mykeydata->pol));126 return known_hives[n].open(mykeydata->binding_handle, mykeydata, &mykeydata->pol); 126 127 } 127 128 … … 161 162 162 163 mykeydata = talloc_zero(mem_ctx, struct rpc_key); 164 W_ERROR_HAVE_NO_MEMORY(mykeydata); 163 165 mykeydata->key.context = parentkeydata->key.context; 164 mykeydata-> pipe = talloc_reference(mykeydata, parentkeydata->pipe);166 mykeydata->binding_handle = parentkeydata->binding_handle; 165 167 mykeydata->num_values = -1; 166 168 mykeydata->num_subkeys = -1; … … 171 173 r.in.parent_handle = &parentkeydata->pol; 172 174 r.in.keyname.name = name; 173 r.in. unknown= 0x00000000;175 r.in.options = 0x00000000; 174 176 r.in.access_mask = 0x02000000; 175 177 r.out.handle = &mykeydata->pol; 176 178 177 status = dcerpc_winreg_OpenKey (mykeydata->pipe, mem_ctx, &r);179 status = dcerpc_winreg_OpenKey_r(mykeydata->binding_handle, mem_ctx, &r); 178 180 179 181 if (!NT_STATUS_IS_OK(status)) { … … 213 215 r.in.enum_index = n; 214 216 r.in.name = &name; 215 r.in.type = type;217 r.in.type = (enum winreg_Type *) type; 216 218 r.in.value = &value; 217 219 r.in.size = &val_size; 218 220 r.in.length = &zero; 219 221 r.out.name = &name; 220 r.out.type = type;222 r.out.type = (enum winreg_Type *) type; 221 223 r.out.value = &value; 222 224 r.out.size = &val_size; 223 225 r.out.length = &zero; 224 226 225 status = dcerpc_winreg_EnumValue (mykeydata->pipe, mem_ctx, &r);227 status = dcerpc_winreg_EnumValue_r(mykeydata->binding_handle, mem_ctx, &r); 226 228 227 229 if (!NT_STATUS_IS_OK(status)) { … … 230 232 } 231 233 232 *value_name = talloc_ reference(mem_ctx, r.out.name->name);234 *value_name = talloc_steal(mem_ctx, r.out.name->name); 233 235 *type = *(r.out.type); 234 236 *data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length); … … 262 264 r.in.handle = &mykeydata->pol; 263 265 r.in.value_name = &name; 264 r.in.type = type;266 r.in.type = (enum winreg_Type *) type; 265 267 r.in.data = &value; 266 268 r.in.data_size = &val_size; 267 269 r.in.data_length = &zero; 268 r.out.type = type;270 r.out.type = (enum winreg_Type *) type; 269 271 r.out.data = &value; 270 272 r.out.data_size = &val_size; 271 273 r.out.data_length = &zero; 272 274 273 status = dcerpc_winreg_QueryValue (mykeydata->pipe, mem_ctx, &r);275 status = dcerpc_winreg_QueryValue_r(mykeydata->binding_handle, mem_ctx, &r); 274 276 275 277 if (!NT_STATUS_IS_OK(status)) { … … 312 314 r.out.last_changed_time = &change_time; 313 315 314 status = dcerpc_winreg_EnumKey (mykeydata->pipe, mem_ctx, &r);316 status = dcerpc_winreg_EnumKey_r(mykeydata->binding_handle, mem_ctx, &r); 315 317 316 318 if (!NT_STATUS_IS_OK(status)) { … … 320 322 321 323 if (name != NULL) 322 *name = talloc_ reference(mem_ctx, r.out.name->name);324 *name = talloc_steal(mem_ctx, r.out.name->name); 323 325 if (keyclass != NULL) 324 *keyclass = talloc_ reference(mem_ctx, r.out.keyclass->name);326 *keyclass = talloc_steal(mem_ctx, r.out.keyclass->name); 325 327 if (last_changed_time != NULL) 326 328 *last_changed_time = *(r.out.last_changed_time); … … 330 332 331 333 static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, 332 struct registry_key *parent, const char * name,334 struct registry_key *parent, const char *path, 333 335 const char *key_class, 334 336 struct security_descriptor *sec, … … 343 345 ZERO_STRUCT(r); 344 346 r.in.handle = &parentkd->pol; 345 r.in.name.name = name;347 r.in.name.name = path; 346 348 r.in.keyclass.name = NULL; 347 349 r.in.options = 0; … … 352 354 r.out.action_taken = NULL; 353 355 354 status = dcerpc_winreg_CreateKey (parentkd->pipe, mem_ctx, &r);356 status = dcerpc_winreg_CreateKey_r(parentkd->binding_handle, mem_ctx, &r); 355 357 356 358 if (!NT_STATUS_IS_OK(status)) { … … 360 362 } 361 363 362 rpck-> pipe = talloc_reference(rpck, parentkd->pipe);364 rpck->binding_handle = parentkd->binding_handle; 363 365 *key = (struct registry_key *)rpck; 364 366 … … 388 390 r.out.last_changed_time = &mykeydata->last_changed_time; 389 391 390 status = dcerpc_winreg_QueryInfoKey (mykeydata->pipe, mem_ctx, &r);392 status = dcerpc_winreg_QueryInfoKey_r(mykeydata->binding_handle, mem_ctx, &r); 391 393 392 394 if (!NT_STATUS_IS_OK(status)) { … … 395 397 } 396 398 397 mykeydata->classname = talloc_reference(mem_ctx, r.out.classname->name); 398 399 return r.out.result; 400 } 401 402 static WERROR rpc_del_key(struct registry_key *parent, const char *name) 399 mykeydata->classname = talloc_steal(mem_ctx, r.out.classname->name); 400 401 return r.out.result; 402 } 403 404 static WERROR rpc_del_key(TALLOC_CTX *mem_ctx, struct registry_key *parent, 405 const char *name) 403 406 { 404 407 NTSTATUS status; 405 408 struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key); 406 409 struct winreg_DeleteKey r; 407 TALLOC_CTX *mem_ctx = talloc_init("del_key");408 410 409 411 ZERO_STRUCT(r); … … 411 413 r.in.key.name = name; 412 414 413 status = dcerpc_winreg_DeleteKey(mykeydata->pipe, mem_ctx, &r); 414 415 talloc_free(mem_ctx); 415 status = dcerpc_winreg_DeleteKey_r(mykeydata->binding_handle, mem_ctx, &r); 416 416 417 417 if (!NT_STATUS_IS_OK(status)) { … … 474 474 .delete_key = rpc_del_key, 475 475 .get_key_info = rpc_get_info, 476 .get_predefined_key = rpc_get_predefined_key,477 476 }; 478 477 … … 490 489 491 490 rctx = talloc(NULL, struct rpc_registry_context); 491 W_ERROR_HAVE_NO_MEMORY(rctx); 492 492 493 493 /* Default to local smbd if no connection is specified */ … … 498 498 status = dcerpc_pipe_connect(rctx /* TALLOC_CTX */, 499 499 &p, location, 500 500 &ndr_table_winreg, 501 501 credentials, ev, lp_ctx); 502 rctx->pipe = p;503 504 502 if(NT_STATUS_IS_ERR(status)) { 505 503 DEBUG(1, ("Unable to open '%s': %s\n", location, … … 510 508 } 511 509 510 rctx->pipe = p; 511 rctx->binding_handle = p->binding_handle; 512 512 513 *ctx = (struct registry_context *)rctx; 513 514 (*ctx)->ops = ®_backend_rpc; -
trunk/server/source4/lib/registry/samba.c
r414 r745 39 39 40 40 location = talloc_asprintf(ctx, "%s/%s.ldb", 41 lp _private_dir(lp_ctx),41 lpcfg_private_dir(lp_ctx), 42 42 name); 43 W_ERROR_HAVE_NO_MEMORY(location); 43 44 44 45 error = reg_open_hive(ctx, location, auth_info, creds, event_ctx, lp_ctx, &hive); … … 47 48 error = reg_open_ldb_file(ctx, location, auth_info, 48 49 creds, event_ctx, lp_ctx, &hive); 50 51 talloc_free(discard_const_p(char, location)); 49 52 50 53 if (!W_ERROR_IS_OK(error)) -
trunk/server/source4/lib/registry/tests/diff.c
r414 r745 53 53 { 54 54 struct diff_tcase_data *td = tcase_data; 55 struct smb_iconv_convenience *ic;56 55 struct reg_diff_callbacks *callbacks; 57 56 void *data; 58 57 WERROR error; 59 58 60 ic = lp_iconv_convenience(tctx->lp_ctx); 61 62 error = reg_diff_load(td->filename, iconv_convenience, callbacks, data); 59 error = reg_diff_load(td->filename, callbacks, data); 63 60 torture_assert_werr_ok(tctx, error, "reg_diff_load"); 64 61 … … 72 69 WERROR error; 73 70 74 error = reg_diff_apply(td->r1_ctx, lp_iconv_convenience(tctx->lp_ctx),td->filename);71 error = reg_diff_apply(td->r1_ctx, td->filename); 75 72 torture_assert_werr_ok(tctx, error, "reg_diff_apply"); 76 73 … … 228 225 torture_assert_werr_ok(tctx, error, "Creating HKLM\\..\\Policies\\Explorer failed"); 229 226 230 231 blob.data = (void *)talloc(r2_ctx, uint32_t); 232 SIVAL(blob.data, 0, 0x03ffffff); 233 blob.length = sizeof(uint32_t); 227 blob.data = talloc_array(r2_ctx, uint8_t, 4); 228 /* set "0x03FFFFFF" in little endian format */ 229 blob.data[0] = 0xFF; blob.data[1] = 0xFF; 230 blob.data[2] = 0xFF; blob.data[3] = 0x03; 231 blob.length = 4; 234 232 235 233 r1_ctx->ops->set_value(newkey, "NoDrives", REG_DWORD, blob); … … 247 245 { 248 246 struct diff_tcase_data *td; 249 struct smb_iconv_convenience *ic;250 247 WERROR error; 251 248 … … 253 250 td = *data; 254 251 255 ic = lp_iconv_convenience(tctx->lp_ctx);256 257 252 td->filename = talloc_asprintf(tctx, "%s/test.pol", td->tempdir); 258 error = reg_preg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data); 253 error = reg_preg_diff_save(tctx, td->filename, &td->callbacks, 254 &td->callback_data); 259 255 torture_assert_werr_ok(tctx, error, "reg_preg_diff_save"); 260 256 … … 265 261 { 266 262 struct diff_tcase_data *td; 267 struct smb_iconv_convenience *ic;268 263 WERROR error; 269 264 … … 271 266 td = *data; 272 267 273 ic = lp_iconv_convenience(tctx->lp_ctx);274 275 268 td->filename = talloc_asprintf(tctx, "%s/test.reg", td->tempdir); 276 error = reg_dotreg_diff_save(tctx, td->filename, ic, &td->callbacks, &td->callback_data); 269 error = reg_dotreg_diff_save(tctx, td->filename, &td->callbacks, 270 &td->callback_data); 277 271 torture_assert_werr_ok(tctx, error, "reg_dotreg_diff_save"); 278 272 … … 283 277 { 284 278 struct torture_tcase *tcase; 285 struct torture_suite *suite = torture_suite_create(mem_ctx, " DIFF");279 struct torture_suite *suite = torture_suite_create(mem_ctx, "diff"); 286 280 287 281 tcase = torture_suite_add_tcase(suite, "PReg"); -
trunk/server/source4/lib/registry/tests/generic.c
r414 r745 32 32 static bool test_str_regtype(struct torture_context *ctx) 33 33 { 34 torture_assert_str_equal(ctx, str_regtype(0), 35 "REG_NONE", "REG_NONE failed"); 34 36 torture_assert_str_equal(ctx, str_regtype(1), 35 37 "REG_SZ", "REG_SZ failed"); 38 torture_assert_str_equal(ctx, str_regtype(2), 39 "REG_EXPAND_SZ", "REG_EXPAND_SZ failed"); 40 torture_assert_str_equal(ctx, str_regtype(3), 41 "REG_BINARY", "REG_BINARY failed"); 36 42 torture_assert_str_equal(ctx, str_regtype(4), 37 43 "REG_DWORD", "REG_DWORD failed"); 44 torture_assert_str_equal(ctx, str_regtype(5), 45 "REG_DWORD_BIG_ENDIAN", "REG_DWORD_BIG_ENDIAN failed"); 46 torture_assert_str_equal(ctx, str_regtype(6), 47 "REG_LINK", "REG_LINK failed"); 48 torture_assert_str_equal(ctx, str_regtype(7), 49 "REG_MULTI_SZ", "REG_MULTI_SZ failed"); 50 torture_assert_str_equal(ctx, str_regtype(8), 51 "REG_RESOURCE_LIST", "REG_RESOURCE_LIST failed"); 52 torture_assert_str_equal(ctx, str_regtype(9), 53 "REG_FULL_RESOURCE_DESCRIPTOR", "REG_FULL_RESOURCE_DESCRIPTOR failed"); 54 torture_assert_str_equal(ctx, str_regtype(10), 55 "REG_RESOURCE_REQUIREMENTS_LIST", "REG_RESOURCE_REQUIREMENTS_LIST failed"); 56 torture_assert_str_equal(ctx, str_regtype(11), 57 "REG_QWORD", "REG_QWORD failed"); 38 58 39 59 return true; … … 43 63 static bool test_reg_val_data_string_dword(struct torture_context *ctx) 44 64 { 45 uint 32_t d = 0x20;46 DATA_BLOB db = { (uint8_t *)&d, sizeof(d)};47 torture_assert_str_equal(ctx, "0x 20",48 reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx),REG_DWORD, db),65 uint8_t d[] = { 0x20, 0x00, 0x00, 0x00 }; 66 DATA_BLOB db = { d, 4 }; 67 torture_assert_str_equal(ctx, "0x00000020", 68 reg_val_data_string(ctx, REG_DWORD, db), 49 69 "dword failed"); 70 return true; 71 } 72 73 static bool test_reg_val_data_string_dword_big_endian(struct torture_context *ctx) 74 { 75 uint8_t d[] = { 0x20, 0x00, 0x00, 0x00 }; 76 DATA_BLOB db = { d, 4 }; 77 torture_assert_str_equal(ctx, "0x00000020", 78 reg_val_data_string(ctx, REG_DWORD_BIG_ENDIAN, db), 79 "dword failed"); 80 return true; 81 } 82 83 static bool test_reg_val_data_string_qword(struct torture_context *ctx) 84 { 85 uint8_t d[] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 86 DATA_BLOB db = { d, 8 }; 87 torture_assert_str_equal(ctx, "0x0000000000000020", 88 reg_val_data_string(ctx, REG_QWORD, db), 89 "qword failed"); 50 90 return true; 51 91 } … … 54 94 { 55 95 DATA_BLOB db; 56 convert_string_talloc _convenience(ctx, lp_iconv_convenience(ctx->lp_ctx), CH_UTF8, CH_UTF16,96 convert_string_talloc(ctx, CH_UTF8, CH_UTF16, 57 97 "bla", 3, (void **)&db.data, &db.length, false); 58 98 torture_assert_str_equal(ctx, "bla", 59 reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx),REG_SZ, db),99 reg_val_data_string(ctx, REG_SZ, db), 60 100 "sz failed"); 61 101 db.length = 4; 62 102 torture_assert_str_equal(ctx, "bl", 63 reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx),REG_SZ, db),103 reg_val_data_string(ctx, REG_SZ, db), 64 104 "sz failed"); 65 105 return true; … … 71 111 DATA_BLOB db = { x, 4 }; 72 112 torture_assert_str_equal(ctx, "01020304", 73 reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx),REG_BINARY, db),113 reg_val_data_string(ctx, REG_BINARY, db), 74 114 "binary failed"); 75 115 return true; … … 81 121 DATA_BLOB db = { NULL, 0 }; 82 122 torture_assert_str_equal(ctx, "", 83 reg_val_data_string(ctx, lp_iconv_convenience(ctx->lp_ctx),REG_BINARY, db),123 reg_val_data_string(ctx, REG_BINARY, db), 84 124 "empty failed"); 85 125 return true; … … 89 129 { 90 130 DATA_BLOB data; 91 convert_string_talloc _convenience(ctx, lp_iconv_convenience(ctx->lp_ctx), CH_UTF8, CH_UTF16,131 convert_string_talloc(ctx, CH_UTF8, CH_UTF16, 92 132 "stationary traveller", 93 133 strlen("stationary traveller"), 94 134 (void **)&data.data, &data.length, false); 95 135 torture_assert_str_equal(ctx, "camel = REG_SZ : stationary traveller", 96 reg_val_description(ctx, lp_iconv_convenience(ctx->lp_ctx),"camel", REG_SZ, data),136 reg_val_description(ctx, "camel", REG_SZ, data), 97 137 "reg_val_description failed"); 98 138 return true; … … 103 143 { 104 144 DATA_BLOB data; 105 convert_string_talloc _convenience(ctx, lp_iconv_convenience(ctx->lp_ctx), CH_UTF8, CH_UTF16,145 convert_string_talloc(ctx, CH_UTF8, CH_UTF16, 106 146 "west berlin", 107 147 strlen("west berlin"), 108 148 (void **)&data.data, &data.length, false); 109 149 torture_assert_str_equal(ctx, "<No Name> = REG_SZ : west berlin", 110 reg_val_description(ctx, lp_iconv_convenience(ctx->lp_ctx),NULL, REG_SZ, data),150 reg_val_description(ctx, NULL, REG_SZ, data), 111 151 "description with null name failed"); 112 152 return true; … … 115 155 struct torture_suite *torture_registry(TALLOC_CTX *mem_ctx) 116 156 { 117 struct torture_suite *suite = torture_suite_create(mem_ctx, " REGISTRY");157 struct torture_suite *suite = torture_suite_create(mem_ctx, "registry"); 118 158 torture_suite_add_simple_test(suite, "str_regtype", 119 159 test_str_regtype); 120 160 torture_suite_add_simple_test(suite, "reg_val_data_string dword", 121 161 test_reg_val_data_string_dword); 162 torture_suite_add_simple_test(suite, "reg_val_data_string dword_big_endian", 163 test_reg_val_data_string_dword_big_endian); 164 torture_suite_add_simple_test(suite, "reg_val_data_string qword", 165 test_reg_val_data_string_qword); 122 166 torture_suite_add_simple_test(suite, "reg_val_data_string sz", 123 167 test_reg_val_data_string_sz); -
trunk/server/source4/lib/registry/tests/hive.c
r414 r745 33 33 { 34 34 const struct hive_key *root = (const struct hive_key *)test_data; 35 WERROR error = hive_key_del( root, "bla");35 WERROR error = hive_key_del(tctx, root, "bla"); 36 36 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 37 37 "invalid return code"); … … 70 70 WERROR error; 71 71 struct hive_key *subkey; 72 char data[4];73 SIVAL(data, 0, 42);72 uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 }; 73 DATA_BLOB db = { d, 4 }; 74 74 75 75 error = hive_key_add_name(tctx, root, "Nested Keyll", NULL, … … 77 77 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 78 78 79 error = hive_key_set_value(root, "Answer", REG_DWORD, 80 data_blob_talloc(tctx, data, sizeof(data))); 79 error = hive_key_set_value(root, "Answer", REG_DWORD, db); 81 80 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 82 81 … … 108 107 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 109 108 110 error = hive_key_del( root, "Nested Key");109 error = hive_key_del(mem_ctx, root, "Nested Key"); 111 110 torture_assert_werr_ok(tctx, error, "reg_key_del"); 112 111 … … 122 121 const struct hive_key *root = (const struct hive_key *)test_data; 123 122 TALLOC_CTX *mem_ctx = tctx; 124 char data[4];125 SIVAL(data, 0, 42);123 uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 }; 124 DATA_BLOB db = { d, 4 }; 126 125 127 126 /* Create a new key under the root */ … … 136 135 137 136 /* Create a new value under "Child Key" */ 138 error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD, 139 data_blob_talloc(mem_ctx, data, sizeof(data))); 137 error = hive_key_set_value(subkey2, "Answer Recursive", REG_DWORD, db); 140 138 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 141 139 142 140 /* Deleting "Parent Key" will also delete "Child Key" and the value. */ 143 error = hive_key_del( root, "Parent Key");141 error = hive_key_del(mem_ctx, root, "Parent Key"); 144 142 torture_assert_werr_ok(tctx, error, "hive_key_del"); 145 143 … … 167 165 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 168 166 169 error = hive_key_del( root, "Nested Key");167 error = hive_key_del(mem_ctx, root, "Nested Key"); 170 168 torture_assert_werr_ok(tctx, error, "reg_key_del"); 171 169 172 error = hive_key_del( root, "Nested Key");170 error = hive_key_del(mem_ctx, root, "Nested Key"); 173 171 torture_assert_werr_equal(tctx, error, WERR_BADFILE, "reg_key_del"); 174 172 … … 183 181 const struct hive_key *root = (const struct hive_key *)test_data; 184 182 TALLOC_CTX *mem_ctx = tctx; 185 char data[4];186 SIVAL(data, 0, 42);183 uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 }; 184 DATA_BLOB db = { d, 4 }; 187 185 188 186 error = hive_key_add_name(mem_ctx, root, "YA Nested Key", NULL, … … 190 188 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 191 189 192 error = hive_key_set_value(subkey, "Answer", REG_DWORD, 193 data_blob_talloc(mem_ctx, data, sizeof(data))); 190 error = hive_key_set_value(subkey, "Answer", REG_DWORD, db); 194 191 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 195 192 … … 203 200 const struct hive_key *root = (const struct hive_key *)test_data; 204 201 TALLOC_CTX *mem_ctx = tctx; 205 char data[4];206 202 uint32_t type; 207 DATA_BLOB value; 208 209 SIVAL(data, 0, 42); 203 uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 }; 204 DATA_BLOB db = { d, 4 }, data; 210 205 211 206 error = hive_key_add_name(mem_ctx, root, "EYA Nested Key", NULL, … … 213 208 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 214 209 215 error = hive_get_value(mem_ctx, subkey, "Answer", &type, & value);210 error = hive_get_value(mem_ctx, subkey, "Answer", &type, &data); 216 211 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 217 212 "getting missing value"); 218 213 219 error = hive_key_set_value(subkey, "Answer", REG_DWORD, 220 data_blob_talloc(mem_ctx, data, sizeof(data))); 221 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 222 223 error = hive_get_value(mem_ctx, subkey, "Answer", &type, &value); 214 error = hive_key_set_value(subkey, "Answer", REG_DWORD, db); 215 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 216 217 error = hive_get_value(mem_ctx, subkey, "Answer", &type, &data); 224 218 torture_assert_werr_ok(tctx, error, "getting value"); 225 219 226 torture_assert_int_equal(tctx, value.length, 4, "value length");220 torture_assert_int_equal(tctx, data.length, 4, "value length"); 227 221 torture_assert_int_equal(tctx, type, REG_DWORD, "value type"); 228 222 229 torture_assert_mem_equal(tctx, &data, value.data, sizeof(uint32_t), 230 "value data"); 223 torture_assert_mem_equal(tctx, data.data, db.data, 4, "value data"); 231 224 232 225 return true; … … 239 232 const struct hive_key *root = (const struct hive_key *)test_data; 240 233 TALLOC_CTX *mem_ctx = tctx; 241 char data[4];242 234 uint32_t type; 243 DATA_BLOB value; 244 245 SIVAL(data, 0, 42); 235 uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 }; 236 DATA_BLOB db = { d, 4 }; 246 237 247 238 error = hive_key_add_name(mem_ctx, root, "EEYA Nested Key", NULL, … … 249 240 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 250 241 251 error = hive_key_set_value(subkey, "Answer", REG_DWORD, 252 data_blob_talloc(mem_ctx, data, sizeof(data))); 253 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 254 255 error = hive_key_del_value(subkey, "Answer"); 242 error = hive_key_set_value(subkey, "Answer", REG_DWORD, db); 243 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 244 245 error = hive_key_del_value(mem_ctx, subkey, "Answer"); 256 246 torture_assert_werr_ok(tctx, error, "deleting value"); 257 247 258 error = hive_get_value(mem_ctx, subkey, "Answer", &type, & value);248 error = hive_get_value(mem_ctx, subkey, "Answer", &type, &db); 259 249 torture_assert_werr_equal(tctx, error, WERR_BADFILE, "getting value"); 260 250 261 error = hive_key_del_value( subkey, "Answer");251 error = hive_key_del_value(mem_ctx, subkey, "Answer"); 262 252 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 263 253 "deleting value"); … … 273 263 const struct hive_key *root = (const struct hive_key *)test_data; 274 264 TALLOC_CTX *mem_ctx = tctx; 275 char data[4];276 265 uint32_t type; 277 DATA_BLOB value; 266 uint8_t d[] = { 0x42, 0x00, 0x00, 0x00 }; 267 DATA_BLOB db = { d, 4 }, data; 278 268 const char *name; 279 int data_val = 42;280 SIVAL(data, 0, data_val);281 269 282 270 error = hive_key_add_name(mem_ctx, root, "AYAYA Nested Key", NULL, … … 284 272 torture_assert_werr_ok(tctx, error, "hive_key_add_name"); 285 273 286 error = hive_key_set_value(subkey, "Answer", REG_DWORD, 287 data_blob_talloc(mem_ctx, data, sizeof(data))); 274 error = hive_key_set_value(subkey, "Answer", REG_DWORD, db); 288 275 torture_assert_werr_ok(tctx, error, "hive_key_set_value"); 289 276 290 277 error = hive_get_value_by_index(mem_ctx, subkey, 0, &name, 291 &type, & value);278 &type, &data); 292 279 torture_assert_werr_ok(tctx, error, "getting value"); 293 280 294 281 torture_assert_str_equal(tctx, name, "Answer", "value name"); 295 282 296 torture_assert_int_equal(tctx, value.length, 4, "value length");283 torture_assert_int_equal(tctx, data.length, 4, "value length"); 297 284 torture_assert_int_equal(tctx, type, REG_DWORD, "value type"); 298 285 286 torture_assert_mem_equal(tctx, data.data, db.data, 4, "value data"); 299 287 300 torture_assert_int_equal(tctx, data_val, IVAL(value.data, 0), "value data");301 302 288 error = hive_get_value_by_index(mem_ctx, subkey, 1, &name, 303 &type, & value);289 &type, &data); 304 290 torture_assert_werr_equal(tctx, error, WERR_NO_MORE_ITEMS, 305 291 "getting missing value"); … … 450 436 rmdir(dirname); 451 437 452 error = reg_create_regf_file(tctx, lp_iconv_convenience(tctx->lp_ctx), 453 dirname, 5, &key); 438 error = reg_create_regf_file(tctx, dirname, 5, &key); 454 439 if (!W_ERROR_IS_OK(error)) { 455 440 fprintf(stderr, "Unable to create new regf file\n"); … … 473 458 { 474 459 struct torture_tcase *tcase; 475 struct torture_suite *suite = torture_suite_create(mem_ctx, " HIVE");460 struct torture_suite *suite = torture_suite_create(mem_ctx, "hive"); 476 461 477 462 torture_suite_add_simple_test(suite, "dir-refuses-null-location", -
trunk/server/source4/lib/registry/tests/registry.c
r414 r745 118 118 { 119 119 struct registry_context *rctx = (struct registry_context *)_data; 120 struct registry_key *root, *newkey 1, *newkey2;120 struct registry_key *root, *newkey; 121 121 WERROR error; 122 122 … … 125 125 "getting predefined key failed"); 126 126 127 error = reg_key_add_name(rctx, root, "Hamburg ", NULL, NULL,128 &newkey 1);127 error = reg_key_add_name(rctx, root, "Hamburg\\Hamburg", NULL, NULL, 128 &newkey); 129 129 torture_assert_werr_ok(tctx, error, "Creating key return code"); 130 torture_assert(tctx, newkey1 != NULL, "Creating new key"); 131 132 error = reg_key_add_name(rctx, root, "Hamburg\\Hamburg", NULL, NULL, 133 &newkey2); 134 torture_assert_werr_ok(tctx, error, "Creating key return code"); 135 torture_assert(tctx, newkey2 != NULL, "Creating new key"); 130 torture_assert(tctx, newkey != NULL, "Creating new key"); 136 131 137 132 return true; … … 201 196 torture_assert(tctx, newkey != NULL, "Creating new key"); 202 197 203 error = reg_key_del( root, "Polen");198 error = reg_key_del(tctx, root, "Polen"); 204 199 torture_assert_werr_ok(tctx, error, "Delete key"); 205 200 206 error = reg_key_del( root, "Polen");201 error = reg_key_del(tctx, root, "Polen"); 207 202 torture_assert_werr_equal(tctx, error, WERR_BADFILE, 208 203 "Delete missing key"); … … 465 460 torture_assert_werr_ok (tctx, error, "setting value"); 466 461 467 error = reg_del_value( subkey, __FUNCTION__);462 error = reg_del_value(tctx, subkey, __FUNCTION__); 468 463 torture_assert_werr_ok (tctx, error, "unsetting value"); 469 464 … … 585 580 { 586 581 struct torture_tcase *tcase; 587 struct torture_suite *suite = torture_suite_create(mem_ctx, " REGISTRY");582 struct torture_suite *suite = torture_suite_create(mem_ctx, "registry"); 588 583 589 584 tcase = torture_suite_add_tcase(suite, "local"); -
trunk/server/source4/lib/registry/tools/regdiff.c
r414 r745 131 131 poptFreeContext(pc); 132 132 133 error = reg_dotreg_diff_save(ctx, outputfile, lp_iconv_convenience(cmdline_lp_ctx), &callbacks, 134 &callback_data); 133 error = reg_dotreg_diff_save(ctx, outputfile, &callbacks, &callback_data); 135 134 if (!W_ERROR_IS_OK(error)) { 136 135 fprintf(stderr, "Problem saving registry diff to '%s': %s\n", -
trunk/server/source4/lib/registry/tools/regpatch.c
r414 r745 69 69 poptFreeContext(pc); 70 70 71 reg_diff_apply(h, lp_iconv_convenience(cmdline_lp_ctx),patch);71 reg_diff_apply(h, patch); 72 72 73 73 return 0; -
trunk/server/source4/lib/registry/tools/regshell.c
r414 r745 25 25 #include "lib/events/events.h" 26 26 #include "system/time.h" 27 #include " lib/smbreadline/smbreadline.h"27 #include "../libcli/smbreadline/smbreadline.h" 28 28 #include "librpc/gen_ndr/ndr_security.h" 29 29 #include "lib/registry/tools/common.h" … … 126 126 printf("Key Class: %s\n", classname); 127 127 last_mod = nt_time_to_unix(last_change); 128 printf("Time Last Modified: %s \n", ctime(&last_mod));128 printf("Time Last Modified: %s", ctime(&last_mod)); 129 129 printf("Number of subkeys: %d\n", num_subkeys); 130 130 printf("Number of values: %d\n", num_values); … … 141 141 error = reg_get_sec_desc(ctx, ctx->current, &sec_desc); 142 142 if (!W_ERROR_IS_OK(error)) { 143 printf("Error getting security descriptor \n");144 return error;143 printf("Error getting security descriptor: %s\n", win_errstr(error)); 144 return WERR_OK; 145 145 } 146 146 ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor, … … 196 196 } 197 197 198 if (!reg_string_to_val(ctx, lp_iconv_convenience(cmdline_lp_ctx), 199 argv[2], argv[3], &val.data_type, 200 &val.data)) { 198 if (!reg_string_to_val(ctx, argv[2], argv[3], &val.data_type, &val.data)) { 201 199 fprintf(stderr, "Unable to interpret data\n"); 202 200 return WERR_INVALID_PARAM; … … 260 258 261 259 printf("%s\n%s\n", str_regtype(value_type), 262 reg_val_data_string(ctx, lp_iconv_convenience(cmdline_lp_ctx),value_type, value_data));260 reg_val_data_string(ctx, value_type, value_data)); 263 261 264 262 return WERR_OK; … … 267 265 static WERROR cmd_ls(struct regshell_context *ctx, int argc, char **argv) 268 266 { 269 int i;267 unsigned int i; 270 268 WERROR error; 271 269 uint32_t valuetype; … … 283 281 284 282 if (!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { 285 fprintf(stderr, "Error occur ed while browsing thrukeys: %s\n",283 fprintf(stderr, "Error occurred while browsing through keys: %s\n", 286 284 win_errstr(error)); 287 285 return error; … … 291 289 ctx->current, i, &name, &valuetype, &valuedata)); i++) 292 290 printf("V \"%s\" %s %s\n", name, str_regtype(valuetype), 293 reg_val_data_string(ctx, lp_iconv_convenience(cmdline_lp_ctx),valuetype, valuedata));291 reg_val_data_string(ctx, valuetype, valuedata)); 294 292 295 293 return WERR_OK; … … 326 324 } 327 325 328 error = reg_key_del(ctx ->current, argv[1]);326 error = reg_key_del(ctx, ctx->current, argv[1]); 329 327 if(!W_ERROR_IS_OK(error)) { 330 328 fprintf(stderr, "Error deleting '%s'\n", argv[1]); … … 346 344 } 347 345 348 error = reg_del_value(ctx ->current, argv[1]);346 error = reg_del_value(ctx, ctx->current, argv[1]); 349 347 if(!W_ERROR_IS_OK(error)) { 350 348 fprintf(stderr, "Error deleting value '%s'\n", argv[1]); … … 389 387 int argc, char **argv) 390 388 { 391 int i;389 unsigned int i; 392 390 printf("Available commands:\n"); 393 391 for(i = 0; regshell_cmds[i].name; i++) { … … 430 428 /* Complete command */ 431 429 char **matches; 432 int i, len, samelen=0, count=1; 430 size_t len, samelen=0; 431 unsigned int i, count=1; 433 432 434 433 matches = malloc_array_p(char *, MAX_COMPLETIONS); … … 478 477 struct registry_key *base; 479 478 const char *subkeyname; 480 int i, j = 1; 481 int samelen = 0; 482 int len; 479 unsigned int i, j = 1; 480 size_t len, samelen = 0; 483 481 char **matches; 484 482 const char *base_n = ""; … … 594 592 595 593 if (ctx->current == NULL) { 596 int i;594 unsigned int i; 597 595 598 596 for (i = 0; (reg_predefined_keys[i].handle != 0) && … … 617 615 if (ctx->current == NULL) { 618 616 fprintf(stderr, "Unable to access any of the predefined keys\n"); 619 return -1;617 return 1; 620 618 } 621 619 … … 625 623 char *line, *prompt; 626 624 627 asprintf(&prompt, "%s\\%s> ", ctx->predef?ctx->predef:"", ctx->path); 625 if (asprintf(&prompt, "%s\\%s> ", ctx->predef?ctx->predef:"", 626 ctx->path) < 0) { 627 ret = false; 628 break; 629 } 628 630 629 631 current_key = ctx->current; /* No way to pass a void * pointer -
trunk/server/source4/lib/registry/tools/regtree.c
r414 r745 34 34 * @param novals Whether values should not be printed 35 35 */ 36 static void print_tree( int level, struct registry_key *p,36 static void print_tree(unsigned int level, struct registry_key *p, 37 37 const char *name, 38 38 bool fullpath, bool novals) … … 44 44 struct security_descriptor *sec_desc; 45 45 WERROR error; 46 int i;46 unsigned int i; 47 47 TALLOC_CTX *mem_ctx; 48 48 … … 70 70 71 71 if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { 72 DEBUG(0, ("Error occur ed while fetching subkeys for '%s': %s\n",72 DEBUG(0, ("Error occurred while fetching subkeys for '%s': %s\n", 73 73 name, win_errstr(error))); 74 74 } … … 79 79 mem_ctx, p, i, &valuename, &valuetype, &valuedata)); 80 80 i++) { 81 int j;81 unsigned int j; 82 82 for(j = 0; j < level+1; j++) putchar(' '); 83 83 printf("%s\n", reg_val_description(mem_ctx, 84 lp_iconv_convenience(cmdline_lp_ctx), valuename, 85 valuetype, valuedata)); 84 valuename, valuetype, valuedata)); 86 85 } 87 86 talloc_free(mem_ctx); 88 87 89 88 if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { 90 DEBUG(0, ("Error occur ed while fetching values for '%s': %s\n",89 DEBUG(0, ("Error occurred while fetching values for '%s': %s\n", 91 90 name, win_errstr(error))); 92 91 } … … 102 101 int main(int argc, char **argv) 103 102 { 104 int opt, i; 103 int opt; 104 unsigned int i; 105 105 const char *file = NULL; 106 106 const char *remote = NULL; -
trunk/server/source4/lib/registry/util.c
r414 r745 3 3 Transparent registry backend handling 4 4 Copyright (C) Jelmer Vernooij 2003-2007. 5 Copyright (C) Wilco Baan Hofman 2010. 5 6 6 7 This program is free software; you can redistribute it and/or modify … … 21 22 #include "lib/registry/registry.h" 22 23 #include "librpc/gen_ndr/winreg.h" 23 24 /** 25 * @file 26 * @brief Registry utility functions 27 */ 28 29 static const struct { 30 uint32_t id; 31 const char *name; 32 } reg_value_types[] = { 33 { REG_SZ, "REG_SZ" }, 34 { REG_DWORD, "REG_DWORD" }, 35 { REG_BINARY, "REG_BINARY" }, 36 { REG_EXPAND_SZ, "REG_EXPAND_SZ" }, 37 { REG_NONE, "REG_NONE" }, 38 { 0, NULL } 39 }; 40 41 /** Return string description of registry value type */ 42 _PUBLIC_ const char *str_regtype(int type) 43 { 44 int i; 45 for (i = 0; reg_value_types[i].name; i++) { 46 if (reg_value_types[i].id == type) 47 return reg_value_types[i].name; 48 } 49 50 return "Unknown"; 51 } 52 53 _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, 54 struct smb_iconv_convenience *iconv_convenience, 55 uint32_t type, 24 #include "lib/util/data_blob.h" 25 26 _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type, 56 27 const DATA_BLOB data) 57 28 { … … 64 35 case REG_EXPAND_SZ: 65 36 case REG_SZ: 66 convert_string_talloc_convenience(mem_ctx, iconv_convenience, CH_UTF16, CH_UNIX, 37 convert_string_talloc(mem_ctx, 38 CH_UTF16, CH_UNIX, 67 39 data.data, data.length, 68 40 (void **)&ret, NULL, false); 69 return ret; 41 break; 42 case REG_DWORD: 43 case REG_DWORD_BIG_ENDIAN: 44 SMB_ASSERT(data.length == sizeof(uint32_t)); 45 ret = talloc_asprintf(mem_ctx, "0x%8.8x", 46 IVAL(data.data, 0)); 47 break; 48 case REG_QWORD: 49 SMB_ASSERT(data.length == sizeof(uint64_t)); 50 ret = talloc_asprintf(mem_ctx, "0x%16.16llx", 51 (long long)BVAL(data.data, 0)); 52 break; 70 53 case REG_BINARY: 71 ret = data_blob_hex_string(mem_ctx, &data); 72 return ret; 73 case REG_DWORD: 74 if (*(int *)data.data == 0) 75 return talloc_strdup(mem_ctx, "0"); 76 return talloc_asprintf(mem_ctx, "0x%x", 77 *(int *)data.data); 54 ret = data_blob_hex_string_upper(mem_ctx, &data); 55 break; 56 case REG_NONE: 57 /* "NULL" is the right return value */ 58 break; 78 59 case REG_MULTI_SZ: 60 /* FIXME: We don't support this yet */ 61 break; 62 default: 79 63 /* FIXME */ 80 break; 81 default: 64 /* Other datatypes aren't supported -> return "NULL" */ 82 65 break; 83 66 } … … 87 70 88 71 /** Generate a string that describes a registry value */ 89 _PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, 90 struct smb_iconv_convenience *iconv_convenience, 72 _PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx, 91 73 const char *name, 92 74 uint32_t data_type, … … 95 77 return talloc_asprintf(mem_ctx, "%s = %s : %s", name?name:"<No Name>", 96 78 str_regtype(data_type), 97 reg_val_data_string(mem_ctx, iconv_convenience, data_type, data)); 98 } 99 100 _PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx, 101 struct smb_iconv_convenience *iconv_convenience, 102 const char *type_str, 103 const char *data_str, uint32_t *type, 104 DATA_BLOB *data) 105 { 106 int i; 107 *type = -1; 108 109 /* Find the correct type */ 110 for (i = 0; reg_value_types[i].name; i++) { 111 if (!strcmp(reg_value_types[i].name, type_str)) { 112 *type = reg_value_types[i].id; 113 break; 79 reg_val_data_string(mem_ctx, data_type, data)); 80 } 81 82 /* 83 * This implements reading hex bytes that include comma's. 84 * It was previously handled by strhex_to_data_blob, but that did not cover 85 * the format used by windows. 86 */ 87 static DATA_BLOB reg_strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *str) 88 { 89 DATA_BLOB ret; 90 const char *HEXCHARS = "0123456789ABCDEF"; 91 size_t i, j; 92 char *hi, *lo; 93 94 ret = data_blob_talloc_zero(mem_ctx, (strlen(str)+(strlen(str) % 3))/3); 95 j = 0; 96 for (i = 0; i < strlen(str); i++) { 97 hi = strchr(HEXCHARS, toupper(str[i])); 98 if (hi == NULL) 99 continue; 100 101 i++; 102 lo = strchr(HEXCHARS, toupper(str[i])); 103 if (lo == NULL) 104 break; 105 106 ret.data[j] = PTR_DIFF(hi, HEXCHARS) << 4; 107 ret.data[j] += PTR_DIFF(lo, HEXCHARS); 108 j++; 109 110 if (j > ret.length) { 111 DEBUG(0, ("Trouble converting hex string to bin\n")); 112 break; 113 } 114 } 115 return ret; 116 } 117 118 119 _PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str, 120 const char *data_str, uint32_t *type, DATA_BLOB *data) 121 { 122 char *tmp_type_str, *p, *q; 123 int result; 124 125 *type = regtype_by_string(type_str); 126 127 if (*type == -1) { 128 /* Normal windows format is hex, hex(type int as string), 129 dword or just a string. */ 130 if (strncmp(type_str, "hex(", 4) == 0) { 131 /* there is a hex string with the value type between 132 the braces */ 133 tmp_type_str = talloc_strdup(mem_ctx, type_str); 134 q = p = tmp_type_str + strlen("hex("); 135 136 /* Go to the closing brace or end of the string */ 137 while (*q != ')' && *q != '\0') q++; 138 *q = '\0'; 139 140 /* Convert hex string to int, store it in type */ 141 result = sscanf(p, "%x", type); 142 if (!result) { 143 DEBUG(0, ("Could not convert hex to int\n")); 144 return false; 145 } 146 talloc_free(tmp_type_str); 147 } else if (strcmp(type_str, "hex") == 0) { 148 *type = REG_BINARY; 149 } else if (strcmp(type_str, "dword") == 0) { 150 *type = REG_DWORD; 114 151 } 115 152 } … … 120 157 /* Convert data appropriately */ 121 158 122 switch (*type) 123 { 159 switch (*type) { 124 160 case REG_SZ: 161 return convert_string_talloc(mem_ctx, 162 CH_UNIX, CH_UTF16, 163 data_str, strlen(data_str)+1, 164 (void **)&data->data, 165 &data->length, false); 166 break; 167 case REG_MULTI_SZ: 125 168 case REG_EXPAND_SZ: 126 convert_string_talloc_convenience(mem_ctx, iconv_convenience, CH_UNIX, CH_UTF16, 127 data_str, strlen(data_str), 128 (void **)&data->data, &data->length, false); 129 break; 130 131 case REG_DWORD: { 132 uint32_t tmp = strtol(data_str, NULL, 0); 133 *data = data_blob_talloc(mem_ctx, &tmp, 4); 169 case REG_BINARY: 170 *data = reg_strhex_to_data_blob(mem_ctx, data_str); 171 break; 172 case REG_DWORD: 173 case REG_DWORD_BIG_ENDIAN: { 174 uint32_t tmp = strtol(data_str, NULL, 16); 175 *data = data_blob_talloc(mem_ctx, NULL, sizeof(uint32_t)); 176 if (data->data == NULL) return false; 177 SIVAL(data->data, 0, tmp); 134 178 } 135 179 break; 136 180 case REG_QWORD: { 181 uint64_t tmp = strtoll(data_str, NULL, 16); 182 *data = data_blob_talloc(mem_ctx, NULL, sizeof(uint64_t)); 183 if (data->data == NULL) return false; 184 SBVAL(data->data, 0, tmp); 185 } 186 break; 137 187 case REG_NONE: 138 188 ZERO_STRUCTP(data); 139 189 break; 140 141 case REG_BINARY:142 *data = strhex_to_data_blob(mem_ctx, data_str);143 break;144 145 190 default: 146 191 /* FIXME */ 192 /* Other datatypes aren't supported -> return no success */ 147 193 return false; 148 194 } … … 156 202 struct registry_key *predef; 157 203 WERROR error; 158 int predeflength;204 size_t predeflength; 159 205 char *predefname; 160 206 … … 165 211 166 212 predefname = talloc_strndup(mem_ctx, name, predeflength); 213 W_ERROR_HAVE_NO_MEMORY(predefname); 167 214 error = reg_get_predefined_key_by_name(handle, predefname, &predef); 168 215 talloc_free(predefname); … … 193 240 194 241 parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-path); 195 242 W_ERROR_HAVE_NO_MEMORY(parent_name); 196 243 error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent); 244 talloc_free(parent_name); 197 245 if (!W_ERROR_IS_OK(error)) { 198 246 return error; … … 200 248 201 249 *name = talloc_strdup(mem_ctx, strrchr(path, '\\')+1); 250 W_ERROR_HAVE_NO_MEMORY(*name); 202 251 203 252 return WERR_OK; … … 217 266 error = get_abs_parent(mem_ctx, ctx, path, &parent, &n); 218 267 if (W_ERROR_IS_OK(error)) { 219 error = reg_key_del( parent, n);268 error = reg_key_del(mem_ctx, parent, n); 220 269 } 221 270 … … 233 282 const char *n; 234 283 WERROR error; 284 285 *result = NULL; 235 286 236 287 if (!strchr(path, '\\')) { -
trunk/server/source4/lib/socket/access.c
r414 r745 35 35 #include "lib/socket/socket.h" 36 36 #include "system/locale.h" 37 #include "lib/util/util_net.h" 37 38 38 39 #define FAIL (-1) -
trunk/server/source4/lib/socket/connect_multi.c
r414 r745 34 34 */ 35 35 struct connect_multi_state { 36 const char*server_address;36 struct socket_address *server_address; 37 37 int num_ports; 38 38 uint16_t *ports; … … 65 65 _PUBLIC_ struct composite_context *socket_connect_multi_send( 66 66 TALLOC_CTX *mem_ctx, 67 const char *server_ address,67 const char *server_name, 68 68 int num_server_ports, 69 69 uint16_t *server_ports, … … 75 75 int i; 76 76 77 struct nbt_name name; 78 struct composite_context *creq; 79 77 80 result = talloc_zero(mem_ctx, struct composite_context); 78 81 if (result == NULL) return NULL; … … 84 87 result->private_data = multi; 85 88 86 multi->server_address = talloc_strdup(multi, server_address);87 if (composite_nomem(multi->server_address, result)) goto failed;88 89 89 multi->num_ports = num_server_ports; 90 90 multi->ports = talloc_array(multi, uint16_t, multi->num_ports); … … 95 95 } 96 96 97 if (!is_ipaddress(server_address)) { 98 /* 99 we don't want to do the name resolution separately 97 /* 98 we don't want to do the name resolution separately 100 99 for each port, so start it now, then only start on 101 100 the real sockets once we have an IP 102 */ 103 struct nbt_name name; 104 struct composite_context *creq; 105 make_nbt_name_server(&name, server_address); 106 creq = resolve_name_send(resolve_ctx, multi, &name, result->event_ctx); 107 if (composite_nomem(creq, result)) goto failed; 108 composite_continue(result, creq, continue_resolve_name, result); 109 return result; 110 } 111 112 /* now we've setup the state we can process the first socket */ 113 connect_multi_next_socket(result); 114 115 if (!NT_STATUS_IS_OK(result->status)) { 116 goto failed; 117 } 101 */ 102 make_nbt_name_server(&name, server_name); 103 104 creq = resolve_name_all_send(resolve_ctx, multi, 0, multi->ports[0], &name, result->event_ctx); 105 if (composite_nomem(creq, result)) goto failed; 106 107 composite_continue(result, creq, continue_resolve_name, result); 118 108 119 109 return result; 110 120 111 121 112 failed: … … 149 140 if (!composite_is_ok(result)) return; 150 141 151 /* Form up the particular address we are interested in */ 152 state->addr = socket_address_from_strings(state, state->sock->backend_name, 153 multi->server_address, multi->ports[next]); 142 state->addr = socket_address_copy(state, multi->server_address); 154 143 if (composite_nomem(state->addr, result)) return; 144 145 socket_address_set_port(state->addr, multi->ports[next]); 155 146 156 147 talloc_steal(state, state->sock); … … 198 189 struct connect_multi_state *multi = talloc_get_type(result->private_data, 199 190 struct connect_multi_state); 200 const char*addr;201 202 result->status = resolve_name_ recv(creq, multi, &addr);191 struct socket_address **addr; 192 193 result->status = resolve_name_all_recv(creq, multi, &addr, NULL); 203 194 if (!composite_is_ok(result)) return; 204 195 205 multi->server_address = addr; 196 /* Let's just go for the first for now */ 197 multi->server_address = addr[0]; 206 198 207 199 connect_multi_next_socket(result); -
trunk/server/source4/lib/socket/interface.c
r414 r745 23 23 #include "system/network.h" 24 24 #include "lib/socket/netif.h" 25 #include "../lib/util/util_net.h" 25 26 #include "../lib/util/dlinklist.h" 26 27 … … 94 95 DLIST_ADD_END(*interfaces, iface, struct interface *); 95 96 96 DEBUG( 2,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s));97 DEBUG(3,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s)); 97 98 } 98 99 -
trunk/server/source4/lib/socket/netif.c
r414 r745 35 35 #include "system/network.h" 36 36 #include "netif.h" 37 #include "lib/util/tsort.h" 37 38 38 39 /**************************************************************************** … … 110 111 111 112 /* now we need to remove duplicates */ 112 qsort(ifaces, total, sizeof(ifaces[0]), QSORT_CASTiface_comp);113 TYPESAFE_QSORT(ifaces, total, iface_comp); 113 114 114 115 for (i=1;i<total;) { -
trunk/server/source4/lib/socket/socket.c
r414 r745 25 25 #include "system/network.h" 26 26 #include "param/param.h" 27 #include "../lib/tsocket/tsocket.h" 28 #include "lib/util/util_net.h" 27 29 28 30 /* … … 343 345 344 346 return sock->ops->fn_get_my_addr(sock, mem_ctx); 347 } 348 349 _PUBLIC_ struct tsocket_address *socket_address_to_tsocket_address(TALLOC_CTX *mem_ctx, 350 const struct socket_address *a) 351 { 352 struct tsocket_address *r; 353 int ret; 354 355 if (a->sockaddr) { 356 ret = tsocket_address_bsd_from_sockaddr(mem_ctx, 357 a->sockaddr, 358 a->sockaddrlen, 359 &r); 360 } else { 361 ret = tsocket_address_inet_from_strings(mem_ctx, 362 a->family, 363 a->addr, 364 a->port, 365 &r); 366 } 367 368 if (ret != 0) { 369 return NULL; 370 } 371 372 return r; 373 } 374 375 _PUBLIC_ void socket_address_set_port(struct socket_address *a, 376 uint16_t port) 377 { 378 if (a->sockaddr) { 379 set_sockaddr_port(a->sockaddr, port); 380 } else { 381 a->port = port; 382 } 383 384 } 385 386 _PUBLIC_ struct socket_address *tsocket_address_to_socket_address(TALLOC_CTX *mem_ctx, 387 const struct tsocket_address *a) 388 { 389 ssize_t ret; 390 struct sockaddr_storage ss; 391 size_t sslen = sizeof(ss); 392 393 ret = tsocket_address_bsd_sockaddr(a, (struct sockaddr *)(void *)&ss, sslen); 394 if (ret < 0) { 395 return NULL; 396 } 397 398 return socket_address_from_sockaddr(mem_ctx, (struct sockaddr *)(void *)&ss, ret); 399 } 400 401 _PUBLIC_ struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) 402 { 403 struct socket_address *a; 404 struct tsocket_address *r; 405 406 a = socket_get_peer_addr(sock, mem_ctx); 407 if (a == NULL) { 408 return NULL; 409 } 410 411 r = socket_address_to_tsocket_address(mem_ctx, a); 412 talloc_free(a); 413 return r; 414 } 415 416 _PUBLIC_ struct tsocket_address *socket_get_local_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx) 417 { 418 struct socket_address *a; 419 struct tsocket_address *r; 420 421 a = socket_get_my_addr(sock, mem_ctx); 422 if (a == NULL) { 423 return NULL; 424 } 425 426 r = socket_address_to_tsocket_address(mem_ctx, a); 427 talloc_free(a); 428 return r; 345 429 } 346 430 -
trunk/server/source4/lib/socket/socket.h
r414 r745 128 128 129 129 struct resolve_context; 130 struct tsocket_address; 130 131 131 132 /* prototypes */ … … 159 160 struct socket_address *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx); 160 161 struct socket_address *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx); 162 struct tsocket_address *socket_address_to_tsocket_address(TALLOC_CTX *mem_ctx, 163 const struct socket_address *a); 164 struct socket_address *tsocket_address_to_socket_address(TALLOC_CTX *mem_ctx, 165 const struct tsocket_address *a); 166 struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx); 167 struct tsocket_address *socket_get_local_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx); 161 168 int socket_get_fd(struct socket_context *sock); 162 169 NTSTATUS socket_dup(struct socket_context *sock); … … 168 175 struct sockaddr *sockaddr, 169 176 size_t addrlen); 177 _PUBLIC_ void socket_address_set_port(struct socket_address *a, 178 uint16_t port); 170 179 struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx, 171 180 const struct socket_address *oaddr); … … 207 216 uint16_t *port); 208 217 void set_socket_options(int fd, const char *options); 209 void socket_set_flags(struct socket_context *sock et, unsigned flags);218 void socket_set_flags(struct socket_context *sock, unsigned flags); 210 219 211 220 void socket_tevent_fd_close_fn(struct tevent_context *ev, -
trunk/server/source4/lib/socket/socket_ip.c
r414 r745 26 26 #include "lib/socket/socket.h" 27 27 #include "system/network.h" 28 #include "lib/util/util_net.h" 28 29 29 30 static NTSTATUS ipv4_init(struct socket_context *sock) … … 712 713 static NTSTATUS ipv6_tcp_accept(struct socket_context *sock, struct socket_context **new_sock) 713 714 { 714 struct sockaddr_in cli_addr;715 struct sockaddr_in6 cli_addr; 715 716 socklen_t cli_addr_len = sizeof(cli_addr); 716 717 int new_fd; -
trunk/server/source4/lib/socket/testsuite.c
r414 r745 43 43 struct interface *ifaces; 44 44 45 load_interfaces(tctx, lp _interfaces(tctx->lp_ctx), &ifaces);45 load_interfaces(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces); 46 46 47 47 status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock1, 0); … … 136 136 talloc_steal(mem_ctx, sock2); 137 137 138 load_interfaces(tctx, lp _interfaces(tctx->lp_ctx), &ifaces);138 load_interfaces(tctx, lpcfg_interfaces(tctx->lp_ctx), &ifaces); 139 139 localhost = socket_address_from_strings(sock1, sock1->backend_name, 140 140 iface_best_ip(ifaces, "127.0.0.1"), 0); … … 189 189 struct torture_suite *torture_local_socket(TALLOC_CTX *mem_ctx) 190 190 { 191 struct torture_suite *suite = torture_suite_create(mem_ctx, 192 "SOCKET"); 191 struct torture_suite *suite = torture_suite_create(mem_ctx, "socket"); 193 192 194 193 torture_suite_add_simple_test(suite, "udp", test_udp); -
trunk/server/source4/lib/stream/packet.c
r414 r745 43 43 int processing; 44 44 bool recv_disable; 45 bool recv_need_enable; 45 46 bool nofree; 46 47 … … 257 258 258 259 if (pc->recv_disable) { 260 pc->recv_need_enable = true; 259 261 EVENT_FD_NOT_READABLE(pc->fde); 260 262 return; … … 465 467 _PUBLIC_ void packet_recv_disable(struct packet_context *pc) 466 468 { 467 EVENT_FD_NOT_READABLE(pc->fde);468 469 pc->recv_disable = true; 469 470 } … … 474 475 _PUBLIC_ void packet_recv_enable(struct packet_context *pc) 475 476 { 476 EVENT_FD_READABLE(pc->fde); 477 if (pc->recv_need_enable) { 478 pc->recv_need_enable = false; 479 EVENT_FD_READABLE(pc->fde); 480 } 477 481 pc->recv_disable = false; 478 482 if (pc->num_read != 0 && pc->packet_size >= pc->num_read) { … … 527 531 call send_callback. 528 532 529 Useful for operations that must occ our after sending a message, such533 Useful for operations that must occur after sending a message, such 530 534 as the switch to SASL encryption after as sucessful LDAP bind relpy. 531 535 */ -
trunk/server/source4/lib/stream/packet.h
r414 r745 24 24 struct tevent_context; 25 25 struct tevent_fd; 26 struct socket_context; 26 27 27 28 typedef NTSTATUS (*packet_full_request_fn_t)(void *private_data, -
trunk/server/source4/lib/tls/tls.c
r414 r745 358 358 int ret; 359 359 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 360 const char *keyfile = lp _tls_keyfile(tmp_ctx, lp_ctx);361 const char *certfile = lp _tls_certfile(tmp_ctx, lp_ctx);362 const char *cafile = lp _tls_cafile(tmp_ctx, lp_ctx);363 const char *crlfile = lp _tls_crlfile(tmp_ctx, lp_ctx);364 const char *dhpfile = lp _tls_dhpfile(tmp_ctx, lp_ctx);360 const char *keyfile = lpcfg_tls_keyfile(tmp_ctx, lp_ctx); 361 const char *certfile = lpcfg_tls_certfile(tmp_ctx, lp_ctx); 362 const char *cafile = lpcfg_tls_cafile(tmp_ctx, lp_ctx); 363 const char *crlfile = lpcfg_tls_crlfile(tmp_ctx, lp_ctx); 364 const char *dhpfile = lpcfg_tls_dhpfile(tmp_ctx, lp_ctx); 365 365 void tls_cert_generate(TALLOC_CTX *, const char *, const char *, const char *, const char *); 366 366 params = talloc(mem_ctx, struct tls_params); … … 370 370 } 371 371 372 if (!lp _tls_enabled(lp_ctx) || keyfile == NULL || *keyfile == 0) {372 if (!lpcfg_tls_enabled(lp_ctx) || keyfile == NULL || *keyfile == 0) { 373 373 params->tls_enabled = false; 374 374 talloc_free(tmp_ctx); … … 378 378 if (!file_exist(cafile)) { 379 379 char *hostname = talloc_asprintf(mem_ctx, "%s.%s", 380 lp_netbios_name(lp_ctx), lp_realm(lp_ctx)); 380 lpcfg_netbios_name(lp_ctx), 381 lpcfg_dnsdomain(lp_ctx)); 381 382 if (hostname == NULL) { 382 383 goto init_failed; -
trunk/server/source4/lib/tls/tls.h
r414 r745 66 66 const struct socket_ops *socket_tls_ops(enum socket_type type); 67 67 68 #endif 68 struct tstream_context; 69 struct tstream_tls_params; 70 71 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx, 72 const char *ca_file, 73 const char *crl_file, 74 struct tstream_tls_params **_tlsp); 75 76 NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx, 77 const char *dns_host_name, 78 bool enabled, 79 const char *key_file, 80 const char *cert_file, 81 const char *ca_file, 82 const char *crl_file, 83 const char *dhp_file, 84 struct tstream_tls_params **_params); 85 86 bool tstream_tls_params_enabled(struct tstream_tls_params *params); 87 88 struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx, 89 struct tevent_context *ev, 90 struct tstream_context *plain_stream, 91 struct tstream_tls_params *tls_params, 92 const char *location); 93 #define tstream_tls_connect_send(mem_ctx, ev, plain_stream, tls_params); \ 94 _tstream_tls_connect_send(mem_ctx, ev, plain_stream, tls_params, __location__) 95 96 int tstream_tls_connect_recv(struct tevent_req *req, 97 int *perrno, 98 TALLOC_CTX *mem_ctx, 99 struct tstream_context **tls_stream); 100 101 struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx, 102 struct tevent_context *ev, 103 struct tstream_context *plain_stream, 104 struct tstream_tls_params *tls_params, 105 const char *location); 106 #define tstream_tls_accept_send(mem_ctx, ev, plain_stream, tls_params) \ 107 _tstream_tls_accept_send(mem_ctx, ev, plain_stream, tls_params, __location__) 108 109 int tstream_tls_accept_recv(struct tevent_req *req, 110 int *perrno, 111 TALLOC_CTX *mem_ctx, 112 struct tstream_context **tls_stream); 113 114 #endif /* _TLS_H_ */ -
trunk/server/source4/lib/tls/tlscert.c
r414 r745 139 139 bufsize = sizeof(buf); 140 140 TLSCHECK(gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buf, &bufsize)); 141 file_save(certfile, buf, bufsize); 141 if (!file_save(certfile, buf, bufsize)) { 142 DEBUG(0,("Unable to save certificate in %s parent dir exists ?\n", certfile)); 143 goto failed; 144 } 142 145 143 146 bufsize = sizeof(buf); 144 147 TLSCHECK(gnutls_x509_crt_export(cacrt, GNUTLS_X509_FMT_PEM, buf, &bufsize)); 145 file_save(cafile, buf, bufsize); 148 if (!file_save(cafile, buf, bufsize)) { 149 DEBUG(0,("Unable to save ca cert in %s parent dir exists ?\n", cafile)); 150 goto failed; 151 } 146 152 147 153 bufsize = sizeof(buf); 148 154 TLSCHECK(gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buf, &bufsize)); 149 file_save(keyfile, buf, bufsize); 155 if (!file_save(keyfile, buf, bufsize)) { 156 DEBUG(0,("Unable to save privatekey in %s parent dir exists ?\n", keyfile)); 157 goto failed; 158 } 150 159 151 160 gnutls_x509_privkey_deinit(key); -
trunk/server/source4/lib/wmi/tools/wmic.c
r414 r745 36 36 37 37 struct program_args { 38 39 40 38 char *hostname; 39 char *query; 40 char *ns; 41 41 }; 42 42 43 43 static void parse_args(int argc, char *argv[], struct program_args *pmyargs) 44 44 { 45 poptContext pc; 46 int opt, i; 47 48 int argc_new; 49 char **argv_new; 50 51 struct poptOption long_options[] = { 52 POPT_AUTOHELP 53 POPT_COMMON_SAMBA 54 POPT_COMMON_CONNECTION 55 POPT_COMMON_CREDENTIALS 56 POPT_COMMON_VERSION 57 {"namespace", 0, POPT_ARG_STRING, &pmyargs->ns, 0, 58 "WMI namespace, default to root\\cimv2", 0}, 59 POPT_TABLEEND 60 }; 61 62 pc = poptGetContext("wmi", argc, (const char **) argv, 63 long_options, POPT_CONTEXT_KEEP_FIRST); 64 65 poptSetOtherOptionHelp(pc, "//host query\n\nExample: wmic -U [domain/]adminuser%password //host \"select * from Win32_ComputerSystem\""); 66 67 while ((opt = poptGetNextOpt(pc)) != -1) { 68 poptPrintUsage(pc, stdout, 0); 69 poptFreeContext(pc); 70 exit(1); 45 poptContext pc; 46 int opt, i; 47 48 int argc_new; 49 char **argv_new; 50 51 struct poptOption long_options[] = { 52 POPT_AUTOHELP 53 POPT_COMMON_SAMBA 54 POPT_COMMON_CONNECTION 55 POPT_COMMON_CREDENTIALS 56 POPT_COMMON_VERSION 57 {"namespace", 0, POPT_ARG_STRING, &pmyargs->ns, 0, 58 "WMI namespace, default to root\\cimv2", 0}, 59 POPT_TABLEEND 60 }; 61 62 pc = poptGetContext("wmi", argc, (const char **) argv, 63 long_options, POPT_CONTEXT_KEEP_FIRST); 64 65 poptSetOtherOptionHelp(pc, "//host query\n\nExample: wmic -U [domain/]adminuser%password //host \"select * from Win32_ComputerSystem\""); 66 67 while ((opt = poptGetNextOpt(pc)) != -1) { 68 poptPrintUsage(pc, stdout, 0); 69 poptFreeContext(pc); 70 exit(1); 71 } 72 73 argv_new = discard_const_p(char *, poptGetArgs(pc)); 74 75 argc_new = argc; 76 for (i = 0; i < argc; i++) { 77 if (argv_new[i] == NULL) { 78 argc_new = i; 79 break; 71 80 } 72 73 argv_new = discard_const_p(char *, poptGetArgs(pc)); 74 75 argc_new = argc; 76 for (i = 0; i < argc; i++) { 77 if (argv_new[i] == NULL) { 78 argc_new = i; 79 break; 80 } 81 } 82 83 if (argc_new != 3 || argv_new[1][0] != '/' 84 || argv_new[1][1] != '/') { 85 poptPrintUsage(pc, stdout, 0); 86 poptFreeContext(pc); 87 exit(1); 88 } 89 90 pmyargs->hostname = argv_new[1] + 2; 91 pmyargs->query = argv_new[2]; 81 } 82 83 if (argc_new != 3 || argv_new[1][0] != '/' 84 || argv_new[1][1] != '/') { 85 poptPrintUsage(pc, stdout, 0); 92 86 poptFreeContext(pc); 93 } 94 95 static void escape_string(const char *src, char *dst, int len) 96 { 97 char *p = dst, *end = dst + len - 1; 98 const char *q = src; 99 100 if ( q == NULL) { 101 strncpy( dst, "(null)", len); 102 return; 103 } 104 105 while ( *q && p <= end ) { 106 if ( strchr( "|\\(),", *q)) { 107 *p++ = '\\'; 108 *p++ = *q++; 109 } else if ( *q == '\n' ) { 110 *p++ = '\\'; 111 *p++ = 'n'; 112 q++; 113 } else if ( *q == '\r' ) { 114 *p++ = '\\'; 115 *p++ = 'r'; 116 q++; 117 } else { 118 *p++ = *q++; 119 } 120 } 121 122 *p++ = 0; 87 exit(1); 88 } 89 90 pmyargs->hostname = argv_new[1] + 2; 91 pmyargs->query = argv_new[2]; 92 poptFreeContext(pc); 123 93 } 124 94 … … 130 100 } 131 101 132 #define RETURN_CVAR_ARRAY_STR _START(arr) {\133 102 #define RETURN_CVAR_ARRAY_STR(fmt, arr) {\ 103 uint32_t i;\ 134 104 char *r;\ 135 105 \ 136 137 return talloc_strdup(mem_ctx, "(null)");\138 106 if (!arr) {\ 107 return talloc_strdup(mem_ctx, "NULL");\ 108 }\ 139 109 r = talloc_strdup(mem_ctx, "(");\ 140 for (i = 0; i < arr->count; ++i) { 141 142 143 #define RETURN_CVAR_ARRAY_STR_END(fmt, arr, item) \ 144 r = talloc_asprintf_append(r, fmt "%s", item, (i+1 == arr->count)?"":",");\ 145 }\ 146 return talloc_asprintf_append(r, ")");\ 147 } 148 149 #define RETURN_CVAR_ARRAY_STR(fmt, arr) \ 150 RETURN_CVAR_ARRAY_STR_START(arr) \ 151 RETURN_CVAR_ARRAY_STR_END(fmt, arr, arr->item[i]) 152 153 #define RETURN_CVAR_ARRAY_ESCAPED(fmt, arr) \ 154 RETURN_CVAR_ARRAY_STR_START(arr) \ 155 char buf[2048]; \ 156 escape_string( arr->item[i], buf, 2048); \ 157 RETURN_CVAR_ARRAY_STR_END(fmt, arr, buf) 110 for (i = 0; i < arr->count; ++i) {\ 111 r = talloc_asprintf_append(r, fmt "%s", arr->item[i], (i+1 == arr->count)?"":",");\ 112 }\ 113 return talloc_asprintf_append(r, ")");\ 114 } 158 115 159 116 char *string_CIMVAR(TALLOC_CTX *mem_ctx, union CIMVAR *v, enum CIMTYPE_ENUMERATION cimtype) … … 173 130 case CIM_STRING: 174 131 case CIM_DATETIME: 175 case CIM_REFERENCE: { 176 char buf[2048]; 177 escape_string((char*) v-> v_string, buf, 2048); 178 return talloc_asprintf(mem_ctx, "%s", buf); 179 } 132 case CIM_REFERENCE: return talloc_asprintf(mem_ctx, "%s", v->v_string); 180 133 case CIM_CHAR16: return talloc_asprintf(mem_ctx, "Unsupported"); 181 134 case CIM_OBJECT: return talloc_asprintf(mem_ctx, "Unsupported"); … … 191 144 case CIM_ARR_REAL64: RETURN_CVAR_ARRAY_STR("%f", v->a_real64); 192 145 case CIM_ARR_BOOLEAN: RETURN_CVAR_ARRAY_STR("%d", v->a_boolean); 193 case CIM_ARR_STRING: RETURN_CVAR_ARRAY_ ESCAPED("%s", v->a_string);194 case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY_ ESCAPED("%s", v->a_datetime);195 case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY_ ESCAPED("%s", v->a_reference);146 case CIM_ARR_STRING: RETURN_CVAR_ARRAY_STR("%s", v->a_string); 147 case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY_STR("%s", v->a_datetime); 148 case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY_STR("%s", v->a_reference); 196 149 default: return talloc_asprintf(mem_ctx, "Unsupported"); 197 150 }
Note:
See TracChangeset
for help on using the changeset viewer.