|
|
59dcbd |
From 767e905e096d9b4f2361a5f307dfb9e622e847aa Mon Sep 17 00:00:00 2001
|
|
|
59dcbd |
From: Sumit Bose <sbose@redhat.com>
|
|
|
59dcbd |
Date: Thu, 14 Jun 2018 16:49:26 +0200
|
|
|
59dcbd |
Subject: [PATCH 7/7] Add add-service-principal and remove-service-principal
|
|
|
59dcbd |
options
|
|
|
59dcbd |
|
|
|
59dcbd |
Currently it is only possible to specific a service name for service
|
|
|
59dcbd |
principals but not to set the full service principal. This is e.g.
|
|
|
59dcbd |
needed if there is a service running on a host which should be reachable
|
|
|
59dcbd |
by a different DNS name as well.
|
|
|
59dcbd |
|
|
|
59dcbd |
With this patch service principal can be added and removed by specifying
|
|
|
59dcbd |
the full name.
|
|
|
59dcbd |
|
|
|
59dcbd |
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547014
|
|
|
59dcbd |
---
|
|
|
59dcbd |
doc/adcli.xml | 21 ++++++++
|
|
|
59dcbd |
library/adenroll.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
|
59dcbd |
library/adenroll.h | 8 +++
|
|
|
59dcbd |
library/adldap.c | 16 ++++--
|
|
|
59dcbd |
tools/computer.c | 13 +++++
|
|
|
59dcbd |
5 files changed, 189 insertions(+), 8 deletions(-)
|
|
|
59dcbd |
|
|
|
59dcbd |
diff --git a/doc/adcli.xml b/doc/adcli.xml
|
|
|
59dcbd |
index b246190..83b6981 100644
|
|
|
59dcbd |
--- a/doc/adcli.xml
|
|
|
59dcbd |
+++ b/doc/adcli.xml
|
|
|
59dcbd |
@@ -290,6 +290,14 @@ Password for Administrator:
|
|
|
59dcbd |
not allow that Kerberos tickets can be forwarded to the
|
|
|
59dcbd |
host.</para></listitem>
|
|
|
59dcbd |
</varlistentry>
|
|
|
59dcbd |
+ <varlistentry>
|
|
|
59dcbd |
+ <term><option>--add-service-principal=<parameter>service/hostname</parameter></option></term>
|
|
|
59dcbd |
+ <listitem><para>Add a service principal name. In
|
|
|
59dcbd |
+ contrast to the <option>--service-name</option> the
|
|
|
59dcbd |
+ hostname part can be specified as well in case the
|
|
|
59dcbd |
+ service should be accessible with a different host
|
|
|
59dcbd |
+ name as well.</para></listitem>
|
|
|
59dcbd |
+ </varlistentry>
|
|
|
59dcbd |
<varlistentry>
|
|
|
59dcbd |
<term><option>--show-details</option></term>
|
|
|
59dcbd |
<listitem><para>After a successful join print out information
|
|
|
59dcbd |
@@ -416,6 +424,19 @@ $ adcli update --login-ccache=/tmp/krbcc_123
|
|
|
59dcbd |
not allow that Kerberos tickets can be forwarded to the
|
|
|
59dcbd |
host.</para></listitem>
|
|
|
59dcbd |
</varlistentry>
|
|
|
59dcbd |
+ <varlistentry>
|
|
|
59dcbd |
+ <term><option>--add-service-principal=<parameter>service/hostname</parameter></option></term>
|
|
|
59dcbd |
+ <listitem><para>Add a service principal name. In
|
|
|
59dcbd |
+ contrast to the <option>--service-name</option> the
|
|
|
59dcbd |
+ hostname part can be specified as well in case the
|
|
|
59dcbd |
+ service should be accessible with a different host
|
|
|
59dcbd |
+ name as well.</para></listitem>
|
|
|
59dcbd |
+ </varlistentry>
|
|
|
59dcbd |
+ <varlistentry>
|
|
|
59dcbd |
+ <term><option>--remove-service-principal=<parameter>service/hostname</parameter></option></term>
|
|
|
59dcbd |
+ <listitem><para>Remove a service principal name from
|
|
|
59dcbd |
+ the keytab and the AD host object.</para></listitem>
|
|
|
59dcbd |
+ </varlistentry>
|
|
|
59dcbd |
<varlistentry>
|
|
|
59dcbd |
<term><option>--show-details</option></term>
|
|
|
59dcbd |
<listitem><para>After a successful join print out information
|
|
|
59dcbd |
diff --git a/library/adenroll.c b/library/adenroll.c
|
|
|
59dcbd |
index 3f8d017..1ecd371 100644
|
|
|
59dcbd |
--- a/library/adenroll.c
|
|
|
59dcbd |
+++ b/library/adenroll.c
|
|
|
59dcbd |
@@ -95,6 +95,9 @@ struct _adcli_enroll {
|
|
|
59dcbd |
char **service_principals;
|
|
|
59dcbd |
int service_principals_explicit;
|
|
|
59dcbd |
|
|
|
59dcbd |
+ char **service_principals_to_add;
|
|
|
59dcbd |
+ char **service_principals_to_remove;
|
|
|
59dcbd |
+
|
|
|
59dcbd |
char *user_principal;
|
|
|
59dcbd |
int user_princpal_generate;
|
|
|
59dcbd |
|
|
|
59dcbd |
@@ -332,6 +335,43 @@ add_service_names_to_service_principals (adcli_enroll *enroll)
|
|
|
59dcbd |
return ADCLI_SUCCESS;
|
|
|
59dcbd |
}
|
|
|
59dcbd |
|
|
|
59dcbd |
+static adcli_result
|
|
|
59dcbd |
+add_and_remove_service_principals (adcli_enroll *enroll)
|
|
|
59dcbd |
+{
|
|
|
59dcbd |
+ int length = 0;
|
|
|
59dcbd |
+ size_t c;
|
|
|
59dcbd |
+ const char **list;
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ if (enroll->service_principals != NULL) {
|
|
|
59dcbd |
+ length = seq_count (enroll->service_principals);
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ list = adcli_enroll_get_service_principals_to_add (enroll);
|
|
|
59dcbd |
+ if (list != NULL) {
|
|
|
59dcbd |
+ for (c = 0; list[c] != NULL; c++) {
|
|
|
59dcbd |
+ enroll->service_principals = _adcli_strv_add (enroll->service_principals,
|
|
|
59dcbd |
+ strdup (list[c]),
|
|
|
59dcbd |
+ &length);
|
|
|
59dcbd |
+ if (enroll->service_principals == NULL) {
|
|
|
59dcbd |
+ return ADCLI_ERR_UNEXPECTED;
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ list = adcli_enroll_get_service_principals_to_remove (enroll);
|
|
|
59dcbd |
+ if (list != NULL) {
|
|
|
59dcbd |
+ for (c = 0; list[c] != NULL; c++) {
|
|
|
59dcbd |
+ /* enroll->service_principals typically refects the
|
|
|
59dcbd |
+ * order of the principal in the keytabm so it is not
|
|
|
59dcbd |
+ * ordered. */
|
|
|
59dcbd |
+ _adcli_strv_remove_unsorted (enroll->service_principals,
|
|
|
59dcbd |
+ list[c], &length);
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ return ADCLI_SUCCESS;
|
|
|
59dcbd |
+}
|
|
|
59dcbd |
+
|
|
|
59dcbd |
static adcli_result
|
|
|
59dcbd |
ensure_service_principals (adcli_result res,
|
|
|
59dcbd |
adcli_enroll *enroll)
|
|
|
59dcbd |
@@ -343,10 +383,14 @@ ensure_service_principals (adcli_result res,
|
|
|
59dcbd |
|
|
|
59dcbd |
if (!enroll->service_principals) {
|
|
|
59dcbd |
assert (enroll->service_names != NULL);
|
|
|
59dcbd |
- return add_service_names_to_service_principals (enroll);
|
|
|
59dcbd |
+ res = add_service_names_to_service_principals (enroll);
|
|
|
59dcbd |
}
|
|
|
59dcbd |
|
|
|
59dcbd |
- return ADCLI_SUCCESS;
|
|
|
59dcbd |
+ if (res == ADCLI_SUCCESS) {
|
|
|
59dcbd |
+ res = add_and_remove_service_principals (enroll);
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ return res;
|
|
|
59dcbd |
}
|
|
|
59dcbd |
|
|
|
59dcbd |
static adcli_result
|
|
|
59dcbd |
@@ -1593,6 +1637,39 @@ free_principal_salts (krb5_context k5,
|
|
|
59dcbd |
free (salts);
|
|
|
59dcbd |
}
|
|
|
59dcbd |
|
|
|
59dcbd |
+static adcli_result
|
|
|
59dcbd |
+remove_principal_from_keytab (adcli_enroll *enroll,
|
|
|
59dcbd |
+ krb5_context k5,
|
|
|
59dcbd |
+ const char *principal_name)
|
|
|
59dcbd |
+{
|
|
|
59dcbd |
+ krb5_error_code code;
|
|
|
59dcbd |
+ krb5_principal principal;
|
|
|
59dcbd |
+ match_principal_kvno closure;
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ code = krb5_parse_name (k5, principal_name, &principal);
|
|
|
59dcbd |
+ if (code != 0) {
|
|
|
59dcbd |
+ _adcli_err ("Couldn't parse principal: %s: %s",
|
|
|
59dcbd |
+ principal_name, krb5_get_error_message (k5, code));
|
|
|
59dcbd |
+ return ADCLI_ERR_FAIL;
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ closure.kvno = enroll->kvno;
|
|
|
59dcbd |
+ closure.principal = principal;
|
|
|
59dcbd |
+ closure.matched = 0;
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ code = _adcli_krb5_keytab_clear (k5, enroll->keytab,
|
|
|
59dcbd |
+ match_principal_and_kvno, &closure);
|
|
|
59dcbd |
+ krb5_free_principal (k5, principal);
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ if (code != 0) {
|
|
|
59dcbd |
+ _adcli_err ("Couldn't update keytab: %s: %s",
|
|
|
59dcbd |
+ enroll->keytab_name, krb5_get_error_message (k5, code));
|
|
|
59dcbd |
+ return ADCLI_ERR_FAIL;
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ return ADCLI_SUCCESS;
|
|
|
59dcbd |
+}
|
|
|
59dcbd |
+
|
|
|
59dcbd |
static adcli_result
|
|
|
59dcbd |
add_principal_to_keytab (adcli_enroll *enroll,
|
|
|
59dcbd |
krb5_context k5,
|
|
|
59dcbd |
@@ -1702,6 +1779,17 @@ update_keytab_for_principals (adcli_enroll *enroll,
|
|
|
59dcbd |
return res;
|
|
|
59dcbd |
}
|
|
|
59dcbd |
|
|
|
59dcbd |
+ if (enroll->service_principals_to_remove != NULL) {
|
|
|
59dcbd |
+ for (i = 0; enroll->service_principals_to_remove[i] != NULL; i++) {
|
|
|
59dcbd |
+ res = remove_principal_from_keytab (enroll, k5,
|
|
|
59dcbd |
+ enroll->service_principals_to_remove[i]);
|
|
|
59dcbd |
+ if (res != ADCLI_SUCCESS) {
|
|
|
59dcbd |
+ _adcli_warn ("Failed to remove %s from keytab.",
|
|
|
59dcbd |
+ enroll->service_principals_to_remove[i]);
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+
|
|
|
59dcbd |
return ADCLI_SUCCESS;
|
|
|
59dcbd |
}
|
|
|
59dcbd |
|
|
|
59dcbd |
@@ -2029,8 +2117,11 @@ adcli_enroll_update (adcli_enroll *enroll,
|
|
|
59dcbd |
if (_adcli_check_nt_time_string_lifetime (value,
|
|
|
59dcbd |
adcli_enroll_get_computer_password_lifetime (enroll))) {
|
|
|
59dcbd |
/* Do not update keytab if neither new service principals have
|
|
|
59dcbd |
- * to be added nor the user principal has to be changed. */
|
|
|
59dcbd |
- if (enroll->service_names == NULL && (enroll->user_principal == NULL || enroll->user_princpal_generate)) {
|
|
|
59dcbd |
+ * to be added or deleted nor the user principal has to be changed. */
|
|
|
59dcbd |
+ if (enroll->service_names == NULL
|
|
|
59dcbd |
+ && (enroll->user_principal == NULL || enroll->user_princpal_generate)
|
|
|
59dcbd |
+ && enroll->service_principals_to_add == NULL
|
|
|
59dcbd |
+ && enroll->service_principals_to_remove == NULL) {
|
|
|
59dcbd |
flags |= ADCLI_ENROLL_NO_KEYTAB;
|
|
|
59dcbd |
}
|
|
|
59dcbd |
flags |= ADCLI_ENROLL_PASSWORD_VALID;
|
|
|
59dcbd |
@@ -2581,3 +2672,43 @@ adcli_enroll_set_trusted_for_delegation (adcli_enroll *enroll,
|
|
|
59dcbd |
enroll->trusted_for_delegation = value;
|
|
|
59dcbd |
enroll->trusted_for_delegation_explicit = 1;
|
|
|
59dcbd |
}
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+const char **
|
|
|
59dcbd |
+adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll)
|
|
|
59dcbd |
+{
|
|
|
59dcbd |
+ return_val_if_fail (enroll != NULL, NULL);
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ return (const char **)enroll->service_principals_to_add;
|
|
|
59dcbd |
+}
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+void
|
|
|
59dcbd |
+adcli_enroll_add_service_principal_to_add (adcli_enroll *enroll,
|
|
|
59dcbd |
+ const char *value)
|
|
|
59dcbd |
+{
|
|
|
59dcbd |
+ return_if_fail (enroll != NULL);
|
|
|
59dcbd |
+ return_if_fail (value != NULL);
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ enroll->service_principals_to_add = _adcli_strv_add (enroll->service_principals_to_add,
|
|
|
59dcbd |
+ strdup (value), NULL);
|
|
|
59dcbd |
+ return_if_fail (enroll->service_principals_to_add != NULL);
|
|
|
59dcbd |
+}
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+const char **
|
|
|
59dcbd |
+adcli_enroll_get_service_principals_to_remove (adcli_enroll *enroll)
|
|
|
59dcbd |
+{
|
|
|
59dcbd |
+ return_val_if_fail (enroll != NULL, NULL);
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ return (const char **)enroll->service_principals_to_remove;
|
|
|
59dcbd |
+}
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+void
|
|
|
59dcbd |
+adcli_enroll_add_service_principal_to_remove (adcli_enroll *enroll,
|
|
|
59dcbd |
+ const char *value)
|
|
|
59dcbd |
+{
|
|
|
59dcbd |
+ return_if_fail (enroll != NULL);
|
|
|
59dcbd |
+ return_if_fail (value != NULL);
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ enroll->service_principals_to_remove = _adcli_strv_add (enroll->service_principals_to_remove,
|
|
|
59dcbd |
+ strdup (value), NULL);
|
|
|
59dcbd |
+ return_if_fail (enroll->service_principals_to_remove != NULL);
|
|
|
59dcbd |
+}
|
|
|
59dcbd |
diff --git a/library/adenroll.h b/library/adenroll.h
|
|
|
59dcbd |
index be2ca18..f87dffa 100644
|
|
|
59dcbd |
--- a/library/adenroll.h
|
|
|
59dcbd |
+++ b/library/adenroll.h
|
|
|
59dcbd |
@@ -98,6 +98,14 @@ const char ** adcli_enroll_get_service_principals (adcli_enroll *enroll);
|
|
|
59dcbd |
void adcli_enroll_set_service_principals (adcli_enroll *enroll,
|
|
|
59dcbd |
const char **value);
|
|
|
59dcbd |
|
|
|
59dcbd |
+const char ** adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll);
|
|
|
59dcbd |
+void adcli_enroll_add_service_principal_to_add (adcli_enroll *enroll,
|
|
|
59dcbd |
+ const char *value);
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+const char ** adcli_enroll_get_service_principals_to_remove (adcli_enroll *enroll);
|
|
|
59dcbd |
+void adcli_enroll_add_service_principal_to_remove (adcli_enroll *enroll,
|
|
|
59dcbd |
+ const char *value);
|
|
|
59dcbd |
+
|
|
|
59dcbd |
const char * adcli_enroll_get_user_principal (adcli_enroll *enroll);
|
|
|
59dcbd |
|
|
|
59dcbd |
void adcli_enroll_set_user_principal (adcli_enroll *enroll,
|
|
|
59dcbd |
diff --git a/library/adldap.c b/library/adldap.c
|
|
|
59dcbd |
index 07dc373..d93efb7 100644
|
|
|
59dcbd |
--- a/library/adldap.c
|
|
|
59dcbd |
+++ b/library/adldap.c
|
|
|
59dcbd |
@@ -210,16 +210,24 @@ _adcli_ldap_have_in_mod (LDAPMod *mod,
|
|
|
59dcbd |
struct berval *vals;
|
|
|
59dcbd |
struct berval **pvals;
|
|
|
59dcbd |
int count = 0;
|
|
|
59dcbd |
+ int count_have = 0;
|
|
|
59dcbd |
int i;
|
|
|
59dcbd |
int ret;
|
|
|
59dcbd |
|
|
|
59dcbd |
- /* Already in berval format, just compare */
|
|
|
59dcbd |
- if (mod->mod_op & LDAP_MOD_BVALUES)
|
|
|
59dcbd |
- return _adcli_ldap_have_vals (mod->mod_vals.modv_bvals, have);
|
|
|
59dcbd |
-
|
|
|
59dcbd |
/* Count number of values */
|
|
|
59dcbd |
for (i = 0; mod->mod_vals.modv_strvals[i] != 0; i++)
|
|
|
59dcbd |
count++;
|
|
|
59dcbd |
+ for (i = 0; have[i] != 0; i++)
|
|
|
59dcbd |
+ count_have++;
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ /* If numbers different something has to be added or removed */
|
|
|
59dcbd |
+ if (count != count_have) {
|
|
|
59dcbd |
+ return 0;
|
|
|
59dcbd |
+ }
|
|
|
59dcbd |
+
|
|
|
59dcbd |
+ /* Already in berval format, just compare */
|
|
|
59dcbd |
+ if (mod->mod_op & LDAP_MOD_BVALUES)
|
|
|
59dcbd |
+ return _adcli_ldap_have_vals (mod->mod_vals.modv_bvals, have);
|
|
|
59dcbd |
|
|
|
59dcbd |
vals = malloc (sizeof (struct berval) * (count + 1));
|
|
|
59dcbd |
pvals = malloc (sizeof (struct berval *) * (count + 1));
|
|
|
59dcbd |
diff --git a/tools/computer.c b/tools/computer.c
|
|
|
59dcbd |
index b905fd1..377d449 100644
|
|
|
59dcbd |
--- a/tools/computer.c
|
|
|
59dcbd |
+++ b/tools/computer.c
|
|
|
59dcbd |
@@ -110,6 +110,8 @@ typedef enum {
|
|
|
59dcbd |
opt_add_samba_data,
|
|
|
59dcbd |
opt_samba_data_tool,
|
|
|
59dcbd |
opt_trusted_for_delegation,
|
|
|
59dcbd |
+ opt_add_service_principal,
|
|
|
59dcbd |
+ opt_remove_service_principal,
|
|
|
59dcbd |
} Option;
|
|
|
59dcbd |
|
|
|
59dcbd |
static adcli_tool_desc common_usages[] = {
|
|
|
59dcbd |
@@ -138,6 +140,8 @@ static adcli_tool_desc common_usages[] = {
|
|
|
59dcbd |
{ opt_computer_password_lifetime, "lifetime of the host accounts password in days", },
|
|
|
59dcbd |
{ opt_trusted_for_delegation, "set/unset the TRUSTED_FOR_DELEGATION flag\n"
|
|
|
59dcbd |
"in the userAccountControl attribute", },
|
|
|
59dcbd |
+ { opt_add_service_principal, "add the given service principal to the account\n" },
|
|
|
59dcbd |
+ { opt_remove_service_principal, "remove the given service principal from the account\n" },
|
|
|
59dcbd |
{ opt_no_password, "don't prompt for or read a password" },
|
|
|
59dcbd |
{ opt_prompt_password, "prompt for a password if necessary" },
|
|
|
59dcbd |
{ opt_stdin_password, "read a password from stdin (until EOF) if\n"
|
|
|
59dcbd |
@@ -289,6 +293,12 @@ parse_option (Option opt,
|
|
|
59dcbd |
adcli_enroll_set_trusted_for_delegation (enroll, false);
|
|
|
59dcbd |
}
|
|
|
59dcbd |
return;
|
|
|
59dcbd |
+ case opt_add_service_principal:
|
|
|
59dcbd |
+ adcli_enroll_add_service_principal_to_add (enroll, optarg);
|
|
|
59dcbd |
+ return;
|
|
|
59dcbd |
+ case opt_remove_service_principal:
|
|
|
59dcbd |
+ adcli_enroll_add_service_principal_to_remove (enroll, optarg);
|
|
|
59dcbd |
+ return;
|
|
|
59dcbd |
case opt_verbose:
|
|
|
59dcbd |
return;
|
|
|
59dcbd |
|
|
|
59dcbd |
@@ -353,6 +363,7 @@ adcli_tool_computer_join (adcli_conn *conn,
|
|
|
59dcbd |
{ "os-service-pack", optional_argument, NULL, opt_os_service_pack },
|
|
|
59dcbd |
{ "user-principal", optional_argument, NULL, opt_user_principal },
|
|
|
59dcbd |
{ "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation },
|
|
|
59dcbd |
+ { "add-service-principal", required_argument, NULL, opt_add_service_principal },
|
|
|
59dcbd |
{ "show-details", no_argument, NULL, opt_show_details },
|
|
|
59dcbd |
{ "show-password", no_argument, NULL, opt_show_password },
|
|
|
59dcbd |
{ "add-samba-data", no_argument, NULL, opt_add_samba_data },
|
|
|
59dcbd |
@@ -458,6 +469,8 @@ adcli_tool_computer_update (adcli_conn *conn,
|
|
|
59dcbd |
{ "user-principal", optional_argument, NULL, opt_user_principal },
|
|
|
59dcbd |
{ "computer-password-lifetime", optional_argument, NULL, opt_computer_password_lifetime },
|
|
|
59dcbd |
{ "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation },
|
|
|
59dcbd |
+ { "add-service-principal", required_argument, NULL, opt_add_service_principal },
|
|
|
59dcbd |
+ { "remove-service-principal", required_argument, NULL, opt_remove_service_principal },
|
|
|
59dcbd |
{ "show-details", no_argument, NULL, opt_show_details },
|
|
|
59dcbd |
{ "show-password", no_argument, NULL, opt_show_password },
|
|
|
59dcbd |
{ "add-samba-data", no_argument, NULL, opt_add_samba_data },
|
|
|
59dcbd |
--
|
|
|
59dcbd |
2.14.4
|
|
|
59dcbd |
|