summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/utils/net_ads.c126
1 files changed, 114 insertions, 12 deletions
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 54998592db..31a6b80912 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -928,7 +928,7 @@ done:
static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
{
ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
- char *host_upn, *new_dn;
+ char *new_dn;
ADS_MODLIST mods;
const char *servicePrincipalName[3] = {NULL, NULL, NULL};
char *psp;
@@ -964,9 +964,7 @@ static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
return ADS_ERROR(LDAP_NO_MEMORY);
}
- /* Windows only creates HOST/shortname & HOST/fqdn. We create
- the UPN as well so that 'kinit -k' will work. You can only
- request a TGT for entries with a UPN in AD. */
+ /* Windows only creates HOST/shortname & HOST/fqdn. */
if ( !(psp = talloc_asprintf(ctx, "HOST/%s", machine_name)) )
goto done;
@@ -979,9 +977,63 @@ static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
goto done;
servicePrincipalName[1] = psp;
- if (!(host_upn = talloc_asprintf(ctx, "%s@%s", servicePrincipalName[0], ads_s->config.realm)))
+ if (!(mods = ads_init_mods(ctx))) {
goto done;
+ }
+
+ /* fields of primary importance */
+
+ ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
+ ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
+
+ status = ads_gen_mod(ads_s, new_dn, mods);
+
+done:
+ ads_msgfree(ads_s, res);
+
+ return status;
+}
+
+/*******************************************************************
+ Set a machines dNSHostName and servicePrincipalName attributes
+ ********************************************************************/
+static ADS_STATUS net_set_machine_upn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s, const char *upn )
+{
+ ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
+ char *new_dn;
+ ADS_MODLIST mods;
+ LDAPMessage *res = NULL;
+ char *dn_string = NULL;
+ const char *machine_name = global_myname();
+ int count;
+
+ if ( !machine_name ) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* Find our DN */
+
+ status = ads_find_machine_acct(ads_s, (void **)(void *)&res, machine_name);
+ if (!ADS_ERR_OK(status))
+ return status;
+
+ if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
+ DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
+ 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_s, dn_string);
+ if (!new_dn) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
/* now do the mods */
if (!(mods = ads_init_mods(ctx))) {
@@ -990,8 +1042,7 @@ static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
/* fields of primary importance */
- ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
- ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
+ ads_mod_str(ctx, &mods, "userPrincipalName", upn);
status = ads_gen_mod(ads_s, new_dn, mods);
@@ -1001,7 +1052,6 @@ done:
return status;
}
-
/*******************************************************************
join a domain using ADS (LDAP mods)
********************************************************************/
@@ -1089,6 +1139,19 @@ static BOOL net_derive_salting_principal( TALLOC_CTX *ctx, ADS_STRUCT *ads )
return kerberos_secrets_store_des_salt( salt );
}
+/*********************************************************
+ utility function to parse an integer parameter from
+ "parameter = value"
+**********************************************************/
+static char* get_string_param( const char* param )
+{
+ char *p;
+
+ if ( (p = strchr( param, '=' )) == NULL )
+ return NULL;
+
+ return (p+1);
+}
/*******************************************************************
join a domain using ADS (LDAP mods)
********************************************************************/
@@ -1103,6 +1166,10 @@ int net_ads_join(int argc, const char **argv)
struct cldap_netlogon_reply cldap_reply;
TALLOC_CTX *ctx;
DOM_SID *domain_sid = NULL;
+ BOOL createupn = False;
+ const char *machineupn = NULL;
+ const char *create_in_ou = NULL;
+ int i;
if ( check_ads_config() != 0 ) {
d_fprintf(stderr, "Invalid configuration. Exiting....\n");
@@ -1126,11 +1193,30 @@ int net_ads_join(int argc, const char **argv)
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 */
+ /* process additional command line args */
+
+ for ( i=0; i<argc; i++ ) {
+ if ( !StrnCaseCmp(argv[i], "createupn", strlen("createupn")) ) {
+ createupn = True;
+ machineupn = get_string_param(argv[i]);
+ }
+ else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
+ if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
+ d_fprintf(stderr, "Please supply a valid OU path\n");
+ return -1;
+ }
+ }
+ else {
+ d_fprintf(stderr, "Bad option: %s\n", argv[i]);
+ 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 ( create_in_ou ) {
+ status = net_precreate_machine_acct( ads, create_in_ou );
if ( !ADS_ERR_OK(status) ) {
d_fprintf( stderr, "Failed to pre-create the machine object "
"in OU %s.\n", argv[0]);
@@ -1218,6 +1304,22 @@ int net_ads_join(int argc, const char **argv)
return -1;
}
+ if ( createupn ) {
+ pstring upn;
+
+ /* default to using the short UPN name */
+ if ( !machineupn ) {
+ snprintf( upn, sizeof(upn), "host/%s@%s", global_myname(),
+ ads->config.realm );
+ machineupn = upn;
+ }
+
+ status = net_set_machine_upn( ctx, ads, machineupn );
+ if ( !ADS_ERR_OK(status) ) {
+ d_fprintf(stderr, "Failed to set userPrincipalName. Are you a Domain Admin?\n");
+ }
+ }
+
/* Now build the keytab, using the same ADS connection */
if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
DEBUG(1,("Error creating host keytab!\n"));