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 /source3 | |
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)
Diffstat (limited to 'source3')
-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); |