GNU SASL examples/saml20/README -- Explanation of SMTP SAML 2.0 example.
Copyright (C) 2012-2026 Simon Josefsson
See the end for copying conditions.

This directory holds a GNU SASL example application that implements a
SMTP server with SAML 2.0 authentication support.  The SAML
implementation used is Lasso: http://lasso.entrouvert.org/

It should be noted that this is just an example of how it could work.
You don't need to implement it this way.  For example, sometimes
having a Apache/PHP web server running is a problem.  Then you could
use something like MicroHTTPD and implement everything in one process
using Lasso in C.  Then you don't need any IPC stuff.  Also, you could
also want to use another SAML implementation instead of Lasso.  The
point of this example is just to proof that it works.

This setup was tested with GNU SASL version 1.7.3.

There is one example SMTP server and some helper tools that implement
the actual SAML part:

  smtp-server-saml20.c:

      The actual SMTP server, based on ../smtp-server.c.  It invokes
      gsasl-saml20-request.c to generate the request, and then waits
      for gsasl-saml20-sp.php to accept the SAML response.

  gsasl-saml20-request.c

      Given a Identity Provider identifier it generates a SAML Request
      and prints a user redirect URL.  This tool is invoked by
      smtp-server-saml20.c.  It uses Lasso as the SAML library.

  gsasl-saml20-sp.php:

      This is the SAML SP responsible for accepting SAML Responses.
      Intended to be invoked via a webserver.

These three tools communicate with each other using a simple
file-based IPC interface, normally placed below /tmp/gsasl-saml20/.

Install the SAML SP:

  The "gsasl-saml20-sp.php" script needs to be install so that it is
  reachable under some URL via a web server.  This is the
  AssertionConsumerService (ACS) for the GNU SASL SP.  For example, on
  interop.josefsson.org I make the ACS available as

    http://interop.josefsson.org/gsasl-saml20-sp.php

  by copying the file into

    /var/www/gsasl-saml20-sp.php

  Configure the tool by specifying the state and configuration
  directories in a file called gsasl-saml20-config.php in the same
  directory, like this:

  echo '<?php $state_path = "/tmp/gsasl-saml20"; $cfg_path = "/etc/gsasl-saml20"; ?>' > /var/www/gsasl-saml20-config.php

  Of course you can chose different paths, but then you need to update
  the paths accordingly in the rest of this documentation.

Create SAML SP configuration:

  /etc/gsasl-saml20/sp-key.pem
  /etc/gsasl-saml20/sp-crt.pem

    This is a private key and certificate for your SP.  It can be
    self-signed.  You may generate the files with GnuTLS like this:

    certtool -p --outfile sp-key.pem
    echo 'organization=My SP' > sp-crt.template
    certtool --generate-self-signed --load-privkey sp-key.pem
             --template sp-crt.template --outfile sp-crt.pem

    Currently the private key is not used to sign requests.

  /etc/gsasl-saml20/sp-metadata.xml

    This is specific for your SP.  Use sp-metadata.xml as a starting
    point if you are unsure, and use a text editor to modify it.  You
    need to:

      1) Change the entityID to something (the URL does not have to
         resolve to anything, but should be unique to this SP).

      2) Replace the ACS URL to point at your gsasl-saml20-sp.php.

      3) Replace the certificate data (in two places) with the base64
         data from sp-crt.pem.

      4) Update with your contact information at the bottom.

    You may want to make the SP metadata reachable over the web as
    well, for example by doing:

      ln -s /etc/gsasl-saml20/sp-metadata.xml /var/www/

  /etc/gsasl-saml20/IDP/idp-metadata.xml

    This is the XML metadata for each IdP.  Replace "IDP" in the
    filename with the Identity Provider Identifier you expect users to
    type.

  /etc/gsasl-saml20/openidp.feide.no/idp-metadata.xml

    Here we used Feide OpenIdP as an example.  The content of
    idp-metadata.xml is retrieved from the IdP.  For Feide OpenIdP you
    can retrieve it from the following URL:

    https://openidp.feide.no/simplesaml/saml2/idp/metadata.php

  /etc/gsasl-saml20/idp.protectnetwork.org/idp-metadata.xml

    As the second test IdP we used Protect Network.  You can retrieve
    the file from here:

      http://www.protectnetwork.org/protectnetwork-metadata.xml

    Lasso requires that the KeyDescriptor tags are qualified with
    attributes use="signing" or use="encryption" respectively, so you
    need to modify the file slightly.

Here is the normal process:

