root/source3/libnet/libnet_samsync_ldif.c

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

DEFINITIONS

This source file includes following definitions.
  1. populate_ldap_for_ldif
  2. map_populate_groups
  3. fprintf_attr
  4. fetch_group_info_to_ldif
  5. fetch_account_info_to_ldif
  6. fetch_alias_info_to_ldif
  7. fetch_groupmem_info_to_ldif
  8. ldif_init_context
  9. ldif_free_context
  10. ldif_write_output
  11. fetch_sam_entry_ldif
  12. ldif_realloc_maps
  13. init_ldif
  14. fetch_sam_entries_ldif
  15. close_ldif
  16. init_ldif
  17. fetch_sam_entries_ldif
  18. close_ldif

   1 /*
   2    Unix SMB/CIFS implementation.
   3    dump the remote SAM using rpc samsync operations
   4 
   5    Copyright (C) Andrew Tridgell 2002
   6    Copyright (C) Tim Potter 2001,2002
   7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
   8    Modified by Volker Lendecke 2002
   9    Copyright (C) Jeremy Allison 2005.
  10    Copyright (C) Guenther Deschner 2008.
  11 
  12    This program is free software; you can redistribute it and/or modify
  13    it under the terms of the GNU General Public License as published by
  14    the Free Software Foundation; either version 3 of the License, or
  15    (at your option) any later version.
  16 
  17    This program is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21 
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24 */
  25 
  26 #include "includes.h"
  27 #include "libnet/libnet_samsync.h"
  28 
  29 #ifdef HAVE_LDAP
  30 
  31 /* uid's and gid's for writing deltas to ldif */
  32 static uint32 ldif_gid = 999;
  33 static uint32 ldif_uid = 999;
  34 
  35 /* global counters */
  36 static uint32_t g_index = 0;
  37 static uint32_t a_index = 0;
  38 
  39 /* Structure for mapping accounts to groups */
  40 /* Array element is the group rid */
  41 typedef struct _groupmap {
  42         uint32_t rid;
  43         uint32_t gidNumber;
  44         const char *sambaSID;
  45         const char *group_dn;
  46 } GROUPMAP;
  47 
  48 typedef struct _accountmap {
  49         uint32_t rid;
  50         const char *cn;
  51 } ACCOUNTMAP;
  52 
  53 struct samsync_ldif_context {
  54         GROUPMAP *groupmap;
  55         ACCOUNTMAP *accountmap;
  56         bool initialized;
  57         const char *add_template;
  58         const char *mod_template;
  59         char *add_name;
  60         char *mod_name;
  61         FILE *add_file;
  62         FILE *mod_file;
  63         FILE *ldif_file;
  64         const char *suffix;
  65         int num_alloced;
  66 };
  67 
  68 /****************************************************************
  69 ****************************************************************/
  70 
  71 static NTSTATUS populate_ldap_for_ldif(const char *sid,
     /* [<][>][^][v][top][bottom][index][help] */
  72                                        const char *suffix,
  73                                        const char *builtin_sid,
  74                                        FILE *add_fd)
  75 {
  76         const char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix;
  77         char *user_attr=NULL, *group_attr=NULL;
  78         char *suffix_attr;
  79         int len;
  80 
  81         /* Get the suffix attribute */
  82         suffix_attr = sstring_sub(suffix, '=', ',');
  83         if (suffix_attr == NULL) {
  84                 len = strlen(suffix);
  85                 suffix_attr = (char*)SMB_MALLOC(len+1);
  86                 memcpy(suffix_attr, suffix, len);
  87                 suffix_attr[len] = '\0';
  88         }
  89 
  90         /* Write the base */
  91         fprintf(add_fd, "# %s\n", suffix);
  92         fprintf(add_fd, "dn: %s\n", suffix);
  93         fprintf(add_fd, "objectClass: dcObject\n");
  94         fprintf(add_fd, "objectClass: organization\n");
  95         fprintf(add_fd, "o: %s\n", suffix_attr);
  96         fprintf(add_fd, "dc: %s\n", suffix_attr);
  97         fprintf(add_fd, "\n");
  98         fflush(add_fd);
  99 
 100         user_suffix = lp_ldap_user_suffix();
 101         if (user_suffix == NULL) {
 102                 SAFE_FREE(suffix_attr);
 103                 return NT_STATUS_NO_MEMORY;
 104         }
 105         /* If it exists and is distinct from other containers,
 106            Write the Users entity */
 107         if (*user_suffix && strcmp(user_suffix, suffix)) {
 108                 user_attr = sstring_sub(lp_ldap_user_suffix(), '=', ',');
 109                 fprintf(add_fd, "# %s\n", user_suffix);
 110                 fprintf(add_fd, "dn: %s\n", user_suffix);
 111                 fprintf(add_fd, "objectClass: organizationalUnit\n");
 112                 fprintf(add_fd, "ou: %s\n", user_attr);
 113                 fprintf(add_fd, "\n");
 114                 fflush(add_fd);
 115         }
 116 
 117 
 118         group_suffix = lp_ldap_group_suffix();
 119         if (group_suffix == NULL) {
 120                 SAFE_FREE(suffix_attr);
 121                 SAFE_FREE(user_attr);
 122                 return NT_STATUS_NO_MEMORY;
 123         }
 124         /* If it exists and is distinct from other containers,
 125            Write the Groups entity */
 126         if (*group_suffix && strcmp(group_suffix, suffix)) {
 127                 group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
 128                 fprintf(add_fd, "# %s\n", group_suffix);
 129                 fprintf(add_fd, "dn: %s\n", group_suffix);
 130                 fprintf(add_fd, "objectClass: organizationalUnit\n");
 131                 fprintf(add_fd, "ou: %s\n", group_attr);
 132                 fprintf(add_fd, "\n");
 133                 fflush(add_fd);
 134         }
 135 
 136         /* If it exists and is distinct from other containers,
 137            Write the Computers entity */
 138         machine_suffix = lp_ldap_machine_suffix();
 139         if (machine_suffix == NULL) {
 140                 SAFE_FREE(suffix_attr);
 141                 SAFE_FREE(user_attr);
 142                 SAFE_FREE(group_attr);
 143                 return NT_STATUS_NO_MEMORY;
 144         }
 145         if (*machine_suffix && strcmp(machine_suffix, user_suffix) &&
 146             strcmp(machine_suffix, suffix)) {
 147                 char *machine_ou = NULL;
 148                 fprintf(add_fd, "# %s\n", machine_suffix);
 149                 fprintf(add_fd, "dn: %s\n", machine_suffix);
 150                 fprintf(add_fd, "objectClass: organizationalUnit\n");
 151                 /* this isn't totally correct as it assumes that
 152                    there _must_ be an ou. just fixing memleak now. jmcd */
 153                 machine_ou = sstring_sub(lp_ldap_machine_suffix(), '=', ',');
 154                 fprintf(add_fd, "ou: %s\n", machine_ou);
 155                 SAFE_FREE(machine_ou);
 156                 fprintf(add_fd, "\n");
 157                 fflush(add_fd);
 158         }
 159 
 160         /* If it exists and is distinct from other containers,
 161            Write the IdMap entity */
 162         idmap_suffix = lp_ldap_idmap_suffix();
 163         if (idmap_suffix == NULL) {
 164                 SAFE_FREE(suffix_attr);
 165                 SAFE_FREE(user_attr);
 166                 SAFE_FREE(group_attr);
 167                 return NT_STATUS_NO_MEMORY;
 168         }
 169         if (*idmap_suffix &&
 170             strcmp(idmap_suffix, user_suffix) &&
 171             strcmp(idmap_suffix, suffix)) {
 172                 char *s;
 173                 fprintf(add_fd, "# %s\n", idmap_suffix);
 174                 fprintf(add_fd, "dn: %s\n", idmap_suffix);
 175                 fprintf(add_fd, "ObjectClass: organizationalUnit\n");
 176                 s = sstring_sub(lp_ldap_idmap_suffix(), '=', ',');
 177                 fprintf(add_fd, "ou: %s\n", s);
 178                 SAFE_FREE(s);
 179                 fprintf(add_fd, "\n");
 180                 fflush(add_fd);
 181         }
 182 
 183         /* Write the domain entity */
 184         fprintf(add_fd, "# %s, %s\n", lp_workgroup(), suffix);
 185         fprintf(add_fd, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
 186                 suffix);
 187         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_DOMINFO);
 188         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_IDPOOL);
 189         fprintf(add_fd, "sambaDomainName: %s\n", lp_workgroup());
 190         fprintf(add_fd, "sambaSID: %s\n", sid);
 191         fprintf(add_fd, "uidNumber: %d\n", ++ldif_uid);
 192         fprintf(add_fd, "gidNumber: %d\n", ++ldif_gid);
 193         fprintf(add_fd, "\n");
 194         fflush(add_fd);
 195 
 196         /* Write the Domain Admins entity */
 197         fprintf(add_fd, "# Domain Admins, %s, %s\n", group_attr,
 198                 suffix);
 199         fprintf(add_fd, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr,
 200                 suffix);
 201         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 202         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 203         fprintf(add_fd, "cn: Domain Admins\n");
 204         fprintf(add_fd, "memberUid: Administrator\n");
 205         fprintf(add_fd, "description: Netbios Domain Administrators\n");
 206         fprintf(add_fd, "gidNumber: 512\n");
 207         fprintf(add_fd, "sambaSID: %s-512\n", sid);
 208         fprintf(add_fd, "sambaGroupType: 2\n");
 209         fprintf(add_fd, "displayName: Domain Admins\n");
 210         fprintf(add_fd, "\n");
 211         fflush(add_fd);
 212 
 213         /* Write the Domain Users entity */
 214         fprintf(add_fd, "# Domain Users, %s, %s\n", group_attr,
 215                 suffix);
 216         fprintf(add_fd, "dn: cn=Domain Users,ou=%s,%s\n", group_attr,
 217                 suffix);
 218         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 219         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 220         fprintf(add_fd, "cn: Domain Users\n");
 221         fprintf(add_fd, "description: Netbios Domain Users\n");
 222         fprintf(add_fd, "gidNumber: 513\n");
 223         fprintf(add_fd, "sambaSID: %s-513\n", sid);
 224         fprintf(add_fd, "sambaGroupType: 2\n");
 225         fprintf(add_fd, "displayName: Domain Users\n");
 226         fprintf(add_fd, "\n");
 227         fflush(add_fd);
 228 
 229         /* Write the Domain Guests entity */
 230         fprintf(add_fd, "# Domain Guests, %s, %s\n", group_attr,
 231                 suffix);
 232         fprintf(add_fd, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr,
 233                 suffix);
 234         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 235         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 236         fprintf(add_fd, "cn: Domain Guests\n");
 237         fprintf(add_fd, "description: Netbios Domain Guests\n");
 238         fprintf(add_fd, "gidNumber: 514\n");
 239         fprintf(add_fd, "sambaSID: %s-514\n", sid);
 240         fprintf(add_fd, "sambaGroupType: 2\n");
 241         fprintf(add_fd, "displayName: Domain Guests\n");
 242         fprintf(add_fd, "\n");
 243         fflush(add_fd);
 244 
 245         /* Write the Domain Computers entity */
 246         fprintf(add_fd, "# Domain Computers, %s, %s\n", group_attr,
 247                 suffix);
 248         fprintf(add_fd, "dn: cn=Domain Computers,ou=%s,%s\n",
 249                 group_attr, suffix);
 250         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 251         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 252         fprintf(add_fd, "gidNumber: 515\n");
 253         fprintf(add_fd, "cn: Domain Computers\n");
 254         fprintf(add_fd, "description: Netbios Domain Computers accounts\n");
 255         fprintf(add_fd, "sambaSID: %s-515\n", sid);
 256         fprintf(add_fd, "sambaGroupType: 2\n");
 257         fprintf(add_fd, "displayName: Domain Computers\n");
 258         fprintf(add_fd, "\n");
 259         fflush(add_fd);
 260 
 261         /* Write the Admininistrators Groups entity */
 262         fprintf(add_fd, "# Administrators, %s, %s\n", group_attr,
 263                 suffix);
 264         fprintf(add_fd, "dn: cn=Administrators,ou=%s,%s\n", group_attr,
 265                 suffix);
 266         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 267         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 268         fprintf(add_fd, "gidNumber: 544\n");
 269         fprintf(add_fd, "cn: Administrators\n");
 270         fprintf(add_fd, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
 271         fprintf(add_fd, "sambaSID: %s-544\n", builtin_sid);
 272         fprintf(add_fd, "sambaGroupType: 5\n");
 273         fprintf(add_fd, "displayName: Administrators\n");
 274         fprintf(add_fd, "\n");
 275 
 276         /* Write the Print Operator entity */
 277         fprintf(add_fd, "# Print Operators, %s, %s\n", group_attr,
 278                 suffix);
 279         fprintf(add_fd, "dn: cn=Print Operators,ou=%s,%s\n",
 280                 group_attr, suffix);
 281         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 282         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 283         fprintf(add_fd, "gidNumber: 550\n");
 284         fprintf(add_fd, "cn: Print Operators\n");
 285         fprintf(add_fd, "description: Netbios Domain Print Operators\n");
 286         fprintf(add_fd, "sambaSID: %s-550\n", builtin_sid);
 287         fprintf(add_fd, "sambaGroupType: 5\n");
 288         fprintf(add_fd, "displayName: Print Operators\n");
 289         fprintf(add_fd, "\n");
 290         fflush(add_fd);
 291 
 292         /* Write the Backup Operators entity */
 293         fprintf(add_fd, "# Backup Operators, %s, %s\n", group_attr,
 294                 suffix);
 295         fprintf(add_fd, "dn: cn=Backup Operators,ou=%s,%s\n",
 296                 group_attr, suffix);
 297         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 298         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 299         fprintf(add_fd, "gidNumber: 551\n");
 300         fprintf(add_fd, "cn: Backup Operators\n");
 301         fprintf(add_fd, "description: Netbios Domain Members can bypass file security to back up files\n");
 302         fprintf(add_fd, "sambaSID: %s-551\n", builtin_sid);
 303         fprintf(add_fd, "sambaGroupType: 5\n");
 304         fprintf(add_fd, "displayName: Backup Operators\n");
 305         fprintf(add_fd, "\n");
 306         fflush(add_fd);
 307 
 308         /* Write the Replicators entity */
 309         fprintf(add_fd, "# Replicators, %s, %s\n", group_attr, suffix);
 310         fprintf(add_fd, "dn: cn=Replicators,ou=%s,%s\n", group_attr,
 311                 suffix);
 312         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 313         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 314         fprintf(add_fd, "gidNumber: 552\n");
 315         fprintf(add_fd, "cn: Replicators\n");
 316         fprintf(add_fd, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
 317         fprintf(add_fd, "sambaSID: %s-552\n", builtin_sid);
 318         fprintf(add_fd, "sambaGroupType: 5\n");
 319         fprintf(add_fd, "displayName: Replicators\n");
 320         fprintf(add_fd, "\n");
 321         fflush(add_fd);
 322 
 323         /* Deallocate memory, and return */
 324         SAFE_FREE(suffix_attr);
 325         SAFE_FREE(user_attr);
 326         SAFE_FREE(group_attr);
 327         return NT_STATUS_OK;
 328 }
 329 
 330 /****************************************************************
 331 ****************************************************************/
 332 
 333 static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 334                                     GROUPMAP *groupmap,
 335                                     ACCOUNTMAP *accountmap,
 336                                     const char *sid,
 337                                     const char *suffix,
 338                                     const char *builtin_sid)
 339 {
 340         char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
 341 
 342         /* Map the groups created by populate_ldap_for_ldif */
 343         groupmap[0].rid         = 512;
 344         groupmap[0].gidNumber   = 512;
 345         groupmap[0].sambaSID    = talloc_asprintf(mem_ctx, "%s-512", sid);
 346         groupmap[0].group_dn    = talloc_asprintf(mem_ctx,
 347                 "cn=Domain Admins,ou=%s,%s", group_attr, suffix);
 348         if (groupmap[0].sambaSID == NULL || groupmap[0].group_dn == NULL) {
 349                 goto err;
 350         }
 351 
 352         accountmap[0].rid       = 512;
 353         accountmap[0].cn        = talloc_strdup(mem_ctx, "Domain Admins");
 354         if (accountmap[0].cn == NULL) {
 355                 goto err;
 356         }
 357 
 358         groupmap[1].rid         = 513;
 359         groupmap[1].gidNumber   = 513;
 360         groupmap[1].sambaSID    = talloc_asprintf(mem_ctx, "%s-513", sid);
 361         groupmap[1].group_dn    = talloc_asprintf(mem_ctx,
 362                 "cn=Domain Users,ou=%s,%s", group_attr, suffix);
 363         if (groupmap[1].sambaSID == NULL || groupmap[1].group_dn == NULL) {
 364                 goto err;
 365         }
 366 
 367         accountmap[1].rid       = 513;
 368         accountmap[1].cn        = talloc_strdup(mem_ctx, "Domain Users");
 369         if (accountmap[1].cn == NULL) {
 370                 goto err;
 371         }
 372 
 373         groupmap[2].rid         = 514;
 374         groupmap[2].gidNumber   = 514;
 375         groupmap[2].sambaSID    = talloc_asprintf(mem_ctx, "%s-514", sid);
 376         groupmap[2].group_dn    = talloc_asprintf(mem_ctx,
 377                 "cn=Domain Guests,ou=%s,%s", group_attr, suffix);
 378         if (groupmap[2].sambaSID == NULL || groupmap[2].group_dn == NULL) {
 379                 goto err;
 380         }
 381 
 382         accountmap[2].rid       = 514;
 383         accountmap[2].cn        = talloc_strdup(mem_ctx, "Domain Guests");
 384         if (accountmap[2].cn == NULL) {
 385                 goto err;
 386         }
 387 
 388         groupmap[3].rid         = 515;
 389         groupmap[3].gidNumber   = 515;
 390         groupmap[3].sambaSID    = talloc_asprintf(mem_ctx, "%s-515", sid);
 391         groupmap[3].group_dn    = talloc_asprintf(mem_ctx,
 392                 "cn=Domain Computers,ou=%s,%s", group_attr, suffix);
 393         if (groupmap[3].sambaSID == NULL || groupmap[3].group_dn == NULL) {
 394                 goto err;
 395         }
 396 
 397         accountmap[3].rid       = 515;
 398         accountmap[3].cn        = talloc_strdup(mem_ctx, "Domain Computers");
 399         if (accountmap[3].cn == NULL) {
 400                 goto err;
 401         }
 402 
 403         groupmap[4].rid         = 544;
 404         groupmap[4].gidNumber   = 544;
 405         groupmap[4].sambaSID    = talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
 406         groupmap[4].group_dn    = talloc_asprintf(mem_ctx,
 407                 "cn=Administrators,ou=%s,%s", group_attr, suffix);
 408         if (groupmap[4].sambaSID == NULL || groupmap[4].group_dn == NULL) {
 409                 goto err;
 410         }
 411 
 412         accountmap[4].rid       = 515;
 413         accountmap[4].cn        = talloc_strdup(mem_ctx, "Administrators");
 414         if (accountmap[4].cn == NULL) {
 415                 goto err;
 416         }
 417 
 418         groupmap[5].rid         = 550;
 419         groupmap[5].gidNumber   = 550;
 420         groupmap[5].sambaSID    = talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
 421         groupmap[5].group_dn    = talloc_asprintf(mem_ctx,
 422                 "cn=Print Operators,ou=%s,%s", group_attr, suffix);
 423         if (groupmap[5].sambaSID == NULL || groupmap[5].group_dn == NULL) {
 424                 goto err;
 425         }
 426 
 427         accountmap[5].rid       = 550;
 428         accountmap[5].cn        = talloc_strdup(mem_ctx, "Print Operators");
 429         if (accountmap[5].cn == NULL) {
 430                 goto err;
 431         }
 432 
 433         groupmap[6].rid         = 551;
 434         groupmap[6].gidNumber   = 551;
 435         groupmap[6].sambaSID    = talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
 436         groupmap[6].group_dn    = talloc_asprintf(mem_ctx,
 437                 "cn=Backup Operators,ou=%s,%s", group_attr, suffix);
 438         if (groupmap[6].sambaSID == NULL || groupmap[6].group_dn == NULL) {
 439                 goto err;
 440         }
 441 
 442         accountmap[6].rid       = 551;
 443         accountmap[6].cn        = talloc_strdup(mem_ctx, "Backup Operators");
 444         if (accountmap[6].cn == NULL) {
 445                 goto err;
 446         }
 447 
 448         groupmap[7].rid         = 552;
 449         groupmap[7].gidNumber   = 552;
 450         groupmap[7].sambaSID    = talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
 451         groupmap[7].group_dn    = talloc_asprintf(mem_ctx,
 452                 "cn=Replicators,ou=%s,%s", group_attr, suffix);
 453         if (groupmap[7].sambaSID == NULL || groupmap[7].group_dn == NULL) {
 454                 goto err;
 455         }
 456 
 457         accountmap[7].rid       = 551;
 458         accountmap[7].cn        = talloc_strdup(mem_ctx, "Replicators");
 459         if (accountmap[7].cn == NULL) {
 460                 goto err;
 461         }
 462 
 463         SAFE_FREE(group_attr);
 464 
 465         return NT_STATUS_OK;
 466 
 467   err:
 468 
 469         SAFE_FREE(group_attr);
 470         return NT_STATUS_NO_MEMORY;
 471 }
 472 
 473 /*
 474  * This is a crap routine, but I think it's the quickest way to solve the
 475  * UTF8->base64 problem.
 476  */
 477 
 478 static int fprintf_attr(FILE *add_fd, const char *attr_name,
     /* [<][>][^][v][top][bottom][index][help] */
 479                         const char *fmt, ...)
 480 {
 481         va_list ap;
 482         char *value, *p, *base64;
 483         DATA_BLOB base64_blob;
 484         bool do_base64 = false;
 485         int res;
 486 
 487         va_start(ap, fmt);
 488         value = talloc_vasprintf(NULL, fmt, ap);
 489         va_end(ap);
 490 
 491         SMB_ASSERT(value != NULL);
 492 
 493         for (p=value; *p; p++) {
 494                 if (*p & 0x80) {
 495                         do_base64 = true;
 496                         break;
 497                 }
 498         }
 499 
 500         if (!do_base64) {
 501                 bool only_whitespace = true;
 502                 for (p=value; *p; p++) {
 503                         /*
 504                          * I know that this not multibyte safe, but we break
 505                          * on the first non-whitespace character anyway.
 506                          */
 507                         if (!isspace(*p)) {
 508                                 only_whitespace = false;
 509                                 break;
 510                         }
 511                 }
 512                 if (only_whitespace) {
 513                         do_base64 = true;
 514                 }
 515         }
 516 
 517         if (!do_base64) {
 518                 res = fprintf(add_fd, "%s: %s\n", attr_name, value);
 519                 TALLOC_FREE(value);
 520                 return res;
 521         }
 522 
 523         base64_blob.data = (unsigned char *)value;
 524         base64_blob.length = strlen(value);
 525 
 526         base64 = base64_encode_data_blob(value, base64_blob);
 527         SMB_ASSERT(base64 != NULL);
 528 
 529         res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
 530         TALLOC_FREE(value);
 531         return res;
 532 }
 533 
 534 /****************************************************************
 535 ****************************************************************/
 536 
 537 static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 538                                          struct netr_DELTA_GROUP *r,
 539                                          GROUPMAP *groupmap,
 540                                          FILE *add_fd,
 541                                          const char *sid,
 542                                          const char *suffix)
 543 {
 544         const char *groupname = r->group_name.string;
 545         uint32 grouptype = 0, g_rid = 0;
 546         char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
 547 
 548         /* Set up the group type (always 2 for group info) */
 549         grouptype = 2;
 550 
 551         /* These groups are entered by populate_ldap_for_ldif */
 552         if (strcmp(groupname, "Domain Admins") == 0 ||
 553             strcmp(groupname, "Domain Users") == 0 ||
 554             strcmp(groupname, "Domain Guests") == 0 ||
 555             strcmp(groupname, "Domain Computers") == 0 ||
 556             strcmp(groupname, "Administrators") == 0 ||
 557             strcmp(groupname, "Print Operators") == 0 ||
 558             strcmp(groupname, "Backup Operators") == 0 ||
 559             strcmp(groupname, "Replicators") == 0) {
 560                 SAFE_FREE(group_attr);
 561                 return NT_STATUS_OK;
 562         } else {
 563                 /* Increment the gid for the new group */
 564                 ldif_gid++;
 565         }
 566 
 567         /* Map the group rid, gid, and dn */
 568         g_rid = r->rid;
 569         groupmap->rid = g_rid;
 570         groupmap->gidNumber = ldif_gid;
 571         groupmap->sambaSID      = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
 572         groupmap->group_dn      = talloc_asprintf(mem_ctx,
 573              "cn=%s,ou=%s,%s", groupname, group_attr, suffix);
 574         if (groupmap->sambaSID == NULL || groupmap->group_dn == NULL) {
 575                 SAFE_FREE(group_attr);
 576                 return NT_STATUS_NO_MEMORY;
 577         }
 578 
 579         /* Write the data to the temporary add ldif file */
 580         fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
 581                 suffix);
 582         fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
 583                      suffix);
 584         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 585         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 586         fprintf_attr(add_fd, "cn", "%s", groupname);
 587         fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
 588         fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
 589         fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
 590         fprintf_attr(add_fd, "displayName", "%s", groupname);
 591         fprintf(add_fd, "\n");
 592         fflush(add_fd);
 593 
 594         SAFE_FREE(group_attr);
 595         /* Return */
 596         return NT_STATUS_OK;
 597 }
 598 
 599 /****************************************************************
 600 ****************************************************************/
 601 
 602 static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 603                                            struct netr_DELTA_USER *r,
 604                                            GROUPMAP *groupmap,
 605                                            ACCOUNTMAP *accountmap,
 606                                            FILE *add_fd,
 607                                            const char *sid,
 608                                            const char *suffix,
 609                                            int alloced)
 610 {
 611         fstring username, logonscript, homedrive, homepath = "", homedir = "";
 612         fstring hex_nt_passwd, hex_lm_passwd;
 613         fstring description, profilepath, fullname, sambaSID;
 614         char *flags, *user_rdn;
 615         const char *ou;
 616         const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
 617         uchar zero_buf[16];
 618         uint32 rid = 0, group_rid = 0, gidNumber = 0;
 619         time_t unix_time;
 620         int i, ret;
 621 
 622         memset(zero_buf, '\0', sizeof(zero_buf));
 623 
 624         /* Get the username */
 625         fstrcpy(username, r->account_name.string);
 626 
 627         /* Get the rid */
 628         rid = r->rid;
 629 
 630         /* Map the rid and username for group member info later */
 631         accountmap->rid = rid;
 632         accountmap->cn = talloc_strdup(mem_ctx, username);
 633         NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);
 634 
 635         /* Get the home directory */
 636         if (r->acct_flags & ACB_NORMAL) {
 637                 fstrcpy(homedir, r->home_directory.string);
 638                 if (!*homedir) {
 639                         snprintf(homedir, sizeof(homedir), "/home/%s", username);
 640                 } else {
 641                         snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
 642                 }
 643                 ou = lp_ldap_user_suffix();
 644         } else {
 645                 ou = lp_ldap_machine_suffix();
 646                 snprintf(homedir, sizeof(homedir), "/machinehomedir");
 647         }
 648 
 649         /* Get the logon script */
 650         fstrcpy(logonscript, r->logon_script.string);
 651 
 652         /* Get the home drive */
 653         fstrcpy(homedrive, r->home_drive.string);
 654 
 655         /* Get the home path */
 656         fstrcpy(homepath, r->home_directory.string);
 657 
 658         /* Get the description */
 659         fstrcpy(description, r->description.string);
 660 
 661         /* Get the display name */
 662         fstrcpy(fullname, r->full_name.string);
 663 
 664         /* Get the profile path */
 665         fstrcpy(profilepath, r->profile_path.string);
 666 
 667         /* Get lm and nt password data */
 668         if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
 669                 pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags);
 670         } else {
 671                 pdb_sethexpwd(hex_lm_passwd, NULL, 0);
 672         }
 673         if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
 674                 pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags);
 675         } else {
 676                 pdb_sethexpwd(hex_nt_passwd, NULL, 0);
 677         }
 678         unix_time = nt_time_to_unix(r->last_password_change);
 679 
 680         /* Increment the uid for the new user */
 681         ldif_uid++;
 682 
 683         /* Set up group id and sambaSID for the user */
 684         group_rid = r->primary_gid;
 685         for (i=0; i<alloced; i++) {
 686                 if (groupmap[i].rid == group_rid) break;
 687         }
 688         if (i == alloced){
 689                 DEBUG(1, ("Could not find rid %d in groupmap array\n",
 690                           group_rid));
 691                 return NT_STATUS_UNSUCCESSFUL;
 692         }
 693         gidNumber = groupmap[i].gidNumber;
 694         ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID);
 695         if (ret < 0 || ret == sizeof(sambaSID)) {
 696                 return NT_STATUS_UNSUCCESSFUL;
 697         }
 698 
 699         /* Set up sambaAcctFlags */
 700         flags = pdb_encode_acct_ctrl(r->acct_flags,
 701                                      NEW_PW_FORMAT_SPACE_PADDED_LEN);
 702 
 703         /* Add the user to the temporary add ldif file */
 704         /* this isn't quite right...we can't assume there's just OU=. jmcd */
 705         user_rdn = sstring_sub(ou, '=', ',');
 706         fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
 707         fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
 708                      suffix);
 709         SAFE_FREE(user_rdn);
 710         fprintf(add_fd, "ObjectClass: top\n");
 711         fprintf(add_fd, "objectClass: inetOrgPerson\n");
 712         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
 713         fprintf(add_fd, "objectClass: shadowAccount\n");
 714         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
 715         fprintf_attr(add_fd, "cn", "%s", username);
 716         fprintf_attr(add_fd, "sn", "%s", username);
 717         fprintf_attr(add_fd, "uid", "%s", username);
 718         fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
 719         fprintf(add_fd, "gidNumber: %d\n", gidNumber);
 720         fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
 721         if (*homepath)
 722                 fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
 723         if (*homedrive)
 724                 fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
 725         if (*logonscript)
 726                 fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
 727         fprintf(add_fd, "loginShell: %s\n",
 728                 ((r->acct_flags & ACB_NORMAL) ?
 729                  "/bin/bash" : "/bin/false"));
 730         fprintf(add_fd, "gecos: System User\n");
 731         if (*description)
 732                 fprintf_attr(add_fd, "description", "%s", description);
 733         fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
 734         fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
 735         if(*fullname)
 736                 fprintf_attr(add_fd, "displayName", "%s", fullname);
 737         if(*profilepath)
 738                 fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
 739         if (strcmp(nopasswd, hex_lm_passwd) != 0)
 740                 fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
 741         if (strcmp(nopasswd, hex_nt_passwd) != 0)
 742                 fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
 743         fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
 744         fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
 745         fprintf(add_fd, "\n");
 746         fflush(add_fd);
 747 
 748         /* Return */
 749         return NT_STATUS_OK;
 750 }
 751 
 752 /****************************************************************
 753 ****************************************************************/
 754 
 755 static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 756                                          struct netr_DELTA_ALIAS *r,
 757                                          GROUPMAP *groupmap,
 758                                          FILE *add_fd,
 759                                          const char *sid,
 760                                          const char *suffix,
 761                                          enum netr_SamDatabaseID database_id)
 762 {
 763         fstring aliasname, description;
 764         uint32 grouptype = 0, g_rid = 0;
 765         char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
 766 
 767         /* Get the alias name */
 768         fstrcpy(aliasname, r->alias_name.string);
 769 
 770         /* Get the alias description */
 771         fstrcpy(description, r->description.string);
 772 
 773         /* Set up the group type */
 774         switch (database_id) {
 775         case SAM_DATABASE_DOMAIN:
 776                 grouptype = 4;
 777                 break;
 778         case SAM_DATABASE_BUILTIN:
 779                 grouptype = 5;
 780                 break;
 781         default:
 782                 grouptype = 4;
 783                 break;
 784         }
 785 
 786         /*
 787           These groups are entered by populate_ldap_for_ldif
 788           Note that populate creates a group called Relicators,
 789           but NT returns a group called Replicator
 790         */
 791         if (strcmp(aliasname, "Domain Admins") == 0 ||
 792             strcmp(aliasname, "Domain Users") == 0 ||
 793             strcmp(aliasname, "Domain Guests") == 0 ||
 794             strcmp(aliasname, "Domain Computers") == 0 ||
 795             strcmp(aliasname, "Administrators") == 0 ||
 796             strcmp(aliasname, "Print Operators") == 0 ||
 797             strcmp(aliasname, "Backup Operators") == 0 ||
 798             strcmp(aliasname, "Replicator") == 0) {
 799                 SAFE_FREE(group_attr);
 800                 return NT_STATUS_OK;
 801         } else {
 802                 /* Increment the gid for the new group */
 803                 ldif_gid++;
 804         }
 805 
 806         /* Map the group rid and gid */
 807         g_rid = r->rid;
 808         groupmap->gidNumber = ldif_gid;
 809         groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
 810         if (groupmap->sambaSID == NULL) {
 811                 SAFE_FREE(group_attr);
 812                 return NT_STATUS_NO_MEMORY;
 813         }
 814 
 815         /* Write the data to the temporary add ldif file */
 816         fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
 817                 suffix);
 818         fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
 819                      suffix);
 820         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 821         fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 822         fprintf(add_fd, "cn: %s\n", aliasname);
 823         fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
 824         fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
 825         fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
 826         fprintf_attr(add_fd, "displayName", "%s", aliasname);
 827         if (description[0])
 828                 fprintf_attr(add_fd, "description", "%s", description);
 829         fprintf(add_fd, "\n");
 830         fflush(add_fd);
 831 
 832         SAFE_FREE(group_attr);
 833         /* Return */
 834         return NT_STATUS_OK;
 835 }
 836 
 837 /****************************************************************
 838 ****************************************************************/
 839 
 840 static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r,
     /* [<][>][^][v][top][bottom][index][help] */
 841                                             uint32_t id_rid,
 842                                             GROUPMAP *groupmap,
 843                                             ACCOUNTMAP *accountmap,
 844                                             FILE *mod_fd, int alloced)
 845 {
 846         fstring group_dn;
 847         uint32 group_rid = 0, rid = 0;
 848         int i, j, k;
 849 
 850         /* Get the dn for the group */
 851         if (r->num_rids > 0) {
 852                 group_rid = id_rid;
 853                 for (j=0; j<alloced; j++) {
 854                         if (groupmap[j].rid == group_rid) break;
 855                 }
 856                 if (j == alloced){
 857                         DEBUG(1, ("Could not find rid %d in groupmap array\n",
 858                                   group_rid));
 859                         return NT_STATUS_UNSUCCESSFUL;
 860                 }
 861                 snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
 862                 fprintf(mod_fd, "dn: %s\n", group_dn);
 863 
 864                 /* Get the cn for each member */
 865                 for (i=0; i < r->num_rids; i++) {
 866                         rid = r->rids[i];
 867                         for (k=0; k<alloced; k++) {
 868                                 if (accountmap[k].rid == rid) break;
 869                         }
 870                         if (k == alloced){
 871                                 DEBUG(1, ("Could not find rid %d in "
 872                                           "accountmap array\n", rid));
 873                                 return NT_STATUS_UNSUCCESSFUL;
 874                         }
 875                         fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
 876                 }
 877                 fprintf(mod_fd, "\n");
 878         }
 879         fflush(mod_fd);
 880 
 881         /* Return */
 882         return NT_STATUS_OK;
 883 }
 884 
 885 /****************************************************************
 886 ****************************************************************/
 887 
 888 static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 889                                   enum netr_SamDatabaseID database_id,
 890                                   const char *ldif_filename,
 891                                   const char *domain_sid_str,
 892                                   struct samsync_ldif_context **ctx)
 893 {
 894         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
 895         struct samsync_ldif_context *r;
 896         const char *add_template = "/tmp/add.ldif.XXXXXX";
 897         const char *mod_template = "/tmp/mod.ldif.XXXXXX";
 898         const char *builtin_sid = "S-1-5-32";
 899 
 900         /* Get other smb.conf data */
 901         if (!(lp_workgroup()) || !*(lp_workgroup())) {
 902                 DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
 903                 exit(1);
 904         }
 905 
 906         /* Get the ldap suffix */
 907         if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) {
 908                 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
 909                 exit(1);
 910         }
 911 
 912         if (*ctx && (*ctx)->initialized) {
 913                 return NT_STATUS_OK;
 914         }
 915 
 916         r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context);
 917         NT_STATUS_HAVE_NO_MEMORY(r);
 918 
 919         /* Get the ldap suffix */
 920         r->suffix = lp_ldap_suffix();
 921 
 922         /* Ensure we have an output file */
 923         if (ldif_filename) {
 924                 r->ldif_file = fopen(ldif_filename, "a");
 925         } else {
 926                 r->ldif_file = stdout;
 927         }
 928 
 929         if (!r->ldif_file) {
 930                 fprintf(stderr, "Could not open %s\n", ldif_filename);
 931                 DEBUG(1, ("Could not open %s\n", ldif_filename));
 932                 status = NT_STATUS_UNSUCCESSFUL;
 933                 goto done;
 934         }
 935 
 936         r->add_template = talloc_strdup(mem_ctx, add_template);
 937         r->mod_template = talloc_strdup(mem_ctx, mod_template);
 938         if (!r->add_template || !r->mod_template) {
 939                 status = NT_STATUS_NO_MEMORY;
 940                 goto done;
 941         }
 942 
 943         r->add_name = talloc_strdup(mem_ctx, add_template);
 944         r->mod_name = talloc_strdup(mem_ctx, mod_template);
 945         if (!r->add_name || !r->mod_name) {
 946                 status = NT_STATUS_NO_MEMORY;
 947                 goto done;
 948         }
 949 
 950         /* Open the add and mod ldif files */
 951         if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) {
 952                 DEBUG(1, ("Could not open %s\n", r->add_name));
 953                 status = NT_STATUS_UNSUCCESSFUL;
 954                 goto done;
 955         }
 956         if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) {
 957                 DEBUG(1, ("Could not open %s\n", r->mod_name));
 958                 status = NT_STATUS_UNSUCCESSFUL;
 959                 goto done;
 960         }
 961 
 962         /* Allocate initial memory for groupmap and accountmap arrays */
 963         r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8);
 964         r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8);
 965         if (r->groupmap == NULL || r->accountmap == NULL) {
 966                 DEBUG(1,("GROUPMAP talloc failed\n"));
 967                 status = NT_STATUS_NO_MEMORY;
 968                 goto done;
 969         }
 970 
 971         /* Remember how many we malloced */
 972         r->num_alloced = 8;
 973 
 974         /* Initial database population */
 975         if (database_id == SAM_DATABASE_DOMAIN) {
 976 
 977                 status = populate_ldap_for_ldif(domain_sid_str,
 978                                                 r->suffix,
 979                                                 builtin_sid,
 980                                                 r->add_file);
 981                 if (!NT_STATUS_IS_OK(status)) {
 982                         goto done;
 983                 }
 984 
 985                 status = map_populate_groups(mem_ctx,
 986                                              r->groupmap,
 987                                              r->accountmap,
 988                                              domain_sid_str,
 989                                              r->suffix,
 990                                              builtin_sid);
 991                 if (!NT_STATUS_IS_OK(status)) {
 992                         goto done;
 993                 }
 994         }
 995 
 996         r->initialized = true;
 997 
 998         *ctx = r;
 999 
