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
)
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 ,
}
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 )
2011-10-13 02:36:44 +04:00
self . outf . write ( cleaneduser + " \n " )
2011-07-28 11:14:28 +04:00
res = sam . search ( expression = " samaccountname= %s " % ldb . binary_encode ( cleaneduser ) ,
2010-07-02 23:52:33 +04:00
scope = ldb . SCOPE_SUBTREE ,
attrs = [ " servicePrincipalName " ] )
if len ( res ) > 0 :
spns = res [ 0 ] . get ( " servicePrincipalName " )
found = False
flag = ldb . FLAG_MOD_ADD
if spns != 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 :
2011-10-13 02:36:44 +04:00
self . outf . write ( " User %s has no servicePrincipalName " %
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 ,
}
2010-07-02 23:52:33 +04:00
takes_options = [
Option ( " --force " , help = " Force the addition of the spn " \
" even it exists already " , action = " store_true " ) ,
]
takes_args = [ " name " , " user " ]
def run ( self , name , user , force = False , 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 )
2011-07-28 11:14:28 +04:00
res = sam . search ( expression = " servicePrincipalName= %s " % ldb . binary_encode ( name ) ,
2010-07-02 23:52:33 +04:00
scope = ldb . SCOPE_SUBTREE ,
)
if len ( res ) != 0 and not force :
raise CommandError ( " Service principal %s already "
" affected to another user " % name )
( cleaneduser , realm , domain ) = _get_user_realm_domain ( user )
2011-07-28 11:14:28 +04:00
res = sam . search ( expression = " samaccountname= %s " % ldb . binary_encode ( cleaneduser ) ,
2010-07-02 23:52:33 +04:00
scope = ldb . SCOPE_SUBTREE ,
attrs = [ " servicePrincipalName " ] )
if len ( res ) > 0 :
res [ 0 ] . dn
msg = ldb . Message ( )
spns = res [ 0 ] . get ( " servicePrincipalName " )
tab = [ ]
found = False
flag = ldb . FLAG_MOD_ADD
if spns != None :
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 ,
" servicePrincipalName " )
if not found :
sam . modify ( msg )
else :
raise CommandError ( " Service principal %s already "
" affected to %s " % ( name , user ) )
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 ,
}
2010-07-02 23:52:33 +04:00
takes_args = [ " name " , " user? " ]
def run ( self , name , user = None , 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 )
2011-07-28 11:14:28 +04:00
res = sam . search ( expression = " servicePrincipalName= %s " % ldb . binary_encode ( name ) ,
2010-07-02 23:52:33 +04:00
scope = ldb . SCOPE_SUBTREE ,
attrs = [ " servicePrincipalName " , " samAccountName " ] )
if len ( res ) > 0 :
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 "
" spn %s " % ( user , name ) )
else :
if len ( res ) != 1 :
listUser = " "
for r in res :
listUser = " %s \n %s " % ( listUser , str ( r . dn ) )
raise CommandError ( " More than one user has the spn %s " \
" and no specific user was specified, list of users " \
" with this spn: %s " % ( name , listUser ) )
else :
result = res [ 0 ]
msg = ldb . Message ( )
spns = result . get ( " servicePrincipalName " )
tab = [ ]
if spns != None :
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 ,
" servicePrincipalName " )
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 ) :
2011-09-02 20:52:54 +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 ( )