Showing posts with label TLS. Show all posts
Showing posts with label TLS. Show all posts

Using TLSv1.3 and strong cryptography for 389 Directory Server (on CentOS 7)

TLS v1.3 support came recently to the 389 Directory Server (via mod_nss) with the latest CentOS 7. Due to an inconstancy between EPEL and CentOS7 upstream, TLS v1.3 is not currently available to the dirsrv admin service!

To activate the TLS v1.3 protocol for 389 Directory Server, do prepare a LDIF file, and describe there the modification that will take place in "cn=encryption,cn=config" (a dn-object which is a part of the 389 start up configuration), and insert there the following text:

dn: cn=encryption,cn=config
changetype:modify
replace: sslVersionMin
sslVersionMin: TLS1.2

dn: cn=encryption,cn=config
changetype: modify
replace: nsSSL3
nsSSL3: off

dn: cn=encryption,cn=config
changetype: modify
replace: nsSSL3Ciphers
nsSSL3Ciphers:  +TLS_CHACHA20_POLY1305_SHA256,+TLS_AES_256_GCM_SHA384,+TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,+TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,+TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,+TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,+TLS_DHE_RSA_WITH_AES_256_GCM_SHA384

Save that content as "modify.ldif", then invoke ldapmodify, and authenticate as "cn=Directory Manager" to enforce the modification:

$ ldapmodify -D "cn=Directory Manager" -x -W -f modify.ldif

In case of successful modification, the following message will appear:

modifying entry "cn=encryption,cn=config"

At this point you need to restart 389 Directory Server:

systemctl reload dirsrv@instance-name

and check if the requested cipher suite, already requested for TLS v1.2 above, is really available to the server (replace "localhost" with the actual server name of your 389 server):

$ nmap -sV --script ssl-enum-ciphers -p 636 localhost

In latest Fedora, CentOS, and Ubuntu, one can use openssl (>= 1.1.1) to verify that that TLS v1.3 is successfully configured and (therefore) available (just replace "server-name" down bellow with your actual server name):

$ openssl s_client -connect server-name:636

This is how a positive result, the one detecting the presence of TLS v1.3, will appear on your screen:

New, TLSv1.3, Cipher is TLS_CHACHA20_POLY1305_SHA256
Server public key is 4096 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent

IMAP connector for FreeRADIUS to support EAP-TTLS authentication in Eduroam

Content:

  1. Introduction
  2. The code of the IMAP connector
  3. Configuring FreeRADIUS to use the IMAP connector
  4. SELinux issues
  5. Notes on the productivity

1. Introduction

In spite its amazing collection of drivers supporting a variety of authentication protocols, FreeRADIUS does not support (yet) verification of the user names and passwords against IMAP/IMAPS servers, especially when using EAP-TTLS method for authenticating the users. It is also true that in average the IMAP servers are slow authenticators, compared to those based on LDAP or Active Directory, which might explain the lack of interest among the developers to create an intrinsic IMAP authentication module and include it into the FreeRADIUS source code. Nevertheless, there are cases when one simply cannot obtain direct access to the authentication data base, and in that case the only possibility available is to authenticate the users of the RADIUS server against publicly available service, like IMAP.

But why the IMAP authentication is considered slow? The goal of the IMAP servers is to provide access to the user's e-mail storage. In that aspect they are more closer to the file serversm then to the dedicated authentication servers (like 389 Directory Server). In other words, the major aim of developing IMAP server code is not to handle fast authentication of intensive stream of authentication requests. But if the intensity of incoming authentication requests is not huge, and the IMAP server is not engaged into intensive operations for managing the mail box content, it might be possible to relay on that server to handle a moderate stream of authentication request, sent by one or more FreeRADIUS servers.

One might find on Internet some solutions connecting the FreeRADIUS authentication process to IMAP server indirectly, through Linux Pluggable Authentication Modules (PAM). That way the FreeRADIUS server deals with local (to the Linux system hosting the server) users. Once sent to the PAM, the authentication request is passed to a specific PAM library, configured to connect to the IMAP server. In turn, the library passes the user name and password combination to the IMAP server for a verification. That kind of authentication process seems clear and simple, but it turns the remote users into local to the Linux system running the RADIUS server. In certain cases that might open an exploitable hole in the system security.