1000         return NT_STATUS_OK;
1001  done:
1002         TALLOC_FREE(r);
1003         return status;
1004 }
1005 
1006 /****************************************************************
1007 ****************************************************************/
1008 
1009 static void ldif_free_context(struct samsync_ldif_context *r)
     /* [<][>][^][v][top][bottom][index][help] */
1010 {
1011         if (!r) {
1012                 return;
1013         }
1014 
1015         /* Close and delete the ldif files */
1016         if (r->add_file) {
1017                 fclose(r->add_file);
1018         }
1019 
1020         if ((r->add_name != NULL) &&
1021             strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) {
1022                 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1023                          r->add_name, strerror(errno)));
1024         }
1025 
1026         if (r->mod_file) {
1027                 fclose(r->mod_file);
1028         }
1029 
1030         if ((r->mod_name != NULL) &&
1031             strcmp(r->mod_name, r->mod_template) && (unlink(r->mod_name))) {
1032                 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1033                          r->mod_name, strerror(errno)));
1034         }
1035 
1036         if (r->ldif_file && (r->ldif_file != stdout)) {
1037                 fclose(r->ldif_file);
1038         }
1039 
1040         TALLOC_FREE(r);
1041 }
1042 
1043 /****************************************************************
1044 ****************************************************************/
1045 
1046 static void ldif_write_output(enum netr_SamDatabaseID database_id,
     /* [<][>][^][v][top][bottom][index][help] */
1047                               struct samsync_ldif_context *l)
1048 {
1049         /* Write ldif data to the user's file */
1050         if (database_id == SAM_DATABASE_DOMAIN) {
1051                 fprintf(l->ldif_file,
1052                         "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
1053                 fprintf(l->ldif_file,
1054                         "# =================================\n\n");
1055                 fflush(l->ldif_file);
1056         } else if (database_id == SAM_DATABASE_BUILTIN) {
1057                 fprintf(l->ldif_file,
1058                         "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
1059                 fprintf(l->ldif_file,
1060                         "# ==================================\n\n");
1061                 fflush(l->ldif_file);
1062         }
1063         fseek(l->add_file, 0, SEEK_SET);
1064         transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
1065 
1066         if (database_id == SAM_DATABASE_DOMAIN) {
1067                 fprintf(l->ldif_file,
1068                         "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
1069                 fprintf(l->ldif_file,
1070                         "# ====================================\n\n");
1071                 fflush(l->ldif_file);
1072         } else if (database_id == SAM_DATABASE_BUILTIN) {
1073                 fprintf(l->ldif_file,
1074                         "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
1075                 fprintf(l->ldif_file,
1076                         "# =====================================\n\n");
1077                 fflush(l->ldif_file);
1078         }
1079         fseek(l->mod_file, 0, SEEK_SET);
1080         transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
1081 }
1082 
1083 /****************************************************************
1084 ****************************************************************/
1085 
1086 static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1087                                      enum netr_SamDatabaseID database_id,
1088                                      struct netr_DELTA_ENUM *r,
1089                                      struct samsync_context *ctx,
1090                                      uint32_t *a_index_p,
1091                                      uint32_t *g_index_p)
1092 {
1093         union netr_DELTA_UNION u = r->delta_union;
1094         union netr_DELTA_ID_UNION id = r->delta_id_union;
1095         struct samsync_ldif_context *l =
1096                 talloc_get_type_abort(ctx->private_data, struct samsync_ldif_context);
1097 
1098         switch (r->delta_type) {
1099                 case NETR_DELTA_DOMAIN:
1100                         break;
1101 
1102                 case NETR_DELTA_GROUP:
1103                         fetch_group_info_to_ldif(mem_ctx,
1104                                                  u.group,
1105                                                  &l->groupmap[*g_index_p],
1106                                                  l->add_file,
1107                                                  ctx->domain_sid_str,
1108                                                  l->suffix);
1109                         (*g_index_p)++;
1110                         break;
1111 
1112                 case NETR_DELTA_USER:
1113                         fetch_account_info_to_ldif(mem_ctx,
1114                                                    u.user,
1115                                                    l->groupmap,
1116                                                    &l->accountmap[*a_index_p],
1117                                                    l->add_file,
1118                                                    ctx->domain_sid_str,
1119                                                    l->suffix,
1120                                                    l->num_alloced);
1121                         (*a_index_p)++;
1122                         break;
1123 
1124                 case NETR_DELTA_ALIAS:
1125                         fetch_alias_info_to_ldif(mem_ctx,
1126                                                  u.alias,
1127                                                  &l->groupmap[*g_index_p],
1128                                                  l->add_file,
1129                                                  ctx->domain_sid_str,
1130                                                  l->suffix,
1131                                                  database_id);
1132                         (*g_index_p)++;
1133                         break;
1134 
1135                 case NETR_DELTA_GROUP_MEMBER:
1136                         fetch_groupmem_info_to_ldif(u.group_member,
1137                                                     id.rid,
1138                                                     l->groupmap,
1139                                                     l->accountmap,
1140                                                     l->mod_file,
1141                                                     l->num_alloced);
1142                         break;
1143 
1144                 case NETR_DELTA_ALIAS_MEMBER:
1145                 case NETR_DELTA_POLICY:
1146                 case NETR_DELTA_ACCOUNT:
1147                 case NETR_DELTA_TRUSTED_DOMAIN:
1148                 case NETR_DELTA_SECRET:
1149                 case NETR_DELTA_RENAME_GROUP:
1150                 case NETR_DELTA_RENAME_USER:
1151                 case NETR_DELTA_RENAME_ALIAS:
1152                 case NETR_DELTA_DELETE_GROUP:
1153                 case NETR_DELTA_DELETE_USER:
1154                 case NETR_DELTA_MODIFY_COUNT:
1155                 default:
1156                         break;
1157         } /* end of switch */
1158 
1159         return NT_STATUS_OK;
1160 }
1161 
1162 /****************************************************************
1163 ****************************************************************/
1164 
1165 static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1166                                   struct samsync_ldif_context *l,
1167                                   uint32_t num_entries)
1168 {
1169         /* Re-allocate memory for groupmap and accountmap arrays */
1170         l->groupmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1171                                            l->groupmap,
1172                                            GROUPMAP,
1173                                            num_entries + l->num_alloced);
1174 
1175         l->accountmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1176                                              l->accountmap,
1177                                              ACCOUNTMAP,
1178                                              num_entries + l->num_alloced);
1179 
1180         if (l->groupmap == NULL || l->accountmap == NULL) {
1181                 DEBUG(1,("GROUPMAP talloc failed\n"));
1182                 return NT_STATUS_NO_MEMORY;
1183         }
1184 
1185         /* Initialize the new records */
1186         memset(&(l->groupmap[l->num_alloced]), 0,
1187                sizeof(GROUPMAP) * num_entries);
1188         memset(&(l->accountmap[l->num_alloced]), 0,
1189                sizeof(ACCOUNTMAP) * num_entries);
1190 
1191         /* Remember how many we alloced this time */
1192         l->num_alloced += num_entries;
1193 
1194         return NT_STATUS_OK;
1195 }
1196 
1197 /****************************************************************
1198 ****************************************************************/
1199 
1200 static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1201                           struct samsync_context *ctx,
1202                           enum netr_SamDatabaseID database_id,
1203                           uint64_t *sequence_num)
1204 {
1205         NTSTATUS status;
1206         struct samsync_ldif_context *ldif_ctx =
1207                 (struct samsync_ldif_context *)ctx->private_data;
1208 
1209         status = ldif_init_context(mem_ctx,
1210                                    database_id,
1211                                    ctx->output_filename,
1212                                    ctx->domain_sid_str,
1213                                    &ldif_ctx);
1214         if (!NT_STATUS_IS_OK(status)) {
1215                 return status;
1216         }
1217 
1218         ctx->private_data = ldif_ctx;
1219 
1220         return NT_STATUS_OK;
1221 }
1222 
1223 /****************************************************************
1224 ****************************************************************/
1225 
1226 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1227                                        enum netr_SamDatabaseID database_id,
1228                                        struct netr_DELTA_ENUM_ARRAY *r,
1229                                        uint64_t *sequence_num,
1230                                        struct samsync_context *ctx)
1231 {
1232         NTSTATUS status;
1233         int i;
1234         struct samsync_ldif_context *ldif_ctx =
1235                 (struct samsync_ldif_context *)ctx->private_data;
1236 
1237         status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas);
1238         if (!NT_STATUS_IS_OK(status)) {
1239                 goto failed;
1240         }
1241 
1242         for (i = 0; i < r->num_deltas; i++) {
1243                 status = fetch_sam_entry_ldif(mem_ctx, database_id,
1244                                               &r->delta_enum[i], ctx,
1245                                               &a_index, &g_index);
1246                 if (!NT_STATUS_IS_OK(status)) {
1247                         goto failed;
1248                 }
1249         }
1250 
1251         return NT_STATUS_OK;
1252 
1253  failed:
1254         ldif_free_context(ldif_ctx);
1255         ctx->private_data = NULL;
1256 
1257         return status;
1258 }
1259 
1260 /****************************************************************
1261 ****************************************************************/
1262 
1263 static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1264                            struct samsync_context *ctx,
1265                            enum netr_SamDatabaseID database_id,
1266                            uint64_t sequence_num)
1267 {
1268         struct samsync_ldif_context *ldif_ctx =
1269                 (struct samsync_ldif_context *)ctx->private_data;
1270 
1271         /* This was the last query */
1272         ldif_write_output(database_id, ldif_ctx);
1273         if (ldif_ctx->ldif_file != stdout) {
1274                 ctx->result_message = talloc_asprintf(ctx,
1275                         "Vampired %d accounts and %d groups to %s",
1276                         a_index, g_index, ctx->output_filename);
1277         }
1278 
1279         ldif_free_context(ldif_ctx);
1280         ctx->private_data = NULL;
1281 
1282         return NT_STATUS_OK;
1283 }
1284 
1285 #else /* HAVE_LDAP */
1286 
1287 static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1288                           struct samsync_context *ctx,
1289                           enum netr_SamDatabaseID database_id,
1290                           uint64_t *sequence_num)
1291 {
1292         return NT_STATUS_NOT_SUPPORTED;
1293 }
1294 
1295 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1296                                        enum netr_SamDatabaseID database_id,
1297                                        struct netr_DELTA_ENUM_ARRAY *r,
1298                                        uint64_t *sequence_num,
1299                                        struct samsync_context *ctx)
1300 {
1301         return NT_STATUS_NOT_SUPPORTED;
1302 }
1303 
1304 static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1305                            struct samsync_context *ctx,
1306                            enum netr_SamDatabaseID database_id,
1307                            uint64_t sequence_num)
1308 {
1309         return NT_STATUS_NOT_SUPPORTED;
1310 }
1311 
1312 #endif
1313 
1314 const struct samsync_ops libnet_samsync_ldif_ops = {
1315         .startup                = init_ldif,
1316         .process_objects        = fetch_sam_entries_ldif,
1317         .finish                 = close_ldif,
1318 };

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