diff options
author | Stef Walter <stefw@redhat.com> | 2013-04-11 15:52:22 +0200 |
---|---|---|
committer | Stef Walter <stefw@redhat.com> | 2013-04-17 23:04:15 +0200 |
commit | 7a3f6105e108312beb2997442ff74bba59c9684f (patch) | |
tree | 8400b6c8c0c1cd7503ff519aedf57a7da24e2db6 | |
parent | c2970e74a8568baca541b46efaa55ee53e38c7de (diff) |
Add --user-principal argument for joining domains
This fills in the userPrincipalName attribute on the account
https://bugs.freedesktop.org/show_bug.cgi?id=62755
-rw-r--r-- | doc/adcli.xml | 13 | ||||
-rw-r--r-- | library/adenroll.c | 107 | ||||
-rw-r--r-- | library/adenroll.h | 7 | ||||
-rw-r--r-- | tools/computer.c | 10 |
4 files changed, 131 insertions, 6 deletions
diff --git a/doc/adcli.xml b/doc/adcli.xml index 023d6b1..0acdd83 100644 --- a/doc/adcli.xml +++ b/doc/adcli.xml @@ -258,6 +258,13 @@ Password for Administrator: option may be specified multiple times.</para></listitem> </varlistentry> <varlistentry> + <term><option>--user-principal=<parameter>host/name@REALM</parameter></option></term> + <listitem><para>Set the userPrincipalName field of the + computer account to this kerberos principal. If you omit + the value for this option, then a principal will be set + in the form of <code>host/host.example.com@REALM</code></para></listitem> + </varlistentry> + <varlistentry> <term><option>--show-details</option></term> <listitem><para>After a successful join print out information about join operation. This is output in a format that should @@ -479,6 +486,12 @@ Password for Administrator: principal to be created on the computer account. This option may be specified multiple times.</para></listitem> </varlistentry> + <varlistentry> + <term><option>--user-principal</option></term> + <listitem><para>Set the userPrincipalName field of the + computer account to this kerberos principal in the form + of <code>host/host.example.com@REALM</code></para></listitem> + </varlistentry> </variablelist> </refsect1> diff --git a/library/adenroll.c b/library/adenroll.c index 33f3022..f262e4c 100644 --- a/library/adenroll.c +++ b/library/adenroll.c @@ -67,6 +67,9 @@ struct _adcli_enroll { char **service_principals; int service_principals_explicit; + char *user_principal; + int user_princpal_generate; + char *os_name; char *os_version; char *os_service_pack; @@ -286,11 +289,8 @@ static adcli_result ensure_service_principals (adcli_result res, adcli_enroll *enroll) { - krb5_context k5; - krb5_error_code code; char *name; int length = 0; - int count; int i; if (res != ADCLI_SUCCESS) @@ -315,6 +315,18 @@ ensure_service_principals (adcli_result res, } } + return ADCLI_SUCCESS; +} + +static adcli_result +ensure_keytab_principals (adcli_result res, + adcli_enroll *enroll) +{ + krb5_context k5; + krb5_error_code code; + int count; + int at, i; + /* Prepare the principals we're going to add to the keytab */ return_unexpected_if_fail (enroll->service_principals); @@ -323,19 +335,34 @@ ensure_service_principals (adcli_result res, k5 = adcli_conn_get_krb5_context (enroll->conn); return_unexpected_if_fail (k5 != NULL); - enroll->keytab_principals = calloc (count + 2, sizeof (krb5_principal)); + enroll->keytab_principals = calloc (count + 3, sizeof (krb5_principal)); + at = 0; /* First add the principal for the computer account name */ code = krb5_copy_principal (k5, enroll->computer_principal, - &enroll->keytab_principals[0]); + &enroll->keytab_principals[at++]); return_unexpected_if_fail (code == 0); + /* Next, optionally add the user principal */ + if (enroll->user_principal) { + code = krb5_parse_name (k5, enroll->user_principal, + &enroll->keytab_principals[at++]); + if (code != 0) { + if (code != 0) { + _adcli_err ("Couldn't parse kerberos user principal: %s: %s", + enroll->user_principal, + krb5_get_error_message (k5, code)); + return ADCLI_ERR_CONFIG; + } + } + } + /* Now add the principals for all the various services */ for (i = 0; i < count; i++) { code = _adcli_krb5_build_principal (k5, enroll->service_principals[i], adcli_conn_get_domain_realm (enroll->conn), - &enroll->keytab_principals[i + 1]); + &enroll->keytab_principals[at++]); if (code != 0) { _adcli_err ("Couldn't parse kerberos service principal: %s: %s", enroll->service_principals[i], @@ -348,6 +375,35 @@ ensure_service_principals (adcli_result res, } static adcli_result +ensure_user_principal (adcli_result res, + adcli_enroll *enroll) +{ + char *name; + + if (res != ADCLI_SUCCESS) + return res; + + if (enroll->user_princpal_generate) { + name = strdup (enroll->computer_name); + return_unexpected_if_fail (name != NULL); + + _adcli_str_down (name); + + assert (enroll->user_principal == NULL); + if (asprintf (&enroll->user_principal, "host/%s@%s", + name, adcli_conn_get_domain_realm (enroll->conn)) < 0) + return_unexpected_if_reached (); + + free (name); + } + + if (enroll->user_principal) + _adcli_info ("With user principal: %s", enroll->user_principal); + + return ADCLI_SUCCESS; +} + +static adcli_result lookup_computer_container (adcli_enroll *enroll, LDAP *ldap) { @@ -1094,6 +1150,13 @@ update_computer_account (adcli_enroll *enroll) res |= update_computer_attribute (enroll, ldap, mods); } + if (res == ADCLI_SUCCESS) { + char *vals_userPrincipalName[] = { enroll->user_principal, NULL }; + LDAPMod userPrincipalName = { LDAP_MOD_REPLACE, "userPrincipalName", { vals_userPrincipalName, }, }; + LDAPMod *mods[] = { &userPrincipalName, NULL, }; + + res |= update_computer_attribute (enroll, ldap, mods); + } if (res != 0) _adcli_info ("Updated existing computer account: %s", enroll->computer_dn); @@ -1405,6 +1468,11 @@ enroll_clear_state (adcli_enroll *enroll) enroll->service_principals = NULL; } + if (enroll->user_princpal_generate) { + free (enroll->user_principal); + enroll->user_principal = NULL; + } + enroll->kvno = 0; if (enroll->computer_attributes) { @@ -1432,11 +1500,13 @@ adcli_enroll_prepare (adcli_enroll *enroll, res = ensure_host_fqdn (res, enroll); res = ensure_computer_name (res, enroll); res = ensure_computer_sam (res, enroll); + res = ensure_user_principal (res, enroll); res = ensure_computer_password (res, enroll); if (!(flags & ADCLI_ENROLL_NO_KEYTAB)) res = ensure_host_keytab (res, enroll); res = ensure_service_names (res, enroll); res = ensure_service_principals (res, enroll); + res = ensure_keytab_principals (res, enroll); return res; } @@ -1628,6 +1698,7 @@ enroll_free (adcli_enroll *enroll) free (enroll->os_version); free (enroll->os_service_pack); + free (enroll->user_principal); _adcli_strv_free (enroll->service_names); _adcli_strv_free (enroll->service_principals); _adcli_password_free (enroll->computer_password); @@ -1951,3 +2022,27 @@ adcli_enroll_set_os_service_pack (adcli_enroll *enroll, value = NULL; _adcli_str_set (&enroll->os_service_pack, value); } + +const char * +adcli_enroll_get_user_principal (adcli_enroll *enroll) +{ + return_val_if_fail (enroll != NULL, NULL); + return enroll->user_principal; +} + +void +adcli_enroll_set_user_principal (adcli_enroll *enroll, + const char *value) +{ + return_if_fail (enroll != NULL); + _adcli_str_set (&enroll->user_principal, value); + enroll->user_princpal_generate = 0; +} + +void +adcli_enroll_auto_user_principal (adcli_enroll *enroll) +{ + return_if_fail (enroll != NULL); + _adcli_str_set (&enroll->user_principal, NULL); + enroll->user_princpal_generate = 1; +} diff --git a/library/adenroll.h b/library/adenroll.h index 9dfb5f8..cfd782b 100644 --- a/library/adenroll.h +++ b/library/adenroll.h @@ -91,6 +91,13 @@ const char ** adcli_enroll_get_service_principals (adcli_enroll *enroll); void adcli_enroll_set_service_principals (adcli_enroll *enroll, const char **value); +const char * adcli_enroll_get_user_principal (adcli_enroll *enroll); + +void adcli_enroll_set_user_principal (adcli_enroll *enroll, + const char *value); + +void adcli_enroll_auto_user_principal (adcli_enroll *enroll); + krb5_kvno adcli_enroll_get_kvno (adcli_enroll *enroll); void adcli_enroll_set_kvno (adcli_enroll *enroll, diff --git a/tools/computer.c b/tools/computer.c index e63f453..3f97e16 100644 --- a/tools/computer.c +++ b/tools/computer.c @@ -90,6 +90,7 @@ typedef enum { opt_os_name, opt_os_version, opt_os_service_pack, + opt_user_principal, } Option; static adcli_tool_desc common_usages[] = { @@ -114,6 +115,7 @@ static adcli_tool_desc common_usages[] = { { opt_os_name, "the computer operating system name", }, { opt_os_version, "the computer operating system version", }, { opt_os_service_pack, "the computer operating system service pack", }, + { opt_user_principal, "add an authentication principal to the account", }, { opt_no_password, "don't prompt for or read a password" }, { opt_prompt_password, "prompt for a password if necessary" }, { opt_stdin_password, "read a password from stdin (until EOF) if\n" @@ -225,6 +227,12 @@ parse_option (Option opt, case opt_os_service_pack: adcli_enroll_set_os_service_pack (enroll, optarg); return; + case opt_user_principal: + if (optarg && optarg[0]) + adcli_enroll_set_user_principal (enroll, optarg); + else + adcli_enroll_auto_user_principal (enroll); + return; case opt_verbose: return; @@ -282,6 +290,7 @@ adcli_tool_computer_join (adcli_conn *conn, { "os-name", optional_argument, NULL, opt_os_name }, { "os-version", optional_argument, NULL, opt_os_version }, { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, + { "user-principal", optional_argument, NULL, opt_user_principal }, { "show-details", no_argument, NULL, opt_show_details }, { "verbose", no_argument, NULL, opt_verbose }, { "help", no_argument, NULL, 'h' }, @@ -371,6 +380,7 @@ adcli_tool_computer_preset (adcli_conn *conn, { "os-name", optional_argument, NULL, opt_os_name }, { "os-version", optional_argument, NULL, opt_os_version }, { "os-service-pack", optional_argument, NULL, opt_os_service_pack }, + { "user-principal", no_argument, NULL, opt_user_principal }, { "verbose", no_argument, NULL, opt_verbose }, { "help", no_argument, NULL, 'h' }, { 0 }, |