diff options
Diffstat (limited to 'ipa-server')
-rw-r--r-- | ipa-server/ipa-install/share/60radius.ldif | 12 | ||||
-rw-r--r-- | ipa-server/ipa-install/share/bootstrap-template.ldif | 4 | ||||
-rw-r--r-- | ipa-server/ipaserver/radiusinstance.py | 67 | ||||
-rw-r--r-- | ipa-server/xmlrpc-server/funcs.py | 155 | ||||
-rw-r--r-- | ipa-server/xmlrpc-server/ipaxmlrpc.py | 5 |
5 files changed, 155 insertions, 88 deletions
diff --git a/ipa-server/ipa-install/share/60radius.ldif b/ipa-server/ipa-install/share/60radius.ldif index 47692352..3562312a 100644 --- a/ipa-server/ipa-install/share/60radius.ldif +++ b/ipa-server/ipa-install/share/60radius.ldif @@ -492,7 +492,7 @@ objectClasses: NAME 'radiusprofile' SUP top AUXILIARY DESC '' - MUST cn + MUST uid MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ radiusCalledStationId $ radiusCallingStationId $ radiusClass $ @@ -527,14 +527,6 @@ objectClasses: MAY ( uid $ userPassword $ description ) ) attributeTypes: - ( 1.3.6.1.4.1.3317.4.3.1.63 - NAME 'radiusClientNASIpAddress' - DESC '' - EQUALITY caseIgnoreIA5Match - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 - SINGLE-VALUE - ) -attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.64 NAME 'radiusClientSecret' DESC '' @@ -564,6 +556,6 @@ objectClasses: NAME 'radiusClientProfile' SUP top STRUCTURAL DESC 'A Container Objectclass to be used for describing radius clients' - MUST (radiusClientNASIpAddress $ radiusClientSecret) + MUST (radiusClientIPAddress $ radiusClientSecret) MAY ( radiusClientNASType $ radiusClientShortName $ description ) ) diff --git a/ipa-server/ipa-install/share/bootstrap-template.ldif b/ipa-server/ipa-install/share/bootstrap-template.ldif index fcc2506d..df59bc0e 100644 --- a/ipa-server/ipa-install/share/bootstrap-template.ldif +++ b/ipa-server/ipa-install/share/bootstrap-template.ldif @@ -92,11 +92,11 @@ objectClass: nsContainer objectClass: top cn: profiles -dn: cn=ipa_default, cn=profiles,cn=radius,cn=services,cn=etc,$SUFFIX +dn: uid=ipa_default, cn=profiles,cn=radius,cn=services,cn=etc,$SUFFIX changetype: add objectClass: top objectClass: radiusprofile -cn: ipa_default +uid: ipa_default dn: cn=admins,cn=groups,cn=accounts,$SUFFIX changetype: add diff --git a/ipa-server/ipaserver/radiusinstance.py b/ipa-server/ipaserver/radiusinstance.py index 8317da03..0c94c713 100644 --- a/ipa-server/ipaserver/radiusinstance.py +++ b/ipa-server/ipaserver/radiusinstance.py @@ -26,6 +26,7 @@ import logging import pwd import time from ipa.ipautil import * +from ipa import radius_util import service @@ -33,18 +34,6 @@ import os import re IPA_RADIUS_VERSION = '0.0.0' -PKG_NAME = 'freeradius' -PKG_CONFIG_DIR = '/etc/raddb' - -RADIUS_SERVICE_NAME = 'radius' -RADIUS_USER = 'radiusd' - -IPA_KEYTAB_FILEPATH = os.path.join(PKG_CONFIG_DIR, 'ipa.keytab') -LDAP_ATTR_MAP_FILEPATH = os.path.join(PKG_CONFIG_DIR, 'ldap.attrmap') -RADIUSD_CONF_FILEPATH = os.path.join(PKG_CONFIG_DIR, 'radiusd.conf') -RADIUSD_CONF_TEMPLATE_FILEPATH = os.path.join(SHARE_DIR, 'radius.radiusd.conf.template') - -RADIUSD = '/usr/sbin/radiusd' # FIXME there should a utility to get the user base dn from ipaserver.funcs import DefaultUserContainer, DefaultGroupContainer @@ -58,7 +47,7 @@ def ldap_mod(fd, dn, pwd): def get_radius_version(): version = None try: - p = subprocess.Popen([RADIUSD, '-v'], stdout=subprocess.PIPE, + p = subprocess.Popen([radius_util.RADIUSD, '-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() status = p.returncode @@ -86,7 +75,7 @@ class RadiusInstance(service.Service): self.suffix = realm_to_suffix(self.realm) self.fqdn = host_name self.ldap_server = ldap_server - self.principal = "%s/%s@%s" % (RADIUS_SERVICE_NAME, self.fqdn, self.realm) + self.principal = "%s/%s@%s" % (radius_util.RADIUS_SERVICE_NAME, self.fqdn, self.realm) self.basedn = self.suffix self.user_basedn = "%s,%s" % (DefaultUserContainer, self.basedn) # FIXME, should be utility to get this self.radius_version = get_radius_version() @@ -117,34 +106,34 @@ class RadiusInstance(service.Service): version = 'IPA_RADIUS_VERSION=%s FREE_RADIUS_VERSION=%s' % (IPA_RADIUS_VERSION, self.radius_version) sub_dict = {'CONFIG_FILE_VERSION_INFO' : version, 'LDAP_SERVER' : self.ldap_server, - 'RADIUS_KEYTAB' : IPA_KEYTAB_FILEPATH, + 'RADIUS_KEYTAB' : radius_util.RADIUS_IPA_KEYTAB_FILEPATH, 'RADIUS_PRINCIPAL' : self.principal, 'RADIUS_USER_BASE_DN' : self.user_basedn, 'ACCESS_ATTRIBUTE' : '', 'ACCESS_ATTRIBUTE_DEFAULT' : 'TRUE', - 'CLIENTS_BASEDN' : 'cn=clients,cn=radius,cn=services,cn=etc,%s' % self.suffix, + 'CLIENTS_BASEDN' : radius_util.radius_clients_basedn(None, self.suffix), 'SUFFIX' : self.suffix, } try: - radiusd_conf = template_file(RADIUSD_CONF_TEMPLATE_FILEPATH, sub_dict) - radiusd_fd = open(RADIUSD_CONF_FILEPATH, 'w+') + radiusd_conf = template_file(radius_util.RADIUSD_CONF_TEMPLATE_FILEPATH, sub_dict) + radiusd_fd = open(radius_util.RADIUSD_CONF_FILEPATH, 'w+') radiusd_fd.write(radiusd_conf) radiusd_fd.close() except Exception, e: - logging.error("could not create %s: %s", RADIUSD_CONF_FILEPATH, e) + logging.error("could not create %s: %s", radius_util.RADIUSD_CONF_FILEPATH, e) def __create_radius_keytab(self): self.step("create radiusd keytab") try: - if file_exists(IPA_KEYTAB_FILEPATH): - os.remove(IPA_KEYTAB_FILEPATH) + if file_exists(radius_util.RADIUS_IPA_KEYTAB_FILEPATH): + os.remove(radius_util.RADIUS_IPA_KEYTAB_FILEPATH) except os.error: - logging.error("Failed to remove %s", IPA_KEYTAB_FILEPATH) + logging.error("Failed to remove %s", radius_util.RADIUS_IPA_KEYTAB_FILEPATH) (kwrite, kread, kerr) = os.popen3("/usr/kerberos/sbin/kadmin.local") kwrite.write("addprinc -randkey %s\n" % (self.principal)) kwrite.flush() - kwrite.write("ktadd -k %s %s\n" % (IPA_KEYTAB_FILEPATH, self.principal)) + kwrite.write("ktadd -k %s %s\n" % (radius_util.RADIUS_IPA_KEYTAB_FILEPATH, self.principal)) kwrite.flush() kwrite.close() kread.close() @@ -152,7 +141,7 @@ class RadiusInstance(service.Service): # give kadmin time to actually write the file before we go on retry = 0 - while not file_exists(IPA_KEYTAB_FILEPATH): + while not file_exists(radius_util.RADIUS_IPA_KEYTAB_FILEPATH): time.sleep(1) retry += 1 if retry > 15: @@ -160,10 +149,10 @@ class RadiusInstance(service.Service): os.exit() try: - pent = pwd.getpwnam(RADIUS_USER) - os.chown(IPA_KEYTAB_FILEPATH, pent.pw_uid, pent.pw_gid) + pent = pwd.getpwnam(radius_util.RADIUS_USER) + os.chown(radius_util.RADIUS_IPA_KEYTAB_FILEPATH, pent.pw_uid, pent.pw_gid) except Exception, e: - logging.error("could not chown on %s to %s: %s", IPA_KEYTAB_FILEPATH, RADIUS_USER, e) + logging.error("could not chown on %s to %s: %s", radius_util.RADIUS_IPA_KEYTAB_FILEPATH, radius_util.RADIUS_USER, e) #FIXME, should use IPAdmin method def __set_ldap_encrypted_attributes(self): @@ -179,27 +168,3 @@ class RadiusInstance(service.Service): #------------------------------------------------------------------------------- -# FIXME: this should be in a common area so it can be shared -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) - diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index 26fdba48..aa557f79 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -30,6 +30,7 @@ import xmlrpclib import copy import attrs from ipa import ipaerror +from ipa import radius_util import string from types import * @@ -458,41 +459,40 @@ class IPAServer: # radius support - # FIXME, why not just use get_entry_by_dn? - def get_radius_client_by_ip_addr(self, ip_addr, sattrs=None, opts=None): - ip_addr = self.__safe_filter(ip_addr) - basedn = 'cn=clients,cn=radius,cn=services,cn=etc,%s' % self.basedn # FIXME, should not be hardcoded - filter = "(&(radiusClientNASIpAddress=%s)(objectclass=radiusClientProfile))" % ip_addr + # clients + def get_radius_client_by_ip_addr(self, ip_addr, container=None, sattrs=None, opts=None): + filter = radius_util.radius_client_filter(ip_addr) + basedn = radius_util.radius_clients_basedn(container, self.basedn) return self.__get_sub_entry(basedn, filter, sattrs, opts) - def __is_radius_client_unique(self, ip_addr, opts): - """Return 1 if the radius client is unique in the tree, 0 otherwise.""" - ip_addr = self.__safe_filter(ip_addr) - basedn = 'cn=clients,cn=radius,cn=services,cn=etc,%s' % self.basedn # FIXME, should not be hardcoded - filter = "(&(radiusClientNASIpAddress=%s)(objectclass=radiusClientProfile))" % ip_addr + def __radius_client_exists(self, ip_addr, container, opts): + filter = radius_util.radius_client_filter(ip_addr) + basedn = radius_util.radius_clients_basedn(container, self.basedn) try: entry = self.__get_sub_entry(basedn, filter, ['dn','uid'], opts) - return 0 + return True except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): - return 1 + return False - def add_radius_client (self, client, opts=None): - client_container = 'cn=clients,cn=radius,cn=services,cn=etc' # FIXME, should not be hardcoded - if self.__is_radius_client_unique(client['radiusClientNASIpAddress'], opts) == 0: - raise ipaerror.gen_exception(ipaerror.LDAP_DUPLICATE) + def add_radius_client (self, client, container=None, opts=None): + if container is None: + container = radius_util.clients_container - dn="radiusClientNASIpAddress=%s,%s,%s" % (ldap.dn.escape_dn_chars(client['radiusClientNASIpAddress']), - client_container,self.basedn) + ip_addr = client['radiusClientIPAddress'] + + if self.__radius_client_exists(ip_addr, container, opts): + raise ipaerror.gen_exception(ipaerror.LDAP_DUPLICATE) + dn = radius_util.radius_client_dn(ip_addr, container, self.basedn) entry = ipaserver.ipaldap.Entry(dn) # some required objectclasses entry.setValues('objectClass', 'top', 'radiusClientProfile') # fill in our new entry with everything sent by the client - for u in client: - entry.setValues(u, client[u]) + for attr in client: + entry.setValues(attr, client[attr]) conn = self.getConnection(opts) try: @@ -504,8 +504,8 @@ class IPAServer: def update_radius_client(self, oldentry, newentry, opts=None): return self.update_entry(oldentry, newentry, opts) - def delete_radius_client(self, ip_addr, opts=None): - client = self.get_radius_client_by_ip_addr(ip_addr, ['dn', 'cn'], opts) + def delete_radius_client(self, ip_addr, container=None, opts=None): + client = self.get_radius_client_by_ip_addr(ip_addr, container, ['dn', 'cn'], opts) if client is None: raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND) @@ -516,7 +516,7 @@ class IPAServer: self.releaseConnection(conn) return res - def find_radius_clients(self, ip_attrs, sattrs=None, searchlimit=0, timelimit=-1, opts=None): + def find_radius_clients(self, ip_attrs, container=None, sattrs=None, searchlimit=0, timelimit=-1, opts=None): def gen_filter(objectclass, attr, values): '''Given ('myclass', 'myattr', [v1, v2]) returns (&(objectclass=myclass)(|(myattr=v1)(myattr=v2))) @@ -527,8 +527,8 @@ class IPAServer: filter = "(&(objectclass=%s)(|%s))" % (objectclass, attrs) return filter - basedn = 'cn=clients,cn=radius,cn=services,cn=etc,%s' % self.basedn # FIXME, should not be hardcoded - filter = gen_filter('radiusClientProfile', 'radiusClientNASIpAddress', ip_attrs) + basedn = radius_util.radius_clients_basedn(container, self.basedn) + filter = gen_filter('radiusClientProfile', 'radiusClientIPAddress', ip_attrs) conn = self.getConnection(opts) try: try: @@ -546,6 +546,111 @@ class IPAServer: return radius_clients + # profiles + def get_radius_profile_by_uid(self, uid, user_profile=True, sattrs=None, opts=None): + if user_profile: + container = DefaultUserContainer + else: + container = radius_util.profiles_container + + uid = self.__safe_filter(uid) + filter = radius_util.radius_profile_filter(uid) + basedn = radius_util.radius_profiles_basedn(container, self.basedn) + return self.__get_sub_entry(basedn, filter, sattrs, opts) + + def __radius_profile_exists(self, uid, user_profile, opts): + if user_profile: + container = DefaultUserContainer + else: + container = radius_util.profiles_container + + uid = self.__safe_filter(uid) + filter = radius_util.radius_profile_filter(uid) + basedn = radius_util.radius_profiles_basedn(container, self.basedn) + + try: + entry = self.__get_sub_entry(basedn, filter, ['dn','uid'], opts) + return True + except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): + return False + + def add_radius_profile (self, uid, user_profile=True, opts=None): + if self.__radius_profile_exists(profile['uid'], user_profile, opts): + raise ipaerror.gen_exception(ipaerror.LDAP_DUPLICATE) + + if user_profile: + container = DefaultUserContainer + else: + container = radius_util.profiles_container + + dn = radius_util.radius_profile_dn(uid, container, self.basedn) + entry = ipaserver.ipaldap.Entry(dn) + + # some required objectclasses + entry.setValues('objectClass', 'top', 'radiusClientProfile') + + # fill in our new entry with everything sent by the profile + for attr in profile: + entry.setValues(attr, profile[attr]) + + conn = self.getConnection(opts) + try: + res = conn.addEntry(entry) + finally: + self.releaseConnection(conn) + return res + + def update_radius_profile(self, oldentry, newentry, opts=None): + return self.update_entry(oldentry, newentry, opts) + + def delete_radius_profile(self, uid, user_profile, opts=None): + profile = self.get_radius_profile_by_uid(uid, user_profile, ['dn', 'cn'], opts) + if profile is None: + raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND) + + conn = self.getConnection(opts) + try: + res = conn.deleteEntry(profile['dn']) + finally: + self.releaseConnection(conn) + return res + + def find_radius_profiles(self, uids, user_profile=True, sattrs=None, searchlimit=0, timelimit=-1, opts=None): + def gen_filter(objectclass, attr, values): + '''Given ('myclass', 'myattr', [v1, v2]) returns + (&(objectclass=myclass)(|(myattr=v1)(myattr=v2))) + ''' + # Don't use __safe_filter, prevents wildcarding + #attrs = ''.join(['(%s=%s)' % (attr, self.__safe_filter(val)) for val in values]) + attrs = ''.join(['(%s=%s)' % (attr, val) for val in values]) + filter = "(&(objectclass=%s)(|%s))" % (objectclass, attrs) + return filter + + if user_profile: + container = DefaultUserContainer + else: + container = radius_util.profiles_container + + uid = self.__safe_filter(uid) + filter = gen_filter('radiusClientProfile' 'uid', uids) + basedn="%s,%s" % (container, self.basedn) + conn = self.getConnection(opts) + try: + try: + results = conn.getListAsync(basedn, self.scope, filter, sattrs, 0, None, None, timelimit, searchlimit) + except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): + results = [0] + finally: + self.releaseConnection(conn) + + counter = results[0] + results = results[1:] + radius_profiles = [counter] + for radius_profile in results: + radius_profiles.append(self.convert_entry(radius_profile)) + + return radius_profiles + def get_add_schema (self): """Get the list of fields to be used when adding users in the GUI.""" diff --git a/ipa-server/xmlrpc-server/ipaxmlrpc.py b/ipa-server/xmlrpc-server/ipaxmlrpc.py index d5bdb6b2..ef48f4aa 100644 --- a/ipa-server/xmlrpc-server/ipaxmlrpc.py +++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py @@ -356,6 +356,11 @@ def handler(req, profiling=False): h.register_function(f.update_radius_client) h.register_function(f.delete_radius_client) h.register_function(f.find_radius_clients) + h.register_function(f.get_radius_profile_by_uid) + h.register_function(f.add_radius_profile) + h.register_function(f.update_radius_profile) + h.register_function(f.delete_radius_profile) + h.register_function(f.find_radius_profiles) h.handle_request(req) finally: pass |