From 80c4ed7af26b5b6a581ccc8e0a9e65e53e43cc4c Mon Sep 17 00:00:00 2001 From: John Dennis Date: Tue, 6 Nov 2007 16:26:10 -0500 Subject: remove offensive use of rpm add the radiusprofile to the list of objectclasses used when creating a user --- ipa-server/freeipa-server.spec | 2 +- ipa-server/ipaserver/radiusinstance.py | 30 +++++++++++++++++++++++------- ipa-server/xmlrpc-server/funcs.py | 2 +- 3 files changed, 25 insertions(+), 9 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/freeipa-server.spec b/ipa-server/freeipa-server.spec index 7606acf0..918e17c3 100755 --- a/ipa-server/freeipa-server.spec +++ b/ipa-server/freeipa-server.spec @@ -11,7 +11,7 @@ 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 rpm +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: mod_nss >= 1.0.7-2 Requires: freeradius >= 1.1.7 diff --git a/ipa-server/ipaserver/radiusinstance.py b/ipa-server/ipaserver/radiusinstance.py index 27e7527e..2aee09b3 100644 --- a/ipa-server/ipaserver/radiusinstance.py +++ b/ipa-server/ipaserver/radiusinstance.py @@ -44,9 +44,30 @@ 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 +#------------------------------------------------------------------------------- + +def get_radius_version(): + version = None + try: + p = subprocess.Popen([RADIUSD, '-v'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + status = p.returncode + + if status == 0: + match = re.search("radiusd: FreeRADIUS Version (.+), for host", stdout) + if match: + version = match.group(1) + except Exception, e: + pass + return version + + #------------------------------------------------------------------------------- class RadiusInstance(service.Service): @@ -63,12 +84,7 @@ class RadiusInstance(service.Service): 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 - + self.radius_version = get_radius_version() self.start_creation(4, "Configuring radiusd") try: @@ -93,7 +109,7 @@ class RadiusInstance(service.Service): def __radiusd_conf(self): self.step('configuring radiusd.conf for radius instance') - version = 'IPA_RADIUS_VERSION=%s RADIUS_PACKAGE_VERSION=%s' % (IPA_RADIUS_VERSION, self.rpm_nvr) + 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, diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index 17a578c2..6fdaaca5 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -443,7 +443,7 @@ class IPAServer: # some required objectclasses entry.setValues('objectClass', 'top', 'person', 'organizationalPerson', - 'inetOrgPerson', 'inetUser', 'posixAccount', 'krbPrincipalAux') + 'inetOrgPerson', 'inetUser', 'posixAccount', 'krbPrincipalAux', 'radiusprofile') # fill in our new entry with everything sent by the user for u in user: -- cgit From 84275328a0f5ff1ac0ddad65da18b7636312c0c1 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Sat, 10 Nov 2007 00:09:07 -0500 Subject: radius now does kerberos auth, reads client entries from LDAP --- ipa-server/ipa-install/share/60radius.ldif | 46 ++++++++++++++++++++++ .../ipa-install/share/bootstrap-template.ldif | 18 +++++++++ .../ipa-install/share/radius.radiusd.conf.template | 21 +++++----- ipa-server/ipaserver/radiusinstance.py | 7 +++- 4 files changed, 81 insertions(+), 11 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/ipa-install/share/60radius.ldif b/ipa-server/ipa-install/share/60radius.ldif index 1802029e..ac9e3bef 100644 --- a/ipa-server/ipa-install/share/60radius.ldif +++ b/ipa-server/ipa-install/share/60radius.ldif @@ -4,6 +4,11 @@ # LDAP v3 version by Jochen Friedrich # Updates by Adrian Pavlykevych # Modified by John Dennis for use with Directory Sever/IPA +# +# Note: These OID's do not seem to be registered, the closest I could find +# was 1.3.6.1.4.1.3317 +# {iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) gnome(3317)} +# ############## dn: cn=schema attributeTypes: @@ -521,3 +526,44 @@ objectClasses: MUST cn 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 '' + 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.65 + NAME 'radiusClientNASType' + 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.66 + NAME 'radiusClientShortName' + DESC '' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + ) +# c->ipaddr = radiusNASIpAddress +# c->secret = radiusSecret +objectClasses: + ( 1.3.6.1.4.1.3317.4.3.2.3 + NAME 'radiusClientProfile' + SUP top STRUCTURAL + DESC 'A Container Objectclass to be used for describing radius clients' + MUST (radiusClientNASIpAddress $ radiusClientSecret) + MAY ( radiusClientNASType $ radiusClientShortName $ nsEncryptionAlgorithm $ description ) + ) diff --git a/ipa-server/ipa-install/share/bootstrap-template.ldif b/ipa-server/ipa-install/share/bootstrap-template.ldif index d793dd9e..35d60a32 100644 --- a/ipa-server/ipa-install/share/bootstrap-template.ldif +++ b/ipa-server/ipa-install/share/bootstrap-template.ldif @@ -56,6 +56,24 @@ homeDirectory: /home/admin loginShell: /bin/bash gecos: Administrator +dn: cn=services,cn=etc,$SUFFIX +changetype: add +objectClass: nsContainer +objectClass: top +cn: services + +dn: cn=radius,cn=services,cn=etc,$SUFFIX +changetype: add +objectClass: nsContainer +objectClass: top +cn: radius + +dn: cn=clients,cn=radius,cn=services,cn=etc,$SUFFIX +changetype: add +objectClass: nsContainer +objectClass: top +cn: clients + dn: cn=admins,cn=groups,cn=accounts,$SUFFIX changetype: add objectClass: top diff --git a/ipa-server/ipa-install/share/radius.radiusd.conf.template b/ipa-server/ipa-install/share/radius.radiusd.conf.template index d0310548..73d101c7 100644 --- a/ipa-server/ipa-install/share/radius.radiusd.conf.template +++ b/ipa-server/ipa-install/share/radius.radiusd.conf.template @@ -57,9 +57,6 @@ thread pool { max_requests_per_server = 0 } modules { - pap { - auto_header = yes - } chap { authtype = CHAP } @@ -85,13 +82,17 @@ $$INCLUDE $${confdir}/eap.conf filter = "(uid=%{Stripped-User-Name:-%{User-Name}})" base_filter = "(objectclass=radiusprofile)" start_tls = no - access_attr = "$ACCESS_ATTRIBUTE" + # FIXME: we'll want to toggle the access_attr feature on/off, + # but it needs a control, so disable it for now. + #access_attr = "$ACCESS_ATTRIBUTE" + #access_attr_used_for_allow = "$ACCESS_ATTRIBUTE_DEFAULT" dictionary_mapping = $${raddbdir}/ldap.attrmap ldap_connections_number = 5 edir_account_policy_check=no timeout = 4 timelimit = 3 net_timeout = 1 + clients_basedn = "$CLIENTS_BASEDN" } realm IPASS { format = prefix @@ -229,6 +230,10 @@ $$INCLUDE $${confdir}/eap.conf override = no maximum-timeout = 0 } + krb5 { + keytab = "$RADIUS_KEYTAB" + service_principal = "$RADIUS_PRINCIPAL" + } } instantiate { exec @@ -242,20 +247,18 @@ authorize { eap #files ldap - pap } authenticate { - Auth-Type PAP { - pap - } Auth-Type CHAP { chap } Auth-Type MS-CHAP { mschap } - unix eap + Auth-Type Kerberos { + krb5 + } } preacct { preprocess diff --git a/ipa-server/ipaserver/radiusinstance.py b/ipa-server/ipaserver/radiusinstance.py index 2aee09b3..90727758 100644 --- a/ipa-server/ipaserver/radiusinstance.py +++ b/ipa-server/ipaserver/radiusinstance.py @@ -79,10 +79,11 @@ class RadiusInstance(service.Service): def create_instance(self, realm_name, host_name, ldap_server): self.realm = realm_name.upper() + 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.basedn = realm_to_suffix(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() self.start_creation(4, "Configuring radiusd") @@ -115,7 +116,9 @@ class RadiusInstance(service.Service): 'RADIUS_KEYTAB' : IPA_KEYTAB_FILEPATH, 'RADIUS_PRINCIPAL' : self.principal, 'RADIUS_USER_BASE_DN' : self.user_basedn, - 'ACCESS_ATTRIBUTE' : 'dialupAccess' + 'ACCESS_ATTRIBUTE' : '', + 'ACCESS_ATTRIBUTE_DEFAULT' : 'TRUE', + 'CLIENTS_BASEDN' : 'cn=clients,cn=radius,cn=services,cn=etc,%s' % self.suffix } try: radiusd_conf = template_file(RADIUSD_CONF_TEMPLATE_FILEPATH, sub_dict) -- cgit From f36872383c51da0453d5387e0e1180ba47e19649 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Sat, 10 Nov 2007 12:04:43 -0500 Subject: add aci's for radius --- ipa-server/ipa-install/share/default-aci.ldif | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ipa-server') diff --git a/ipa-server/ipa-install/share/default-aci.ldif b/ipa-server/ipa-install/share/default-aci.ldif index 3eee2ae3..5d19329e 100644 --- a/ipa-server/ipa-install/share/default-aci.ldif +++ b/ipa-server/ipa-install/share/default-aci.ldif @@ -7,5 +7,6 @@ aci: (targetattr=*)(version 3.0; acl "Admin can manage any entry"; allow (all) u aci: (targetattr="krbPrincipalName || krbUPEnabled || krbPrincipalKey || krbTicketPolicyReference || krbPrincipalExpiration || krbPasswordExpiration || krbPwdPolicyReference || krbPrincipalType || krbPwdHistory || krbLastPwdChange || krbPrincipalAliases || krbExtraData")(version 3.0; acl "KDC System Account"; allow (read, search, compare) userdn="ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";) aci: (targetattr="krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount")(version 3.0; acl "KDC System Account"; allow (read, search, compare, write) userdn="ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";) aci: (targetattr="userPassword || krbPrincipalKey ||sambaLMPassword || sambaNTPassword || krbPasswordExpiration || krbPwdHistory || krbLastPwdChange")(version 3.0; acl "Kpasswd access to passowrd hashes for passowrd changes"; allow (read, write) userdn="ldap:///krbprincipalname=kadmin/changepw@$REALM,cn=$REALM,cn=kerberos,$SUFFIX";) -aci: (targetfilter="(|(objectClass=person)(objectClass=krbPrincipalAux)(objectClass=posixAccount)(objectClass=groupOfUniqueNames)(objectClass=posixGroup))")(targetattr="*")(version 3.0; acl "Account Admins can manage Users and Groups"; allow (add,delete,read,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";) +aci: (targetfilter="(|(objectClass=person)(objectClass=krbPrincipalAux)(objectClass=posixAccount)(objectClass=groupOfUniqueNames)(objectClass=posixGroup)(objectClass=radiusprofile))")(targetattr="*")(version 3.0; acl "Account Admins can manage Users and Groups"; allow (add,delete,read,write) groupdn="ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";) aci: (targetattr = "givenName || sn || cn || displayName || initials || loginShell || homePhone || mobile || pager || facsimileTelephoneNumber || telephoneNumber || street || roomNumber || l || st || postalCode || manager || description || carLicense || labeledURI || inetUserHTTPURL || seeAlso || userPassword")(version 3.0;acl "Self service";allow (write) userdn="ldap:///self";) +aci: (target="ldap:///cn=radius,cn=services,cn=etc,$SUFFIX")(version 3.0; acl "Only radius and admin can access radius service data"; deny (all) userdn!="ldap:///uid=admin,cn=sysaccounts,cn=etc,$SUFFIX || ldap:///krbprincipalname=radius/$FQDN@$REALM,cn=$REALM,cn=kerberos,$SUFFIX";) -- cgit From eab5a89d4a3e8159348b5a709cd4401c9784f058 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Tue, 13 Nov 2007 20:05:02 -0500 Subject: ipa-addradiusclient now working --- .../ipa-install/share/bootstrap-template.ldif | 4 ++-- ipa-server/ipaserver/dsinstance.py | 2 +- ipa-server/ipaserver/radiusinstance.py | 6 ++++-- ipa-server/xmlrpc-server/funcs.py | 22 +++++++++++++++++++--- ipa-server/xmlrpc-server/ipaxmlrpc.py | 1 + 5 files changed, 27 insertions(+), 8 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/ipa-install/share/bootstrap-template.ldif b/ipa-server/ipa-install/share/bootstrap-template.ldif index df59bc0e..fcc2506d 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: uid=ipa_default, cn=profiles,cn=radius,cn=services,cn=etc,$SUFFIX +dn: cn=ipa_default, cn=profiles,cn=radius,cn=services,cn=etc,$SUFFIX changetype: add objectClass: top objectClass: radiusprofile -uid: ipa_default +cn: ipa_default dn: cn=admins,cn=groups,cn=accounts,$SUFFIX changetype: add diff --git a/ipa-server/ipaserver/dsinstance.py b/ipa-server/ipaserver/dsinstance.py index 9a539470..ce3c154f 100644 --- a/ipa-server/ipaserver/dsinstance.py +++ b/ipa-server/ipaserver/dsinstance.py @@ -78,7 +78,7 @@ class DsInstance(service.Service): self.dm_password = dm_password self.__setup_sub_dict() - self.start_creation(11, "Configuring directory server:") + self.start_creation(14, "Configuring directory server:") self.__create_ds_user() self.__create_instance() self.__add_default_schemas() diff --git a/ipa-server/ipaserver/radiusinstance.py b/ipa-server/ipaserver/radiusinstance.py index 38091d69..8317da03 100644 --- a/ipa-server/ipaserver/radiusinstance.py +++ b/ipa-server/ipaserver/radiusinstance.py @@ -122,7 +122,8 @@ class RadiusInstance(service.Service): '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' : 'cn=clients,cn=radius,cn=services,cn=etc,%s' % self.suffix, + 'SUFFIX' : self.suffix, } try: radiusd_conf = template_file(RADIUSD_CONF_TEMPLATE_FILEPATH, sub_dict) @@ -164,10 +165,11 @@ class RadiusInstance(service.Service): except Exception, e: logging.error("could not chown on %s to %s: %s", IPA_KEYTAB_FILEPATH, RADIUS_USER, e) + #FIXME, should use IPAdmin method def __set_ldap_encrypted_attributes(self): ldif_file = 'encrypted_attribute.ldif' self.step("setting ldap encrypted attributes") - ldif_txt = template_file(SHARE_DIR + ldif_file, {'ENCRYPTED_ATTRIBUTE':'radiusClientSecret') + ldif_txt = template_file(SHARE_DIR + ldif_file, {'ENCRYPTED_ATTRIBUTE':'radiusClientSecret'}) ldif_fd = write_tmp_file(ldif_txt) try: ldap_mod(ldif_fd, "cn=Directory Manager", self.dm_password) diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index 8169b446..7c53e6d0 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -456,22 +456,38 @@ class IPAServer: self.releaseConnection(conn) return res + 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 + + try: + entry = self.__get_sub_entry(basedn, filter, ['dn','uid'], opts) + return 0 + except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): + return 1 + def add_radius_client (self, client, opts=None): + print "add_radius_client:" client_container = 'cn=clients,cn=radius,cn=services,cn=etc' # FIXME, should not be hardcoded - if self.__is_client_unique(client['radiusClientNASIpAddress'], opts) == 0: + if self.__is_radius_client_unique(client['radiusClientNASIpAddress'], opts) == 0: raise ipaerror.gen_exception(ipaerror.LDAP_DUPLICATE) dn="radiusClientNASIpAddress=%s,%s,%s" % (ldap.dn.escape_dn_chars(client['radiusClientNASIpAddress']), client_container,self.basedn) - entry = ipaserver.ipaldap.Entry(dn) - # FIXME: This should be dynamic and can include just about anything + print "add_radius_client: dn=%s" % (dn) + + 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: + print "add_radius_client: attr=%s %s" % (u, client[u]) entry.setValues(u, client[u]) conn = self.getConnection(opts) diff --git a/ipa-server/xmlrpc-server/ipaxmlrpc.py b/ipa-server/xmlrpc-server/ipaxmlrpc.py index 6aaad117..fe71aec4 100644 --- a/ipa-server/xmlrpc-server/ipaxmlrpc.py +++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py @@ -351,6 +351,7 @@ def handler(req, profiling=False): h.register_function(f.delete_group) h.register_function(f.attrs_to_labels) h.register_function(f.group_members) + h.register_function(f.add_radius_client) h.handle_request(req) finally: pass -- cgit From c24da12fe1c68cc2ea5211763e8904b646a17d95 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Wed, 14 Nov 2007 00:04:19 -0500 Subject: radius client modify and delete work --- ipa-server/xmlrpc-server/funcs.py | 29 ++++++++++++++++++++++++----- ipa-server/xmlrpc-server/ipaxmlrpc.py | 3 +++ 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index 7c53e6d0..38ba8c2b 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -456,11 +456,19 @@ class IPAServer: self.releaseConnection(conn) return res +# 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 + 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 try: @@ -470,7 +478,6 @@ class IPAServer: return 1 def add_radius_client (self, client, opts=None): - print "add_radius_client:" 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) @@ -478,8 +485,6 @@ class IPAServer: dn="radiusClientNASIpAddress=%s,%s,%s" % (ldap.dn.escape_dn_chars(client['radiusClientNASIpAddress']), client_container,self.basedn) - print "add_radius_client: dn=%s" % (dn) - entry = ipaserver.ipaldap.Entry(dn) # some required objectclasses @@ -487,7 +492,6 @@ class IPAServer: # fill in our new entry with everything sent by the client for u in client: - print "add_radius_client: attr=%s %s" % (u, client[u]) entry.setValues(u, client[u]) conn = self.getConnection(opts) @@ -497,6 +501,21 @@ class IPAServer: self.releaseConnection(conn) return res + 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) + if client is None: + raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND) + + conn = self.getConnection(opts) + try: + res = conn.deleteEntry(client['dn']) + finally: + self.releaseConnection(conn) + return res + 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 fe71aec4..f958414a 100644 --- a/ipa-server/xmlrpc-server/ipaxmlrpc.py +++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py @@ -351,7 +351,10 @@ def handler(req, profiling=False): h.register_function(f.delete_group) h.register_function(f.attrs_to_labels) h.register_function(f.group_members) + h.register_function(f.get_radius_client_by_ip_addr) h.register_function(f.add_radius_client) + h.register_function(f.update_radius_client) + h.register_function(f.delete_radius_client) h.handle_request(req) finally: pass -- cgit From c4dbe6433da131b618ea2bfd9f0bfc5076c40ff2 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Wed, 14 Nov 2007 15:32:08 -0500 Subject: add ipa-findradiusclient search --- ipa-server/xmlrpc-server/funcs.py | 31 +++++++++++++++++++++++++++++++ ipa-server/xmlrpc-server/ipaxmlrpc.py | 1 + 2 files changed, 32 insertions(+) (limited to 'ipa-server') diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index 38ba8c2b..26fdba48 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -516,6 +516,36 @@ class IPAServer: self.releaseConnection(conn) return res + def find_radius_clients(self, ip_attrs, 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 + + basedn = 'cn=clients,cn=radius,cn=services,cn=etc,%s' % self.basedn # FIXME, should not be hardcoded + filter = gen_filter('radiusClientProfile', 'radiusClientNASIpAddress', ip_attrs) + 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_clients = [counter] + for radius_client in results: + radius_clients.append(self.convert_entry(radius_client)) + + return radius_clients + def get_add_schema (self): """Get the list of fields to be used when adding users in the GUI.""" @@ -1152,6 +1182,7 @@ class IPAServer: return entries + def ldap_search_escape(match): """Escapes out nasty characters from the ldap search. See RFC 2254.""" diff --git a/ipa-server/xmlrpc-server/ipaxmlrpc.py b/ipa-server/xmlrpc-server/ipaxmlrpc.py index f958414a..d5bdb6b2 100644 --- a/ipa-server/xmlrpc-server/ipaxmlrpc.py +++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py @@ -355,6 +355,7 @@ def handler(req, profiling=False): h.register_function(f.add_radius_client) h.register_function(f.update_radius_client) h.register_function(f.delete_radius_client) + h.register_function(f.find_radius_clients) h.handle_request(req) finally: pass -- cgit From 087d11af5cebe7bb7a87d0581c7fa95353d9aa3b Mon Sep 17 00:00:00 2001 From: John Dennis Date: Wed, 14 Nov 2007 16:01:27 -0500 Subject: map attrs to friendly name --- ipa-server/ipa-install/share/60radius.ldif | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ipa-server') diff --git a/ipa-server/ipa-install/share/60radius.ldif b/ipa-server/ipa-install/share/60radius.ldif index ac9e3bef..47692352 100644 --- a/ipa-server/ipa-install/share/60radius.ldif +++ b/ipa-server/ipa-install/share/60radius.ldif @@ -565,5 +565,5 @@ objectClasses: SUP top STRUCTURAL DESC 'A Container Objectclass to be used for describing radius clients' MUST (radiusClientNASIpAddress $ radiusClientSecret) - MAY ( radiusClientNASType $ radiusClientShortName $ nsEncryptionAlgorithm $ description ) + MAY ( radiusClientNASType $ radiusClientShortName $ description ) ) -- cgit From d98686e96758870cb4a56d41fb0aaae54d4067c5 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Wed, 21 Nov 2007 13:11:10 -0500 Subject: 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 --- ipa-server/ipa-install/share/60radius.ldif | 12 +- .../ipa-install/share/bootstrap-template.ldif | 4 +- ipa-server/ipaserver/radiusinstance.py | 67 +++------ ipa-server/xmlrpc-server/funcs.py | 155 +++++++++++++++++---- ipa-server/xmlrpc-server/ipaxmlrpc.py | 5 + 5 files changed, 155 insertions(+), 88 deletions(-) (limited to 'ipa-server') 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 $ @@ -526,14 +526,6 @@ objectClasses: MUST cn 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' @@ -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 -- cgit From 9a8326c5c1d281def17852e6de9708b827f5f959 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Fri, 23 Nov 2007 10:35:22 -0500 Subject: clean up radius client command line tools --- ipa-server/ipaserver/radiusinstance.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/ipaserver/radiusinstance.py b/ipa-server/ipaserver/radiusinstance.py index 0c94c713..dd14bf20 100644 --- a/ipa-server/ipaserver/radiusinstance.py +++ b/ipa-server/ipaserver/radiusinstance.py @@ -18,6 +18,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +import sys import subprocess import string import tempfile @@ -123,7 +124,7 @@ class RadiusInstance(service.Service): logging.error("could not create %s: %s", radius_util.RADIUSD_CONF_FILEPATH, e) def __create_radius_keytab(self): - self.step("create radiusd keytab") + self.step("creating a keytab for httpd") try: if file_exists(radius_util.RADIUS_IPA_KEYTAB_FILEPATH): os.remove(radius_util.RADIUS_IPA_KEYTAB_FILEPATH) @@ -146,7 +147,7 @@ class RadiusInstance(service.Service): retry += 1 if retry > 15: print "Error timed out waiting for kadmin to finish operations\n" - os.exit() + sys.exit() try: pent = pwd.getpwnam(radius_util.RADIUS_USER) -- cgit From 09238510ff0dced7998e6a1b72f450070e8c6116 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Mon, 26 Nov 2007 19:30:33 -0500 Subject: add command line utilites for radius profiles --- ipa-server/xmlrpc-server/funcs.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index aa557f79..de9b265e 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -574,8 +574,10 @@ class IPAServer: 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): + def add_radius_profile (self, profile, user_profile=True, opts=None): + uid = profile['uid'] + + if self.__radius_profile_exists(uid, user_profile, opts): raise ipaerror.gen_exception(ipaerror.LDAP_DUPLICATE) if user_profile: @@ -587,7 +589,7 @@ class IPAServer: entry = ipaserver.ipaldap.Entry(dn) # some required objectclasses - entry.setValues('objectClass', 'top', 'radiusClientProfile') + entry.setValues('objectClass', 'top', 'radiusprofile') # fill in our new entry with everything sent by the profile for attr in profile: @@ -631,8 +633,7 @@ class IPAServer: else: container = radius_util.profiles_container - uid = self.__safe_filter(uid) - filter = gen_filter('radiusClientProfile' 'uid', uids) + filter = gen_filter('radiusprofile', 'uid', uids) basedn="%s,%s" % (container, self.basedn) conn = self.getConnection(opts) try: -- cgit From 6be932e8af1f9e874071da943c129457d724b46c Mon Sep 17 00:00:00 2001 From: John Dennis Date: Thu, 29 Nov 2007 11:44:50 -0500 Subject: fix merge error --- ipa-server/ipa-install/share/60radius.ldif | 2 -- ipa-server/xmlrpc-server/funcs.py | 44 ------------------------------ 2 files changed, 46 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/ipa-install/share/60radius.ldif b/ipa-server/ipa-install/share/60radius.ldif index 3562312a..93a5ba31 100644 --- a/ipa-server/ipa-install/share/60radius.ldif +++ b/ipa-server/ipa-install/share/60radius.ldif @@ -549,8 +549,6 @@ attributeTypes: EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -# c->ipaddr = radiusNASIpAddress -# c->secret = radiusSecret objectClasses: ( 1.3.6.1.4.1.3317.4.3.2.3 NAME 'radiusClientProfile' diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index 04b05324..3be61989 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -707,50 +707,6 @@ class IPAServer: return radius_profiles - def get_add_schema (self): - """Get the list of fields to be used when adding users in the GUI.""" - - # FIXME: this needs to be pulled from LDAP - fields = [] - - field1 = { - "name": "uid" , - "label": "Login:", - "type": "text", - "validator": "text", - "required": "true" - } - fields.append(field1) - - field1 = { - "name": "givenName" , - "label": "First name:", - "type": "text", - "validator": "string", - "required": "true" - } - fields.append(field1) - - field1 = { - "name": "sn" , - "label": "Last name:", - "type": "text", - "validator": "string", - "required": "true" - } - fields.append(field1) - - field1 = { - "name": "mail" , - "label": "E-mail address:", - "type": "text", - "validator": "email", - "required": "false" - } - fields.append(field1) - - return fields - def set_custom_fields (self, schema, opts=None): """Set the list of custom user fields. -- cgit From 4e1d291d15e198a0517a2c6787f865fe41147440 Mon Sep 17 00:00:00 2001 From: John Dennis Date: Fri, 30 Nov 2007 20:29:12 -0500 Subject: change location of radius data in ldap from cn=radius,cn=services,cn=etc to cn=radius --- ipa-server/ipa-install/share/bootstrap-template.ldif | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/ipa-install/share/bootstrap-template.ldif b/ipa-server/ipa-install/share/bootstrap-template.ldif index 6232a3f6..f981005d 100644 --- a/ipa-server/ipa-install/share/bootstrap-template.ldif +++ b/ipa-server/ipa-install/share/bootstrap-template.ldif @@ -75,31 +75,25 @@ homeDirectory: /home/admin loginShell: /bin/bash gecos: Administrator -dn: cn=services,cn=etc,$SUFFIX -changetype: add -objectClass: nsContainer -objectClass: top -cn: services - -dn: cn=radius,cn=services,cn=etc,$SUFFIX +dn: cn=radius,$SUFFIX changetype: add objectClass: nsContainer objectClass: top cn: radius -dn: cn=clients,cn=radius,cn=services,cn=etc,$SUFFIX +dn: cn=clients,cn=radius,$SUFFIX changetype: add objectClass: nsContainer objectClass: top cn: clients -dn: cn=profiles,cn=radius,cn=services,cn=etc,$SUFFIX +dn: cn=profiles,cn=radius,$SUFFIX changetype: add objectClass: nsContainer objectClass: top cn: profiles -dn: uid=ipa_default, cn=profiles,cn=radius,cn=services,cn=etc,$SUFFIX +dn: uid=ipa_default, cn=profiles,cn=radius,$SUFFIX changetype: add objectClass: top objectClass: radiusprofile -- cgit From 3b4f0db73e73912e39baa4a4c8b8c2e9ae3ab5be Mon Sep 17 00:00:00 2001 From: Karl MacMillan Date: Thu, 6 Dec 2007 17:17:43 -0500 Subject: Convert the setup of ssl from a shell script to a python module. This is in preparation for user supplied certs. --- ipa-server/ipa-install/Makefile.am | 6 - ipa-server/ipa-install/ipa-server-setupssl | 216 ----------------------------- ipa-server/ipaserver/Makefile.am | 1 + ipa-server/ipaserver/certs.py | 192 +++++++++++++++++++++++++ ipa-server/ipaserver/dsinstance.py | 39 +++++- ipa-server/ipaserver/httpinstance.py | 10 ++ 6 files changed, 235 insertions(+), 229 deletions(-) delete mode 100644 ipa-server/ipa-install/ipa-server-setupssl create mode 100644 ipa-server/ipaserver/certs.py (limited to 'ipa-server') diff --git a/ipa-server/ipa-install/Makefile.am b/ipa-server/ipa-install/Makefile.am index 4765cfb5..1b46d354 100644 --- a/ipa-server/ipa-install/Makefile.am +++ b/ipa-server/ipa-install/Makefile.am @@ -10,14 +10,8 @@ sbin_SCRIPTS = \ ipa-replica-prepare \ $(NULL) -appdir = $(IPA_DATA_DIR) -app_SCRIPTS = \ - ipa-server-setupssl \ - $(NULL) - EXTRA_DIST = \ README \ - $(app_SCRIPTS) \ $(sbin_SCRIPTS) \ $(NULL) diff --git a/ipa-server/ipa-install/ipa-server-setupssl b/ipa-server/ipa-install/ipa-server-setupssl deleted file mode 100644 index 1774f214..00000000 --- a/ipa-server/ipa-install/ipa-server-setupssl +++ /dev/null @@ -1,216 +0,0 @@ -#!/bin/bash - -if [ "$1" ] ; then - password=$1 -else - echo "password required" - exit 1 -fi - -if [ "$2" -a -d "$2" ] ; then - secdir="$2" -else - secdir=/etc/dirsrv/slapd-localhost -fi - -if [ "$3" ] ; then - myhost=$3 -else - myhost=`hostname --fqdn` -fi - - -if [ "$4" ] ; then - ldapport=$4 -else - ldapport=389 -fi - -me=`whoami` -if [ "$me" = "root" ] ; then - isroot=1 -fi - -# see if there are already certs and keys -if [ -f $secdir/cert8.db ] ; then - # look for CA cert - if certutil -L -d $secdir -n "CA certificate" 2> /dev/null ; then - echo "Using existing CA certificate" - else - echo "No CA certificate found - will create new one" - needCA=1 - fi - - # look for server cert - if certutil -L -d $secdir -n "Server-Cert" 2> /dev/null ; then - echo "Using existing directory Server-Cert" - else - echo "No Server Cert found - will create new one" - needServerCert=1 - fi - - prefix="new-" - prefixarg="-P $prefix" -else - needCA=1 - needServerCert=1 -fi - -if test -z "$needCA" -a -z "$needServerCert" ; then - echo "No certs needed - exiting" - exit 0 -fi - -# get our user and group -if test -n "$isroot" ; then - uid=`/bin/ls -ald $secdir | awk '{print $3}'` - gid=`/bin/ls -ald $secdir | awk '{print $4}'` -fi - -# 2. Create a password file for your security token password: -if [ -f $secdir/pwdfile.txt ] ; then - echo "Using existing $secdir/pwdfile.txt" -else - (ps -ef ; w ) | sha1sum | awk '{print $1}' > $secdir/pwdfile.txt - if test -n "$isroot" ; then - chown $uid:$gid $secdir/pwdfile.txt - fi - chmod 400 $secdir/pwdfile.txt -fi - -# 3. Create a "noise" file for your encryption mechanism: -if [ -f $secdir/noise.txt ] ; then - echo "Using existing $secdir/noise.txt file" -else - (w ; ps -ef ; date ) | sha1sum | awk '{print $1}' > $secdir/noise.txt - if test -n "$isroot" ; then - chown $uid:$gid $secdir/noise.txt - fi - chmod 400 $secdir/noise.txt -fi - -# 4. Create the key3.db and cert8.db databases: -certutil -N $prefixarg -d $secdir -f $secdir/pwdfile.txt -if test -n "$isroot" ; then - chown $uid:$gid $secdir/${prefix}key3.db $secdir/${prefix}cert8.db -fi -chmod 600 $secdir/${prefix}key3.db $secdir/${prefix}cert8.db - - -if test -n "$needCA" ; then -# 5. Generate the encryption key: - certutil -G $prefixarg -d $secdir -z $secdir/noise.txt -f $secdir/pwdfile.txt -# 6. Generate the self-signed certificate: - certutil -S $prefixarg -n "CA certificate" -s "cn=CAcert" -x -t "CT,," -m 1000 -v 120 -d $secdir -z $secdir/noise.txt -f $secdir/pwdfile.txt -# export the CA cert for use with other apps - certutil -L $prefixarg -d $secdir -n "CA certificate" -a > $secdir/cacert.asc - pk12util -d $secdir $prefixarg -o $secdir/cacert.p12 -n "CA certificate" -w $secdir/pwdfile.txt -k $secdir/pwdfile.txt -fi - -if test -n "$needServerCert" ; then -# 7. Generate the server certificate: - certutil -S $prefixarg -n "Server-Cert" -s "cn=$myhost,ou=Fedora Directory Server" -c "CA certificate" -t "u,u,u" -m 1001 -v 120 -d $secdir -z $secdir/noise.txt -f $secdir/pwdfile.txt -fi - -# create the pin file -if [ ! -f $secdir/pin.txt ] ; then - pinfile=$secdir/pin.txt - echo 'Internal (Software) Token:'`cat $secdir/pwdfile.txt` > $pinfile - if test -n "$isroot" ; then - chown $uid:$gid $pinfile - fi - chmod 400 $pinfile -else - echo Using existing $secdir/pin.txt -fi - -if [ -n "$prefix" ] ; then - # move the old files out of the way - mv $secdir/cert8.db $secdir/orig-cert8.db - mv $secdir/key3.db $secdir/orig-key3.db - # move in the new files - will be used after server restart - mv $secdir/${prefix}cert8.db $secdir/cert8.db - mv $secdir/${prefix}key3.db $secdir/key3.db -fi - -modnssdir=/etc/httpd/alias - -# Setup SSL in Apache -if [ -e $modnssdir ]; then - mkdir ${modnssdir}.ipa - mv $modnssdir/cert8.db ${modnssdir}.ipa - mv $modnssdir/key3.db ${modnssdir}.ipa -fi - -# Create a new database for mod_nss -echo -e "\n" > $modnssdir/pw.txt -certutil -N -d $modnssdir -f $modnssdir/pw.txt - -# Add the CA we created -certutil -A -d $modnssdir -n "CA certificate" -t "CT,CT," -a -i $secdir/cacert.asc - -# Request a new server cert -certutil -R -d $modnssdir \ - -s "cn=$myhost,ou=Apache Web Server" \ - -o $modnssdir/tmpcertreq \ - -g 1024 \ - -z $secdir/noise.txt \ - -f $modnssdir/pw.txt - -# Have the FDS CA issue the cert -echo -e "2\n9\nn\n1\n9\nn\n" | \ -certutil -C -d $secdir \ - -c "CA certificate" \ - -i $modnssdir/tmpcertreq \ - -o $modnssdir/tmpcert.der \ - -m 1002 \ - -v 120 \ - -f $secdir/pwdfile.txt \ - -1 \ - -5 - -# Now add this cert to the Apache database -certutil -A -d $modnssdir -n "Server-Cert"\ - -t u,u,u \ - -i $modnssdir/tmpcert.der \ - -f $modnsdir/tmpcert.der - -rm -f $modnssdir/pw.txt $modnssdir/tmpcertreq $modnssder/tmpcert.der - -# enable SSL in the directory server - -ldapmodify -x -h localhost -p $ldapport -D "cn=Directory Manager" -w $password < +# +# 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 os, stat, subprocess +import sha + +from ipa import ipautil + +class CertDB(object): + def __init__(self, dir): + self.secdir = dir + self.prefix = "new-" + + self.noise_fname = self.secdir + "/noise.txt" + self.passwd_fname = self.secdir + "/pwdfile.txt" + self.certdb_fname = self.secdir + "/cert8.db" + self.keydb_fname = self.secdir + "/key3.db" + self.cacert_fname = self.secdir + "/cacert.asc" + self.pk12_fname = self.secdir + "/cacert.p12" + self.pin_fname = self.secdir + "/pin.txt" + self.certreq_fname = self.secdir + "/tmpcertreq" + self.certder_fname = self.secdir + "/tmpcert.der" + + # We are going to set the owner of all of the cert + # files to the owner of the containing directory + # instead of that of the process. This works when + # this is called by root for a daemon that runs as + # a normal user + mode = os.stat(self.secdir) + self.uid = mode[stat.ST_UID] + self.gid = mode[stat.ST_GID] + + def set_perms(self, fname, write=False): + os.chown(fname, self.uid, self.gid) + perms = stat.S_IRUSR + if write: + perms |= stat.S_IWUSR + os.chmod(fname, perms) + + def gen_password(self): + return sha.sha(ipautil.ipa_generate_password()).hexdigest() + + def run_certutil(self, args, stdin=None): + new_args = ["/usr/bin/certutil", "-d", self.secdir] + new_args = new_args + args + ipautil.run(new_args, stdin) + + def create_noise_file(self): + ipautil.backup_file(self.noise_fname) + f = open(self.noise_fname, "w") + f.write(self.gen_password()) + self.set_perms(self.noise_fname) + + def create_passwd_file(self, passwd=True): + ipautil.backup_file(self.passwd_fname) + f = open(self.passwd_fname, "w") + if passwd: + f.write(self.gen_password()) + else: + f.write("\n") + f.close() + self.set_perms(self.passwd_fname) + + def create_certdbs(self): + ipautil.backup_file(self.certdb_fname) + ipautil.backup_file(self.keydb_fname) + self.run_certutil(["-N", + "-f", self.passwd_fname]) + self.set_perms(self.passwd_fname, write=True) + + def create_ca_cert(self): + # Generate the encryption key + self.run_certutil(["-G", "-z", self.noise_fname, "-f", self.passwd_fname]) + # Generate the self-signed cert + self.run_certutil(["-S", "-n", "CA certificate", + "-s", "cn=CAcert", + "-x", + "-t", "CT,,", + "-m", "1000", + "-v", "120", + "-z", self.noise_fname, + "-f", self.passwd_fname]) + # export the CA cert for use with other apps + ipautil.backup_file(self.cacert_fname) + self.run_certutil(["-L", "-n", "CA certificate", + "-a", + "-o", self.cacert_fname]) + self.set_perms(self.cacert_fname) + ipautil.backup_file(self.pk12_fname) + ipautil.run(["/usr/bin/pk12util", "-d", self.secdir, + "-o", self.pk12_fname, + "-n", "CA certificate", + "-w", self.passwd_fname, + "-k", self.passwd_fname]) + self.set_perms(self.pk12_fname) + + def load_cacert(self, cacert_fname): + self.run_certutil(["-A", "-n", "CA certificate", + "-t", "CT,CT,", + "-a", + "-i", cacert_fname]) + + def create_server_cert(self, nickname, name): + self.run_certutil(["-S", "-n", nickname, + "-s", name, + "-c", "CA certificate", + "-t", "u,u,u", + "-m", "1001", + "-v", "120", + "-z", self.noise_fname, + "-f", self.passwd_fname]) + + def request_cert(self, name): + self.run_certutil(["-R", "-s", name, + "-o", self.certreq_fname, + "-g", "1024", + "-z", self.noise_fname, + "-f", self.passwd_fname]) + + def issue_cert(self, certreq_fname, cert_fname): + p = subprocess.Popen(["/usr/bin/certutil", + "-d", self.secdir, + "-C", "-c", "CA certificate", + "-i", certreq_fname, + "-o", cert_fname, + "-m", "1002", + "-v", "120", + "-f", self.passwd_fname, + "-1", "-5"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + + # bah - this sucks, but I guess it isn't possible to fully + # control this with command line arguments + p.stdin.write("2\n9\nn\n1\n9\nn\n") + p.wait() + + + def add_cert(self, cert_fname, nickname): + self.run_certutil(["-A", "-n", nickname, + "-t", "u,u,u", + "-i", cert_fname, + "-f", cert_fname]) + + def create_server_cert_extca(self, nickname, name, other_certdb): + self.request_cert(name) + other_certdb.issue_cert(self.certreq_fname, self.certder_fname) + self.add_cert(self.certder_fname, nickname) + os.unlink(self.certreq_fname) + os.unlink(self.certder_fname) + + + def create_pin_file(self): + ipautil.backup_file(self.pin_fname) + f = open(self.pin_fname, "w") + f.write("Internal (Software) Token:") + pwd = open(self.passwd_fname) + f.write(pwd.read()) + f.close() + self.set_perms(self.pin_fname) + + def create_self_signed(self, passwd=True): + self.create_noise_file() + self.create_passwd_file(passwd) + self.create_certdbs() + self.create_ca_cert() + self.create_pin_file() + + def create_from_cacert(self, cacert_fname, passwd=False): + self.create_noise_file() + self.create_passwd_file(passwd) + self.create_certdbs() + self.load_cacert(cacert_fname) + + + diff --git a/ipa-server/ipaserver/dsinstance.py b/ipa-server/ipaserver/dsinstance.py index 6ba721c3..5edc3879 100644 --- a/ipa-server/ipaserver/dsinstance.py +++ b/ipa-server/ipaserver/dsinstance.py @@ -29,6 +29,8 @@ from ipa import ipautil import service import installutils +import certs +import ipaldap, ldap SERVER_ROOT_64 = "/usr/lib64/dirsrv" SERVER_ROOT_32 = "/usr/lib/dirsrv" @@ -290,13 +292,36 @@ class DsInstance(service.Service): def __enable_ssl(self): self.step("configuring ssl for ds instance") dirname = config_dirname(self.realm_name) - args = ["/usr/share/ipa/ipa-server-setupssl", self.dm_password, - dirname, self.host_name] - try: - ipautil.run(args) - logging.debug("done configuring ssl for ds instance") - except ipautil.CalledProcessError, e: - logging.critical("Failed to configure ssl in ds instance %s" % e) + ca = certs.CertDB(dirname) + ca.create_self_signed() + ca.create_server_cert("Server-Cert", "cn=%s,ou=Fedora Directory Server" % self.host_name) + + conn = ipaldap.IPAdmin("127.0.0.1") + conn.simple_bind_s("cn=directory manager", self.dm_password) + + mod = [(ldap.MOD_REPLACE, "nsSSLClientAuth", "allowed"), + (ldap.MOD_REPLACE, "nsSSL3Ciphers", + "-rsa_null_md5,+rsa_rc4_128_md5,+rsa_rc4_40_md5,+rsa_rc2_40_md5,\ ++rsa_des_sha,+rsa_fips_des_sha,+rsa_3des_sha,+rsa_fips_3des_sha,+fortezza,\ ++fortezza_rc4_128_sha,+fortezza_null,+tls_rsa_export1024_with_rc4_56_sha,\ ++tls_rsa_export1024_with_des_cbc_sha")] + conn.modify_s("cn=encryption,cn=config", mod) + + mod = [(ldap.MOD_ADD, "nsslapd-security", "on"), + (ldap.MOD_REPLACE, "nsslapd-ssl-check-hostname", "off")] + conn.modify_s("cn=config", mod) + + entry = ipaldap.Entry("cn=RSA,cn=encryption,cn=config") + + entry.setValues("objectclass", "top", "nsEncryptionModule") + entry.setValues("cn", "RSA") + entry.setValues("nsSSLPersonalitySSL", "Server-Cert") + entry.setValues("nsSSLToken", "internal (software)") + entry.setValues("nsSSLActivation", "on") + + conn.addEntry(entry) + + conn.unbind() def __add_default_layout(self): self.step("adding default layout") diff --git a/ipa-server/ipaserver/httpinstance.py b/ipa-server/ipaserver/httpinstance.py index 30103513..448a9d97 100644 --- a/ipa-server/ipaserver/httpinstance.py +++ b/ipa-server/ipaserver/httpinstance.py @@ -27,6 +27,8 @@ import sys import time import service +import certs +import dsinstance from ipa.ipautil import * HTTPD_DIR = "/etc/httpd" @@ -143,3 +145,11 @@ class HTTPInstance(service.Service): self.step("Setting mod_nss port to 443") if update_file(NSS_CONF, '8443', '443') != 0: print "Updating %s failed." % NSS_CONF + + def __setup_ssl(self): + self.step("Setting up ssl") + ds_ca = certs.CertDB(dsinstance.config_dirname(self.realm)) + ca = certs.CertDB(dirname) + ca.create_from_cacert(ds_ca.cacert_fname) + ca.create_server_cert_extca("Server-Cert", "cn=%s,ou=Apache Web Server" % self.fqdn, ds_ca) + -- cgit From 158b4e8ff4704b967d4049e2a16f9b32fbb33b80 Mon Sep 17 00:00:00 2001 From: Karl MacMillan Date: Tue, 11 Dec 2007 12:55:27 -0500 Subject: Commit corrected certs.py --- ipa-server/ipaserver/certs.py | 77 +++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 28 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/ipaserver/certs.py b/ipa-server/ipaserver/certs.py index 55737605..fb6b01d0 100644 --- a/ipa-server/ipaserver/certs.py +++ b/ipa-server/ipaserver/certs.py @@ -25,18 +25,29 @@ from ipa import ipautil class CertDB(object): def __init__(self, dir): self.secdir = dir - self.prefix = "new-" self.noise_fname = self.secdir + "/noise.txt" self.passwd_fname = self.secdir + "/pwdfile.txt" self.certdb_fname = self.secdir + "/cert8.db" self.keydb_fname = self.secdir + "/key3.db" + self.secmod_fname = self.secdir + "/secmod.db" self.cacert_fname = self.secdir + "/cacert.asc" self.pk12_fname = self.secdir + "/cacert.p12" self.pin_fname = self.secdir + "/pin.txt" self.certreq_fname = self.secdir + "/tmpcertreq" self.certder_fname = self.secdir + "/tmpcert.der" + # Making this a starting value that will generate + # unique values for the current DB is the + # responsibility of the caller for now. In the + # future we might automatically determine this + # for a given db. + self.cur_serial = 1000 + + self.cacert_name = "CA certificate" + self.valid_months = "120" + self.keysize = "1024" + # We are going to set the owner of all of the cert # files to the owner of the containing directory # instead of that of the process. This works when @@ -45,6 +56,11 @@ class CertDB(object): mode = os.stat(self.secdir) self.uid = mode[stat.ST_UID] self.gid = mode[stat.ST_GID] + + def next_serial(self): + r = self.cur_serial + self.cur_serial += 1 + return str(r) def set_perms(self, fname, write=False): os.chown(fname, self.uid, self.gid) @@ -80,6 +96,7 @@ class CertDB(object): def create_certdbs(self): ipautil.backup_file(self.certdb_fname) ipautil.backup_file(self.keydb_fname) + ipautil.backup_file(self.secmod_fname) self.run_certutil(["-N", "-f", self.passwd_fname]) self.set_perms(self.passwd_fname, write=True) @@ -88,14 +105,15 @@ class CertDB(object): # Generate the encryption key self.run_certutil(["-G", "-z", self.noise_fname, "-f", self.passwd_fname]) # Generate the self-signed cert - self.run_certutil(["-S", "-n", "CA certificate", + self.run_certutil(["-S", "-n", self.cacert_name, "-s", "cn=CAcert", "-x", "-t", "CT,,", - "-m", "1000", - "-v", "120", + "-m", self.next_serial(), + "-v", self.valid_months, "-z", self.noise_fname, "-f", self.passwd_fname]) + # export the CA cert for use with other apps ipautil.backup_file(self.cacert_fname) self.run_certutil(["-L", "-n", "CA certificate", @@ -111,43 +129,54 @@ class CertDB(object): self.set_perms(self.pk12_fname) def load_cacert(self, cacert_fname): - self.run_certutil(["-A", "-n", "CA certificate", + self.run_certutil(["-A", "-n", self.cacert_name, "-t", "CT,CT,", "-a", "-i", cacert_fname]) - def create_server_cert(self, nickname, name): - self.run_certutil(["-S", "-n", nickname, - "-s", name, - "-c", "CA certificate", - "-t", "u,u,u", - "-m", "1001", - "-v", "120", - "-z", self.noise_fname, - "-f", self.passwd_fname]) + def create_server_cert(self, nickname, name, other_certdb=None): + cdb = other_certdb + if not cdb: + cdb = self + self.request_cert(name) + cdb.issue_cert(self.certreq_fname, self.certder_fname) + self.add_cert(self.certder_fname, nickname) + os.unlink(self.certreq_fname) + os.unlink(self.certder_fname) def request_cert(self, name): self.run_certutil(["-R", "-s", name, "-o", self.certreq_fname, - "-g", "1024", + "-g", self.keysize, "-z", self.noise_fname, "-f", self.passwd_fname]) def issue_cert(self, certreq_fname, cert_fname): p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir, - "-C", "-c", "CA certificate", + "-C", "-c", self.cacert_name, "-i", certreq_fname, "-o", cert_fname, - "-m", "1002", - "-v", "120", + "-m", self.next_serial(), + "-v", self.valid_months, "-f", self.passwd_fname, "-1", "-5"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) - # bah - this sucks, but I guess it isn't possible to fully - # control this with command line arguments + # Bah - this sucks, but I guess it isn't possible to fully + # control this with command line arguments. + # + # What this is requesting is: + # -1 (Create key usage extension) + # 2 - Key encipherment + # 9 - done + # n - not critical + # + # -5 (Create netscape cert type extension) + # 1 - SSL Server + # 9 - done + # n - not critical p.stdin.write("2\n9\nn\n1\n9\nn\n") p.wait() @@ -158,14 +187,6 @@ class CertDB(object): "-i", cert_fname, "-f", cert_fname]) - def create_server_cert_extca(self, nickname, name, other_certdb): - self.request_cert(name) - other_certdb.issue_cert(self.certreq_fname, self.certder_fname) - self.add_cert(self.certder_fname, nickname) - os.unlink(self.certreq_fname) - os.unlink(self.certder_fname) - - def create_pin_file(self): ipautil.backup_file(self.pin_fname) f = open(self.pin_fname, "w") -- cgit From abdbc50683fd4d3ec9e699eb19c8ed96b0cef0dd Mon Sep 17 00:00:00 2001 From: Karl MacMillan Date: Tue, 11 Dec 2007 12:55:38 -0500 Subject: Import correct httpinstance.py --- ipa-server/ipaserver/httpinstance.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/ipaserver/httpinstance.py b/ipa-server/ipaserver/httpinstance.py index 448a9d97..1799cca0 100644 --- a/ipa-server/ipaserver/httpinstance.py +++ b/ipa-server/ipaserver/httpinstance.py @@ -34,6 +34,7 @@ from ipa.ipautil import * HTTPD_DIR = "/etc/httpd" SSL_CONF = HTTPD_DIR + "/conf.d/ssl.conf" NSS_CONF = HTTPD_DIR + "/conf.d/nss.conf" +NSS_DIR = HTTPD_DIR + "/alias" selinux_warning = """WARNING: could not set selinux boolean httpd_can_network_connect to true. The web interface may not function correctly until this boolean is @@ -66,12 +67,13 @@ class HTTPInstance(service.Service): self.fqdn = fqdn self.realm = realm - self.start_creation(6, "Configuring the web interface") + self.start_creation(7, "Configuring the web interface") self.__disable_mod_ssl() self.__set_mod_nss_port() self.__configure_http() self.__create_http_keytab() + self.__setup_ssl() self.step("restarting httpd") self.restart() @@ -149,7 +151,8 @@ class HTTPInstance(service.Service): def __setup_ssl(self): self.step("Setting up ssl") ds_ca = certs.CertDB(dsinstance.config_dirname(self.realm)) - ca = certs.CertDB(dirname) + ca = certs.CertDB(NSS_DIR) + ds_ca.cur_serial = 2000 ca.create_from_cacert(ds_ca.cacert_fname) - ca.create_server_cert_extca("Server-Cert", "cn=%s,ou=Apache Web Server" % self.fqdn, ds_ca) + ca.create_server_cert("Server-Cert", "cn=%s,ou=Apache Web Server" % self.fqdn, ds_ca) -- cgit From 592329af18f48969cdd74461e57300a2b4dceb5e Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Mon, 10 Dec 2007 11:55:52 -0500 Subject: Use more common names for first and last name labels --- ipa-server/ipa-gui/ipagui/forms/user.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/ipa-gui/ipagui/forms/user.py b/ipa-server/ipa-gui/ipagui/forms/user.py index b0c4d0aa..74369a6a 100644 --- a/ipa-server/ipa-gui/ipagui/forms/user.py +++ b/ipa-server/ipa-gui/ipagui/forms/user.py @@ -3,8 +3,8 @@ from turbogears import validators, widgets from tg_expanding_form_widget.tg_expanding_form_widget import ExpandingForm class UserFields(object): - givenname = widgets.TextField(name="givenname", label="Given Name") - sn = widgets.TextField(name="sn", label="Family Name") + givenname = widgets.TextField(name="givenname", label="First Name") + sn = widgets.TextField(name="sn", label="Last Name") cn = widgets.TextField(name="cn", label="Common Names") cns = ExpandingForm(name="cns", label="Common Names", fields=[cn]) title = widgets.TextField(name="title", label="Title") -- cgit From 40ff6f21dbde577bd65721285d659152f27e90a6 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Thu, 6 Dec 2007 11:56:14 -0500 Subject: Prompt user before downloading a keytab that this will create a new secret, breaking any existing keytabs for that principal. --- ipa-server/ipa-gui/ipagui/templates/principallist.kid | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'ipa-server') diff --git a/ipa-server/ipa-gui/ipagui/templates/principallist.kid b/ipa-server/ipa-gui/ipagui/templates/principallist.kid index dcd9dd4b..d4177d8d 100644 --- a/ipa-server/ipa-gui/ipagui/templates/principallist.kid +++ b/ipa-server/ipa-gui/ipagui/templates/principallist.kid @@ -16,6 +16,14 @@ +