1) Start the example SMTP server "smtp-server-saml20", for example
   when running it on the interop.josefsson.org server the following
   is used:

     su -c "env LD_LIBRARY_PATH=/root/gsasl/lib/src/.libs PATH=$PATH:/root/gsasl/examples/saml20 nohup /root/gsasl/examples/saml20/smtp-server-saml20 2001 /etc/gsasl-saml20 /tmp/gsasl-saml20 /etc/gsasl-saml20/sp-metadata.xml /etc/gsasl-saml20/sp-key.pem /etc/gsasl-saml20/sp-crt.pem 2>&1 | logger -t saml20" www-data &

   For permission reasons, you should run the server under the same
   user as the webserver runs gsasl-saml20-sp.php.

   The "gsasl-saml20" tool takes some parameters, the port, the
   configuration directory, the IPC directory, and the metadata, key
   and certificate for the SP.

2) The smtp-server-saml20 receives incoming connections from clients.
   The client sends the Identity Provider Identifier.  You may use the
   gsasl command line tool to act as a client.  For example:

jas@latte:~$ gsasl --smtp -m SAML20 interop.josefsson.org 2001
Trying ‘interop.josefsson.org’...
220 localhost ESMTP GNU SASL smtp-server
EHLO [127.0.0.1]
250-localhost
250 AUTH ANONYMOUS EXTERNAL LOGIN PLAIN SECURID DIGEST-MD5 CRAM-MD5 SCRAM-SHA-1 SAML20 OPENID20
EHLO [127.0.0.1]
250-localhost
250 AUTH ANONYMOUS EXTERNAL LOGIN PLAIN SECURID DIGEST-MD5 CRAM-MD5 SCRAM-SHA-1 SAML20 OPENID20
AUTH SAML20
334
Enter SAML authentication identifier (e.g. "http://example.org/"):

   At the prompt, you could type for example "openidp.feide.no".

3) smtp-server-saml20 invokes "gsasl-saml20-request" to get the
   redirect URL, which is also stored in this file:

   /tmp/gsasl-saml20/SESSIONID/redirect_url

   The SESSIONID will be unique for every SAML Request, it looks for
   example like "_B6F098F6D17C63796A9DF3BB63EF58AA".

4) The server continue with the SMTP authentication process, the
   output from the gsasl client looks like:

