diff options
author | Gerald Carter <jerry@samba.org> | 2006-05-13 04:39:19 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:17:01 -0500 |
commit | f1039b8fb461c6e1276dba8564f62ec1496a7b88 (patch) | |
tree | 1e8a5883ce479e51167806cec189030770d6fa4c | |
parent | 453e4b50aae52089eb2c2ae6a2abc3b48425ee55 (diff) | |
download | samba-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.c | 196 | ||||
-rw-r--r-- | source3/utils/net_ads.c | 76 |
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); |