summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2006-05-13 04:39:19 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:17:01 -0500
commitf1039b8fb461c6e1276dba8564f62ec1496a7b88 (patch)
tree1e8a5883ce479e51167806cec189030770d6fa4c
parent453e4b50aae52089eb2c2ae6a2abc3b48425ee55 (diff)
downloadsamba-f1039b8fb461c6e1276dba8564f62ec1496a7b88.tar.gz
samba-f1039b8fb461c6e1276dba8564f62ec1496a7b88.tar.bz2
samba-f1039b8fb461c6e1276dba8564f62ec1496a7b88.zip
r15560: Since the hotel doesn't have Sci-Fi and no "Doctor Who"....
Re-add the capability to specify an OU in which to create the machine account. Done via LDAP prior to the RPC join. (This used to be commit b69ac0e30441faea7a7d677b6bb551aa8ffbf55d)
-rw-r--r--source3/libads/ldap.c196
-rw-r--r--source3/utils/net_ads.c76
2 files changed, 96 insertions, 176 deletions
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 6f698dc3a9..63056645cd 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -980,6 +980,7 @@ ADS_STATUS ads_mod_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
name, (const void **) vals);
}
+#if 0
/**
* Add a single ber-encoded value to a mod list
* @param ctx An initialized TALLOC_CTX
@@ -1000,6 +1001,7 @@ static ADS_STATUS ads_mod_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods,
return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE|LDAP_MOD_BVALUES,
name, (const void **) values);
}
+#endif
/**
* Perform an ldap modify
@@ -1421,105 +1423,33 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n
* @return 0 upon success, or non-zero otherwise
**/
-static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *machine_name,
- uint32 account_type,
- const char *org_unit)
+ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
+ const char *org_unit)
{
- ADS_STATUS ret, status;
- char *host_spn, *host_upn, *new_dn, *samAccountName, *controlstr;
+ ADS_STATUS ret;
+ char *samAccountName, *controlstr;
TALLOC_CTX *ctx;
ADS_MODLIST mods;
+ char *new_dn;
const char *objectClass[] = {"top", "person", "organizationalPerson",
"user", "computer", NULL};
- const char *servicePrincipalName[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
- char *psp, *psp2, *psp3, *psp4;
- unsigned acct_control;
- unsigned exists=0;
- fstring my_fqdn;
LDAPMessage *res = NULL;
- int i, next_spn;
-
+ uint32 acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\
+ UF_DONT_EXPIRE_PASSWD |\
+ UF_ACCOUNTDISABLE );
+
if (!(ctx = talloc_init("ads_add_machine_acct")))
return ADS_ERROR(LDAP_NO_MEMORY);
ret = ADS_ERROR(LDAP_NO_MEMORY);
+
+ new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_name, org_unit);
+ samAccountName = talloc_asprintf(ctx, "%s$", machine_name);
- name_to_fqdn(my_fqdn, machine_name);
-
- status = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
- if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
- char *dn_string = ads_get_dn(ads, res);
- if (!dn_string) {
- DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
- goto done;
- }
- new_dn = talloc_strdup(ctx, dn_string);
- ads_memfree(ads,dn_string);
- DEBUG(0, ("ads_add_machine_acct: Host account for %s already exists - modifying old account\n",
- machine_name));
- exists=1;
- } else {
- char *ou_str = ads_ou_string(ads,org_unit);
- if (!ou_str) {
- DEBUG(1, ("ads_add_machine_acct: ads_ou_string returned NULL (malloc failure?)\n"));
- goto done;
- }
- new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", machine_name, ou_str,
- ads->config.bind_path);
-
- SAFE_FREE(ou_str);
- }
-
- if (!new_dn) {
- goto done;
- }
-
- if (!(host_spn = talloc_asprintf(ctx, "HOST/%s", machine_name)))
- goto done;
- if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm)))
- goto done;
- servicePrincipalName[0] = talloc_asprintf(ctx, "HOST/%s", machine_name);
- psp = talloc_asprintf(ctx, "HOST/%s.%s",
- machine_name,
- ads->config.realm);
- strlower_m(&psp[5]);
- servicePrincipalName[1] = psp;
- servicePrincipalName[2] = talloc_asprintf(ctx, "CIFS/%s", machine_name);
- psp2 = talloc_asprintf(ctx, "CIFS/%s.%s",
- machine_name,
- ads->config.realm);
- strlower_m(&psp2[5]);
- servicePrincipalName[3] = psp2;
-
- /* Ensure servicePrincipalName[4] and [5] are unique. */
- strlower_m(my_fqdn);
- psp3 = talloc_asprintf(ctx, "CIFS/%s", my_fqdn);
- strlower_m(&psp3[5]);
-
- next_spn = 4;
- for (i = 0; i < next_spn; i++) {
- if (strequal(servicePrincipalName[i], psp3))
- break;
- }
- if (i == next_spn) {
- servicePrincipalName[next_spn++] = psp3;
- }
-
- psp4 = talloc_asprintf(ctx, "HOST/%s", my_fqdn);
- strlower_m(&psp4[5]);
- for (i = 0; i < next_spn; i++) {
- if (strequal(servicePrincipalName[i], psp4))
- break;
- }
- if (i == next_spn) {
- servicePrincipalName[next_spn++] = psp4;
- }
-
- if (!(samAccountName = talloc_asprintf(ctx, "%s$", machine_name))) {
+ if ( !new_dn || !samAccountName ) {
goto done;
}
-
- acct_control = account_type | UF_DONT_EXPIRE_PASSWD;
+
#ifndef ENCTYPE_ARCFOUR_HMAC
acct_control |= UF_USE_DES_KEY_ONLY;
#endif
@@ -1531,44 +1461,18 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *machine_name
if (!(mods = ads_init_mods(ctx))) {
goto done;
}
-
- if (!exists) {
- ads_mod_str(ctx, &mods, "cn", machine_name);
- ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName);
- ads_mod_strlist(ctx, &mods, "objectClass", objectClass);
- }
+
+ ads_mod_str(ctx, &mods, "cn", machine_name);
+ ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName);
+ ads_mod_strlist(ctx, &mods, "objectClass", objectClass);
ads_mod_str(ctx, &mods, "userAccountControl", controlstr);
- ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
- ads_mod_str(ctx, &mods, "userPrincipalName", host_upn);
- ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
- ads_mod_str(ctx, &mods, "operatingSystem", "Samba");
- ads_mod_str(ctx, &mods, "operatingSystemVersion", SAMBA_VERSION_STRING);
-
- if (!exists) {
- ret = ads_gen_add(ads, new_dn, mods);
- } else {
- ret = ads_gen_mod(ads, new_dn, mods);
- }
- if (!ADS_ERR_OK(ret)) {
- goto done;
- }
+ ret = ads_gen_add(ads, new_dn, mods);
- /* Do not fail if we can't set security descriptor
- * it shouldn't be mandatory and probably we just
- * don't have enough rights to do it.
- */
- if (!exists) {
- status = ads_set_machine_sd(ads, machine_name, new_dn);
-
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("Warning: ads_set_machine_sd: %s\n",
- ads_errstr(status)));
- }
- }
done:
ads_msgfree(ads, res);
talloc_destroy(ctx);
+
return ret;
}
@@ -1784,58 +1688,6 @@ int ads_count_replies(ADS_STRUCT *ads, void *res)
}
/**
- * Join a machine to a realm
- * Creates the machine account and sets the machine password
- * @param ads connection to ads server
- * @param machine name of host to add
- * @param org_unit Organizational unit to place machine in
- * @return status of join
- **/
-ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
- uint32 account_type, const char *org_unit)
-{
- ADS_STATUS status;
- LDAPMessage *res = NULL;
- char *machine;
-
- /* machine name must be lowercase */
- machine = SMB_STRDUP(machine_name);
- strlower_m(machine);
-
- /*
- status = ads_find_machine_acct(ads, (void **)&res, machine);
- if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
- DEBUG(0, ("Host account for %s already exists - deleting old account\n", machine));
- status = ads_leave_realm(ads, machine);
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("Failed to delete host '%s' from the '%s' realm.\n",
- machine, ads->config.realm));
- return status;
- }
- }
- */
-
- status = ads_add_machine_acct(ads, machine, account_type, org_unit);
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("ads_join_realm: ads_add_machine_acct failed (%s): %s\n", machine, ads_errstr(status)));
- SAFE_FREE(machine);
- return status;
- }
-
- status = ads_find_machine_acct(ads, (void **)(void *)&res, machine);
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("ads_join_realm: Host account test failed for machine %s\n", machine));
- SAFE_FREE(machine);
- return status;
- }
-
- SAFE_FREE(machine);
- ads_msgfree(ads, res);
-
- return status;
-}
-
-/**
* Delete a machine from the realm
* @param ads connection to ads server
* @param hostname Machine to remove
@@ -1895,6 +1747,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
return status;
}
+#if 0
/**
* add machine account to existing security descriptor
* @param ads connection to ads server
@@ -1902,7 +1755,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
* @param dn DN of security descriptor
* @return status
**/
-ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
+static ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
{
const char *attrs[] = {"nTSecurityDescriptor", "objectSid", 0};
char *expr = 0;
@@ -2016,6 +1869,7 @@ ads_set_sd_error:
talloc_destroy(ctx);
return ret;
}
+#endif
/**
* pull the first entry from a ADS result
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index e75090449d..e913437ef1 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -4,6 +4,7 @@
Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
+ Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1163,6 +1164,61 @@ done:
return status;
}
+
+/*******************************************************************
+ join a domain using ADS (LDAP mods)
+ ********************************************************************/
+
+static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou )
+{
+ ADS_STRUCT *ads_s = ads;
+ ADS_STATUS rc = ADS_ERROR(LDAP_SERVER_DOWN);
+ char *dn, *ou_str;
+ LDAPMessage *res = NULL;
+
+ ou_str = ads_ou_string(ads, ou);
+ asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
+ free(ou_str);
+
+ if ( !ads->ld ) {
+ ads_s = ads_init( ads->config.realm, NULL, ads->config.ldap_server_name );
+
+ if ( ads_s ) {
+ rc = ads_connect( ads_s );
+ }
+
+ if ( !ADS_ERR_OK(rc) ) {
+ goto done;
+ }
+ }
+
+ rc = ads_search_dn(ads, (void**)&res, dn, NULL);
+ ads_msgfree(ads, res);
+
+ if (!ADS_ERR_OK(rc)) {
+ goto done;
+ }
+
+ /* Attempt to create the machine account and bail if this fails.
+ Assume that the admin wants exactly what they requested */
+
+ rc = ads_create_machine_acct( ads, global_myname(), dn );
+ if ( rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_ALREADY_EXISTS ) {
+ rc = ADS_SUCCESS;
+ goto done;
+ }
+ if ( !ADS_ERR_OK(rc) ) {
+ goto done;
+ }
+
+done:
+ if ( ads_s != ads )
+ ads_destroy( &ads_s );
+ SAFE_FREE( dn );
+
+ return rc;
+}
+
/*******************************************************************
join a domain using ADS (LDAP mods)
********************************************************************/
@@ -1183,11 +1239,9 @@ int net_ads_join(int argc, const char **argv)
return -1;
}
- if (!(ads = ads_init(lp_realm(), NULL, NULL ))) {
+ if ( (ads = ads_startup()) == NULL ) {
return -1;
}
- ads->auth.flags = ADS_AUTH_NO_BIND;
- status = ads_connect(ads);
if (strcmp(ads->config.realm, lp_realm()) != 0) {
d_fprintf(stderr, "realm of remote server (%s) and realm in smb.conf "
@@ -1197,12 +1251,24 @@ int net_ads_join(int argc, const char **argv)
return -1;
}
-
- if (!(ctx = talloc_init("net_join_domain"))) {
+ if (!(ctx = talloc_init("net_ads_join"))) {
DEBUG(0, ("Could not initialise talloc context\n"));
return -1;
}
+ /* If we were given an OU, try to create the machine in the OU account
+ first and then do the normal RPC join */
+
+ if ( argc > 0 ) {
+ status = net_precreate_machine_acct( ads, argv[0] );
+ if ( !ADS_ERR_OK(status) ) {
+ d_fprintf( stderr, "Failed to pre-create the machine object "
+ "in OU %s.\n", argv[0]);
+ ads_destroy( &ads );
+ return -1;
+ }
+ }
+
/* Do the domain join here */
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);