1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-07 17:18:11 +03:00
samba-mirror/source4/scripting/bin/samba_spnupdate
Andrew Tridgell 06022dad70 s4-kerberos: use TZ=GMT when we are invoking krb5 code in helpers
Our helper scripts can fail on Fedora with the PDT timezone (Western
USA). This is the same issue we found with Heimdal earlier today, the
24 second difference between GMT and UTC, but this time in MIT
Kerberos as linked into bind9.

By forcing TZ=GMT in these scripts we avoid the problem

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
2010-09-29 03:55:04 +00:00

175 lines
5.1 KiB
Python
Executable File

#!/usr/bin/env python
#
# update our servicePrincipalName names from spn_update_list
#
# Copyright (C) Andrew Tridgell 2010
#
# 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/>.
import os, sys
# ensure we get messages out immediately, so they get in the samba logs,
# and don't get swallowed by a timeout
os.putenv('PYTHONUNBUFFERED', '1')
# forcing GMT avoids a problem in some timezones with kerberos. Both MIT
# heimdal can get mutual authentication errors due to the 24 second difference
# between UTC and GMT when using some zone files (eg. the PDT zone from
# the US)
os.putenv("TZ", "GMT")
# Find right directory when running from source tree
sys.path.insert(0, "bin/python")
import samba, ldb
import optparse
from samba import Ldb
from samba import getopt as options
from samba.auth import system_session
from samba.samdb import SamDB
from samba.credentials import Credentials, DONT_USE_KERBEROS
parser = optparse.OptionParser("samba_spnupdate")
sambaopts = options.SambaOptions(parser)
parser.add_option_group(sambaopts)
parser.add_option_group(options.VersionOptions(parser))
parser.add_option("--verbose", action="store_true")
credopts = options.CredentialsOptions(parser)
parser.add_option_group(credopts)
ccachename = None
opts, args = parser.parse_args()
if len(args) != 0:
parser.print_usage()
sys.exit(1)
lp = sambaopts.get_loadparm()
creds = credopts.get_credentials(lp)
domain = lp.get("realm")
host = lp.get("netbios name")
# get the list of substitution vars
def get_subst_vars(samdb):
global lp
vars = {}
vars['DNSDOMAIN'] = lp.get('realm').lower()
vars['HOSTNAME'] = lp.get('netbios name').lower() + "." + vars['DNSDOMAIN']
vars['NETBIOSNAME'] = lp.get('netbios name').upper()
vars['WORKGROUP'] = lp.get('workgroup')
vars['NTDSGUID'] = samdb.get_ntds_GUID()
res = samdb.search(base=None, scope=ldb.SCOPE_BASE, attrs=["objectGUID"])
guid = samdb.schema_format_value("objectGUID", res[0]['objectGUID'][0])
vars['DOMAINGUID'] = guid
return vars
try:
private_dir = lp.get("private dir")
secrets_path = os.path.join(private_dir, lp.get("secrets database"))
secrets_db = Ldb(url=secrets_path, session_info=system_session(),
credentials=creds, lp=lp)
res = secrets_db.search(base=None,
expression="(&(objectclass=ldapSecret)(cn=SAMDB Credentials))",
attrs=["samAccountName", "secret"])
if len(res) == 1:
credentials = Credentials()
credentials.set_kerberos_state(DONT_USE_KERBEROS)
if "samAccountName" in res[0]:
credentials.set_username(res[0]["samAccountName"][0])
if "secret" in res[0]:
credentials.set_password(res[0]["secret"][0])
else:
credentials = None
samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), credentials=credentials, lp=lp)
except ldb.LdbError, (num, msg):
print("Unable to open sam database %s : %s" % (lp.get("sam database"), msg))
sys.exit(1)
if samdb.am_rodc():
# don't try and update SPNs on RODC
exit(0)
# get the substitution dictionary
sub_vars = get_subst_vars(samdb)
# get the list of SPN entries we should have
spn_update_list = lp.private_path('spn_update_list')
file = open(spn_update_list, "r")
spn_list = []
# build the spn list
for line in file:
line = line.strip()
if line == '' or line[0] == "#":
continue
line = samba.substitute_var(line, sub_vars)
spn_list.append(line)
# get the current list of SPNs in our sam
res = samdb.search(base="",
expression='(&(objectClass=computer)(samaccountname=%s$))' % sub_vars['NETBIOSNAME'],
attrs=["servicePrincipalName"])
if not res or len(res) != 1:
print("Failed to find computer object for %s$" % sub_vars['NETBIOSNAME'])
sys.exit(1)
old_spns = []
for s in res[0]['servicePrincipalName']:
old_spns.append(s)
if opts.verbose:
print("Existing SPNs: %s" % old_spns)
add_list = []
# work out what needs to be added
for s in spn_list:
in_list = False
for s2 in old_spns:
if s2.upper() == s.upper():
in_list = True
break
if not in_list:
add_list.append(s)
if opts.verbose:
print("New SPNs: %s" % add_list)
if add_list == []:
if opts.verbose:
print("Nothing to add")
sys.exit(0)
# build the modify request
msg = ldb.Message()
msg.dn = res[0]['dn']
msg[""] = ldb.MessageElement(add_list,
ldb.FLAG_MOD_ADD, "servicePrincipalName")
res = samdb.modify(msg)
sys.exit(0)