Creating an external IMAP connector - an application or script that can be invoked by the FreeRADIUS server process on demand - seems a way more elegant and secure method for verifying the user name and password pairs against external IMAP servers. Especially, if the connector code is based on a set of software components, that can be installed and kept updated by using the Linux distribution package management system. One such set of software components is Python and its modules, because: (1) every modern Linux distribution have its own optimized and supported (via updates) Python packages, and (2) it is easy and simple to write a Python code that established and manages connections to IMAP servers, by means of intrinsic modules (like imaplib and ssl). The connector (regardless the programming language) need to receive at least the user name and password, as invoking parameters, and return back an exit status value (return value) on completion. If that value is zero, the FreeRADIUS sever process considers the user credentials verified.

Given bellow is a simple Python script, behaving as IMAP connector.

2. The code of the IMAP connector

Provided bellow is a Python 3 code, based on the modules imaplib, sys, and ssl, all intrinsic to the Python distribution included in CentOS distribution (check if the Python package in your distribution does not include imaplib, which is unlikely):

#!/usr/bin/env python3

import imaplib
import ssl
import sys

if len(sys.argv) == 3:

    hostname = 'imap.example.com'

    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)

    context.options |= ssl.OP_NO_SSLv2
    context.options |= ssl.OP_NO_SSLv3

    context.set_ciphers('EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:' + \
                        'EECDH+ECDSA+SHA512:EECDH+ECDSA+SHA384:' + \
                        'EECDH+ECDSA+SHA256:ECDH+AESGCM:ECDH+AES256:' + \
                        'DH+AESGCM:DH+AES256:RSA+AESGCM:!aNULL:' + \
                        '!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS')

    context.verify_mode = ssl.CERT_REQUIRED
    context.check_hostname = True
    context.load_verify_locations("/etc/pki/tls/certs/ca-bundle.crt")

    try:
        imap_obj =  imaplib.IMAP4_SSL(hostname, 993, ssl_context = context)
    except:
        sys.exit(1)

    try:
        status = imap_obj.login(sys.argv[1], sys.argv[2])
    except:
        sys.exit(1)

The code establishes a SSL session (using TLSv1.2 protocol) to the IMAP server with host name imap.example.com (change it to that of your IMAP server), and thus checks the user credentials (the user name is assigned to sys.argv[1], the password is the value of sys.argv[2]). One might edit the list of ciphers in context.set_ciphers, if that is necessary, following the OpenSSL syntax for selecting ciphers.

If IP address is required instead of fully qualified host name (not recommended), the value of context.check_hostname have to be set False.

The file /etc/pki/tls/certs/ca-bundle.crt is the standard bundle file containing copies of the most used and trusted CA certificates (it is maintained by the vendor of the Linux distribution). That file is part of the package ca-certificates, installed by default in CentOS 7. That file might have different name and path in other distribution. Note, that if the X.509 certificate of the IMAP server is signed by some local certificate authority, whose CA certificate is not included in the list of CA certificates provided by the vendor of the Linux distribution, that particular CA certificate can be stored in a file alone. Then the file path and name should be declared an argument of context.load_verify_locations.

3. Configuring FreeRADIUS to use the IMAP connector

Before starting, do save the script given above as /var/lib/radiusd/login_imap.py.

To terminate the TLS tunnel, decrypt its content, and authenticate the users with realm (domain) "wifi.example.com" locally, the following configuration should be included to the file /etc/raddb/proxy.conf:

realm "wifi.example.com" {
   type = radius
   authhost = LOCAL
   accthost = LOCAL
}

To set PAP as default authentication protocol (after executing the EAP part of the authentication process), create the following entry inside the file /etc/raddb/users:

DEFAULT  Auth-Type = PAP

Then open the file /etc/raddb/modules/pap and add there the configuration section:

exec papauth {
     wait = yes
     program = "/var/lib/radiusd/login_imap.py '%{Stripped-User-Name}' '%{User-Password}'"
     input_pairs = request
     output_pairs = config
     }

If the IMAP server accepts e-mail addresses as user names, replace there %{Stripped-User-Name} with %{User-Name}.

Finally, open the file /etc/raddb/sites-available/inner-tunnel, go to the authenticate section there and change the declaration:

        Auth-Type PAP {
                pap
        }

