From cb5634a305256a70daa2fcbd85d9a5459b4aeaa3 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Wed, 6 Jul 2005 21:02:43 +0000 Subject: [PATCH] r8189: commit vampire ldif patch, mostly from Don Watson (dwatson@us.ibm.com). Yes, that's my copyright...that's just how we have to do things at big blue. Adds subcommand to vampire to allow data to be put into an ldif file instead of actually writing to the passdb. See "net rpc help vampire" for usage info. This should be added to docs as well. --- source/lib/util_str.c | 27 + source/utils/net.h | 13 + source/utils/net_rpc.c | 1 + source/utils/net_rpc_samsync.c | 1005 +++++++++++++++++++++++++++++++- 4 files changed, 1043 insertions(+), 3 deletions(-) diff --git a/source/lib/util_str.c b/source/lib/util_str.c index f600d1704e0..42229f105a1 100644 --- a/source/lib/util_str.c +++ b/source/lib/util_str.c @@ -2194,3 +2194,30 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len, *len = -1; *string = NULL; } + +/* + Returns the substring from src between the first occurrence of + the char "front" and the first occurence of the char "back". + Mallocs the return string which must be freed. Not for use + with wide character strings. +*/ +char *sstring_sub(const char *src, char front, char back) +{ + char *temp1, *temp2, *temp3; + ptrdiff_t len; + + temp1 = strchr(src, front); + if (temp1 == NULL) return NULL; + temp2 = strchr(src, back); + if (temp2 == NULL) return NULL; + len = temp2 - temp1; + if (len <= 0) return NULL; + temp3 = (char*)SMB_MALLOC(len); + if (temp3 == NULL) { + DEBUG(1,("Malloc failure in sstring_sub\n")); + return NULL; + } + memcpy(temp3, temp1+1, len-1); + temp3[len-1] = '\0'; + return temp3; +} diff --git a/source/utils/net.h b/source/utils/net.h index 0bec621c3c3..a2df6596b47 100644 --- a/source/utils/net.h +++ b/source/utils/net.h @@ -97,3 +97,16 @@ extern struct in_addr opt_dest_ip; extern const char *share_type[]; +/* Structure for mapping accounts to groups */ +/* Array element is the group rid */ +typedef struct _groupmap { + uint32 rid; + uint32 gidNumber; + fstring sambaSID; + fstring group_dn; +} GROUPMAP; + +typedef struct _accountmap { + uint32 rid; + fstring cn; +} ACCOUNTMAP; diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c index 2e8e6b64f8f..3f92404dda2 100644 --- a/source/utils/net_rpc.c +++ b/source/utils/net_rpc.c @@ -5989,6 +5989,7 @@ int net_rpc_help(int argc, const char **argv) {"trustdom", rpc_trustdom_usage}, /*{"abortshutdown", rpc_shutdown_abort_usage},*/ /*{"shutdown", rpc_shutdown_usage}, */ + {"vampire", rpc_vampire_usage}, {NULL, NULL} }; diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c index ef12038d5ec..dd3364dfcb0 100644 --- a/source/utils/net_rpc_samsync.c +++ b/source/utils/net_rpc_samsync.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 2002 Copyright (C) Tim Potter 2001,2002 + Copyright (C) Jim McDonough 2005 Modified by Volker Lendecke 2002 This program is free software; you can redistribute it and/or modify @@ -24,6 +25,12 @@ #include "includes.h" #include "utils/net.h" +/* uid's and gid's for writing deltas to ldif */ +static uint32 ldif_gid = 999; +static uint32 ldif_uid = 999; +/* Kkeep track of ldap initialization */ +static int init_ldap = 1; + static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g) { int i; @@ -1148,6 +1155,985 @@ fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds, return result; } +static NTSTATUS +populate_ldap_for_ldif(fstring sid, const char *suffix, const char + *builtin_sid, FILE *add_fd) +{ + char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix; + char *user_attr=NULL, *group_attr=NULL; + char *suffix_attr; + int len; + + /* Get the suffix attribute */ + suffix_attr = sstring_sub(suffix, '=', ','); + if (suffix_attr == NULL) { + len = strlen(suffix); + suffix_attr = (char*)SMB_MALLOC(len+1); + memcpy(suffix_attr, suffix, len); + suffix_attr[len] = '\0'; + } + + /* Write the base */ + fprintf(add_fd, "# %s\n", suffix); + fprintf(add_fd, "dn: %s\n", suffix); + fprintf(add_fd, "objectClass: dcObject\n"); + fprintf(add_fd, "objectClass: organization\n"); + fprintf(add_fd, "o: %s\n", suffix_attr); + fprintf(add_fd, "dc: %s\n", suffix_attr); + fprintf(add_fd, "\n"); + fflush(add_fd); + + user_suffix = lp_ldap_user_suffix(); + /* If it exists and is distinct from other containers, + Write the Users entity */ + if (user_suffix && *user_suffix && + strcmp(user_suffix, suffix)) { + user_attr = sstring_sub(lp_ldap_user_suffix(), '=', ','); + fprintf(add_fd, "# %s\n", user_suffix); + fprintf(add_fd, "dn: %s\n", user_suffix); + fprintf(add_fd, "objectClass: organizationalUnit\n"); + fprintf(add_fd, "ou: %s\n", user_attr); + fprintf(add_fd, "\n"); + fflush(add_fd); + } + + + group_suffix = lp_ldap_group_suffix(); + /* If it exists and is distinct from other containers, + Write the Groups entity */ + if (group_suffix && *group_suffix && + strcmp(group_suffix, suffix)) { + group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ','); + fprintf(add_fd, "# %s\n", group_suffix); + fprintf(add_fd, "dn: %s\n", group_suffix); + fprintf(add_fd, "objectClass: organizationalUnit\n"); + fprintf(add_fd, "ou: %s\n", group_attr); + fprintf(add_fd, "\n"); + fflush(add_fd); + } + + /* If it exists and is distinct from other containers, + Write the Computers entity */ + machine_suffix = lp_ldap_machine_suffix(); + if (machine_suffix && *machine_suffix && + strcmp(machine_suffix, user_suffix) && + strcmp(machine_suffix, suffix)) { + fprintf(add_fd, "# %s\n", lp_ldap_machine_suffix()); + fprintf(add_fd, "dn: %s\n", lp_ldap_machine_suffix()); + fprintf(add_fd, "objectClass: organizationalUnit\n"); + fprintf(add_fd, "ou: %s\n", + sstring_sub(lp_ldap_machine_suffix(), '=', ',')); + fprintf(add_fd, "\n"); + fflush(add_fd); + } + + /* If it exists and is distinct from other containers, + Write the IdMap entity */ + idmap_suffix = lp_ldap_idmap_suffix(); + if (idmap_suffix && *idmap_suffix && + strcmp(idmap_suffix, user_suffix) && + strcmp(idmap_suffix, suffix)) { + fprintf(add_fd, "# %s\n", idmap_suffix); + fprintf(add_fd, "dn: %s\n", idmap_suffix); + fprintf(add_fd, "ObjectClass: organizationalUnit\n"); + fprintf(add_fd, "ou: %s\n", + sstring_sub(lp_ldap_idmap_suffix(), '=', ',')); + fprintf(add_fd, "\n"); + fflush(add_fd); + } + + /* Write the root entity */ + fprintf(add_fd, "# root, %s, %s\n", user_attr, suffix); + fprintf(add_fd, "dn: uid=root,ou=%s,%s\n", user_attr, suffix); + fprintf(add_fd, "cn: root\n"); + fprintf(add_fd, "sn: root\n"); + fprintf(add_fd, "objectClass: inetOrgPerson\n"); + fprintf(add_fd, "objectClass: sambaSAMAccount\n"); + fprintf(add_fd, "objectClass: posixAccount\n"); + fprintf(add_fd, "objectClass: shadowAccount\n"); + fprintf(add_fd, "gidNumber: 0\n"); + fprintf(add_fd, "uid: root\n"); + fprintf(add_fd, "uidNumber: 0\n"); + fprintf(add_fd, "homeDirectory: /home/root\n"); + fprintf(add_fd, "sambaPwdLastSet: 0\n"); + fprintf(add_fd, "sambaLogonTime: 0\n"); + fprintf(add_fd, "sambaLogoffTime: 2147483647\n"); + fprintf(add_fd, "sambaKickoffTime: 2147483647\n"); + fprintf(add_fd, "sambaPwdCanChange: 0\n"); + fprintf(add_fd, "sambaPwdMustChange: 2147483647\n"); + fprintf(add_fd, "sambaHomePath: \\\\PDC-SRV\root\n"); + fprintf(add_fd, "sambaHomeDrive: H:\n"); + fprintf(add_fd, "sambaProfilePath: \\\\PDC-SRV\\profiles\\root\n"); + fprintf(add_fd, "sambaprimaryGroupSID: %s-512\n", sid); + fprintf(add_fd, "sambaLMPassword: XXX\n"); + fprintf(add_fd, "sambaNTPassword: XXX\n"); + fprintf(add_fd, "sambaAcctFlags: [U\n"); + fprintf(add_fd, "sambaSID: %s-500\n", sid); + fprintf(add_fd, "loginShell: /bin/false\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write the domain entity */ + fprintf(add_fd, "# %s, %s\n", lp_workgroup(), suffix); + fprintf(add_fd, "dn: sambaDomainName=%s,%s\n", lp_workgroup(), + suffix); + fprintf(add_fd, "objectClass: sambaDomain\n"); + fprintf(add_fd, "objectClass: sambaUnixIdPool\n"); + fprintf(add_fd, "sambaDomainName: %s\n", lp_workgroup()); + fprintf(add_fd, "sambaSID: %s\n", sid); + fprintf(add_fd, "uidNumber: %d\n", ++ldif_uid); + fprintf(add_fd, "gidNumber: %d\n", ++ldif_gid); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write user nobody entity */ + fprintf(add_fd, "# nobody, %s, %s\n", user_attr, suffix); + fprintf(add_fd, "dn: uid=nobody,ou=%s,%s\n", user_attr, suffix); + fprintf(add_fd, "cn: nobody\n"); + fprintf(add_fd, "sn: nobody\n"); + fprintf(add_fd, "objectClass: inetOrgPerson\n"); + fprintf(add_fd, "objectClass: sambaSAMAccount\n"); + fprintf(add_fd, "objectClass: posixAccount\n"); + fprintf(add_fd, "objectClass: shadowAccount\n"); + fprintf(add_fd, "gidNumber: 514\n"); + fprintf(add_fd, "uid: nobody\n"); + fprintf(add_fd, "uidNumber: 999\n"); + fprintf(add_fd, "homeDirectory: /dev/null\n"); + fprintf(add_fd, "sambaPwdLastSet: 0\n"); + fprintf(add_fd, "sambaLogonTime: 0\n"); + fprintf(add_fd, "sambaLogoffTime: 2147483647\n"); + fprintf(add_fd, "sambaKickoffTime: 2147483647\n"); + fprintf(add_fd, "sambaPwdCanChange: 0\n"); + fprintf(add_fd, "sambaPwdMustChange: 2147483647\n"); + fprintf(add_fd, "sambaHomePath: \\\\PDC-SMD3\\homes\\nobody\n"); + fprintf(add_fd, "sambaHomeDrive: H:\n"); + fprintf(add_fd, "sambaProfilePath: \\\\PDC-SMB3\\profiles\\nobody\n"); + fprintf(add_fd, "sambaprimaryGroupSID: %s-514\n", sid); + fprintf(add_fd, "sambaLMPassword: NOPASSWORDXXXXXXXXXXXXXXXXXXXXX\n"); + fprintf(add_fd, "sambaNTPassword: NOPASSWORDXXXXXXXXXXXXXXXXXXXXX\n"); + fprintf(add_fd, "sambaAcctFlags: [NU\n"); + fprintf(add_fd, "sambaSID: %s-2998\n", sid); + fprintf(add_fd, "loginShell: /bin/false\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write the Domain Admins entity */ + fprintf(add_fd, "# Domain Admins, %s, %s\n", group_attr, + suffix); + fprintf(add_fd, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr, + suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "cn: Domain Admins\n"); + fprintf(add_fd, "memberUid: Administrator\n"); + fprintf(add_fd, "description: Netbios Domain Administrators\n"); + fprintf(add_fd, "gidNumber: 512\n"); + fprintf(add_fd, "sambaSID: %s-512\n", sid); + fprintf(add_fd, "sambaGroupType: 2\n"); + fprintf(add_fd, "displayName: Domain Admins\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write the Domain Users entity */ + fprintf(add_fd, "# Domain Users, %s, %s\n", group_attr, + suffix); + fprintf(add_fd, "dn: cn=Domain Users,ou=%s,%s\n", group_attr, + suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "cn: Domain Users\n"); + fprintf(add_fd, "description: Netbios Domain Users\n"); + fprintf(add_fd, "gidNumber: 513\n"); + fprintf(add_fd, "sambaSID: %s-513\n", sid); + fprintf(add_fd, "sambaGroupType: 2\n"); + fprintf(add_fd, "displayName: Domain Users\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write the Domain Guests entity */ + fprintf(add_fd, "# Domain Guests, %s, %s\n", group_attr, + suffix); + fprintf(add_fd, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr, + suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "cn: Domain Guests\n"); + fprintf(add_fd, "description: Netbios Domain Guests\n"); + fprintf(add_fd, "gidNumber: 514\n"); + fprintf(add_fd, "sambaSID: %s-514\n", sid); + fprintf(add_fd, "sambaGroupType: 2\n"); + fprintf(add_fd, "displayName: Domain Guests\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write the Domain Computers entity */ + fprintf(add_fd, "# Domain Computers, %s, %s\n", group_attr, + suffix); + fprintf(add_fd, "dn: cn=Domain Computers,ou=%s,%s\n", + group_attr, suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "gidNumber: 515\n"); + fprintf(add_fd, "cn: Domain Computers\n"); + fprintf(add_fd, "description: Netbios Domain Computers accounts\n"); + fprintf(add_fd, "sambaSID: %s-515\n", sid); + fprintf(add_fd, "sambaGroupType: 2\n"); + fprintf(add_fd, "displayName: Domain Computers\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write the Admininistrators Groups entity */ + fprintf(add_fd, "# Administrators, %s, %s\n", group_attr, + suffix); + fprintf(add_fd, "dn: cn=Administrators,ou=%s,%s\n", group_attr, + suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "gidNumber: 544\n"); + fprintf(add_fd, "cn: Administrators\n"); + fprintf(add_fd, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n"); + fprintf(add_fd, "sambaSID: %s-544\n", builtin_sid); + fprintf(add_fd, "sambaGroupType: 5\n"); + fprintf(add_fd, "displayName: Administrators\n"); + fprintf(add_fd, "\n"); + + /* Write the Print Operator entity */ + fprintf(add_fd, "# Print Operators, %s, %s\n", group_attr, + suffix); + fprintf(add_fd, "dn: cn=Print Operators,ou=%s,%s\n", + group_attr, suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "gidNumber: 550\n"); + fprintf(add_fd, "cn: Print Operators\n"); + fprintf(add_fd, "description: Netbios Domain Print Operators\n"); + fprintf(add_fd, "sambaSID: %s-550\n", builtin_sid); + fprintf(add_fd, "sambaGroupType: 5\n"); + fprintf(add_fd, "displayName: Print Operators\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write the Backup Operators entity */ + fprintf(add_fd, "# Backup Operators, %s, %s\n", group_attr, + suffix); + fprintf(add_fd, "dn: cn=Backup Operators,ou=%s,%s\n", + group_attr, suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "gidNumber: 551\n"); + fprintf(add_fd, "cn: Backup Operators\n"); + fprintf(add_fd, "description: Netbios Domain Members can bypass file security to back up files\n"); + fprintf(add_fd, "sambaSID: %s-551\n", builtin_sid); + fprintf(add_fd, "sambaGroupType: 5\n"); + fprintf(add_fd, "displayName: Backup Operators\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Write the Replicators entity */ + fprintf(add_fd, "# Replicators, %s, %s\n", group_attr, suffix); + fprintf(add_fd, "dn: cn=Replicators,ou=%s,%s\n", group_attr, + suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "gidNumber: 552\n"); + fprintf(add_fd, "cn: Replicators\n"); + fprintf(add_fd, "description: Netbios Domain Supports file replication in a sambaDomainName\n"); + fprintf(add_fd, "sambaSID: %s-552\n", builtin_sid); + fprintf(add_fd, "sambaGroupType: 5\n"); + fprintf(add_fd, "displayName: Replicators\n"); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Deallocate memory, and return */ + if (suffix_attr != NULL) SAFE_FREE(suffix_attr); + return NT_STATUS_OK; +} + +static NTSTATUS +map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap, fstring sid, + const char *suffix, const char *builtin_sid) +{ + char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ','); + + /* Map the groups created by populate_ldap_for_ldif */ + groupmap[0].rid = 512; + groupmap[0].gidNumber = 512; + pstr_sprintf(groupmap[0].sambaSID, "%s-512", sid); + pstr_sprintf(groupmap[0].group_dn, "cn=Domain Admins,ou=%s,%s", + group_attr, suffix); + accountmap[0].rid = 512; + pstr_sprintf(accountmap[0].cn, "%s", "Domain Admins"); + + groupmap[1].rid = 513; + groupmap[1].gidNumber = 513; + pstr_sprintf(groupmap[1].sambaSID, "%s-513", sid); + pstr_sprintf(groupmap[1].group_dn, "cn=Domain Users,ou=%s,%s", + group_attr, suffix); + accountmap[1].rid = 513; + pstr_sprintf(accountmap[1].cn, "%s", "Domain Users"); + + groupmap[2].rid = 514; + groupmap[2].gidNumber = 514; + pstr_sprintf(groupmap[2].sambaSID, "%s-514", sid); + pstr_sprintf(groupmap[2].group_dn, "cn=Domain Guests,ou=%s,%s", + group_attr, suffix); + accountmap[2].rid = 514; + pstr_sprintf(accountmap[2].cn, "%s", "Domain Guests"); + + groupmap[3].rid = 515; + groupmap[3].gidNumber = 515; + pstr_sprintf(groupmap[3].sambaSID, "%s-515", sid); + pstr_sprintf(groupmap[3].group_dn, "cn=Domain Computers,ou=%s,%s", + group_attr, suffix); + accountmap[3].rid = 515; + pstr_sprintf(accountmap[3].cn, "%s", "Domain Computers"); + + groupmap[4].rid = 544; + groupmap[4].gidNumber = 544; + pstr_sprintf(groupmap[4].sambaSID, "%s-544", builtin_sid); + pstr_sprintf(groupmap[4].group_dn, "cn=Administrators,ou=%s,%s", + group_attr, suffix); + accountmap[4].rid = 515; + pstr_sprintf(accountmap[4].cn, "%s", "Administrators"); + + groupmap[5].rid = 550; + groupmap[5].gidNumber = 550; + pstr_sprintf(groupmap[5].sambaSID, "%s-550", builtin_sid); + pstr_sprintf(groupmap[5].group_dn, "cn=Print Operators,ou=%s,%s", + group_attr, suffix); + accountmap[5].rid = 550; + pstr_sprintf(accountmap[5].cn, "%s", "Print Operators"); + + groupmap[6].rid = 551; + groupmap[6].gidNumber = 551; + pstr_sprintf(groupmap[6].sambaSID, "%s-551", builtin_sid); + pstr_sprintf(groupmap[6].group_dn, "cn=Backup Operators,ou=%s,%s", + group_attr, suffix); + accountmap[6].rid = 551; + pstr_sprintf(accountmap[6].cn, "%s", "Backup Operators"); + + groupmap[7].rid = 552; + groupmap[7].gidNumber = 552; + pstr_sprintf(groupmap[7].sambaSID, "%s-552", builtin_sid); + pstr_sprintf(groupmap[7].group_dn, "cn=Replicators,ou=%s,%s", + group_attr, suffix); + accountmap[7].rid = 551; + pstr_sprintf(accountmap[7].cn, "%s", "Replicators"); + return NT_STATUS_OK; +} + +static NTSTATUS +fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, + FILE *add_fd, fstring sid, char *suffix) +{ + fstring groupname; + uint32 grouptype = 0, g_rid = 0; + char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ','); + + /* Get the group name */ + unistr2_to_ascii(groupname, + &(delta->group_info.uni_grp_name), + sizeof(groupname)-1); + + /* Set up the group type (always 2 for group info) */ + grouptype = 2; + + /* These groups are entered by populate_ldap_for_ldif */ + if (strcmp(groupname, "Domain Admins") == 0 || + strcmp(groupname, "Domain Users") == 0 || + strcmp(groupname, "Domain Guests") == 0 || + strcmp(groupname, "Domain Computers") == 0 || + strcmp(groupname, "Administrators") == 0 || + strcmp(groupname, "Print Operators") == 0 || + strcmp(groupname, "Backup Operators") == 0 || + strcmp(groupname, "Replicators") == 0) { + return NT_STATUS_OK; + } else { + /* Increment the gid for the new group */ + ldif_gid++; + } + + /* Map the group rid, gid, and dn */ + g_rid = delta->group_info.gid.g_rid; + groupmap->rid = g_rid; + groupmap->gidNumber = ldif_gid; + pstr_sprintf(groupmap->sambaSID, "%s-%d", sid, g_rid); + pstr_sprintf(groupmap->group_dn, + "cn=%s,ou=%s,%s", groupname, group_attr, suffix); + + /* Write the data to the temporary add ldif file */ + fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr, + suffix); + fprintf(add_fd, "dn: cn=%s,ou=%s,%s\n", groupname, group_attr, + suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "cn: %s\n", groupname); + fprintf(add_fd, "gidNumber: %d\n", ldif_gid); + fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID); + fprintf(add_fd, "sambaGroupType: %d\n", grouptype); + fprintf(add_fd, "displayName: %s\n", groupname); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Return */ + return NT_STATUS_OK; +} + +static NTSTATUS +fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, + ACCOUNTMAP *accountmap, FILE *add_fd, + fstring sid, char *suffix, int alloced) +{ + fstring username, homedir, logonscript, homedrive, homepath; + fstring hex_nt_passwd, hex_lm_passwd; + fstring description, fullname, sambaSID; + uchar lm_passwd[16], nt_passwd[16]; + char *flags; + const char *blank = "", *shell = "/bin/bash"; + const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; + static uchar zero_buf[16]; + uint32 rid = 0, group_rid = 0, gidNumber = 0; + time_t unix_time; + int i; + + /* Get the username */ + unistr2_to_ascii(username, + &(delta->account_info.uni_acct_name), + sizeof(username)-1); + + /* Get the rid */ + rid = delta->account_info.user_rid; + + /* Map the rid and username for group member info later */ + accountmap->rid = rid; + pstr_sprintf(accountmap->cn, "%s", username); + + /* Get the home directory */ + unistr2_to_ascii(homedir, &(delta->account_info.uni_home_dir), + sizeof(homedir)-1); + if (strcmp(homedir, blank) == 0) { + pstr_sprintf(homedir, "/home/%s", username); + } else { + strncpy(homepath, homedir, sizeof(homepath)); + } + + /* Get the logon script */ + unistr2_to_ascii(logonscript, &(delta->account_info.uni_logon_script), + sizeof(logonscript)-1); + + /* Get the home drive */ + unistr2_to_ascii(homedrive, &(delta->account_info.uni_dir_drive), + sizeof(homedrive)-1); + + /* Get the description */ + unistr2_to_ascii(description, &(delta->account_info.uni_acct_desc), + sizeof(description)-1); + if (strcmp(description, blank) == 0) { + pstr_sprintf(description, "System User"); + } + + /* Get the display name */ + unistr2_to_ascii(fullname, &(delta->account_info.uni_full_name), + sizeof(fullname)-1); + + /* Get lm and nt password data */ + if (memcmp(delta->account_info.pass.buf_lm_pwd, zero_buf, 16) != 0) { + sam_pwd_hash(delta->account_info.user_rid, + delta->account_info.pass.buf_lm_pwd, + lm_passwd, 0); + pdb_sethexpwd(hex_lm_passwd, lm_passwd, + delta->account_info.acb_info); + } else { + pdb_sethexpwd(hex_lm_passwd, NULL, 0); + } + if (memcmp(delta->account_info.pass.buf_nt_pwd, zero_buf, 16) != 0) { + sam_pwd_hash(delta->account_info.user_rid, + delta->account_info.pass.buf_nt_pwd, + nt_passwd, 0); + pdb_sethexpwd(hex_nt_passwd, nt_passwd, + delta->account_info.acb_info); + } else { + pdb_sethexpwd(hex_nt_passwd, NULL, 0); + } + unix_time = nt_time_to_unix(&(delta->account_info.pwd_last_set_time)); + + /* The nobody user is entered by populate_ldap_for_ldif */ + if (strcmp(username, "nobody") == 0) { + return NT_STATUS_OK; + } else { + /* Increment the uid for the new user */ + ldif_uid++; + } + + /* Set up group id and sambaSID for the user */ + group_rid = delta->account_info.group_rid; + for (i=0; iaccount_info.acb_info, + NEW_PW_FORMAT_SPACE_PADDED_LEN); + + /* Add the user to the temporary add ldif file */ + fprintf(add_fd, "# %s, %s, %s\n", username, + sstring_sub(lp_ldap_user_suffix(), '=', ','), suffix); + fprintf(add_fd, "dn: uid=%s,ou=%s,%s\n", username, + sstring_sub(lp_ldap_user_suffix(), '=', ','), suffix); + fprintf(add_fd, "ObjectClass: top\n"); + fprintf(add_fd, "objectClass: inetOrgPerson\n"); + fprintf(add_fd, "objectClass: posixAccount\n"); + fprintf(add_fd, "objectClass: shadowAccount\n"); + fprintf(add_fd, "objectClass: sambaSamAccount\n"); + fprintf(add_fd, "cn: %s\n", username); + fprintf(add_fd, "sn: %s\n", username); + fprintf(add_fd, "uid: %s\n", username); + fprintf(add_fd, "uidNumber: %d\n", ldif_uid); + fprintf(add_fd, "gidNumber: %d\n", gidNumber); + fprintf(add_fd, "homeDirectory: %s\n", homedir); + if (strcmp(homepath, blank) != 0) + fprintf(add_fd, "SambaHomePath: %s\n", homepath); + if (strcmp(homedrive, blank) != 0) + fprintf(add_fd, "SambaHomeDrive: %s\n", homedrive); + if (strcmp(logonscript, blank) != 0) + fprintf(add_fd, "SambaLogonScript: %s\n", logonscript); + fprintf(add_fd, "loginShell: %s\n", shell); + fprintf(add_fd, "gecos: System User\n"); + fprintf(add_fd, "description: %s\n", description); + fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid); + fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID); + if(strcmp(fullname, blank) != 0) + fprintf(add_fd, "displayName: %s\n", fullname); + if (strcmp(nopasswd, hex_lm_passwd) != 0) + fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd); + if (strcmp(nopasswd, hex_nt_passwd) != 0) + fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd); + fprintf(add_fd, "sambaPwdLastSet: %d\n", unix_time); + fprintf(add_fd, "sambaAcctFlags: %s\n", flags); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Return */ + return NT_STATUS_OK; +} + +static NTSTATUS +fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, + FILE *add_fd, fstring sid, char *suffix, + unsigned db_type) +{ + fstring aliasname, description; + uint32 grouptype = 0, g_rid = 0; + char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ','); + + /* Get the alias name */ + unistr2_to_ascii(aliasname, &(delta->alias_info.uni_als_name), + sizeof(aliasname)-1); + + /* Get the alias description */ + unistr2_to_ascii(description, &(delta->alias_info.uni_als_desc), + sizeof(description)-1); + + /* Set up the group type */ + switch (db_type) { + case SAM_DATABASE_DOMAIN: + grouptype = 4; + break; + case SAM_DATABASE_BUILTIN: + grouptype = 5; + break; + default: + grouptype = 4; + break; + } + + /* + These groups are entered by populate_ldap_for_ldif + Note that populate creates a group called Relicators, + but NT returns a group called Replicator + */ + if (strcmp(aliasname, "Domain Admins") == 0 || + strcmp(aliasname, "Domain Users") == 0 || + strcmp(aliasname, "Domain Guests") == 0 || + strcmp(aliasname, "Domain Computers") == 0 || + strcmp(aliasname, "Administrators") == 0 || + strcmp(aliasname, "Print Operators") == 0 || + strcmp(aliasname, "Backup Operators") == 0 || + strcmp(aliasname, "Replicator") == 0) { + return NT_STATUS_OK; + } else { + /* Increment the gid for the new group */ + ldif_gid++; + } + + /* Map the group rid and gid */ + g_rid = delta->group_info.gid.g_rid; + groupmap->gidNumber = ldif_gid; + pstr_sprintf(groupmap->sambaSID, "%s-%d", sid, g_rid); + + /* Write the data to the temporary add ldif file */ + fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr, + suffix); + fprintf(add_fd, "dn: cn=%s,ou=%s,%s\n", aliasname, group_attr, + suffix); + fprintf(add_fd, "objectClass: posixGroup\n"); + fprintf(add_fd, "objectClass: sambaGroupMapping\n"); + fprintf(add_fd, "cn: %s\n", aliasname); + fprintf(add_fd, "gidNumber: %d\n", ldif_gid); + fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID); + fprintf(add_fd, "sambaGroupType: %d\n", grouptype); + fprintf(add_fd, "displayName: %s\n", aliasname); + fprintf(add_fd, "description: %s\n", description); + fprintf(add_fd, "\n"); + fflush(add_fd); + + /* Return */ + return NT_STATUS_OK; +} + +static NTSTATUS +fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR *hdr_delta, + GROUPMAP *groupmap, ACCOUNTMAP *accountmap, + FILE *mod_fd, int alloced) +{ + fstring group_dn; + uint32 group_rid = 0, rid = 0; + int i, j, k; + + /* Get the dn for the group */ + if (delta->grp_mem_info.num_members > 0) { + group_rid = hdr_delta->target_rid; + for (j=0; jgrp_mem_info.num_members; i++) { + rid = delta->grp_mem_info.rids[i]; + for (k=0; ksess_key, &(cli->clnt_cred), + ret_creds); + + /* Re-allocate memory for groupmap and accountmap arrays */ + groupmap = SMB_REALLOC_ARRAY(groupmap, GROUPMAP, + num_deltas+num_alloced); + accountmap = SMB_REALLOC_ARRAY(accountmap, ACCOUNTMAP, + num_deltas+num_alloced); + if (groupmap == NULL || accountmap == NULL) { + DEBUG(1,("GROUPMAP malloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + + /* Initialize the new records */ + memset(&groupmap[num_alloced], 0, + sizeof(GROUPMAP)*num_deltas); + memset(&accountmap[num_alloced], 0, + sizeof(ACCOUNTMAP)*num_deltas); + + /* Remember how many we alloced this time */ + num_alloced += num_deltas; + + /* Loop through the deltas */ + for (k=0; k> %s", add_ldif, ldif_file); + system(sys_cmd); + if (db_type == SAM_DATABASE_DOMAIN) { + fprintf(ldif_fd, + "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n"); + fprintf(ldif_fd, + "# ====================================\n\n"); + fflush(ldif_fd); + } else if (db_type == SAM_DATABASE_BUILTIN) { + fprintf(ldif_fd, + "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n"); + fprintf(ldif_fd, + "# =====================================\n\n"); + fflush(ldif_fd); + } + pstr_sprintf(sys_cmd, "cat %s >> %s", mod_ldif, ldif_file); + system(sys_cmd); + + /* Delete the temporary ldif files */ + pstr_sprintf(sys_cmd, "rm -f %s %s", add_ldif, mod_ldif); + system(sys_cmd); + + /* Close the ldif file */ + fclose(ldif_fd); + + /* Deallocate memory for the mapping arrays */ + SAFE_FREE(groupmap); + SAFE_FREE(accountmap); + + /* Return */ + talloc_destroy(mem_ctx); + return NT_STATUS_OK; +} + +/** + * Basic usage function for 'net rpc vampire' + * @param argc Standard main() style argc + * @param argc Standard main() style argv. Initial components are already + * stripped + **/ + +int rpc_vampire_usage(int argc, const char **argv) +{ + d_printf("net rpc vampire [ldif [] [options]\n"\ + "\t to pull accounts from a remote PDC where we are a BDC\n"\ + "\t\t no args puts accounts in local passdb from smb.conf\n"\ + "\t\t ldif - put accounts in ldif format (file defaults to /tmp/tmp.ldif\n"); + + net_common_flags_usage(argc, argv); + return -1; +} + + /* dump sam database via samsync rpc calls */ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, const char *domain_name, @@ -1193,7 +2179,13 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, goto fail; } - result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, *domain_sid); + if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) { + result = fetch_database_to_ldif(cli, SAM_DATABASE_DOMAIN, + &ret_creds, *domain_sid, argv[1]); + } else { + result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, + *domain_sid); + } if (!NT_STATUS_IS_OK(result)) { d_printf("Failed to fetch domain database: %s\n", @@ -1204,8 +2196,14 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, goto fail; } - result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, - global_sid_Builtin); + if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) { + result = fetch_database_to_ldif(cli, SAM_DATABASE_BUILTIN, + &ret_creds, global_sid_Builtin, + argv[1]); + } else { + result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, + global_sid_Builtin); + } if (!NT_STATUS_IS_OK(result)) { d_printf("Failed to fetch builtin database: %s\n", @@ -1219,3 +2217,4 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, fail: return result; } +