mirror of
https://github.com/samba-team/samba.git
synced 2024-12-30 13:18:05 +03:00
5fa82263ad
This patch adds 'delete' to the 'net ads setspn' subcommand (see https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/cc731241(v=ws.11) Usage: net ads setspn delete <computer> <SPN> Note: <computer> is optional, if not specified the computer account associated with value returned by lp_netbios_name() is used instead. Signed-off-by: Noel Power <noel.power@suse.com> Reviewed-by: Jeremy Allison <jra@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
230 lines
5.0 KiB
C
230 lines
5.0 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
net ads setspn routines
|
|
Copyright (C) Noel Power 2018
|
|
|
|
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
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "ads.h"
|
|
|
|
#ifdef HAVE_ADS
|
|
bool ads_setspn_list(ADS_STRUCT *ads, const char *machine_name)
|
|
{
|
|
size_t i = 0;
|
|
TALLOC_CTX *frame = NULL;
|
|
char **spn_array = NULL;
|
|
size_t num_spns = 0;
|
|
bool ok = false;
|
|
ADS_STATUS status;
|
|
|
|
frame = talloc_stackframe();
|
|
status = ads_get_service_principal_names(frame,
|
|
ads,
|
|
machine_name,
|
|
&spn_array,
|
|
&num_spns);
|
|
if (!ADS_ERR_OK(status)) {
|
|
goto done;
|
|
}
|
|
|
|
d_printf("Registered SPNs for %s\n", machine_name);
|
|
for (i = 0; i < num_spns; i++) {
|
|
d_printf("\t%s\n", spn_array[i]);
|
|
}
|
|
|
|
ok = true;
|
|
done:
|
|
TALLOC_FREE(frame);
|
|
return ok;
|
|
}
|
|
|
|
/* returns true if spn exists in spn_array (match is NOT case-sensitive) */
|
|
static bool find_spn_in_spnlist(TALLOC_CTX *ctx,
|
|
const char *spn,
|
|
char **spn_array,
|
|
size_t num_spns)
|
|
{
|
|
char *lc_spn = NULL;
|
|
size_t i = 0;
|
|
|
|
lc_spn = strlower_talloc(ctx, spn);
|
|
if (lc_spn == NULL) {
|
|
DBG_ERR("Out of memory, lowercasing %s.\n",
|
|
spn);
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < num_spns; i++) {
|
|
char *lc_spn_attr = strlower_talloc(ctx, spn_array[i]);
|
|
if (lc_spn_attr == NULL) {
|
|
DBG_ERR("Out of memory, lowercasing %s.\n",
|
|
spn_array[i]);
|
|
return false;
|
|
}
|
|
|
|
if (strequal(lc_spn, lc_spn_attr)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ads_setspn_add(ADS_STRUCT *ads, const char *machine_name, const char * spn)
|
|
{
|
|
bool ret = false;
|
|
TALLOC_CTX *frame = NULL;
|
|
ADS_STATUS status;
|
|
struct spn_struct *spn_struct = NULL;
|
|
const char *spns[2] = {NULL, NULL};
|
|
char **existing_spns = NULL;
|
|
size_t num_spns = 0;
|
|
bool found = false;
|
|
|
|
frame = talloc_stackframe();
|
|
spns[0] = spn;
|
|
spn_struct = parse_spn(frame, spn);
|
|
if (spn_struct == NULL) {
|
|
goto done;
|
|
}
|
|
|
|
status = ads_get_service_principal_names(frame,
|
|
ads,
|
|
machine_name,
|
|
&existing_spns,
|
|
&num_spns);
|
|
|
|
if (!ADS_ERR_OK(status)) {
|
|
goto done;
|
|
}
|
|
|
|
found = find_spn_in_spnlist(frame, spn, existing_spns, num_spns);
|
|
if (found) {
|
|
d_printf("Duplicate SPN found, aborting operation.\n");
|
|
goto done;
|
|
}
|
|
|
|
d_printf("Registering SPN %s for object %s\n", spn, machine_name);
|
|
status = ads_add_service_principal_names(ads, machine_name, spns);
|
|
if (!ADS_ERR_OK(status)) {
|
|
goto done;
|
|
}
|
|
ret = true;
|
|
d_printf("Updated object\n");
|
|
done:
|
|
TALLOC_FREE(frame);
|
|
return ret;
|
|
}
|
|
|
|
bool ads_setspn_delete(ADS_STRUCT *ads,
|
|
const char *machine_name,
|
|
const char * spn)
|
|
{
|
|
size_t i = 0, j = 0;
|
|
TALLOC_CTX *frame = NULL;
|
|
char **spn_array = NULL;
|
|
const char **new_spn_array = NULL;
|
|
char *lc_spn = NULL;
|
|
size_t num_spns = 0;
|
|
ADS_STATUS status;
|
|
ADS_MODLIST mods;
|
|
bool ok = false;
|
|
LDAPMessage *res = NULL;
|
|
|
|
frame = talloc_stackframe();
|
|
|
|
lc_spn = strlower_talloc(frame, spn);
|
|
if (lc_spn == NULL) {
|
|
DBG_ERR("Out of memory, lowercasing %s.\n", spn);
|
|
goto done;
|
|
}
|
|
|
|
status = ads_find_machine_acct(ads,
|
|
&res,
|
|
machine_name);
|
|
if (!ADS_ERR_OK(status)) {
|
|
goto done;
|
|
}
|
|
|
|
status = ads_get_service_principal_names(frame,
|
|
ads,
|
|
machine_name,
|
|
&spn_array,
|
|
&num_spns);
|
|
if (!ADS_ERR_OK(status)) {
|
|
goto done;
|
|
}
|
|
|
|
new_spn_array = talloc_zero_array(frame, const char*, num_spns + 1);
|
|
if (!new_spn_array) {
|
|
DBG_ERR("Out of memory, failed to allocate array.\n");
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* create new spn list to write to object (excluding the spn to
|
|
* be deleted).
|
|
*/
|
|
for (i = 0, j = 0; i < num_spns; i++) {
|
|
/*
|
|
* windows setspn.exe deletes matching spn in a case
|
|
* insensitive way.
|
|
*/
|
|
char *lc_spn_attr = strlower_talloc(frame, spn_array[i]);
|
|
if (lc_spn_attr == NULL) {
|
|
DBG_ERR("Out of memory, lowercasing %s.\n",
|
|
spn_array[i]);
|
|
goto done;
|
|
}
|
|
|
|
if (!strequal(lc_spn, lc_spn_attr)) {
|
|
new_spn_array[j++] = spn_array[i];
|
|
}
|
|
}
|
|
|
|
/* found and removed spn */
|
|
if (j < num_spns) {
|
|
char *dn = NULL;
|
|
mods = ads_init_mods(frame);
|
|
if (mods == NULL) {
|
|
goto done;
|
|
}
|
|
d_printf("Unregistering SPN %s for %s\n", spn, machine_name);
|
|
status = ads_mod_strlist(frame, &mods, "servicePrincipalName", new_spn_array);
|
|
if (!ADS_ERR_OK(status)) {
|
|
goto done;
|
|
}
|
|
|
|
dn = ads_get_dn(ads, frame, res);
|
|
if (dn == NULL ) {
|
|
goto done;
|
|
}
|
|
|
|
status = ads_gen_mod(ads, dn, mods);
|
|
if (!ADS_ERR_OK(status)) {
|
|
goto done;
|
|
}
|
|
}
|
|
d_printf("Updated object\n");
|
|
|
|
ok = true;
|
|
done:
|
|
TALLOC_FREE(frame);
|
|
return ok;
|
|
}
|
|
|
|
#endif /* HAVE_ADS */
|