summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@redhat.com>2013-04-11 15:52:22 +0200
committerStef Walter <stefw@redhat.com>2013-04-17 23:04:15 +0200
commit7a3f6105e108312beb2997442ff74bba59c9684f (patch)
tree8400b6c8c0c1cd7503ff519aedf57a7da24e2db6
parentc2970e74a8568baca541b46efaa55ee53e38c7de (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.xml13
-rw-r--r--library/adenroll.c107
-rw-r--r--library/adenroll.h7
-rw-r--r--tools/computer.c10
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 },