--- utils/net_rpc_join.c.orig Fri Jun 23 13:16:53 2006 +++ utils/net_rpc_join.c Wed Aug 8 03:47:19 2007 @@ -97,6 +97,136 @@ } /** + * utility function to parse an integer parameter from + * "parameter = value" + */ +static const char* get_string_param( const char* param ) +{ + const char *p; + + if ( (p = strchr( param, '=' )) == NULL ) + return NULL; + + return (p+1); +} + + +/** + * Build an org unit string + * if org unit is empty then assume org to be Computers + * @param org_unit - Organizational unit + * @return org unit string - caller must free + **/ +static char *build_ou_string(const char *org_unit) +{ + if (!org_unit || !*org_unit || strequal(org_unit, "Computers")) + return SMB_STRDUP("cn=Computers"); + + return ads_build_path(org_unit, "/", "ou=", 1); +} + +static int netrpc_precreate_machine_acct(const char *ou) +{ + char *binddn = NULL; + char *ldap_uri = NULL; + const char *realm = lp_realm(); + + char *machine_escaped = NULL; + char *ou_str = NULL; + char *new_dn = NULL; + char *samAccountName = NULL; + char *controlstr = NULL; + const char *objectClass[] = {"top", "person", "organizationalPerson", + "user", "computer", NULL}; + TALLOC_CTX *tc = NULL; + struct smbldap_state *ldap_state = NULL; + int retval = 0; + int rc; + int i; + LDAPMod **mods = NULL; + const char *machine_name = global_myname(); + uint32 acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\ + UF_DONT_EXPIRE_PASSWD |\ + UF_ACCOUNTDISABLE ); + +#ifndef ENCTYPE_ARCFOUR_HMAC + acct_control |= UF_USE_DES_KEY_ONLY; +#endif + + machine_escaped = escape_rdn_val_string_alloc(machine_name); + if (!machine_escaped) { + d_fprintf(stderr, "ERROR: Out of memory while escaping machine name\n"); + retval = 1; + goto done; + } + + ou_str = build_ou_string(ou); + if ((asprintf(&new_dn, "cn=%s,%s,%s", machine_escaped, ou_str, ads_build_dn(realm)) == -1)) { + d_fprintf(stderr, "ERROR: Out of memory while creating dn\n"); + retval = 1; + goto done; + } + + asprintf(&binddn, "%s\\%s", opt_target_workgroup, opt_user_name); + asprintf(&ldap_uri, "ldap://%s", opt_host); + asprintf(&samAccountName, "%s$", machine_name); + asprintf(&controlstr, "%u", acct_control); + + smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", machine_name); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "sAMAccountName", samAccountName); + + for (i = 0; objectClass[i] != NULL; i++) + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", objectClass[i]); + + smbldap_set_mod(&mods, LDAP_MOD_ADD, "userAccountControl", controlstr); + + tc = talloc_new(NULL); + if (!tc) { + d_fprintf(stderr, "ERROR: Out of memory while allocating internal buffer\n"); + retval = 1; + goto done; + } + + if (!NT_STATUS_IS_OK(smbldap_init(tc, ldap_uri, &ldap_state))) { + d_fprintf(stderr, "ERROR: smbldap_init: Unable to initialize connection with server.\n"); + retval = 1; + goto done; + } + + if (!smbldap_set_creds(ldap_state, false, binddn, opt_password)) { + d_fprintf(stderr, "ERROR: Failure to set credentials\n"); + retval = 1; + goto done; + } + + if (LDAP_SUCCESS != (rc = smbldap_add(ldap_state, new_dn, mods))) { + if (rc != LDAP_ALREADY_EXISTS) { + d_fprintf(stderr, "ERROR: Failure to create " + "machine account: %s\n", ldap_err2string(rc)); + } + retval = rc; + goto done; + } + +done: + if (ldap_state) + smbldap_free_struct(&ldap_state); + + if (tc) + TALLOC_FREE(tc); + + SAFE_FREE(ldap_uri); + SAFE_FREE(binddn); + SAFE_FREE(machine_escaped); + SAFE_FREE(ou_str); + SAFE_FREE(new_dn); + SAFE_FREE(samAccountName); + SAFE_FREE(controlstr); + + return retval; +} + +/** * Join a domain using the administrator username and password * * @param argc Standard main() style argc @@ -142,6 +272,9 @@ uint32 flags = 0x3e8; char *acct_name; const char *const_acct_name; + const char *create_in_ou = NULL; + int i; + int status; /* check what type of join */ if (argc >= 0) { @@ -221,6 +354,23 @@ domain_sid, &domain_pol), "could not open domain"); + for (i = 0; i < argc; i++) { + if (strnequal(argv[i], "createcomputer=", sizeof("createcomputer=")-1)) { + if ((create_in_ou = get_string_param(argv[i])) == NULL) { + d_fprintf(stderr, "Please supply a valid OU path.\n"); + goto done; + } + } + } + + if (create_in_ou) { + status = netrpc_precreate_machine_acct(create_in_ou); + if (status && status != LDAP_ALREADY_EXISTS) { + d_fprintf(stderr, "Failed to pre-create the machine object " + "in OU '%s'.\n", create_in_ou); + goto done; + } + } /* Create domain user */ if ((acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname())) == NULL) { result = NT_STATUS_NO_MEMORY;