Monday, April 15, 2013

Authenticating Users with SASL for Postfix

Authenticating Users with SASL for Postfix

Continued from setting up Postfix - SMTP and TLS - on an Amazon Cloud EC2 instance:

http://websitenotebook.blogspot.com/2013/03/configuring-tls-on-postfix-redhat-aws.html


Simple Authentication and Security Layer 

http://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer

Simple Authentication and Security Layer (SASL) is a framework for authentication and data security in Internet protocols. It decouples authentication mechanisms from application protocols, in theory allowing any authentication mechanism supported by SASL to be used in any application protocol that uses SASL.

saslauthd is not a part of Postfix per se. It is a used by and integrated with Postfix to support authentication of users (users login functionality). 

Postfix works with two different implementations of SASL: Cyrus and Dovecot

Not a fan of the curly braces configuration files in Dovecot so going to try Cyrus.

Basically when you type testsaslauthd you aren't testing Postfix. You are just testing that a user can authenticate with saslauthd.  If you don't have the correct hook up between Postfix and saslauthd then you'll authenticate but won't get you to Postfix functionality. 

Now let's try to decipher the Postfix documentation...

Configuring Cyrus saslauthd implementation to work with PAM for Postfix



http://www.postfix.org/SASL_README.html 

Configuring Cyrus SASL

There may be a different configuration file for each application Cyrus provides authentication for within Postfix (SMTP, POP, IMAP, etc).

The first step configuring Cyrus SASL is to determine name andlocation of a configuration file that describes how the PostfixSMTP server will use the SASL framework.

The name of the configuration file (default: smtpd.conf)is configurable.

The configuration file used by Cyrus is a concatentation of the value in the configuration file (smtpd by default) and .conf.

i.e. by default the value in your config file is smtpd + .conf so the default configuration file is smtpd.conf

Configuration variables in main.cf for smtpd:
/etc/postfix/main.cf:    # Postfix 2.3 and later    smtpd_sasl_path = smtpd    # Postfix < 2.3    smtpd_sasl_application_name = smtpd

Cyrus SASL configuration file directory

The location where Cyrus SASL searches for the named file dependson the Cyrus SASL version and the OS/distribution used. [Worked fine on my AWS ec2 instance. Skipping the details]

Note Cyrus SASL searches /usr/lib/sasl2/ first. If itfinds the specified configuration file there, it will not examineother locations. [On my Amazon EC2 instance -- I did find sasl2 in this directory.]

Postfix to Cyrus SASL user databases

The SASL library uses one of the following for user database which are discussed in the Postfix documentation.
authentication backendpassword verification service / plugin
/etc/shadowsaslauthd
PAMsaslauthd
IMAP serversaslauthd
sasldbsasldb
MySQL, PostgreSQL, SQLitesql
LDAPldapdb

saslauthd - Cyrus SASL password verification service

