2010-07-02 23:52:33 +04:00
# spn management
#
# Copyright Matthieu Patou mat@samba.org 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 samba . getopt as options
import ldb
from samba import provision
from samba . samdb import SamDB
from samba . auth import system_session
2011-09-07 19:11:38 +04:00
from samba . netcmd . common import _get_user_realm_domain
2010-07-02 23:52:33 +04:00
from samba . netcmd import (
Command ,
CommandError ,
SuperCommand ,
Option
2018-07-30 09:14:37 +03:00
)
2010-07-02 23:52:33 +04:00
2011-09-02 20:52:54 +04:00
2010-07-02 23:52:33 +04:00
class cmd_spn_list ( Command ) :
""" List spns of a given user. """
2011-09-02 20:52:54 +04:00
2011-10-14 01:27:22 +04:00
synopsis = " % prog <user> [options] "
2010-07-02 23:52:33 +04:00
2012-02-06 19:33:38 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" credopts " : options . CredentialsOptions ,
" versionopts " : options . VersionOptions ,
2018-07-30 09:14:37 +03:00
}
2012-02-06 19:33:38 +04:00
2010-07-02 23:52:33 +04:00
takes_args = [ " user " ]
def run ( self , user , credopts = None , sambaopts = None , versionopts = None ) :
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp )
paths = provision . provision_paths_from_lp ( lp , lp . get ( " realm " ) )
sam = SamDB ( paths . samdb , session_info = system_session ( ) ,
credentials = creds , lp = lp )
# TODO once I understand how, use the domain info to naildown
# to the correct domain
( cleaneduser , realm , domain ) = _get_user_realm_domain ( user )
2018-07-30 09:18:25 +03:00
self . outf . write ( cleaneduser + " \n " )
2012-09-16 16:18:39 +04:00
res = sam . search (
expression = " samaccountname= %s " % ldb . binary_encode ( cleaneduser ) ,
scope = ldb . SCOPE_SUBTREE , attrs = [ " servicePrincipalName " ] )
2018-07-30 09:18:03 +03:00
if len ( res ) > 0 :
2010-07-02 23:52:33 +04:00
spns = res [ 0 ] . get ( " servicePrincipalName " )
found = False
flag = ldb . FLAG_MOD_ADD
2012-09-27 20:30:47 +04:00
if spns is not None :
2011-10-13 02:36:44 +04:00
self . outf . write (
" User %s has the following servicePrincipalName: \n " %
res [ 0 ] . dn )
2010-07-02 23:52:33 +04:00
for e in spns :
2011-10-13 02:36:44 +04:00
self . outf . write ( " \t %s \n " % e )
2010-07-02 23:52:33 +04:00
else :
2017-04-10 05:40:20 +03:00
self . outf . write ( " User %s has no servicePrincipalName \n " %
res [ 0 ] . dn )
2010-07-02 23:52:33 +04:00
else :
raise CommandError ( " User %s not found " % user )
2011-09-02 20:52:54 +04:00
2010-07-02 23:52:33 +04:00
class cmd_spn_add ( Command ) :
""" Create a new spn. """
2011-09-02 20:52:54 +04:00
2011-10-14 01:27:22 +04:00
synopsis = " % prog <name> <user> [options] "
2010-07-02 23:52:33 +04:00
2012-02-06 19:33:38 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" credopts " : options . CredentialsOptions ,
" versionopts " : options . VersionOptions ,
2018-07-30 09:14:37 +03:00
}
2010-07-02 23:52:33 +04:00
takes_options = [
2012-09-27 20:30:47 +04:00
Option ( " --force " , help = " Force the addition of the spn "
2010-07-02 23:52:33 +04:00
" even it exists already " , action = " store_true " ) ,
]
takes_args = [ " name " , " user " ]
2018-07-30 09:19:11 +03:00
def run ( self , name , user , force = False , credopts = None , sambaopts = None ,
2012-09-16 16:18:39 +04:00
versionopts = None ) :
2010-07-02 23:52:33 +04:00
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp )
paths = provision . provision_paths_from_lp ( lp , lp . get ( " realm " ) )
sam = SamDB ( paths . samdb , session_info = system_session ( ) ,
credentials = creds , lp = lp )
2012-09-16 16:18:39 +04:00
res = sam . search (
expression = " servicePrincipalName= %s " % ldb . binary_encode ( name ) ,
scope = ldb . SCOPE_SUBTREE )
2012-09-27 20:30:47 +04:00
if len ( res ) != 0 and not force :
2010-07-02 23:52:33 +04:00
raise CommandError ( " Service principal %s already "
2018-07-30 09:15:34 +03:00
" affected to another user " % name )
2010-07-02 23:52:33 +04:00
( cleaneduser , realm , domain ) = _get_user_realm_domain ( user )
2012-09-16 16:18:39 +04:00
res = sam . search (
expression = " samaccountname= %s " % ldb . binary_encode ( cleaneduser ) ,
scope = ldb . SCOPE_SUBTREE , attrs = [ " servicePrincipalName " ] )
2018-07-30 09:18:03 +03:00
if len ( res ) > 0 :
2010-07-02 23:52:33 +04:00
res [ 0 ] . dn
msg = ldb . Message ( )
spns = res [ 0 ] . get ( " servicePrincipalName " )
tab = [ ]
found = False
flag = ldb . FLAG_MOD_ADD
2012-09-27 20:30:47 +04:00
if spns is not None :
2010-07-02 23:52:33 +04:00
for e in spns :
if str ( e ) == name :
found = True
tab . append ( str ( e ) )
flag = ldb . FLAG_MOD_REPLACE
tab . append ( name )
msg . dn = res [ 0 ] . dn
msg [ " servicePrincipalName " ] = ldb . MessageElement ( tab , flag ,
2018-07-30 09:16:12 +03:00
" servicePrincipalName " )
2010-07-02 23:52:33 +04:00
if not found :
sam . modify ( msg )
else :
raise CommandError ( " Service principal %s already "
2018-07-30 09:15:34 +03:00
" affected to %s " % ( name , user ) )
2010-07-02 23:52:33 +04:00
else :
raise CommandError ( " User %s not found " % user )
class cmd_spn_delete ( Command ) :
""" Delete a spn. """
2011-09-02 20:52:54 +04:00
2011-10-14 01:27:22 +04:00
synopsis = " % prog <name> [user] [options] "
2010-07-02 23:52:33 +04:00
2012-02-06 19:33:38 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" credopts " : options . CredentialsOptions ,
" versionopts " : options . VersionOptions ,
2018-07-30 09:14:37 +03:00
}
2012-02-06 19:33:38 +04:00
2010-07-02 23:52:33 +04:00
takes_args = [ " name " , " user? " ]
2012-09-16 16:18:39 +04:00
def run ( self , name , user = None , credopts = None , sambaopts = None ,
versionopts = None ) :
2010-07-02 23:52:33 +04:00
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp )
paths = provision . provision_paths_from_lp ( lp , lp . get ( " realm " ) )
sam = SamDB ( paths . samdb , session_info = system_session ( ) ,
credentials = creds , lp = lp )
2012-09-16 16:18:39 +04:00
res = sam . search (
expression = " servicePrincipalName= %s " % ldb . binary_encode ( name ) ,
scope = ldb . SCOPE_SUBTREE ,
attrs = [ " servicePrincipalName " , " samAccountName " ] )
2018-07-30 09:18:03 +03:00
if len ( res ) > 0 :
2010-07-02 23:52:33 +04:00
result = None
if user is not None :
( cleaneduser , realm , domain ) = _get_user_realm_domain ( user )
for elem in res :
if str ( elem [ " samAccountName " ] ) . lower ( ) == cleaneduser :
result = elem
if result is None :
raise CommandError ( " Unable to find user %s with "
2018-07-30 09:15:34 +03:00
" spn %s " % ( user , name ) )
2010-07-02 23:52:33 +04:00
else :
if len ( res ) != 1 :
listUser = " "
for r in res :
listUser = " %s \n %s " % ( listUser , str ( r . dn ) )
2012-09-27 20:30:47 +04:00
raise CommandError ( " More than one user has the spn %s "
2018-07-30 09:16:12 +03:00
" and no specific user was specified, list of users "
" with this spn: %s " % ( name , listUser ) )
2010-07-02 23:52:33 +04:00
else :
2018-07-30 09:18:03 +03:00
result = res [ 0 ]
2010-07-02 23:52:33 +04:00
msg = ldb . Message ( )
spns = result . get ( " servicePrincipalName " )
tab = [ ]
2012-09-27 20:30:47 +04:00
if spns is not None :
2010-07-02 23:52:33 +04:00
for e in spns :
if str ( e ) != name :
tab . append ( str ( e ) )
flag = ldb . FLAG_MOD_REPLACE
msg . dn = result . dn
msg [ " servicePrincipalName " ] = ldb . MessageElement ( tab , flag ,
2018-07-30 09:16:12 +03:00
" servicePrincipalName " )
2010-07-02 23:52:33 +04:00
sam . modify ( msg )
else :
raise CommandError ( " Service principal %s not affected " % name )
2011-09-02 20:52:54 +04:00
2010-07-02 23:52:33 +04:00
class cmd_spn ( SuperCommand ) :
2012-10-09 13:53:21 +04:00
""" Service Principal Name (SPN) management. """
2010-07-02 23:52:33 +04:00
subcommands = { }
subcommands [ " add " ] = cmd_spn_add ( )
subcommands [ " list " ] = cmd_spn_list ( )
subcommands [ " delete " ] = cmd_spn_delete ( )