biwsb3BlbmlkcC5mZWlkZS5ubw==
334 aHR0cHM6Ly9vcGVuaWRwLmZlaWRlLm5vL3NpbXBsZXNhbWwvc2FtbDIvaWRwL1NTT1NlcnZpY2UucGhwP1NBTUxSZXF1ZXN0PWZaRlBiNE13RE1XJTJGQ3NvZFFzdEthUVJJdEF5cDB2NVVZOXBobHltaXBzMFVraXdPM2ZidEIxU2R0a3N2UGp6N0p6OCUyRnA4ZzdhVmpSdTZONmdvOGUwSGxmblZUSXBrWkdlcXVZNWlpUUtkNEJNdGV3dXJpJTJGWSUyRk1nWk1acXB4c3R5UiUyRmtPc0VSd1RxaEZmRzJaVWJlMW5FVnJwSXFMbWZMVFJ3dFYzR3hLcXRvdlk2ajIycVJGQVh4WHNEaU1KJTJCUkFSOGd4QjYyQ2gxWGJwREMyZHdQYiUyRnhaOGh3bWJMRmcwZXlWZU9Wd2cxRGNUZFRST1lPTVVtMUFpYjBKV2hCN0NKU21LRG9qWVhSTXh6S25RNWZXOVdNTjlpUWFDTXpSRUslMkZTdG9FcG00eTBYQ0tNRG5iREVlSUVGeVZQUjU1TnpteCUyQjJTZVVBNnROOEs0UldrU3RBbTBQOUlBY3BUJTJGdEMzMDBLZjJMcHVkWFBBeWhiY3VkbHFMNUhnMTAzRjNQZEZURTNtJTJCblVlWXNWeWhBT2VJVlV1clBqUVh1ZnMzUyUyRkx6eiUyRjhmekh3JTNEJTNEJlNpZ0FsZz1odHRwJTNBJTJGJTJGd3d3LnczLm9yZyUyRjIwMDAlMkYwOSUyRnhtbGRzaWclMjNyc2Etc2hhMSZTaWduYXR1cmU9RU1hR3JERWZFZUlXeGJSUFREazZNUXllJTJGalF1cVVsY1p0bE9Ob0VnMkVSOUxwckU4UWhSbXdpMU02QzliMnNJbEU1b01PZXUzeCUyRlM1aWJiTlV3Y1ZwMk1lRTRlWnFWdm5xQThGZzklMkJhc2FHQTY4QVpRWWxxelNGZXJqdWljWkwwN2NWVkElMkZGRWsyWmJPcGdUdGZKbWg1dWtiUXY5VUROeHUwazlkWHY4ejQwVldsVDVSRUJHYjFkUVRFMEFFczNrQyUyQlZxR0ZkUVpHYmtJeGt3MVBZblVHTkQzJTJCUnZ1OFcyTENRTGE5ZDN1RGlTUllMekhvJTJGSGZKTnhuTVFjTVliMHV0dFNQNnp2bktqJTJCSGJRTGxERUNMemxpJTJCRkFuWUYxTDBpOXo0cFFSQUthVmRNYmNHaWFBZSUyRnVoZDAlMkJUQVVRZlJraGpDRWFoS1dYeXN5OEtualIlMkY5TThDZWNUMU4lMkJ1NFV4emhVM1BDcG1zVnNUVW9ZekxYUGxWRnBod2owb0l4S2JGQUd0bnF3TktieENTV2JaUk5RJTNEJTNE
Visit this URL to proceed with authentication:
https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php?SAMLRequest=fZFPb4MwDMW%2FCsodQstKaQRItAyp0v5UY9phlymips0UkiwO3fbtB1SdtksvPjz7Jz8%2Fp8g7aVjRu6N6go8e0HlfnVTIpkZGequY5iiQKd4BMtewuri%2FY%2FMgZMZqpxstyR%2FkOsERwTqhFfG2ZUbe1nEVrpIqLmfLTRwtV3GxKqtovY6j22qRFAXxXsDiMJ%2BRAR8gxB62Ch1XbpDC2dwPb%2FxZ8hwmbLFg0eyVeOVwg1DcTdTROYOMUm1Aib0JWhB7CJSmKDojYXRMxzKnQ5fW9WMN9iQaCMzREK%2FStoEpm4y0XCKMDnbDEeIEFyVPR55Nzmx%2B2SeUA6tN8K4RWkStAm0P9IAcpT%2FtC300Kf2LpudXPAyhbcudlqL5Hg103F3PdFTE3m%2BnUeYsVyhAOeIVUurPjQXufs3S%2FLzz%2F8fzHw%3D%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=EMaGrDEfEeIWxbRPTDk6MQye%2FjQuqUlcZtlONoEg2ER9LprE8QhRmwi1M6C9b2sIlE5oMOeu3x%2FS5ibbNUwcVp2MeE4eZqVvnqA8Fg9%2BasaGA68AZQYlqzSFerjuicZL07cVVA%2FFEk2ZbOpgTtfJmh5ukbQv9UDNxu0k9dXv8z40VWlT5REBGb1dQTE0AEs3kC%2BVqGFdQZGbkIxkw1PYnUGND3%2BRvu8W2LCQLa9d3uDiSRYLzHo%2FHfJNxnMQcMYb0uttSP6zvnKj%2BHbQLlDECLzli%2BFAnYF1L0i9z4pQRAKaVdMbcGiaAe%2Fuhd0%2BTAUQfRkhjCEahKWXysy8KnjR%2F9M8CecT1N%2Bu4UxzhU3PCpmsVsTUoYzLXPlVFphwj0oIxKbFAGtnqwNKbxCSWbZRNQ%3D%3D
PQ==

5) smtp-server-saml20 waits for one of the following files to appear:

   /tmp/gsasl-saml20/_B6F098F6D17C63796A9DF3BB63EF58AA/success
   /tmp/gsasl-saml20/_B6F098F6D17C63796A9DF3BB63EF58AA/fail

6) Meanwhile the user will receive the redirect URL over the SMTP
   connection and will access the URL in his browser.  Eventually,
   after IdP approval, the browser will be redirected to the SP with
   the SAML response.

7) The gsasl-saml20-sp.php verify the SAML Response (using Lasso as
   the SAML library) and writes files to the IPC store.

8) smtp-server-saml20 notice that one of the IPC files is present and
   proceeds by reading the files and returning success/fail to the
   client as appropriate.  The client will print something like this:

235 OK [authid: _d69b0f484333df7eea73fccfd0b4dae2629f2eeb89 authzid: N/A]
Client authentication finished (server trusted)...
Enter application data (EOF to finish):

----------------------------------------------------------------------
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved.