${len(principals)} results returned:

@@ -33,7 +41,7 @@ - ${principal.hostname} -- cgit From 2675f35fdf3121dd23658e4ea89e1600291d2b70 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Tue, 11 Dec 2007 09:56:37 -0500 Subject: Tie the logging module to 'PythonOption IPADebug' in /etc/httpd/conf.d/ipa.conf --- ipa-server/xmlrpc-server/funcs.py | 6 +----- ipa-server/xmlrpc-server/ipaxmlrpc.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'ipa-server') diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py index 26fee6ab..4943da24 100644 --- a/ipa-server/xmlrpc-server/funcs.py +++ b/ipa-server/xmlrpc-server/funcs.py @@ -53,11 +53,6 @@ DefaultUserContainer = "cn=users,cn=accounts" DefaultGroupContainer = "cn=groups,cn=accounts" DefaultServiceContainer = "cn=services,cn=accounts" -# FIXME: need to check the ipadebug option in ipa.conf -#logging.basicConfig(level=logging.DEBUG, -# format='%(asctime)s %(levelname)s %(message)s', -# stream=sys.stderr) - # # Apache runs in multi-process mode so each process will have its own # connection. This could theoretically drive the total number of connections @@ -807,6 +802,7 @@ class IPAServer: """Returns a list: counter followed by the results. If the results are truncated, counter will be set to -1.""" + logging.debug("IPA: find users %s" % criteria) config = self.get_ipa_config(opts) if timelimit < 0: timelimit = float(config.get('ipasearchtimelimit')) diff --git a/ipa-server/xmlrpc-server/ipaxmlrpc.py b/ipa-server/xmlrpc-server/ipaxmlrpc.py index d15ed5dd..7752b258 100644 --- a/ipa-server/xmlrpc-server/ipaxmlrpc.py +++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py @@ -32,6 +32,7 @@ import traceback import pprint from xmlrpclib import Marshaller,loads,dumps,Fault from mod_python import apache +import logging import ipaserver import funcs @@ -148,12 +149,15 @@ class ModXMLRPCRequestHandler(object): opts['ipadebug'] = pythonopts.get("IPADebug") if opts['ipadebug'].lower() == "on": + logging.basicConfig(level=logging.DEBUG, + format='[%(asctime)s] [%(levelname)s] %(message)s', + datefmt='%a %b %d %H:%M:%S %Y', + stream=sys.stderr) + for o in opts: - sys.stderr.write("IPA: setting option %s: %s\n" % (o, opts[o])) - sys.stderr.flush() - for e in req.subprocess_env: - sys.stderr.write("IPA: environment %s: %s\n" % (e, req.subprocess_env[e])) - sys.stderr.flush() + logging.debug("IPA: setting option %s: %s" % (o, opts[o])) +# for e in req.subprocess_env: +# logging.debug("IPA: environment %s: %s" % (e, req.subprocess_env[e])) # Tack onto the end of the passed-in arguments any options we also # need -- cgit From 01131e2a37a9aec197b4e286e0559165d403fe73 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 11 Dec 2007 12:25:58 -0500 Subject: Make sure we don't keep around old keys. Fixes problem changing passwords seen only on servers where re-installations where performed (and old secrets piled up) --- ipa-server/ipaserver/krbinstance.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'ipa-server') diff --git a/ipa-server/ipaserver/krbinstance.py b/ipa-server/ipaserver/krbinstance.py index ede008a8..76818af7 100644 --- a/ipa-server/ipaserver/krbinstance.py +++ b/ipa-server/ipaserver/krbinstance.py @@ -383,6 +383,11 @@ class KrbInstance(service.Service): def __export_kadmin_changepw_keytab(self): self.step("exporting the kadmin keytab") + try: + if file_exists("/var/kerberos/krb5kdc/kpasswd.keytab"): + os.remove("/var/kerberos/krb5kdc/kpasswd.keytab") + except os.error: + logging.critical("Failed to remove /var/kerberos/krb5kdc/kpasswd.keytab.") (kwrite, kread, kerr) = os.popen3("/usr/kerberos/sbin/kadmin.local") kwrite.write("modprinc +requires_preauth kadmin/changepw\n") kwrite.flush() -- cgit