Communication between the Postfix SMTP server (read: Cyrus SASL'slibsasl) and the saslauthd server takesplace over a UNIX-domain socket.
 
saslauthd usually establishes the UNIX domainsocket in /var/run/saslauthd/ and waits for authenticationrequests. The Postfix SMTP server must have read+execute permissionto this directory or authentication attempts will fail.
Important Some distributions require the user postfix to bemember of a special group e.g. sasl, otherwise itwill not be able to access the saslauthd socketdirectory. [Note: I did not see this group on my AWS EC2 instance]
The following example configures the Cyrus SASL library tocontact saslauthd as its password verification service:
/etc/sasl2/smtpd.conf:    pwcheck_method: saslauthd    mech_list: PLAIN LOGIN
Important Do not specify any other mechanisms in mech_listthan PLAIN or LOGIN when usingsaslauthd! It can only handle these two mechanisms,and authentication will fail if clients are allowed to choose othermechanisms.
Important Plaintext mechanisms (PLAIN, LOGIN)send credentials unencrypted. This information should be protectedby an additional security layer such as a TLS-encrypted SMTP session [see my last post:(http://websitenotebook.blogspot.com/2013/03/configuring-tls-on-postfix-redhat-aws.html)]
Additionally the saslauthd server itself must beconfigured. It must be told which authentication backend to turnto for password verification. The backend is selected with asaslauthd command-line option and will be shown in thefollowing examples.
Note Some distributions use a configuration file to provide saslauthdcommand line options to set e.g. the authentication backend. Typicallocations are /etc/sysconfig/saslauthd or/etc/default/saslauthd.

Using saslauthd with /etc/shadow

Access to the /etc/shadow system password filerequires root privileges. [I stopped here. Next option...]

Using saslauthd with PAM

Cyrus SASL can use the PAM framework to authenticate credentials.saslauthd uses the PAM framework when started likethis:
% saslauthd -a pam

In other words, stop saslauthd if already running and start it again as shown above

sudo service saslauthd stop
sudo saslauthd -a pam
Note PAM configuration for the Postfix SMTP server is usually givenin /etc/pam.d/smtp and is beyond the scope of thisdocument.
See section "Testing saslauthdauthentication" for test instructions.
 

Using saslauthd with an IMAP server

[Not doing this...so skipping]

Testing saslauthd authentication

[
Um...it would have explained that users for this option are system users on the Linux box, unlike other options listed in the documentation.

useradd newuser
passwd newuser [enter new password at prompt).

For this option you do *not* use saslpasswd or saslpasswd2
]

Cyrus SASL provides the testsaslauthd utility totest saslauthd authentication.

[For the record the user name should *not* have the domain name on it like other options. You may find some documentation for other variants which indicate domain name is needed - not in this case]

% testsaslauthd -u username -p password0: OK "Success."
[the above worked for me. I didn't need any of the following mumbo jumbo]
Note Sometimes the testsaslauthd program is not distributedwith a the Cyrus SASL main package. In that case, it may bedistributed with -devel, -dev or-debug packages.
Specify an additional "-s smtp" if saslauthdwas configured to contact the PAM authentication framework, andspecify an additional "-f /path/to/socketdir/mux"if saslauthd establishes the UNIX-domain socket in anon-default location.
 
If authentication succeeds, proceed with the section "Enabling SASL authentication and authorizationin the Postfix SMTP server".

Cyrus SASL Plugins - auxiliary propertyplugins

Didn't use any of these...

The sasldb plugin

Or this..tried it with no success but I can tell you that you should add a 2 to the end of most commands if using the latest version.

Enabling SASL authentication andauthorization in the Postfix SMTP server

By default the Postfix SMTP server uses the Cyrus SASLimplementation.

[skipping Dovecot text here]

Enabling SASL authenticationin the Postfix SMTP server

Regardless of the SASL implementation type, enabling SMTPauthentication in the Postfix SMTP server always requires settingthe smtpd_sasl_auth_enable option:
/etc/postfix/main.cf:    smtpd_sasl_auth_enable = yes
After a "postfix reload", SMTP clients will see the additionalcapability AUTH in an SMTP session, followed by a list ofauthentication mechanisms the server supports:
% telnet server.example.com 25...220 server.example.com ESMTP PostfixEHLO client.example.com250-server.example.com250-PIPELINING250-SIZE 10240000250-AUTH DIGEST-MD5 PLAIN CRAM-MD5...
However not all clients recognize the AUTH capability as definedby the SASL authentication RFC. Some historical implementations expect theserver to send an "=" as separator between the AUTHverb and the list of mechanisms that follows it.
The broken_sasl_auth_clients configuration optionlets Postfix repeat the AUTH statement in a form that these brokenclients understand:
/etc/postfix/main.cf:    broken_sasl_auth_clients = yes
Note Enable this option for Outlook up to and including version 2003and Outlook Express up to version 6. This option does not hurt otherclients.
After "postfix reload", the Postfix SMTP server will propagatethe AUTH capability twice - once for compliant and once for brokenclients:
% telnet server.example.com 25...220 server.example.com ESMTP PostfixEHLO client.example.com250-server.example.com250-PIPELINING250-SIZE 10240000250-AUTH DIGEST-MD5 PLAIN CRAM-MD5250-AUTH=DIGEST-MD5 PLAIN CRAM-MD5...

Postfix SMTP Server policy- SASL mechanism properties

The Postfix SMTP server supports policies that limit the SASLmechanisms that it makes available to clients, based on the propertiesof those mechanisms. The next two sections give examples of howthese policies are used.
Property Description
noanonymous Don't use mechanisms that permitanonymous authentication.
noplaintext Don't use mechanisms that transmitunencrypted username and password information.
nodictionary Don't use mechanisms that arevulnerable to dictionary attacks.
forward_secrecy Require forward secrecy betweensessions (breaking one session does not break earlier sessions).
mutual_auth Use only mechanisms that authenticateboth the client and the server to each other.
 
 

Unencrypted SMTP session

The default policy is to allow any mechanism in the Postfix SMTP serverexcept for those based on anonymous authentication:
/etc/postfix/main.cf:    # Specify a list of properties separated by comma or whitespace    smtpd_sasl_security_options = noanonymous
Important Always set at least the noanonymous option.Otherwise, the Postfix SMTP server can give strangers the sameauthorization as a properly-authenticated client.

Encrypted SMTP session (TLS)

A separate parameter controls Postfix SASL mechanism policyduring a TLS-encrypted SMTP session. The default is to copy thesettings from the unencrypted session:
/etc/postfix/main.cf:    smtpd_sasl_tls_security_options = $smtpd_sasl_security_options
A more sophisticated policy allows plaintext mechanisms, butonly over a TLS-encrypted connection:
/etc/postfix/main.cf:    smtpd_sasl_security_options = noanonymous, noplaintext    smtpd_sasl_tls_security_options = noanonymous
To offer SASL authentication only after a TLS-encrypted session has beenestablished specify this:
/etc/postfix/main.cf:    smtpd_tls_auth_only = yes

Enabling SASL authorization in the PostfixSMTP server

After the client has authenticated with SASL, the Postfix SMTPserver decides what the remote SMTP client will be authorizedfor. Examples of possible SMTP clients authorizations are:
  • Send a message to a remote recipient.
  • Use a specific envelope sender in the MAIL FROM command.
These permissions are not enabled by default.

Mail relay authorization

With permit_sasl_authenticated the Postfix SMTPserver can allowSASL-authenticated SMTP clients to send mail to remote destinations.Examples:
# With Postfix 2.10 and later, the mail relay policy is# preferably specified under smtpd_relay_restrictions./etc/postfix/main.cf:    smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination
# Older configurations combine relay control and spam control under# smtpd_recipient_restrictions. To use this example with Postfix ≥# 2.10 specify "smtpd_relay_restrictions="./etc/postfix/main.cf:    smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination ...other rules...
  
Skipping other options

Testing SASL authentication in the Postfix SMTP Server

To test the server side, connect (for example, withtelnet) to the Postfix SMTP server port and you shouldbe able to have a conversation as shown below. Information sent bythe client (that is, you) is shown in bold font.
% telnet server.example.com 25...220 server.example.com ESMTP PostfixEHLO client.example.com250-server.example.com250-PIPELINING250-SIZE 10240000250-ETRN250-AUTH DIGEST-MD5 PLAIN CRAM-MD5250 8BITMIMEAUTH PLAIN AHRlc3QAdGVzdHBhc3M=235 Authentication successful

And...let the errors begin...checking the logs I see:


I set up port 25 with no tls to test plain login (since testing on a secure TLS port can't see anything). I didn't exactly read the above and with TLS you first must establish the TLS connection, then do the authentication, which you can't do through Telent (see next test).

First I get this error related to mismatch between some options:

The problem is a mis-match between smtpd_sasl_security_options
(e.g., noplaintext) and the available server mechanisms (e.g.,
plaintext only). 


In otherwords remove noplaintext from main.cf because we're using TLS to encrypt traffic. OK now I can connect again...

And I see AUTH PLAIN LOGIN when I telnet to the server on port 25 and do an EHLO (see previous post for more info)

Next error. Tried test above to test a login from Telnet

AUTH PLAIN AHRlc3QAdGVzdHBhc3M=

 
Ok darnitalll now we have a new error...

I test using the telnet example shown above and I get this error:

535 5.7.8 Error: authentication failed: no mechanism available.

I found that in my smtpd.conf file I had a space instead of an underscore in pw

Restart - no dice.

Out of curiosity I search for smtpd.conf and find three versions:

/usr/lib/sasl2/smtpd.conf
/var/run/saslauthd/smtpd.conf
/etc/sasl2/smtpd.conf

Which one is being used? The documentation above says the first in the list.

Not true!! Argh.

/var/run/saslauthd/smtpd.conf was empty. I renamed it and restarted - same error.

Then I checked /etc/sasl2/smtpd.conf and I had altered that file at some point. I changed pwd_check back to saslauthd.

Restart.

Authentication successful! Oh the agony of unhelpful error messages and inaccurate documentation and open source crypticness....yes I just made that word up.

Now. Let's see about authentication over TLS...crossing fingers.

So first I test from an app that was working fine before I moved everything to the Amazon cloud. Sending an email from a web site. No dice.

I can see that my web app is able to connect to and negotiate a connection with the mail server because I see the connection attempt in the maillog

sudo tail -f /var/log/maillog

lost connection after UNKNOWN from unknown 
disconnect from unknown

I can only assume at this point it's some kind of problem with TLS or relay.

 So let's try this example below and see what happens...

To test this over a connection that is encrypted with TLS, useopenssl s_client instead of telnet:
% openssl s_client -connect server.example.com:25 -starttls smtp...220 server.example.com ESMTP PostfixEHLO client.example.com...see above example for more...
Lovely. Again no worky. Does anyone find this as painful as I do yet?

getaddrinfo: Name or service not known
connect:errno=2


Oops. Typed the example and forgot to change domain name.

Here's a page with some error codes:
 

http://tud.at/programm/apache-ssl-win32-howto.php3

ok typing with correct domain it seems to attempt to connect to TLS but times out:

socket: Connection timed out
connect:errno=110


And in the case of a local connection from the same box using domain name it times out so maybe it's VPC/firewall thing. Try the local IP: 127.0.0.1 instead of the domain name. 

Ok something useful at least. Maybe:

139834971027272:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:766:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 228 bytes and written 206 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
 

I found some sites suggesting to take the passphrase off the key -- same error
http://www.mnxsolutions.com/apache/removing-a-passphrase-from-an-ssl-key.html


Could be a problem with OpenSSL library - not sure yet.

http://comments.gmane.org/gmane.mail.postfix.user/228998

Instead of AHRlc3QAdGVzdHBhc3M=, specify thebase64-encoded form of \0username\0password (the \0is a null byte). The example above is for a user named `test'with password `testpass'.
Caution When posting logs of the SASL negotiations to public lists,please keep in mind that username/password information is trivialto recover from the base64-encoded form.
You can use one of the following commands to generate base64encoded authentication information:
  • Using a recent version of the bash shell:
    % echo -ne '\000username\000password' | openssl base64
    Some other shells support similar syntax.
  • Using the printf command:
    % printf '\0%s\0%s' 'username' 'password' | openssl base64% printf '\0%s\0%s' 'username' 'password' | mmencode
    The mmencode command is part of the metamailsoftware.
  • Using Perl MIME::Base64:
    % perl -MMIME::Base64 -e \    'print encode_base64("\0username\0password");'