into:

        Auth-Type PAP {
                papauth
        }

Why does the script check the number of elements in sys.argv list? It is because radiusd invokes the script twice for every single user authentication and therefore some polymorphic code is required to treat each call differently. The first time, the script is invoked, is right after the TLS tunnel is established. In this case the goal is to check the real user name and password against the specified IMAP server. If radiusd is running in debug mode (as radiusd -X), the following messages, related to the first call, will appear:

# Executing group from file /etc/raddb/sites-enabled/inner-tunnel
+group PAP {
[papauth]  expand: %{Stripped-User-Name} -> username
[papauth]  expand: %{User-Password} -> userpassword

Note that only two actual parameters are passed to the script by radiusd. Nevertheless, the result is the Python list sys.argv that contains three elements. The first element (sys.argv[0]) is the path to the script file, known to the radiusd (following the configuration above that should be /var/lib/radiusd/login_imap.py), and its value is assigned implicitly by the Python interpreter, the second one (sys.argv[1]) is the value of %{Stripped-User-Name}, and the third element (sys.argv[2]) is the password (that is the value of %{User-Password}). Therefore, sys.argv of this length will trigger the execution of the IMAP authentication section in the Python code. Otherwise, the script will return exit status 0 regardless the number of elements in sys.argv. The last is used to complete the authentication when radiusd is following the instructions found in the post-auth section located inside /etc/raddb/sites-enabled/default. In debug mode (radiusd) the following sequence of messages, related to the post-auth instructions, will be displayed on the screen:

# Executing section post-auth from file /etc/raddb/sites-enabled/default
+group post-auth {
[exec]  expand: %{Stripped-User-Name} -> anonymous
[exec]  expand: %{User-Password} ->
[exec]  expand: %{Calling-Station-Id} -> 02-00-00-00-00-01
[exec]  expand: %{NAS-IP-Address} -> 127.0.0.1
[exec]  expand: %{Framed-Protocol} ->

From those messages, it becomes clear that during that second execution of the script, the number of input parameters to the script is greater than two (unless there is some specific FreeRADIUS configuration, that reduces that number down to two). Therefore, the Python interpreter will not execute the IMAP authentication section in the script and will send back to radiusd an exit status 0.

4. SELinux issues

The radiusd expects the SELinux context of the IMAP connector script /var/lib/radiusd/login_imap.py to be the one of radiusd_t. That kind of context cannot be assigned by using chcon (at the present) and therefore radiusd cannot invoke the script. The only way to solve this issue is to create a specific SELinux module and install it. Srart radiusd and try to authenticate an user (if SELinux is enforced the authentication will fail). Then find the following type of entries in /var/log/audit/audit.log:

type=AVC msg=audit(1536040511.292:21627): avc:  denied  { execute } for  pid=29569 comm="radiusd" name="login_imap.py" dev=sda3 ino=132112 scontext=unconfined_u:system_r:radiusd_t:s0 tcontext=unconfined_u:object_r:radiusd_var_lib_t:s0 tclass=file
type=AVC msg=audit(1536040931.979:21649): avc:  denied  { execute_no_trans } for  pid=29739 comm="radiusd" path="/var/lib/radiusd/login_imap.py" dev=sda3 ino=132112 scontext=unconfined_u:system_r:radiusd_t:s0 tcontext=unconfined_u:object_r:radiusd_var_lib_t:s0 tclass=file
type=AVC msg=audit(1536041114.006:21653): avc:  denied  { name_connect } for  pid=29802 comm="python" dest=143 scontext=unconfined_u:system_r:radiusd_t:s0 tcontext=system_u:object_r:pop_port_t:s0 tclass=tcp_socket

and save them in a file (the file name myradius.avc is adopted in the example bellow). Finally, generate and then install the custom SELinux module:

# audit2allow -a -M myradius < myradius.avc
# semodule -i myradius.pp

5. Notes on the productivity

Establishing and supporting high number of simultaneous IMAP over SSL sessions, might bring a significant latency to the authentication process. One possible way to reduce the latency is to adopt an external SSL wrapper (like stunnel) to connect the radius server host to the IMAP server, and use a modification of the connector script, based on plain IMAP sessions to localhost:

#!/usr/bin/env python3

import imaplib
import sys

if len(sys.argv) == 3:

    hostname = 'localhost'

    try:
        imap_obj = imaplib.IMAP4(hostname)
    except:
        sys.exit(1)

    try:
        status = imap_obj.login(sys.argv[1], sys.argv[2])
    except:
        sys.exit(1)

Using LDAPS (LDAP+TLS) from within the Sendmail configuration file

 

Content:

1. Introduction.

2. Installing and configuring OpenLDAP certificate database

3. SELinux configuration.

4. LDAP+TLS in sendmail.mc/sendmail.cf.

 

1. Introduction.

If one need to implement LDAP+TLS to securely connect sendmail daemon to the LDAP directory server, they need to enable and use the existing OpenLDAP integration of Sendmail. Most of the modern Linux distributions provide as a part of their package collections Sendmail compiled with OpenLDAP integration. But when it comes to configure Sendmail to connect to LDAP server by securing the TCP session with TLS it is very hard to find online an useful example. Almost all examples available explain how to configure Sendmail to use LDAP server through a plain TCP session. The goal of this document is to explain how to do that configuration. The explanations bellow are 100% compatible to Sendmail setup based on CentOS 7 or Red Hat Enterprise Linux 7, but they might be implemented to any other modern Linux distribution as well.

 

2. Installing and configuring OpenLDAP certificate database.

In CentOS 7 and Red Hat Enterprise Linux 7 the OpenLDAP clients configuration used by default the configuration and certificated based located in the directory /etc/openldap. That folder is supplied to the system by the package named openldap. In most cases, but also depend on the type of the installation, the package openldap should be presented in the system by default. Nevertheless one must check and verify that the package exists and it is up to date (not keeping your system up to date is risky). If the package openldap is not presented, install it by using yum:

# yum install openldap

If the installation is successful the package will create the folders /etc/openldap and /etc/openldap/certs. That last folder contains NSS database:

/etc/openldap/certs/cert8.db
/etc/openldap/certs/key3.db
/etc/openldap/certs/password
/etc/openldap/certs/secmod.db

There the file named "password" contains the password for unlocking the NSS database when accessing the stored private keys and passwords. The NSS base is created empty by default which means that one must add there at least the CA certificate that helps to verify the validity of the LDAP server X.509 certificate (the LDAP server Sendmail will be connected to). For example, if the CA X.509 certificate "COMODO RSA Certification Authority", stored in PEM format in the file /tmp/COMODO_RSA_Certification_Authority.crt, should be added to the NSS database and trusted, that can be done in the following way:

# cd /etc/openldap/certs # certutil -A -d . -n "COMODO RSA Certification Authority" -a -i /tmp/COMODO_RSA_Certification_Authority.crt -t "CT,c,"

Please, note that the use of NSS libraries with OpenLDAP is specific to CentOS and Red Hat Enterprise Linux 7. Another Linux distributions might use OpenSSL libraries instead of NSS ones.

 

3. SELinux configuration.

By default the Sendmail OpenLDAP client process cannot access the NSS certificate database of OpenLDAP. In order to make the access possible, one need to set the SELinux boolean authlogin_nsswitch_use_ldap to true:

# setsebool -P authlogin_nsswitch_use_ldap 1

 

4. LDAP+TLS in sendmail.mc/sendmail.cf.

The LDAP+TLS can be configured by using a specific URI format "-H ldaps://hosname:port", where the port number is optional. Bellow is a detailed example in m4 format which need to become part of the m4 Sendmail configuration file sendmail.m4:

define(`confLDAP_DEFAULT_SPEC', `-H ldaps://directory.example.com -b "o=example.com" -d "cn=sendmail,ou=Special Users,o=example.com" -M simple -P /etc/mail/password-sendmail.ldap')dnl

If one need to specify the LDAP client settings directly in sendmail.cf the following configuration line should be added there:

O LDAPDefaultSpec=-H ldaps://directory.example.com -b "o=example.com" -d "cn=sendmail,ou=Special Users,o=example.com" -M simple -P /etc/mail/password-sendmail.ldap

Creative Commons - Attribution 2.5 Generic. Powered by Blogger.

Implementing LUKS Encryption on Software RAID Arrays with LVM2 Management

A comprehensive guide to partition-level encryption for maximum security ...

Search This Blog

Translate