Add radius profile implementations:

get_radius_profile_by_uid
  add_radius_profile
  update_radius_profile
  delete_radius_profile
  find_radius_profiles

Rewrite command line arg handling, now support pair entry, interactive
mode with auto completion, reading pairs from a file, better handling
of mandatory values, better help, long arg names now match attribute
name in pairs

Establish mappings for all attributes and names used in clients and
profiles

Add notion of containers to radius clients and profiles in LDAP

Move common code, variables, constants, and strings into the files
radius_client.py, radius_util.py, ipautil.py to eliminate redundant
elements which could get out of sync if modified and to provide access
to other code which might benefit from using these items in the
future.

Add utility functions:
  format_list()
  parse_key_value_pairs()

Add utility class:
  AttributeValueCompleter

Unify attribute usage in radius ldap schema
This commit is contained in:
John Dennis
2007-11-21 13:11:10 -05:00
parent 087d11af5c
commit d98686e967
13 changed files with 956 additions and 241 deletions

View File

@@ -334,29 +334,29 @@ class IPAClient:
return entries
# radius support
def get_radius_client_by_ip_addr(self,ip_addr,sattrs=None):
result = self.transport.get_radius_client_by_ip_addr(ip_addr,sattrs)
def get_radius_client_by_ip_addr(self, ip_addr, container=None, sattrs=None):
result = self.transport.get_radius_client_by_ip_addr(ip_addr, container, sattrs)
return radius_client.RadiusClient(result)
def add_radius_client(self,client):
def add_radius_client(self,client, container=None):
client_dict = client.toDict()
# dn is set on the server-side
del client_dict['dn']
# convert to a regular dict before sending
result = self.transport.add_radius_client(client_dict)
result = self.transport.add_radius_client(client_dict, container)
return result
def update_radius_client(self,client):
result = self.transport.update_radius_client(client.origDataDict(), client.toDict())
return result
def delete_radius_client(self,ip_addr):
return self.transport.delete_radius_client(ip_addr)
def delete_radius_client(self, ip_addr, container=None):
return self.transport.delete_radius_client(ip_addr, container)
def find_radius_clients(self, criteria, sattrs=None, searchlimit=0, timelimit=-1):
result = self.transport.find_radius_clients(criteria, sattrs, searchlimit, timelimit)
def find_radius_clients(self, criteria, container=None, sattrs=None, searchlimit=0, timelimit=-1):
result = self.transport.find_radius_clients(criteria, container, sattrs, searchlimit, timelimit)
counter = result[0]
users = [counter]

View File

