root/source4/lib/ldb-samba/ldif_handlers.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ldif_read_objectSid
  2. ldif_write_objectSid
  3. ldb_comparision_objectSid_isString
  4. ldb_comparison_objectSid
  5. ldb_canonicalise_objectSid
  6. extended_dn_read_SID
  7. ldif_read_objectGUID
  8. ldif_write_objectGUID
  9. ldb_comparision_objectGUID_isString
  10. extended_dn_read_GUID
  11. ldb_comparison_objectGUID
  12. ldb_canonicalise_objectGUID
  13. ldif_read_ntSecurityDescriptor
  14. ldif_write_ntSecurityDescriptor
  15. ldif_canonicalise_objectCategory
  16. ldif_comparison_objectCategory
  17. ldif_read_prefixMap
  18. ldif_write_prefixMap
  19. ldif_comparision_prefixMap_isString
  20. ldif_canonicalise_prefixMap
  21. ldif_comparison_prefixMap
  22. extended_dn_write_hex
  23. ldb_samba_syntax_by_name
  24. ldb_register_samba_handlers

   1 /* 
   2    ldb database library - ldif handlers for Samba
   3 
   4    Copyright (C) Andrew Tridgell 2005
   5    Copyright (C) Andrew Bartlett 2006-2007
   6      ** NOTE! The following LGPL license applies to the ldb
   7      ** library. This does NOT imply that all of Samba is released
   8      ** under the LGPL
   9    
  10    This library is free software; you can redistribute it and/or
  11    modify it under the terms of the GNU Lesser General Public
  12    License as published by the Free Software Foundation; either
  13    version 3 of the License, or (at your option) any later version.
  14 
  15    This library is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18    Lesser General Public License for more details.
  19 
  20    You should have received a copy of the GNU Lesser General Public
  21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 #include "ldb_private.h"
  26 #include "ldb_handlers.h"
  27 #include "dsdb/samdb/samdb.h"
  28 #include "librpc/gen_ndr/ndr_security.h"
  29 #include "librpc/gen_ndr/ndr_misc.h"
  30 #include "librpc/gen_ndr/ndr_drsblobs.h"
  31 #include "libcli/security/security.h"
  32 #include "param/param.h"
  33 
  34 /*
  35   convert a ldif formatted objectSid to a NDR formatted blob
  36 */
  37 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  38                                const struct ldb_val *in, struct ldb_val *out)
  39 {
  40         enum ndr_err_code ndr_err;
  41         struct dom_sid *sid;
  42         sid = dom_sid_parse_length(mem_ctx, in);
  43         if (sid == NULL) {
  44                 return -1;
  45         }
  46         ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, sid,
  47                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
  48         talloc_free(sid);
  49         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
  50                 return -1;
  51         }
  52         return 0;
  53 }
  54 
  55 /*
  56   convert a NDR formatted blob to a ldif formatted objectSid
  57 */
  58 static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  59                                 const struct ldb_val *in, struct ldb_val *out)
  60 {
  61         struct dom_sid *sid;
  62         enum ndr_err_code ndr_err;
  63 
  64         sid = talloc(mem_ctx, struct dom_sid);
  65         if (sid == NULL) {
  66                 return -1;
  67         }
  68         ndr_err = ndr_pull_struct_blob_all(in, sid, NULL, sid,
  69                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
  70         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
  71                 talloc_free(sid);
  72                 return -1;
  73         }
  74         *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
  75         talloc_free(sid);
  76         if (out->data == NULL) {
  77                 return -1;
  78         }
  79         return 0;
  80 }
  81 
  82 static bool ldb_comparision_objectSid_isString(const struct ldb_val *v)
     /* [<][>][^][v][top][bottom][index][help] */
  83 {
  84         if (v->length < 3) {
  85                 return false;
  86         }
  87 
  88         if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
  89         
  90         return true;
  91 }
  92 
  93 /*
  94   compare two objectSids
  95 */
  96 static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  97                                     const struct ldb_val *v1, const struct ldb_val *v2)
  98 {
  99         if (ldb_comparision_objectSid_isString(v1) && ldb_comparision_objectSid_isString(v2)) {
 100                 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 101         } else if (ldb_comparision_objectSid_isString(v1)
 102                    && !ldb_comparision_objectSid_isString(v2)) {
 103                 struct ldb_val v;
 104                 int ret;
 105                 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
 106                         /* Perhaps not a string after all */
 107                         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 108                 }
 109                 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
 110                 talloc_free(v.data);
 111                 return ret;
 112         } else if (!ldb_comparision_objectSid_isString(v1)
 113                    && ldb_comparision_objectSid_isString(v2)) {
 114                 struct ldb_val v;
 115                 int ret;
 116                 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
 117                         /* Perhaps not a string after all */
 118                         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 119                 }
 120                 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
 121                 talloc_free(v.data);
 122                 return ret;
 123         }
 124         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 125 }
 126 
 127 /*
 128   canonicalise a objectSid
 129 */
 130 static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 131                                       const struct ldb_val *in, struct ldb_val *out)
 132 {
 133         if (ldb_comparision_objectSid_isString(in)) {
 134                 if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
 135                         /* Perhaps not a string after all */
 136                         return ldb_handler_copy(ldb, mem_ctx, in, out);
 137                 }
 138                 return 0;
 139         }
 140         return ldb_handler_copy(ldb, mem_ctx, in, out);
 141 }
 142 
 143 static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 144                               const struct ldb_val *in, struct ldb_val *out)
 145 {
 146         struct dom_sid sid;
 147         enum ndr_err_code ndr_err;
 148         if (ldb_comparision_objectSid_isString(in)) {
 149                 if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
 150                         return 0;
 151                 }
 152         }
 153         
 154         /* Perhaps not a string after all */
 155         *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
 156 
 157         if (!out->data) {
 158                 return -1;
 159         }
 160 
 161         (*out).length = strhex_to_str((char *)out->data, out->length,
 162                                      (const char *)in->data, in->length);
 163 
 164         /* Check it looks like a SID */
 165         ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, NULL, &sid,
 166                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
 167         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 168                 return -1;
 169         }
 170         return 0;
 171 }
 172 
 173 /*
 174   convert a ldif formatted objectGUID to a NDR formatted blob
 175 */
 176 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 177                                 const struct ldb_val *in, struct ldb_val *out)
 178 {
 179         struct GUID guid;
 180         NTSTATUS status;
 181         enum ndr_err_code ndr_err;
 182 
 183         status = GUID_from_data_blob(in, &guid);
 184         if (!NT_STATUS_IS_OK(status)) {
 185                 return -1;
 186         }
 187 
 188         ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, &guid,
 189                                        (ndr_push_flags_fn_t)ndr_push_GUID);
 190         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 191                 return -1;
 192         }
 193         return 0;
 194 }
 195 
 196 /*
 197   convert a NDR formatted blob to a ldif formatted objectGUID
 198 */
 199 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 200                                  const struct ldb_val *in, struct ldb_val *out)
 201 {
 202         struct GUID guid;
 203         enum ndr_err_code ndr_err;
 204         ndr_err = ndr_pull_struct_blob_all(in, mem_ctx, NULL, &guid,
 205                                            (ndr_pull_flags_fn_t)ndr_pull_GUID);
 206         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 207                 return -1;
 208         }
 209         out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
 210         if (out->data == NULL) {
 211                 return -1;
 212         }
 213         out->length = strlen((const char *)out->data);
 214         return 0;
 215 }
 216 
 217 static bool ldb_comparision_objectGUID_isString(const struct ldb_val *v)
     /* [<][>][^][v][top][bottom][index][help] */
 218 {
 219         if (v->length != 36 && v->length != 38) return false;
 220 
 221         /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
 222         return true;
 223 }
 224 
 225 static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 226                               const struct ldb_val *in, struct ldb_val *out)
 227 {
 228         struct GUID guid;
 229         enum ndr_err_code ndr_err;
 230         if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
 231                 return 0;
 232         }
 233 
 234         /* Try as 'hex' form */
 235         if (in->length != 32) {
 236                 return -1;
 237         }
 238                 
 239         *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
 240         
 241         if (!out->data) {
 242                 return -1;
 243         }
 244         
 245         (*out).length = strhex_to_str((char *)out->data, out->length,
 246                                       (const char *)in->data, in->length);
 247         
 248         /* Check it looks like a GUID */
 249         ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, NULL, &guid,
 250                                            (ndr_pull_flags_fn_t)ndr_pull_GUID);
 251         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 252                 return -1;
 253         }
 254         return 0;
 255 }
 256 
 257 /*
 258   compare two objectGUIDs
 259 */
 260 static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 261                                      const struct ldb_val *v1, const struct ldb_val *v2)
 262 {
 263         if (ldb_comparision_objectGUID_isString(v1) && ldb_comparision_objectGUID_isString(v2)) {
 264                 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 265         } else if (ldb_comparision_objectGUID_isString(v1)
 266                    && !ldb_comparision_objectGUID_isString(v2)) {
 267                 struct ldb_val v;
 268                 int ret;
 269                 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
 270                         /* Perhaps it wasn't a valid string after all */
 271                         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 272                 }
 273                 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
 274                 talloc_free(v.data);
 275                 return ret;
 276         } else if (!ldb_comparision_objectGUID_isString(v1)
 277                    && ldb_comparision_objectGUID_isString(v2)) {
 278                 struct ldb_val v;
 279                 int ret;
 280                 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
 281                         /* Perhaps it wasn't a valid string after all */
 282                         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 283                 }
 284                 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
 285                 talloc_free(v.data);
 286                 return ret;
 287         }
 288         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 289 }
 290 
 291 /*
 292   canonicalise a objectGUID
 293 */
 294 static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 295                                        const struct ldb_val *in, struct ldb_val *out)
 296 {
 297         if (ldb_comparision_objectGUID_isString(in)) {
 298                 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
 299                         /* Perhaps it wasn't a valid string after all */
 300                         return ldb_handler_copy(ldb, mem_ctx, in, out);
 301                 }
 302                 return 0;
 303         }
 304         return ldb_handler_copy(ldb, mem_ctx, in, out);
 305 }
 306 
 307 
 308 /*
 309   convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
 310 */
 311 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 312                                           const struct ldb_val *in, struct ldb_val *out)
 313 {
 314         struct security_descriptor *sd;
 315         enum ndr_err_code ndr_err;
 316 
 317         sd = sddl_decode(mem_ctx, (const char *)in->data, NULL);
 318         if (sd == NULL) {
 319                 return -1;
 320         }
 321         ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, sd,
 322                                        (ndr_push_flags_fn_t)ndr_push_security_descriptor);
 323         talloc_free(sd);
 324         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 325                 return -1;
 326         }
 327         return 0;
 328 }
 329 
 330 /*
 331   convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
 332 */
 333 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 334                                            const struct ldb_val *in, struct ldb_val *out)
 335 {
 336         struct security_descriptor *sd;
 337         enum ndr_err_code ndr_err;
 338 
 339         sd = talloc(mem_ctx, struct security_descriptor);
 340         if (sd == NULL) {
 341                 return -1;
 342         }
 343         /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
 344         ndr_err = ndr_pull_struct_blob(in, sd, NULL, sd,
 345                                            (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
 346         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 347                 talloc_free(sd);
 348                 return -1;
 349         }
 350         out->data = (uint8_t *)sddl_encode(mem_ctx, sd, NULL);
 351         talloc_free(sd);
 352         if (out->data == NULL) {
 353                 return -1;
 354         }
 355         out->length = strlen((const char *)out->data);
 356         return 0;
 357 }
 358 
 359 /* 
 360    canonicalise an objectCategory.  We use the short form as the cannoical form:
 361    cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
 362 */
 363 
 364 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 365                                             const struct ldb_val *in, struct ldb_val *out)
 366 {
 367         struct ldb_dn *dn1 = NULL;
 368         const struct dsdb_schema *schema = dsdb_get_schema(ldb);
 369         const struct dsdb_class *sclass;
 370         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 371         if (!tmp_ctx) {
 372                 return LDB_ERR_OPERATIONS_ERROR;
 373         }
 374 
 375         if (!schema) {
 376                 *out = data_blob_talloc(mem_ctx, in->data, in->length);
 377                 if (in->data && !out->data) {
 378                         return LDB_ERR_OPERATIONS_ERROR;
 379                 }
 380                 return LDB_SUCCESS;
 381         }
 382         dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
 383         if ( ! ldb_dn_validate(dn1)) {
 384                 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
 385                 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
 386                 if (sclass) {
 387                         struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,  
 388                                                        sclass->defaultObjectCategory);
 389                         *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
 390                         talloc_free(tmp_ctx);
 391 
 392                         if (!out->data) {
 393                                 return LDB_ERR_OPERATIONS_ERROR;
 394                         }
 395                         return LDB_SUCCESS;
 396                 } else {
 397                         *out = data_blob_talloc(mem_ctx, in->data, in->length);
 398                         talloc_free(tmp_ctx);
 399 
 400                         if (in->data && !out->data) {
 401                                 return LDB_ERR_OPERATIONS_ERROR;
 402                         }
 403                         return LDB_SUCCESS;
 404                 }
 405         }
 406         *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
 407         talloc_free(tmp_ctx);
 408 
 409         if (!out->data) {
 410                 return LDB_ERR_OPERATIONS_ERROR;
 411         }
 412         return LDB_SUCCESS;
 413 }
 414 
 415 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 416                                           const struct ldb_val *v1,
 417                                           const struct ldb_val *v2)
 418 {
 419 
 420         int ret, ret1, ret2;
 421         struct ldb_val v1_canon, v2_canon;
 422         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 423 
 424         /* I could try and bail if tmp_ctx was NULL, but what return
 425          * value would I use?
 426          *
 427          * It seems easier to continue on the NULL context 
 428          */
 429         ret1 = ldif_canonicalise_objectCategory(ldb, tmp_ctx, v1, &v1_canon);
 430         ret2 = ldif_canonicalise_objectCategory(ldb, tmp_ctx, v2, &v2_canon);
 431 
 432         if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
 433                 ret = data_blob_cmp(&v1_canon, &v2_canon);
 434         } else {
 435                 ret = data_blob_cmp(v1, v2);
 436         }
 437         talloc_free(tmp_ctx);
 438         return ret;
 439 }
 440 
 441 /*
 442   convert a ldif formatted prefixMap to a NDR formatted blob
 443 */
 444 static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 445                                const struct ldb_val *in, struct ldb_val *out)
 446 {
 447         struct prefixMapBlob *blob;
 448         enum ndr_err_code ndr_err;
 449         char *string, *line, *p, *oid;
 450 
 451         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 452 
 453         if (tmp_ctx == NULL) {
 454                 return -1;
 455         }
 456 
 457         blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
 458         if (blob == NULL) {
 459                 talloc_free(blob);
 460                 return -1;
 461         }
 462 
 463         blob->version = PREFIX_MAP_VERSION_DSDB;
 464         
 465         string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
 466         if (string == NULL) {
 467                 talloc_free(blob);
 468                 return -1;
 469         }
 470 
 471         line = string;
 472         while (line && line[0]) {
 473                 p=strchr(line, ';');
 474                 if (p) {
 475                         p[0] = '\0';
 476                 } else {
 477                         p=strchr(line, '\n');
 478                         if (p) {
 479                                 p[0] = '\0';
 480                         }
 481                 }
 482                 /* allow a traling seperator */
 483                 if (line == p) {
 484                         break;
 485                 }
 486                 
 487                 blob->ctr.dsdb.mappings = talloc_realloc(blob, 
 488                                                          blob->ctr.dsdb.mappings, 
 489                                                          struct drsuapi_DsReplicaOIDMapping,
 490                                                          blob->ctr.dsdb.num_mappings+1);
 491                 if (!blob->ctr.dsdb.mappings) {
 492                         talloc_free(tmp_ctx);
 493                         return -1;
 494                 }
 495 
 496                 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
 497 
 498                 if (oid[0] != ':') {
 499                         talloc_free(tmp_ctx);
 500                         return -1;
 501                 }
 502 
 503                 /* we know there must be at least ":" */
 504                 oid++;
 505 
 506                 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.oid
 507                         = talloc_strdup(blob->ctr.dsdb.mappings, oid);
 508 
 509                 blob->ctr.dsdb.num_mappings++;
 510 
 511                 /* Now look past the terminator we added above */
 512                 if (p) {
 513                         line = p + 1;
 514                 } else {
 515                         line = NULL;
 516                 }
 517         }
 518 
 519         ndr_err = ndr_push_struct_blob(out, mem_ctx, 
 520                                        lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 
 521                                        blob,
 522                                        (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
 523         talloc_free(tmp_ctx);
 524         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 525                 return -1;
 526         }
 527         return 0;
 528 }
 529 
 530 /*
 531   convert a NDR formatted blob to a ldif formatted prefixMap
 532 */
 533 static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 534                                 const struct ldb_val *in, struct ldb_val *out)
 535 {
 536         struct prefixMapBlob *blob;
 537         enum ndr_err_code ndr_err;
 538         char *string;
 539         uint32_t i;
 540 
 541         blob = talloc(mem_ctx, struct prefixMapBlob);
 542         if (blob == NULL) {
 543                 return -1;
 544         }
 545         ndr_err = ndr_pull_struct_blob_all(in, blob, 
 546                                            lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), 
 547                                            blob,
 548                                            (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
 549         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 550                 talloc_free(blob);
 551                 return -1;
 552         }
 553         if (blob->version != PREFIX_MAP_VERSION_DSDB) {
 554                 return -1;
 555         }
 556         string = talloc_strdup(mem_ctx, "");
 557         if (string == NULL) {
 558                 return -1;
 559         }
 560 
 561         for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
 562                 if (i > 0) {
 563                         string = talloc_asprintf_append(string, ";"); 
 564                 }
 565                 string = talloc_asprintf_append(string, "%u:%s", 
 566                                                    blob->ctr.dsdb.mappings[i].id_prefix,
 567                                                    blob->ctr.dsdb.mappings[i].oid.oid);
 568                 if (string == NULL) {
 569                         return -1;
 570                 }
 571         }
 572 
 573         talloc_free(blob);
 574         *out = data_blob_string_const(string);
 575         return 0;
 576 }
 577 
 578 static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
     /* [<][>][^][v][top][bottom][index][help] */
 579 {
 580         if (v->length < 4) {
 581                 return true;
 582         }
 583 
 584         if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
 585                 return false;
 586         }
 587         
 588         return true;
 589 }
 590 
 591 /*
 592   canonicalise a prefixMap
 593 */
 594 static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 595                                        const struct ldb_val *in, struct ldb_val *out)
 596 {
 597         if (ldif_comparision_prefixMap_isString(in)) {
 598                 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
 599         }
 600         return ldb_handler_copy(ldb, mem_ctx, in, out);
 601 }
 602 
 603 static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 604                                      const struct ldb_val *v1,
 605                                      const struct ldb_val *v2)
 606 {
 607 
 608         int ret, ret1, ret2;
 609         struct ldb_val v1_canon, v2_canon;
 610         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 611 
 612         /* I could try and bail if tmp_ctx was NULL, but what return
 613          * value would I use?
 614          *
 615          * It seems easier to continue on the NULL context 
 616          */
 617         ret1 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v1, &v1_canon);
 618         ret2 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v2, &v2_canon);
 619 
 620         if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
 621                 ret = data_blob_cmp(&v1_canon, &v2_canon);
 622         } else {
 623                 ret = data_blob_cmp(v1, v2);
 624         }
 625         talloc_free(tmp_ctx);
 626         return ret;
 627 }
 628 
 629 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 630                                  const struct ldb_val *in, struct ldb_val *out)
 631 {
 632         *out = data_blob_string_const(data_blob_hex_string(mem_ctx, in));
 633         if (!out->data) {
 634                 return -1;
 635         }
 636         return 0;
 637 }
 638 
 639 
 640 #define LDB_SYNTAX_SAMBA_GUID                   "LDB_SYNTAX_SAMBA_GUID"
 641 #define LDB_SYNTAX_SAMBA_OBJECT_CATEGORY        "LDB_SYNTAX_SAMBA_OBJECT_CATEGORY"
 642 #define LDB_SYNTAX_SAMBA_PREFIX_MAP     "LDB_SYNTAX_SAMBA_PREFIX_MAP"
 643 
 644 static const struct ldb_schema_syntax samba_syntaxes[] = {
 645         {
 646                 .name             = LDB_SYNTAX_SAMBA_SID,
 647                 .ldif_read_fn     = ldif_read_objectSid,
 648                 .ldif_write_fn    = ldif_write_objectSid,
 649                 .canonicalise_fn  = ldb_canonicalise_objectSid,
 650                 .comparison_fn    = ldb_comparison_objectSid
 651         },{
 652                 .name             = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
 653                 .ldif_read_fn     = ldif_read_ntSecurityDescriptor,
 654                 .ldif_write_fn    = ldif_write_ntSecurityDescriptor,
 655                 .canonicalise_fn  = ldb_handler_copy,
 656                 .comparison_fn    = ldb_comparison_binary
 657         },{
 658                 .name             = LDB_SYNTAX_SAMBA_GUID,
 659                 .ldif_read_fn     = ldif_read_objectGUID,
 660                 .ldif_write_fn    = ldif_write_objectGUID,
 661                 .canonicalise_fn  = ldb_canonicalise_objectGUID,
 662                 .comparison_fn    = ldb_comparison_objectGUID
 663         },{
 664                 .name             = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
 665                 .ldif_read_fn     = ldb_handler_copy,
 666                 .ldif_write_fn    = ldb_handler_copy,
 667                 .canonicalise_fn  = ldif_canonicalise_objectCategory,
 668                 .comparison_fn    = ldif_comparison_objectCategory
 669         },{
 670                 .name             = LDB_SYNTAX_SAMBA_PREFIX_MAP,
 671                 .ldif_read_fn     = ldif_read_prefixMap,
 672                 .ldif_write_fn    = ldif_write_prefixMap,
 673                 .canonicalise_fn  = ldif_canonicalise_prefixMap,
 674                 .comparison_fn    = ldif_comparison_prefixMap
 675         }
 676 };
 677 
 678 static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
 679         {
 680                 .name             = "SID",
 681                 .read_fn          = extended_dn_read_SID,
 682                 .write_clear_fn   = ldif_write_objectSid,
 683                 .write_hex_fn     = extended_dn_write_hex
 684         },{
 685                 .name             = "GUID",
 686                 .read_fn          = extended_dn_read_GUID,
 687                 .write_clear_fn   = ldif_write_objectGUID,
 688                 .write_hex_fn     = extended_dn_write_hex
 689         },{
 690                 .name             = "WKGUID",
 691                 .read_fn          = ldb_handler_copy,
 692                 .write_clear_fn   = ldb_handler_copy,
 693                 .write_hex_fn     = ldb_handler_copy
 694         }
 695 };
 696 
 697 static const struct {
 698         const char *name;
 699         const char *syntax;
 700 } samba_attributes[] = {
 701         { "objectSid",                  LDB_SYNTAX_SAMBA_SID },
 702         { "securityIdentifier",         LDB_SYNTAX_SAMBA_SID },
 703         { "ntSecurityDescriptor",       LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
 704         { "objectGUID",                 LDB_SYNTAX_SAMBA_GUID },
 705         { "invocationId",               LDB_SYNTAX_SAMBA_GUID },
 706         { "schemaIDGUID",               LDB_SYNTAX_SAMBA_GUID },
 707         { "attributeSecurityGUID",      LDB_SYNTAX_SAMBA_GUID },
 708         { "parentGUID",                 LDB_SYNTAX_SAMBA_GUID },
 709         { "siteGUID",                   LDB_SYNTAX_SAMBA_GUID },
 710         { "pKTGUID",                    LDB_SYNTAX_SAMBA_GUID },
 711         { "fRSVersionGUID",             LDB_SYNTAX_SAMBA_GUID },
 712         { "fRSReplicaSetGUID",          LDB_SYNTAX_SAMBA_GUID },
 713         { "netbootGUID",                LDB_SYNTAX_SAMBA_GUID },
 714         { "objectCategory",             LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
 715         { "prefixMap",                  LDB_SYNTAX_SAMBA_PREFIX_MAP }
 716 };
 717 
 718 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 719 {
 720         uint32_t j;
 721         const struct ldb_schema_syntax *s = NULL;
 722         
 723         for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
 724                 if (strcmp(name, samba_syntaxes[j].name) == 0) {
 725                         s = &samba_syntaxes[j];
 726                         break;
 727                 }
 728         }
 729         return s;
 730 }
 731 
 732 
 733 /*
 734   register the samba ldif handlers
 735 */
 736 int ldb_register_samba_handlers(struct ldb_context *ldb)
     /* [<][>][^][v][top][bottom][index][help] */
 737 {
 738         uint32_t i;
 739 
 740         for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
 741                 int ret;
 742                 const struct ldb_schema_syntax *s = NULL;
 743 
 744                 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
 745 
 746                 if (!s) {
 747                         s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
 748                 }
 749 
 750                 if (!s) {
 751                         return -1;
 752                 }
 753 
 754                 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
 755                 if (ret != LDB_SUCCESS) {
 756                         return ret;
 757                 }
 758         }
 759 
 760         for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
 761                 int ret;
 762                 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
 763                 if (ret != LDB_SUCCESS) {
 764                         return ret;
 765                 }
 766 
 767                 
 768         }
 769 
 770         return LDB_SUCCESS;
 771 }

/* [<][>][^][v][top][bottom][index][help] */