root/source3/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. ldif_read_objectGUID
  7. ldif_write_objectGUID
  8. ldb_comparision_objectGUID_isString
  9. ldb_comparison_objectGUID
  10. ldb_canonicalise_objectGUID
  11. ldif_read_ntSecurityDescriptor
  12. ldif_write_ntSecurityDescriptor
  13. ldif_canonicalise_objectCategory
  14. ldif_comparison_objectCategory
  15. 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
   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/include/includes.h"
  26 
  27 #include "librpc/gen_ndr/ndr_security.h"
  28 #include "librpc/gen_ndr/ndr_misc.h"
  29 #include "dsdb/samdb/samdb.h"
  30 #include "libcli/security/security.h"
  31 
  32 /*
  33   convert a ldif formatted objectSid to a NDR formatted blob
  34 */
  35 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  36                                const struct ldb_val *in, struct ldb_val *out)
  37 {
  38         struct dom_sid *sid;
  39         NTSTATUS status;
  40         sid = dom_sid_parse_talloc(mem_ctx, (const char *)in->data);
  41         if (sid == NULL) {
  42                 return -1;
  43         }
  44         status = ndr_push_struct_blob(out, mem_ctx, sid, 
  45                                       (ndr_push_flags_fn_t)ndr_push_dom_sid);
  46         talloc_free(sid);
  47         if (!NT_STATUS_IS_OK(status)) {
  48                 return -1;
  49         }
  50         return 0;
  51 }
  52 
  53 /*
  54   convert a NDR formatted blob to a ldif formatted objectSid
  55 */
  56 static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  57                                 const struct ldb_val *in, struct ldb_val *out)
  58 {
  59         struct dom_sid *sid;
  60         NTSTATUS status;
  61         sid = talloc(mem_ctx, struct dom_sid);
  62         if (sid == NULL) {
  63                 return -1;
  64         }
  65         status = ndr_pull_struct_blob(in, sid, sid, 
  66                                       (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
  67         if (!NT_STATUS_IS_OK(status)) {
  68                 talloc_free(sid);
  69                 return -1;
  70         }
  71         out->data = (uint8_t *)dom_sid_string(mem_ctx, sid);
  72         talloc_free(sid);
  73         if (out->data == NULL) {
  74                 return -1;
  75         }
  76         out->length = strlen((const char *)out->data);
  77         return 0;
  78 }
  79 
  80 static BOOL ldb_comparision_objectSid_isString(const struct ldb_val *v)
     /* [<][>][^][v][top][bottom][index][help] */
  81 {
  82         if (v->length < 3) {
  83                 return False;
  84         }
  85 
  86         if (strncmp("S-", (const char *)v->data, 2) != 0) return False;
  87         
  88         return True;
  89 }
  90 
  91 /*
  92   compare two objectSids
  93 */
  94 static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  95                                     const struct ldb_val *v1, const struct ldb_val *v2)
  96 {
  97         if (ldb_comparision_objectSid_isString(v1) && ldb_comparision_objectSid_isString(v2)) {
  98                 return strcmp((const char *)v1->data, (const char *)v2->data);
  99         } else if (ldb_comparision_objectSid_isString(v1)
 100                    && !ldb_comparision_objectSid_isString(v2)) {
 101                 struct ldb_val v;
 102                 int ret;
 103                 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
 104                         return -1;
 105                 }
 106                 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
 107                 talloc_free(v.data);
 108                 return ret;
 109         } else if (!ldb_comparision_objectSid_isString(v1)
 110                    && ldb_comparision_objectSid_isString(v2)) {
 111                 struct ldb_val v;
 112                 int ret;
 113                 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
 114                         return -1;
 115                 }
 116                 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
 117                 talloc_free(v.data);
 118                 return ret;
 119         }
 120         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 121 }
 122 
 123 /*
 124   canonicalise a objectSid
 125 */
 126 static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 127                                       const struct ldb_val *in, struct ldb_val *out)
 128 {
 129         if (ldb_comparision_objectSid_isString(in)) {
 130                 return ldif_read_objectSid(ldb, mem_ctx, in, out);
 131         }
 132         return ldb_handler_copy(ldb, mem_ctx, in, out);
 133 }
 134 
 135 /*
 136   convert a ldif formatted objectGUID to a NDR formatted blob
 137 */
 138 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 139                                 const struct ldb_val *in, struct ldb_val *out)
 140 {
 141         struct GUID guid;
 142         NTSTATUS status;
 143 
 144         status = GUID_from_string((const char *)in->data, &guid);
 145         if (!NT_STATUS_IS_OK(status)) {
 146                 return -1;
 147         }
 148 
 149         status = ndr_push_struct_blob(out, mem_ctx, &guid,
 150                                       (ndr_push_flags_fn_t)ndr_push_GUID);
 151         if (!NT_STATUS_IS_OK(status)) {
 152                 return -1;
 153         }
 154         return 0;
 155 }
 156 
 157 /*
 158   convert a NDR formatted blob to a ldif formatted objectGUID
 159 */
 160 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 161                                  const struct ldb_val *in, struct ldb_val *out)
 162 {
 163         struct GUID guid;
 164         NTSTATUS status;
 165         status = ndr_pull_struct_blob(in, mem_ctx, &guid,
 166                                       (ndr_pull_flags_fn_t)ndr_pull_GUID);
 167         if (!NT_STATUS_IS_OK(status)) {
 168                 return -1;
 169         }
 170         out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
 171         if (out->data == NULL) {
 172                 return -1;
 173         }
 174         out->length = strlen((const char *)out->data);
 175         return 0;
 176 }
 177 
 178 static BOOL ldb_comparision_objectGUID_isString(const struct ldb_val *v)
     /* [<][>][^][v][top][bottom][index][help] */
 179 {
 180         struct GUID guid;
 181         NTSTATUS status;
 182 
 183         if (v->length < 33) return False;
 184 
 185         /* see if the input if null-terninated (safety check for the below) */
 186         if (v->data[v->length] != '\0') return False;
 187 
 188         status = GUID_from_string((const char *)v->data, &guid);
 189         if (!NT_STATUS_IS_OK(status)) {
 190                 return False;
 191         }
 192 
 193         return True;
 194 }
 195 
 196 /*
 197   compare two objectGUIDs
 198 */
 199 static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 200                                      const struct ldb_val *v1, const struct ldb_val *v2)
 201 {
 202         if (ldb_comparision_objectGUID_isString(v1) && ldb_comparision_objectGUID_isString(v2)) {
 203                 return strcmp((const char *)v1->data, (const char *)v2->data);
 204         } else if (ldb_comparision_objectGUID_isString(v1)
 205                    && !ldb_comparision_objectGUID_isString(v2)) {
 206                 struct ldb_val v;
 207                 int ret;
 208                 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
 209                         return -1;
 210                 }
 211                 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
 212                 talloc_free(v.data);
 213                 return ret;
 214         } else if (!ldb_comparision_objectGUID_isString(v1)
 215                    && ldb_comparision_objectGUID_isString(v2)) {
 216                 struct ldb_val v;
 217                 int ret;
 218                 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
 219                         return -1;
 220                 }
 221                 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
 222                 talloc_free(v.data);
 223                 return ret;
 224         }
 225         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 226 }
 227 
 228 /*
 229   canonicalise a objectGUID
 230 */
 231 static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 232                                        const struct ldb_val *in, struct ldb_val *out)
 233 {
 234         if (ldb_comparision_objectGUID_isString(in)) {
 235                 return ldif_read_objectGUID(ldb, mem_ctx, in, out);
 236         }
 237         return ldb_handler_copy(ldb, mem_ctx, in, out);
 238 }
 239 
 240 
 241 /*
 242   convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
 243 */
 244 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 245                                           const struct ldb_val *in, struct ldb_val *out)
 246 {
 247         struct security_descriptor *sd;
 248         NTSTATUS status;
 249 
 250         sd = sddl_decode(mem_ctx, (const char *)in->data, NULL);
 251         if (sd == NULL) {
 252                 return -1;
 253         }
 254         status = ndr_push_struct_blob(out, mem_ctx, sd, 
 255                                       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
 256         talloc_free(sd);
 257         if (!NT_STATUS_IS_OK(status)) {
 258                 return -1;
 259         }
 260         return 0;
 261 }
 262 
 263 /*
 264   convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
 265 */
 266 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 267                                            const struct ldb_val *in, struct ldb_val *out)
 268 {
 269         struct security_descriptor *sd;
 270         NTSTATUS status;
 271 
 272         sd = talloc(mem_ctx, struct security_descriptor);
 273         if (sd == NULL) {
 274                 return -1;
 275         }
 276         status = ndr_pull_struct_blob(in, sd, sd, 
 277                                       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
 278         if (!NT_STATUS_IS_OK(status)) {
 279                 talloc_free(sd);
 280                 return -1;
 281         }
 282         out->data = (uint8_t *)sddl_encode(mem_ctx, sd, NULL);
 283         talloc_free(sd);
 284         if (out->data == NULL) {
 285                 return -1;
 286         }
 287         out->length = strlen((const char *)out->data);
 288         return 0;
 289 }
 290 
 291 /* 
 292    canonicolise an objectCategory.  We use the short form as the cannoical form:
 293    cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
 294 */
 295 
 296 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 297                                             const struct ldb_val *in, struct ldb_val *out)
 298 {
 299         struct ldb_dn *dn1 = NULL;
 300         char *oc1, *oc2;
 301 
 302         dn1 = ldb_dn_explode(mem_ctx, (char *)in->data);
 303         if (dn1 == NULL) {
 304                 oc1 = talloc_strndup(mem_ctx, (char *)in->data, in->length);
 305         } else if (ldb_dn_get_comp_num(dn1) >= 1 && strcasecmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) {
 306                 const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
 307                 oc1 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
 308         } else {
 309                 return -1;
 310         }
 311 
 312         oc2 = ldb_casefold(ldb, mem_ctx, oc1);
 313         out->data = (void *)oc2;
 314         out->length = strlen(oc2);
 315         talloc_free(oc1);
 316         talloc_free(dn1);
 317         return 0;
 318 }
 319 
 320 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 321                                           const struct ldb_val *v1,
 322                                           const struct ldb_val *v2)
 323 {
 324         struct ldb_dn *dn1 = NULL, *dn2 = NULL;
 325         const char *oc1, *oc2;
 326 
 327         dn1 = ldb_dn_explode(mem_ctx, (char *)v1->data);
 328         if (dn1 == NULL) {
 329                 oc1 = talloc_strndup(mem_ctx, (char *)v1->data, v1->length);
 330         } else if (ldb_dn_get_comp_num(dn1) >= 1 && strcasecmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) {
 331                 const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
 332                 oc1 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
 333         } else {
 334                 oc1 = NULL;
 335         }
 336 
 337         dn2 = ldb_dn_explode(mem_ctx, (char *)v2->data);
 338         if (dn2 == NULL) {
 339                 oc2 = talloc_strndup(mem_ctx, (char *)v2->data, v2->length);
 340         } else if (ldb_dn_get_comp_num(dn2) >= 2 && strcasecmp(ldb_dn_get_rdn_name(dn2), "cn") == 0) {
 341                 const struct ldb_val *val = ldb_dn_get_rdn_val(dn2);
 342                 oc2 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
 343         } else {
 344                 oc2 = NULL;
 345         }
 346 
 347         oc1 = ldb_casefold(ldb, mem_ctx, oc1);
 348         oc2 = ldb_casefold(ldb, mem_ctx, oc2);
 349         if (!oc1 && oc2) {
 350                 return -1;
 351         } 
 352         if (oc1 && !oc2) {
 353                 return 1;
 354         }       
 355         if (!oc1 && !oc2) {
 356                 return -1;
 357         }
 358 
 359         return strcmp(oc1, oc2);
 360 }
 361 
 362 static const struct ldb_attrib_handler samba_handlers[] = {
 363         { 
 364                 .attr            = "objectSid",
 365                 .flags           = 0,
 366                 .ldif_read_fn    = ldif_read_objectSid,
 367                 .ldif_write_fn   = ldif_write_objectSid,
 368                 .canonicalise_fn = ldb_canonicalise_objectSid,
 369                 .comparison_fn   = ldb_comparison_objectSid
 370         },
 371         { 
 372                 .attr            = "securityIdentifier",
 373                 .flags           = 0,
 374                 .ldif_read_fn    = ldif_read_objectSid,
 375                 .ldif_write_fn   = ldif_write_objectSid,
 376                 .canonicalise_fn = ldb_canonicalise_objectSid,
 377                 .comparison_fn   = ldb_comparison_objectSid
 378         },
 379         { 
 380                 .attr            = "ntSecurityDescriptor",
 381                 .flags           = 0,
 382                 .ldif_read_fn    = ldif_read_ntSecurityDescriptor,
 383                 .ldif_write_fn   = ldif_write_ntSecurityDescriptor,
 384                 .canonicalise_fn = ldb_handler_copy,
 385                 .comparison_fn   = ldb_comparison_binary
 386         },
 387         { 
 388                 .attr            = "objectGUID",
 389                 .flags           = 0,
 390                 .ldif_read_fn    = ldif_read_objectGUID,
 391                 .ldif_write_fn   = ldif_write_objectGUID,
 392                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 393                 .comparison_fn   = ldb_comparison_objectGUID
 394         },
 395         { 
 396                 .attr            = "invocationId",
 397                 .flags           = 0,
 398                 .ldif_read_fn    = ldif_read_objectGUID,
 399                 .ldif_write_fn   = ldif_write_objectGUID,
 400                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 401                 .comparison_fn   = ldb_comparison_objectGUID
 402         },
 403         { 
 404                 .attr            = "schemaIDGUID",
 405                 .flags           = 0,
 406                 .ldif_read_fn    = ldif_read_objectGUID,
 407                 .ldif_write_fn   = ldif_write_objectGUID,
 408                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 409                 .comparison_fn   = ldb_comparison_objectGUID
 410         },
 411         { 
 412                 .attr            = "attributeSecurityGUID",
 413                 .flags           = 0,
 414                 .ldif_read_fn    = ldif_read_objectGUID,
 415                 .ldif_write_fn   = ldif_write_objectGUID,
 416                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 417                 .comparison_fn   = ldb_comparison_objectGUID
 418         },
 419         { 
 420                 .attr            = "parentGUID",
 421                 .flags           = 0,
 422                 .ldif_read_fn    = ldif_read_objectGUID,
 423                 .ldif_write_fn   = ldif_write_objectGUID,
 424                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 425                 .comparison_fn   = ldb_comparison_objectGUID
 426         },
 427         { 
 428                 .attr            = "siteGUID",
 429                 .flags           = 0,
 430                 .ldif_read_fn    = ldif_read_objectGUID,
 431                 .ldif_write_fn   = ldif_write_objectGUID,
 432                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 433                 .comparison_fn   = ldb_comparison_objectGUID
 434         },
 435         { 
 436                 .attr            = "pKTGUID",
 437                 .flags           = 0,
 438                 .ldif_read_fn    = ldif_read_objectGUID,
 439                 .ldif_write_fn   = ldif_write_objectGUID,
 440                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 441                 .comparison_fn   = ldb_comparison_objectGUID
 442         },
 443         { 
 444                 .attr            = "fRSVersionGUID",
 445                 .flags           = 0,
 446                 .ldif_read_fn    = ldif_read_objectGUID,
 447                 .ldif_write_fn   = ldif_write_objectGUID,
 448                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 449                 .comparison_fn   = ldb_comparison_objectGUID
 450         },
 451         { 
 452                 .attr            = "fRSReplicaSetGUID",
 453                 .flags           = 0,
 454                 .ldif_read_fn    = ldif_read_objectGUID,
 455                 .ldif_write_fn   = ldif_write_objectGUID,
 456                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 457                 .comparison_fn   = ldb_comparison_objectGUID
 458         },
 459         { 
 460                 .attr            = "netbootGUID",
 461                 .flags           = 0,
 462                 .ldif_read_fn    = ldif_read_objectGUID,
 463                 .ldif_write_fn   = ldif_write_objectGUID,
 464                 .canonicalise_fn = ldb_canonicalise_objectGUID,
 465                 .comparison_fn   = ldb_comparison_objectGUID
 466         },
 467         { 
 468                 .attr            = "objectCategory",
 469                 .flags           = 0,
 470                 .ldif_read_fn    = ldb_handler_copy,
 471                 .ldif_write_fn   = ldb_handler_copy,
 472                 .canonicalise_fn = ldif_canonicalise_objectCategory,
 473                 .comparison_fn   = ldif_comparison_objectCategory,
 474         }
 475 };
 476 
 477 /*
 478   register the samba ldif handlers
 479 */
 480 int ldb_register_samba_handlers(struct ldb_context *ldb)
     /* [<][>][^][v][top][bottom][index][help] */
 481 {
 482         return ldb_set_attrib_handlers(ldb, samba_handlers, ARRAY_SIZE(samba_handlers));
 483 }

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