From 8cfd270f3441094390d16df9c0d59b0c7ce42284 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Sat, 3 Nov 2007 12:22:20 -0400 Subject: merge initial radius work --- ipa-python/ipautil.py | 37 ++ ipa-server/freeipa-server.spec | 3 +- ipa-server/freeipa-server.spec.in | 3 +- ipa-server/ipa-install/ipa-server-install | 6 + ipa-server/ipa-install/share/60radius.ldif | 523 +++++++++++++++++++++ ipa-server/ipa-install/share/Makefile.am | 42 +- .../ipa-install/share/radius.radiusd.conf.template | 280 +++++++++++ ipa-server/ipaserver/Makefile.am | 1 + ipa-server/ipaserver/dsinstance.py | 2 + ipa-server/ipaserver/radiusinstance.py | 168 +++++++ 10 files changed, 1043 insertions(+), 22 deletions(-) create mode 100644 ipa-server/ipa-install/share/60radius.ldif create mode 100644 ipa-server/ipa-install/share/radius.radiusd.conf.template create mode 100644 ipa-server/ipaserver/radiusinstance.py diff --git a/ipa-python/ipautil.py b/ipa-python/ipautil.py index 1979ceb45..96a74d757 100644 --- a/ipa-python/ipautil.py +++ b/ipa-python/ipautil.py @@ -30,6 +30,7 @@ from string import lower import re import xmlrpclib import datetime +import rpm def realm_to_suffix(realm_name): s = realm_name.split(".") @@ -330,3 +331,39 @@ def parse_generalized_time(timestr): except ValueError: return None + +#------------------------------------------------------------------------------- + +def get_rpm_nvr_from_header(hdr): + 'Given an RPM header return the package NVR as a string' + name = hdr['name'] + version = hdr['version'] + release = hdr['release'] + + return '%s-%s-%s' % (name, version, release) + +def get_rpm_nvr_by_name(name): + if name is None: + return None + + nvr = None + try: + ts = rpm.ts() + mi = ts.dbMatch(rpm.RPMTAG_NAME, name) + for h in mi: + nvr = get_rpm_nvr_from_header(h) + break + except: + logging.exception('failed to retrieve rpm info for %s', name) + return nvr + +def split_rpm_nvr(nvr): + components = nvr.split('-') + release = components[-1] + version = components[-2] + name = '-'.join(components[:-2]) + return (name, version, release) + + + + diff --git a/ipa-server/freeipa-server.spec b/ipa-server/freeipa-server.spec index 0981b26e0..7606acf03 100755 --- a/ipa-server/freeipa-server.spec +++ b/ipa-server/freeipa-server.spec @@ -11,8 +11,9 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: fedora-ds-base-devel openldap-devel krb5-devel nss-devel mozldap-devel openssl-devel -Requires: python fedora-ds-base krb5-server krb5-server-ldap nss-tools openldap-clients httpd mod_python mod_auth_kerb python-ldap freeipa-python ntp cyrus-sasl-gssapi nss TurboGears python-krbV acl freeipa-admintools +Requires: python fedora-ds-base krb5-server krb5-server-ldap nss-tools openldap-clients httpd mod_python mod_auth_kerb python-ldap freeipa-python ntp cyrus-sasl-gssapi nss TurboGears python-krbV acl freeipa-admintools rpm Requires: mod_nss >= 1.0.7-2 +Requires: freeradius >= 1.1.7 %define httpd_conf /etc/httpd/conf.d %define plugin_dir %{_libdir}/dirsrv/plugins diff --git a/ipa-server/freeipa-server.spec.in b/ipa-server/freeipa-server.spec.in index e25f48367..d40aaf32a 100644 --- a/ipa-server/freeipa-server.spec.in +++ b/ipa-server/freeipa-server.spec.in @@ -11,8 +11,9 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: fedora-ds-base-devel openldap-devel krb5-devel nss-devel mozldap-devel openssl-devel -Requires: python fedora-ds-base krb5-server krb5-server-ldap nss-tools openldap-clients httpd mod_python mod_auth_kerb python-ldap freeipa-python ntp cyrus-sasl-gssapi nss TurboGears python-krbV acl freeipa-admintools +Requires: python fedora-ds-base krb5-server krb5-server-ldap nss-tools openldap-clients httpd mod_python mod_auth_kerb python-ldap freeipa-python ntp cyrus-sasl-gssapi nss TurboGears python-krbV acl freeipa-admintools rpm Requires: mod_nss >= 1.0.7-2 +Requires: freeradius >= 1.1.7 %define httpd_conf /etc/httpd/conf.d %define plugin_dir %{_libdir}/dirsrv/plugins diff --git a/ipa-server/ipa-install/ipa-server-install b/ipa-server/ipa-install/ipa-server-install index 06297d492..107c0d368 100644 --- a/ipa-server/ipa-install/ipa-server-install +++ b/ipa-server/ipa-install/ipa-server-install @@ -47,6 +47,7 @@ import ipaserver.krbinstance import ipaserver.bindinstance import ipaserver.httpinstance import ipaserver.ntpinstance +import ipaserver.radiusinstance from ipa.ipautil import run @@ -526,6 +527,11 @@ def main(): http = ipaserver.httpinstance.HTTPInstance() http.create_instance() + # Create a radius instance + radius = ipaserver.radiusinstance.RadiusInstance() + # FIXME: ldap_server should be derived, not hardcoded to localhost, also should it be a URL? + radius.create_instance(realm_name, host_name, 'localhost') + bind.setup(host_name, ip_address, realm_name) if options.setup_bind: skipbind = False diff --git a/ipa-server/ipa-install/share/60radius.ldif b/ipa-server/ipa-install/share/60radius.ldif new file mode 100644 index 000000000..1802029ea --- /dev/null +++ b/ipa-server/ipa-install/share/60radius.ldif @@ -0,0 +1,523 @@ +# This is a LDAPv3 schema for RADIUS attributes. +# Tested on OpenLDAP 2.0.7 +# Posted by Javier Fernandez-Sanguino Pena +# LDAP v3 version by Jochen Friedrich +# Updates by Adrian Pavlykevych +# Modified by John Dennis for use with Directory Sever/IPA +############## +dn: cn=schema +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.1 + NAME 'radiusArapFeatures' + 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.2 + NAME 'radiusArapSecurity' + 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.3 + NAME 'radiusArapZoneAccess' + 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.44 + NAME 'radiusAuthType' + 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.4 + NAME 'radiusCallbackId' + 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.5 + NAME 'radiusCallbackNumber' + 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.6 + NAME 'radiusCalledStationId' + 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.7 + NAME 'radiusCallingStationId' + 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.8 + NAME 'radiusClass' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.45 + NAME 'radiusClientIPAddress' + 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.9 + NAME 'radiusFilterId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.10 + NAME 'radiusFramedAppleTalkLink' + 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.11 + NAME 'radiusFramedAppleTalkNetwork' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.12 + NAME 'radiusFramedAppleTalkZone' + 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.13 + NAME 'radiusFramedCompression' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.14 + NAME 'radiusFramedIPAddress' + 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.15 + NAME 'radiusFramedIPNetmask' + 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.16 + NAME 'radiusFramedIPXNetwork' + 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.17 + NAME 'radiusFramedMTU' + 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.18 + NAME 'radiusFramedProtocol' + 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.19 + NAME 'radiusFramedRoute' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.20 + NAME 'radiusFramedRouting' + 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.46 + NAME 'radiusGroupName' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.47 + NAME 'radiusHint' + 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.48 + NAME 'radiusHuntgroupName' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.21 + NAME 'radiusIdleTimeout' + 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.22 + NAME 'radiusLoginIPHost' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.23 + NAME 'radiusLoginLATGroup' + 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.24 + NAME 'radiusLoginLATNode' + 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.25 + NAME 'radiusLoginLATPort' + 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.26 + NAME 'radiusLoginLATService' + 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.27 + NAME 'radiusLoginService' + 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.28 + NAME 'radiusLoginTCPPort' + 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.29 + NAME 'radiusPasswordRetry' + 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.30 + NAME 'radiusPortLimit' + 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.49 + NAME 'radiusProfileDn' + DESC '' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.31 + NAME 'radiusPrompt' + 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.50 + NAME 'radiusProxyToRealm' + 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.51 + NAME 'radiusReplicateToRealm' + 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.52 + NAME 'radiusRealm' + 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.32 + NAME 'radiusServiceType' + 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.33 + NAME 'radiusSessionTimeout' + 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.34 + NAME 'radiusTerminationAction' + 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.35 + NAME 'radiusTunnelAssignmentId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.36 + NAME 'radiusTunnelMediumType' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.37 + NAME 'radiusTunnelPassword' + 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.38 + NAME 'radiusTunnelPreference' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.39 + NAME 'radiusTunnelPrivateGroupId' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.40 + NAME 'radiusTunnelServerEndpoint' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.41 + NAME 'radiusTunnelType' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.42 + NAME 'radiusVSA' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.43 + NAME 'radiusTunnelClientEndpoint' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +#need to change asn1.id +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.53 + NAME 'radiusSimultaneousUse' + DESC '' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.54 + NAME 'radiusLoginTime' + 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.55 + NAME 'radiusUserCategory' + 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.56 + NAME 'radiusStripUserName' + DESC '' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.57 + NAME 'dialupAccess' + 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.58 + NAME 'radiusExpiration' + 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.59 + NAME 'radiusCheckItem' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.60 + NAME 'radiusReplyItem' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +attributeTypes: + ( 1.3.6.1.4.1.3317.4.3.1.61 + NAME 'radiusNASIpAddress' + 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.62 + NAME 'radiusReplyMessage' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +objectClasses: + ( 1.3.6.1.4.1.3317.4.3.2.1 + NAME 'radiusprofile' + SUP top AUXILIARY + DESC '' + MUST cn + MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ + radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ + radiusCalledStationId $ radiusCallingStationId $ radiusClass $ + radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ + radiusFramedAppleTalkNetwork $ radiusFramedAppleTalkZone $ + radiusFramedCompression $ radiusFramedIPAddress $ + radiusFramedIPNetmask $ radiusFramedIPXNetwork $ + radiusFramedMTU $ radiusFramedProtocol $ + radiusCheckItem $ radiusReplyItem $ + radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ + radiusGroupName $ radiusHint $ radiusHuntgroupName $ + radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ + radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $ + radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ + radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ + radiusRealm $ radiusReplicateToRealm $ radiusServiceType $ + radiusSessionTimeout $ radiusStripUserName $ + radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDn $ + radiusSimultaneousUse $ radiusTunnelAssignmentId $ + radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $ + radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ + radiusTunnelType $ radiusUserCategory $ radiusVSA $ + radiusExpiration $ dialupAccess $ radiusNASIpAddress $ + radiusReplyMessage ) + ) +objectClasses: + ( 1.3.6.1.4.1.3317.4.3.2.2 + NAME 'radiusObjectProfile' + SUP top STRUCTURAL + DESC 'A Container Objectclass to be used for creating radius profile object' + MUST cn + MAY ( uid $ userPassword $ description ) + ) diff --git a/ipa-server/ipa-install/share/Makefile.am b/ipa-server/ipa-install/share/Makefile.am index 50d81c3ad..cdccb5893 100644 --- a/ipa-server/ipa-install/share/Makefile.am +++ b/ipa-server/ipa-install/share/Makefile.am @@ -1,28 +1,30 @@ NULL = appdir = $(IPA_DATA_DIR) -app_DATA = \ - 60kerberos.ldif \ - 60samba.ldif \ - bootstrap-template.ldif \ - default-aci.ldif \ - kerberos.ldif \ - indeces.ldif \ - bind.named.conf.template\ - bind.zone.db.template \ - certmap.conf.template \ - kdc.conf.template \ - krb5.conf.template \ - krb5.ini.template \ - krb.con.template \ - krbrealm.con.template \ - ntp.conf.server.template \ +app_DATA = \ + 60kerberos.ldif \ + 60samba.ldif \ + 60radius.ldif \ + bootstrap-template.ldif \ + default-aci.ldif \ + kerberos.ldif \ + indeces.ldif \ + bind.named.conf.template \ + bind.zone.db.template \ + certmap.conf.template \ + kdc.conf.template \ + krb5.conf.template \ + krb5.ini.template \ + krb.con.template \ + krbrealm.con.template \ + ntp.conf.server.template \ + radius.radiusd.conf.template \ $(NULL) -EXTRA_DIST = \ - $(app_DATA) \ +EXTRA_DIST = \ + $(app_DATA) \ $(NULL) -MAINTAINERCLEANFILES = \ - *~ \ +MAINTAINERCLEANFILES = \ + *~ \ Makefile.in diff --git a/ipa-server/ipa-install/share/radius.radiusd.conf.template b/ipa-server/ipa-install/share/radius.radiusd.conf.template new file mode 100644 index 000000000..d03105485 --- /dev/null +++ b/ipa-server/ipa-install/share/radius.radiusd.conf.template @@ -0,0 +1,280 @@ +# +# WARNING: This file is automatically generated, do not edit +# +# $CONFIG_FILE_VERSION_INFO +# +prefix = /usr +exec_prefix = /usr +sysconfdir = /etc +localstatedir = /var +sbindir = /usr/sbin +logdir = $${localstatedir}/log/radius +raddbdir = $${sysconfdir}/raddb +radacctdir = $${logdir}/radacct +confdir = $${raddbdir} +run_dir = $${localstatedir}/run/radiusd +db_dir = $${localstatedir}/lib/radiusd +log_file = $${logdir}/radius.log +libdir = /usr/lib +pidfile = $${run_dir}/radiusd.pid +user = radiusd +group = radiusd +max_request_time = 30 +delete_blocked_requests = no +cleanup_delay = 5 +max_requests = 1024 +bind_address = * +port = 0 +hostname_lookups = no +allow_core_dumps = no +regular_expressions = yes +extended_expressions = yes +log_stripped_names = no +log_auth = no +log_auth_badpass = no +log_auth_goodpass = no +usercollide = no +lower_user = no +lower_pass = no +nospace_user = no +nospace_pass = no +checkrad = $${sbindir}/checkrad +security { + max_attributes = 200 + reject_delay = 1 + status_server = no +} +proxy_requests = yes +$$INCLUDE $${confdir}/proxy.conf +$$INCLUDE $${confdir}/clients.conf +snmp = no +$$INCLUDE $${confdir}/snmp.conf +thread pool { + start_servers = 5 + max_servers = 32 + min_spare_servers = 3 + max_spare_servers = 10 + max_requests_per_server = 0 +} +modules { + pap { + auto_header = yes + } + chap { + authtype = CHAP + } + pam { + pam_auth = radiusd + } + unix { + cache = no + cache_reload = 600 + shadow = /etc/shadow + radwtmp = $${logdir}/radwtmp + } +$$INCLUDE $${confdir}/eap.conf + mschap { + } + ldap { + server = "$LDAP_SERVER" + use_sasl = yes + sasl_mech = "GSSAPI" + krb_keytab = "$RADIUS_KEYTAB" + krb_principal = "$RADIUS_PRINCIPAL" + basedn = "$RADIUS_USER_BASE_DN" + filter = "(uid=%{Stripped-User-Name:-%{User-Name}})" + base_filter = "(objectclass=radiusprofile)" + start_tls = no + access_attr = "$ACCESS_ATTRIBUTE" + dictionary_mapping = $${raddbdir}/ldap.attrmap + ldap_connections_number = 5 + edir_account_policy_check=no + timeout = 4 + timelimit = 3 + net_timeout = 1 + } + realm IPASS { + format = prefix + delimiter = "/" + ignore_default = no + ignore_null = no + } + realm suffix { + format = suffix + delimiter = "@" + ignore_default = no + ignore_null = no + } + realm realmpercent { + format = suffix + delimiter = "%" + ignore_default = no + ignore_null = no + } + realm ntdomain { + format = prefix + delimiter = "\\" + ignore_default = no + ignore_null = no + } + checkval { + item-name = Calling-Station-Id + check-name = Calling-Station-Id + data-type = string + } + preprocess { + huntgroups = $${confdir}/huntgroups + hints = $${confdir}/hints + with_ascend_hack = no + ascend_channels_per_line = 23 + with_ntdomain_hack = no + with_specialix_jetstream_hack = no + with_cisco_vsa_hack = no + } + files { + usersfile = $${confdir}/users + acctusersfile = $${confdir}/acct_users + preproxy_usersfile = $${confdir}/preproxy_users + compat = no + } + detail { + detailfile = $${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d + detailperm = 0600 + } + acct_unique { + key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port" + } + radutmp { + filename = $${logdir}/radutmp + username = %{User-Name} + case_sensitive = yes + check_with_nas = yes + perm = 0600 + callerid = "yes" + } + radutmp sradutmp { + filename = $${logdir}/sradutmp + perm = 0644 + callerid = "no" + } + attr_filter { + attrsfile = $${confdir}/attrs + } + counter daily { + filename = $${db_dir}/db.daily + key = User-Name + count-attribute = Acct-Session-Time + reset = daily + counter-name = Daily-Session-Time + check-name = Max-Daily-Session + allowed-servicetype = Framed-User + cache-size = 5000 + } + sqlcounter dailycounter { + counter-name = Daily-Session-Time + check-name = Max-Daily-Session + reply-name = Session-Timeout + sqlmod-inst = sql + key = User-Name + reset = daily + query = "SELECT SUM(AcctSessionTime - \ + GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) \ + FROM radacct WHERE UserName='%{%k}' AND \ + UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'" + } + sqlcounter monthlycounter { + counter-name = Monthly-Session-Time + check-name = Max-Monthly-Session + reply-name = Session-Timeout + sqlmod-inst = sql + key = User-Name + reset = monthly + query = "SELECT SUM(AcctSessionTime - \ + GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) \ + FROM radacct WHERE UserName='%{%k}' AND \ + UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'" + } + always fail { + rcode = fail + } + always reject { + rcode = reject + } + always ok { + rcode = ok + simulcount = 0 + mpp = no + } + expr { + } + digest { + } + exec { + wait = yes + input_pairs = request + } + exec echo { + wait = yes + program = "/bin/echo %{User-Name}" + input_pairs = request + output_pairs = reply + } + ippool main_pool { + range-start = 192.168.1.1 + range-stop = 192.168.3.254 + netmask = 255.255.255.0 + cache-size = 800 + session-db = $${db_dir}/db.ippool + ip-index = $${db_dir}/db.ipindex + override = no + maximum-timeout = 0 + } +} +instantiate { + exec + expr +} +authorize { + preprocess + chap + mschap + suffix + eap + #files + ldap + pap +} +authenticate { + Auth-Type PAP { + pap + } + Auth-Type CHAP { + chap + } + Auth-Type MS-CHAP { + mschap + } + unix + eap +} +preacct { + preprocess + acct_unique + suffix + files +} +accounting { + detail + unix + radutmp +} +session { + radutmp +} +post-auth { +} +pre-proxy { +} +post-proxy { + eap +} diff --git a/ipa-server/ipaserver/Makefile.am b/ipa-server/ipaserver/Makefile.am index b4469b20b..7c765f917 100644 --- a/ipa-server/ipaserver/Makefile.am +++ b/ipa-server/ipaserver/Makefile.am @@ -9,6 +9,7 @@ app_PYTHON = \ krbinstance.py \ httpinstance.py \ ntpinstance.py \ + radiusinstance.py \ $(NULL) EXTRA_DIST = \ diff --git a/ipa-server/ipaserver/dsinstance.py b/ipa-server/ipaserver/dsinstance.py index df71fe3fd..6bcbb6f15 100644 --- a/ipa-server/ipaserver/dsinstance.py +++ b/ipa-server/ipaserver/dsinstance.py @@ -159,6 +159,8 @@ class DsInstance: self.schema_dirname() + "60kerberos.ldif") shutil.copyfile(SHARE_DIR + "60samba.ldif", self.schema_dirname() + "60samba.ldif") + shutil.copyfile(SHARE_DIR + "60radius.ldif", + self.schema_dirname() + "60radius.ldif") def __add_memberof_module(self): memberof_txt = template_file(SHARE_DIR + "memberof-conf.ldif", self.sub_dict) diff --git a/ipa-server/ipaserver/radiusinstance.py b/ipa-server/ipaserver/radiusinstance.py new file mode 100644 index 000000000..8c7a929d0 --- /dev/null +++ b/ipa-server/ipaserver/radiusinstance.py @@ -0,0 +1,168 @@ +#! /usr/bin/python -E +# Authors: John Dennis +# +# 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 or later +# +# 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 subprocess +import string +import tempfile +import shutil +import logging +import pwd +import time +from ipa.ipautil import * + +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') + +# FIXME there should a utility to get the user base dn +from ipaserver.funcs import DefaultUserContainer, DefaultGroupContainer + +#------------------------------------------------------------------------------- + +class RadiusInstance: + def __init__(self): + self.fqdn = None + self.realm = None + self.principal = None + + def create_instance(self, realm_name, host_name, ldap_server): + self.realm = realm_name.upper() + self.fqdn = host_name + self.ldap_server = ldap_server + self.principal = "%s/%s@%s" % (RADIUS_SERVICE_NAME, self.fqdn, self.realm) + self.basedn = realm_to_suffix(self.realm) + self.user_basedn = "%s,%s" % (DefaultUserContainer, self.basedn) # FIXME, should be utility to get this + self.rpm_nvr = get_rpm_nvr_by_name(PKG_NAME) + if self.rpm_nvr is not None: + self.rpm_name, self.rpm_version, self.rpm_release = split_rpm_nvr(self.rpm_nvr) + else: + self.rpm_name = self.rpm_version = self.rpm_release = None + + try: + self.stop() + except: + # It could have been not running + pass + + self.__create_radius_keytab() + self.__radiusd_conf() + + try: + self.start() + except: + logging.error("radiusd service failed to start") + + + def stop(self): + run(['/sbin/service', 'radiusd', 'stop']) + + def start(self): + run(['/sbin/service', 'radiusd', 'start']) + + def restart(self): + run(['/sbin/service', 'radiusd', 'restart']) + + def __radiusd_conf(self): + logging.debug('configuring radiusd.conf for radius instance') + + version = 'IPA_RADIUS_VERSION=%s RADIUS_PACKAGE_VERSION=%s' % (IPA_RADIUS_VERSION, self.rpm_nvr) + sub_dict = {'CONFIG_FILE_VERSION_INFO' : version, + 'LDAP_SERVER' : self.ldap_server, + 'RADIUS_KEYTAB' : IPA_KEYTAB_FILEPATH, + 'RADIUS_PRINCIPAL' : self.principal, + 'RADIUS_USER_BASE_DN' : self.user_basedn, + 'ACCESS_ATTRIBUTE' : 'dialupAccess' + } + try: + radiusd_conf = template_file(RADIUSD_CONF_TEMPLATE_FILEPATH, sub_dict) + radiusd_fd = open(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) + + def __create_radius_keytab(self): + try: + if file_exists(IPA_KEYTAB_FILEPATH): + os.remove(IPA_KEYTAB_FILEPATH) + except os.error: + logging.error("Failed to remove %s", 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.flush() + kwrite.close() + kread.close() + kerr.close() + + # give kadmin time to actually write the file before we go on + retry = 0 + while not file_exists(IPA_KEYTAB_FILEPATH): + time.sleep(1) + retry += 1 + if retry > 15: + print "Error timed out waiting for kadmin to finish operations\n" + os.exit() + + try: + pent = pwd.getpwnam(RADIUS_USER) + os.chown(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) + +#------------------------------------------------------------------------------- + +# 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) + -- cgit