@@ -25,6 +25,10 @@ import logging
import subprocess
import os
import stat
import copy
import readline
import traceback
from types import *
from string import lower
import re
@@ -331,3 +335,329 @@ def parse_generalized_time(timestr):
except ValueError:
return None
def format_list(items, quote=None, page_width=80):
'''Format a list of items formatting them so they wrap to fit the
available width. The items will be sorted.
The items may optionally be quoted. The quote parameter may either be
a string, in which case it is added before and after the item. Or the
quote parameter may be a pair (either a tuple or list). In this case
quote[0] is left hand quote and quote[1] is the right hand quote.
'''
left_quote = right_quote = ''
num_items = len(items)
if not num_items: return text
if quote is not None:
if type(quote) in StringTypes:
left_quote = right_quote = quote
elif type(quote) is TupleType or type(quote) is ListType:
left_quote = quote[0]
right_quote = quote[1]
max_len = max(map(len, items))
max_len += len(left_quote) + len(right_quote)
num_columns = (page_width + max_len) / (max_len+1)
num_rows = (num_items + num_columns - 1) / num_columns
items.sort()
rows = [''] * num_rows
i = row = col = 0
while i < num_items:
row = 0
if col == 0:
separator = ''
else:
separator = ' '
while i < num_items and row < num_rows:
rows[row] += "%s%*s" % (separator, -max_len, "%s%s%s" % (left_quote, items[i], right_quote))
i += 1
row += 1
col += 1
return '\n'.join(rows)
key_value_re = re.compile("([^\s=]+)\s*=\s*((\S+)|(?P<quote>['\\\"])((?P=quote)|(.*?[^\\\])(?P=quote)))")
def parse_key_value_pairs(input):
''' Given a string composed of key=value pairs parse it and return
a dict of the key/value pairs. Keys must be a word, a key must be followed
by an equal sign (=) and a value. The value may be a single word or may be
quoted. Quotes may be either single or double quotes, but must be balanced.
Inside the quoted text the same quote used to start the quoted value may be
used if it is escaped by preceding it with a backslash (\).
White space between the key, the equal sign, and the value is ignored.
Values are always strings. Empty values must be specified with an empty
quoted string, it's value after parsing will be an empty string.
Example: The string
arg0 = '' arg1 = 1 arg2='two' arg3 = "three's a crowd" arg4 = "this is a \" quote"
will produce
arg0= arg1=1
arg2=two
arg3=three's a crowd
arg4=this is a " quote
'''
kv_dict = {}
for match in key_value_re.finditer(input):
key = match.group(1)
quote = match.group('quote')
if match.group(5):
value = match.group(6)
if value is None: value = ''
value = re.sub('\\\%s' % quote, quote, value)
else:
value = match.group(2)
kv_dict[key] = value
return kv_dict
class AttributeValueCompleter:
'''
Gets input from the user in the form "lhs operator rhs"
TAB completes partial input.
lhs completes to a name in @lhs_names
The lhs is fully parsed if a lhs_delim delimiter is seen, then TAB will
complete to the operator and a default value.
Default values for a lhs value can specified as:
- a string, all lhs values will use this default
- a dict, the lhs value is looked up in the dict to return the default or None
- a function with a single arg, the lhs value, it returns the default or None
After creating the completer you must open it to set the terminal
up, Then get a line of input from the user by calling read_input()
which returns two values, the lhs and rhs, which might be None if
lhs or rhs was not parsed. After you are done getting input you
should close the completer to restore the terminal.
Example: (note this is essentially what the convenience function get_pairs() does)
This will allow the user to autocomplete foo & foobar, both have
defaults defined in a dict. In addition the foobar attribute must
be specified before the prompting loop will exit. Also, this
example show how to require that each attrbute entered by the user
is valid.
attrs = ['foo', 'foobar']
defaults = {'foo' : 'foo_default', 'foobar' : 'foobar_default'}
mandatory_attrs = ['foobar']
c = AttributeValueCompleter(attrs, defaults)
c.open()
mandatory_attrs_remaining = copy.copy(mandatory_attrs)
while True:
if mandatory_attrs_remaining:
attribute, value = c.read_input("Enter: ", mandatory_attrs_remaining[0])
try:
mandatory_attrs_remaining.remove(attribute)
except ValueError:
pass
else:
attribute, value = c.read_input("Enter: ")
if attribute is None:
# Are we done?
if mandatory_attrs_remaining:
print "ERROR, you must specify: %s" % (','.join(mandatory_attrs_remaining))
continue
else:
break
if attribute not in attrs:
print "ERROR: %s is not a valid attribute" % (attribute)
else:
print "got '%s' = '%s'" % (attribute, value)
c.close()
print "exiting..."
'''
def __init__(self, lhs_names, default_value=None, lhs_regexp=r'^\s*(?P<lhs>[^ =]+)', lhs_delims=' =',
operator='=', strip_rhs=True):
self.lhs_names = lhs_names
self.default_value = default_value
# lhs_regexp must have named group 'lhs' which returns the contents of the lhs
self.lhs_regexp = lhs_regexp
self.lhs_re = re.compile(self.lhs_regexp)
self.lhs_delims = lhs_delims
self.operator = operator
self.strip_rhs = strip_rhs
self._reset()
def _reset(self):
self.lhs = None
self.lhs_complete = False
self.operator_complete = False
self.rhs = None
def open(self):
# Save state
self.prev_completer = readline.get_completer()
self.prev_completer_delims = readline.get_completer_delims()
# Set up for ourself
readline.parse_and_bind("tab: complete")
readline.set_completer(self.complete)
readline.set_completer_delims(self.lhs_delims)
def close(self):
# Restore previous state
readline.set_completer_delims(self.prev_completer_delims)
readline.set_completer(self.prev_completer)
def _debug(self):
print >> output_fd, "lhs='%s' lhs_complete=%s operator='%s' operator_complete=%s rhs='%s'" % \
(self.lhs, self.lhs_complete, self.operator, self.operator_complete, self.rhs)
def parse_input(self):
'''We are looking for 3 tokens: <lhs,op,rhs>
Extract as much of each token as possible.
Set flags indicating if token is fully parsed.
'''
try:
self._reset()
buf_len = len(self.line_buffer)
pos = 0
lhs_match = self.lhs_re.search(self.line_buffer, pos)
if not lhs_match: return # no lhs content
self.lhs = lhs_match.group('lhs') # get lhs contents
pos = lhs_match.end('lhs') # new scanning position
if pos == buf_len: return # nothing after lhs, lhs incomplete
self.lhs_complete = True # something trails the lhs, lhs is complete
operator_beg = self.line_buffer.find(self.operator, pos) # locate operator
if operator_beg == -1: return # did not find the operator
self.operator_complete = True # operator fully parsed
operator_end = operator_beg + len(self.operator)
pos = operator_end # step over the operator
self.rhs = self.line_buffer[pos:]
except Exception, e:
traceback.print_exc()
print "Exception in %s.parse_input(): %s" % (self.__class__.__name__, e)
def get_default_value(self):
'''default_value can be a string, a dict, or a function.
If it's a string it's a global default for all attributes.
If it's a dict the default is looked up in the dict index by attribute.
If it's a function, the function is called with 1 parameter, the attribute
and it should return the default value for the attriubte or None'''
if not self.lhs_complete: raise ValueError("attribute not parsed")
default_value_type = type(self.default_value)
if default_value_type is DictType:
return self.default_value.get(self.lhs, None)
elif default_value_type is FunctionType:
return self.default_value(self.lhs)
elif default_value_type is StringsType:
return self.default_value
else:
return None
def get_lhs_completions(self, text):
if text:
self.completions = [lhs for lhs in self.lhs_names if lhs.startswith(text)]
else:
self.completions = self.lhs_names
def complete(self, text, state):
self.line_buffer= readline.get_line_buffer()
self.parse_input()
if not self.lhs_complete:
# lhs is not complete, set up to complete the lhs
if state == 0:
beg = readline.get_begidx()
end = readline.get_endidx()
self.get_lhs_completions(self.line_buffer[beg:end])
if state >= len(self.completions): return None
return self.completions[state]
elif not self.operator_complete:
# lhs is complete, but the operator is not so we complete
# by inserting the operator manually.
# Also try to complete the default value at this time.
readline.insert_text('%s ' % self.operator)
default_value = self.get_default_value()
if default_value is not None:
readline.insert_text(default_value)
readline.redisplay()
return None
else:
# lhs and operator are complete, if the the rhs is blank
# (either empty or only only whitespace) then attempt
# to complete by inserting the default value, otherwise
# there is nothing we can complete to so we're done.
if self.rhs.strip():
return None
default_value = self.get_default_value()
if default_value is not None:
readline.insert_text(default_value)
readline.redisplay()
return None
def pre_input_hook(self):
readline.insert_text('%s %s ' % (self.initial_lhs, self.operator))
readline.redisplay()
def read_input(self, prompt, initial_lhs=None):
self.initial_lhs = initial_lhs
try:
self._reset()
if initial_lhs is None:
readline.set_pre_input_hook(None)
else:
readline.set_pre_input_hook(self.pre_input_hook)
self.line_buffer = raw_input(prompt).strip()
self.parse_input()
if self.strip_rhs and self.rhs is not None:
return self.lhs, self.rhs.strip()
else:
return self.lhs, self.rhs
except EOFError:
return None, None
def get_pairs(self, prompt, mandatory_attrs=None, validate_callback=None, must_match=True, value_required=True):
pairs = {}
if mandatory_attrs:
mandatory_attrs_remaining = copy.copy(mandatory_attrs)
else:
mandatory_attrs_remaining = []
print "Enter name = value"
print "Press <ENTER> to accept, a blank line terminates input"
print "Pressing <TAB> will auto completes name, assignment, and value"
print
while True:
if mandatory_attrs_remaining:
attribute, value = self.read_input(prompt, mandatory_attrs_remaining[0])
else:
attribute, value = self.read_input(prompt)
if attribute is None:
# Are we done?
if mandatory_attrs_remaining:
print "ERROR, you must specify: %s" % (','.join(mandatory_attrs_remaining))
continue
else:
break
if value is None:
if value_required:
print "ERROR: you must specify a value for %s" % attribute
continue
else:
if must_match and attribute not in self.lhs_names:
print "ERROR: %s is not a valid name" % (attribute)
continue
if validate_callback is not None:
if not validate_callback(attribute, value):
print "ERROR: %s is not valid for %s" % (value, attribute)
continue
try:
mandatory_attrs_remaining.remove(attribute)
except ValueError:
pass
pairs[attribute] = value
return pairs

View File

@@ -21,6 +21,7 @@ import getpass
import re
from ipa.entity import Entity
import ipa.ipavalidate as ipavalidate
__all__ = ['RadiusClient',
'get_secret',
@@ -29,6 +30,7 @@ __all__ = ['RadiusClient',
'validate_name',
'validate_nastype',
'validate_desc',
'validate',
]
#------------------------------------------------------------------------------
@@ -41,7 +43,10 @@ valid_name_len = (1,31)
valid_nastype_len = (1,31)
valid_ip_addr_len = (1,255)
valid_ip_addr_msg = "IP address must be either a DNS name (letters,digits,dot,hyphen, beginning with a letter),or a dotted octet followed by an optional mask (e.g 192.168.1.0/24)"
valid_ip_addr_msg = '''\
IP address must be either a DNS name (letters,digits,dot,hyphen, beginning with
a letter),or a dotted octet followed by an optional mask (e.g 192.168.1.0/24)'''
valid_desc_msg = "Description must text string"
#------------------------------------------------------------------------------
@@ -101,38 +106,60 @@ def validate_length(value, limits):
def valid_length_msg(name, limits):
return "%s length must be at least %d and not more than %d" % (name, limits[0], limits[1])
def err_msg(variable, variable_name=None):
if variable_name is None: variable_name = 'value'
print "ERROR: %s = %s" % (variable_name, variable)
#------------------------------------------------------------------------------
def validate_ip_addr(ip_addr):
def validate_ip_addr(ip_addr, variable_name=None):
if not validate_length(ip_addr, valid_ip_addr_len):
err_msg(ip_addr, variable_name)
print valid_length_msg('ip address', valid_ip_addr_len)
return False
if not valid_ip_addr(ip_addr):
err_msg(ip_addr, variable_name)
print valid_ip_addr_msg
return False
return True
def validate_secret(secret):
def validate_secret(secret, variable_name=None):
if not validate_length(secret, valid_secret_len):
err_msg(secret, variable_name)
print valid_length_msg('secret', valid_secret_len)
return False
return True
def validate_name(name):
def validate_name(name, variable_name=None):
if not validate_length(name, valid_name_len):
err_msg(name, variable_name)
print valid_length_msg('name', valid_name_len)
return False
return True
def validate_nastype(nastype):
def validate_nastype(nastype, variable_name=None):
if not validate_length(nastype, valid_nastype_len):
err_msg(nastype, variable_name)
print valid_length_msg('NAS Type', valid_nastype_len)
return False
return True
def validate_desc(desc):
def validate_desc(desc, variable_name=None):
if ipavalidate.plain(desc, notEmpty=True) != 0:
print valid_desc_msg
return False
return True
def validate(attribute, value):
if attribute == 'Client-IP-Address':
return validate_ip_addr(value, attribute)
if attribute == 'Secret':
return validate_secret(value, attribute)
if attribute == 'NAS-Type':
return validate_nastype(value, attribute)
if attribute == 'Name':
return validate_name(value, attribute)
if attribute == 'Description':
return validate_desc(value, attribute)
return True

231
ipa-python/radius_util.py Normal file
View File

@@ -0,0 +1,231 @@
# Authors: John Dennis <jdennis@redhat.com>
#
# Copyright (C) 2007 Red Hat
# see file 'COPYING' for use and warranty information
#
# 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; version 2 only
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys
import os
import re
import ldap
import ldap.filter
from ipa import ipautil
__all__ = [
'RADIUS_PKG_NAME',
'RADIUS_PKG_CONFIG_DIR',
'RADIUS_SERVICE_NAME',
'RADIUS_USER',
'RADIUS_IPA_KEYTAB_FILEPATH',
'RADIUS_LDAP_ATTR_MAP_FILEPATH',
'RADIUSD_CONF_FILEPATH',
'RADIUSD_CONF_TEMPLATE_FILEPATH',
'RADIUSD',
'clients_container',
'radius_clients_basedn',
'radius_client_filter',
'radius_client_dn',
'profiles_container',
'radius_profiles_basedn',
'radius_profile_filter',
'radius_profile_dn',
'client_ldap_attr_to_name',
'client_name_to_ldap_attr',
'read_pairs_file',
]
#------------------------------------------------------------------------------
RADIUS_PKG_NAME = 'freeradius'
RADIUS_PKG_CONFIG_DIR = '/etc/raddb'
RADIUS_SERVICE_NAME = 'radius'
RADIUS_USER = 'radiusd'
RADIUS_IPA_KEYTAB_FILEPATH = os.path.join(RADIUS_PKG_CONFIG_DIR, 'ipa.keytab')
RADIUS_LDAP_ATTR_MAP_FILEPATH = os.path.join(RADIUS_PKG_CONFIG_DIR, 'ldap.attrmap')
RADIUSD_CONF_FILEPATH = os.path.join(RADIUS_PKG_CONFIG_DIR, 'radiusd.conf')
RADIUSD_CONF_TEMPLATE_FILEPATH = os.path.join(ipautil.SHARE_DIR, 'radius.radiusd.conf.template')
RADIUSD = '/usr/sbin/radiusd'
#------------------------------------------------------------------------------
def reverse_map_dict(src_dict):
reverse_dict = {}
for k,v in src_dict.items():
if reverse_dict.has_key(v):
raise ValueError("reverse_map_dict: collision on (%s) with values (%s),(%s)" % \
v, reverse_dict[v], src_dict[k])
reverse_dict[v] = k
return reverse_dict
#------------------------------------------------------------------------------
client_ldap_attr_to_name = ipautil.CIDict({
'radiusClientIPAddress' : 'Client-IP-Address',
'radiusClientSecret' : 'Secret',
'radiusClientNASType' : 'NAS-Type',
'radiusClientShortName' : 'Name',
'description' : 'Description',
})
client_name_to_ldap_attr = reverse_map_dict(client_ldap_attr_to_name)
#------------------------------------------------------------------------------
profile_ldap_attr_to_name = {
'radiusArapFeatures' : 'Arap-Features',
'radiusArapSecurity' : 'Arap-Security',
'radiusArapZoneAccess' : 'Arap-Zone-Access',
'radiusAuthType' : 'Auth-Type',
'radiusCallbackId' : 'Callback-Id',
'radiusCallbackNumber' : 'Callback-Number',
'radiusCalledStationId' : 'Called-Station-Id',
'radiusCallingStationId' : 'Calling-Station-Id',
'radiusClass' : 'Class',
'radiusClientIPAddress' : 'Client-IP-Address',
'radiusExpiration' : 'Expiration',
'radiusFilterId' : 'Filter-Id',
'radiusFramedAppleTalkLink' : 'Framed-AppleTalk-Link',
'radiusFramedAppleTalkNetwork' : 'Framed-AppleTalk-Network',
'radiusFramedAppleTalkZone' : 'Framed-AppleTalk-Zone',
'radiusFramedCompression' : 'Framed-Compression',
'radiusFramedIPAddress' : 'Framed-IP-Address',
'radiusFramedIPNetmask' : 'Framed-IP-Netmask',
'radiusFramedIPXNetwork' : 'Framed-IPX-Network',
'radiusFramedMTU' : 'Framed-MTU',
'radiusFramedProtocol' : 'Framed-Protocol',
'radiusFramedRoute' : 'Framed-Route',
'radiusFramedRouting' : 'Framed-Routing',
'radiusGroupName' : 'Group-Name',
'radiusHint' : 'Hint',
'radiusHuntgroupName' : 'Huntgroup-Name',
'radiusIdleTimeout' : 'Idle-Timeout',
'radiusLoginIPHost' : 'Login-IP-Host',
'radiusLoginLATGroup' : 'Login-LAT-Group',
'radiusLoginLATNode' : 'Login-LAT-Node',
'radiusLoginLATPort' : 'Login-LAT-Port',
'radiusLoginLATService' : 'Login-LAT-Service',
'radiusLoginService' : 'Login-Service',
'radiusLoginTCPPort' : 'Login-TCP-Port',
'radiusLoginTime' : 'Login-Time',
'radiusNASIpAddress' : 'NAS-IP-Address',
'radiusPasswordRetry' : 'Password-Retry',
'radiusPortLimit' : 'Port-Limit',
'radiusProfileDn' : 'Profile-Dn',
'radiusPrompt' : 'Prompt',
'radiusProxyToRealm' : 'Proxy-To-Realm',
'radiusRealm' : 'Realm',
'radiusReplicateToRealm' : 'Replicate-To-Realm',
'radiusReplyMessage' : 'Reply-Message',
'radiusServiceType' : 'Service-Type',
'radiusSessionTimeout' : 'Session-Timeout',
'radiusSimultaneousUse' : 'Simultaneous-Use',
'radiusStripUserName' : 'Strip-User-Name',
'radiusTerminationAction' : 'Termination-Action',
'radiusTunnelAssignmentId' : 'Tunnel-Assignment-Id',
'radiusTunnelClientEndpoint' : 'Tunnel-Client-Endpoint',
'radiusTunnelMediumType' : 'Tunnel-Medium-Type',
'radiusTunnelPassword' : 'Tunnel-Password',
'radiusTunnelPreference' : 'Tunnel-Preference',
'radiusTunnelPrivateGroupId' : 'Tunnel-Private-Group-Id',
'radiusTunnelServerEndpoint' : 'Tunnel-Server-Endpoint',
'radiusTunnelType' : 'Tunnel-Type',
'radiusUserCategory' : 'User-Category',
'radiusVSA' : 'VSA',
}
profile_name_to_ldap_attr = reverse_map_dict(profile_ldap_attr_to_name)
#------------------------------------------------------------------------------
clients_container = 'cn=clients,cn=radius,cn=services,cn=etc'
def radius_clients_basedn(container, suffix):
if container is None: container = clients_container
return '%s,%s' % (container, suffix)
def radius_client_filter(ip_addr):
return "(&(radiusClientIPAddress=%s)(objectclass=radiusClientProfile))" % \
ldap.filter.escape_filter_chars(ip_addr)
def radius_client_dn(client, container, suffix):
if container is None: container = clients_container
return 'radiusClientIPAddress=%s,%s,%s' % (ldap.dn.escape_dn_chars(client), container, suffix)
# --
profiles_container = 'cn=profiles,cn=radius,cn=services,cn=etc'
def radius_profiles_basedn(container, suffix):
if container is None: container = profiles_container
return '%s,%s' % (container, suffix)
def radius_profile_filter(uid):
return "(&(uid=%s)(objectclass=radiusprofile))" % \
ldap.filter.escape_filter_chars(uid)
def radius_profile_dn(uid, container, suffix):
if container is None: container = profiles_container
return 'uid=%s,%s,%s' % (ldap.dn.escape_dn_chars(uid), container, suffix)
#------------------------------------------------------------------------------
comment_re = re.compile('#.*$', re.MULTILINE)
def read_pairs_file(filename):
if filename == '-':
fd = sys.stdin
else:
fd = open(filename)
data = fd.read()
data = comment_re.sub('', data) # kill comments
pairs = ipautil.parse_key_value_pairs(data)
if fd != sys.stdin: fd.close()
return pairs
def get_ldap_attr_translations():
comment_re = re.compile('#.*$')
radius_attr_to_ldap_attr = {}
ldap_attr_to_radius_attr = {}
try:
f = open(LDAP_ATTR_MAP_FILEPATH)
for line in f.readlines():
line = comment_re.sub('', line).strip()
if not line: continue
attr_type, radius_attr, ldap_attr = line.split()
print 'type="%s" radius="%s" ldap="%s"' % (attr_type, radius_attr, ldap_attr)
radius_attr_to_ldap_attr[radius_attr] = {'ldap_attr':ldap_attr, 'attr_type':attr_type}
ldap_attr_to_radius_attr[ldap_attr] = {'radius_attr':radius_attr, 'attr_type':attr_type}
f.close()
except Exception, e:
logging.error('cold not read radius ldap attribute map file (%s): %s', LDAP_ATTR_MAP_FILEPATH, e)
pass # FIXME
#for k,v in radius_attr_to_ldap_attr.items():
# print '%s --> %s' % (k,v)
#for k,v in ldap_attr_to_radius_attr.items():
# print '%s --> %s' % (k,v)

View File

@@ -594,12 +594,12 @@ class RPCClient:
# radius support
def get_radius_client_by_ip_addr(self,ip_addr,sattrs=None):
def get_radius_client_by_ip_addr(self,ip_addr, container, sattrs=None):
server = self.setup_server()
if sattrs is None:
sattrs = "__NONE__"
if container is None: container = "__NONE__"
if sattrs is None: sattrs = "__NONE__"
try:
result = server.get_radius_client_by_ip_addr(ip_addr, sattrs)
result = server.get_radius_client_by_ip_addr(ip_addr, container, sattrs)
except xmlrpclib.Fault, fault:
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
except socket.error, (value, msg):
@@ -607,11 +607,13 @@ class RPCClient:
return ipautil.unwrap_binary_data(result)
def add_radius_client(self,client):
def add_radius_client(self,client, container=None):
server = self.setup_server()
if container is None: container = "__NONE__"
try:
result = server.add_radius_client(ipautil.wrap_binary_data(client))
result = server.add_radius_client(ipautil.wrap_binary_data(client), container)
except xmlrpclib.Fault, fault:
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
except socket.error, (value, msg):
@@ -633,11 +635,12 @@ class RPCClient:
return ipautil.unwrap_binary_data(result)
def delete_radius_client(self,ip_addr):
def delete_radius_client(self,ip_addr, container=None):
server = self.setup_server()
if container is None: container = "__NONE__"
try:
result = server.delete_radius_client(ip_addr)
result = server.delete_radius_client(ip_addr, container)
except xmlrpclib.Fault, fault:
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
except socket.error, (value, msg):
@@ -645,13 +648,14 @@ class RPCClient:
return ipautil.unwrap_binary_data(result)
def find_radius_clients(self, criteria, sattrs=None, searchlimit=0, timelimit=-1):
def find_radius_clients(self, criteria, container=None, sattrs=None, searchlimit=0, timelimit=-1):
server = self.setup_server()
if container is None: container = "__NONE__"
try:
# None values are not allowed in XML-RPC
if sattrs is None:
sattrs = "__NONE__"
result = server.find_radius_clients(criteria, sattrs, searchlimit, timelimit)
result = server.find_radius_clients(criteria, container, sattrs, searchlimit, timelimit)
except xmlrpclib.Fault, fault:
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
except socket.error, (value, msg):