Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  smtp_sasl_glue.c

  Sprache: C
 

/*++
/* NAME
/* smtp_sasl_glue 3
/* SUMMARY
/* Postfix SASL interface for SMTP client
/* SYNOPSIS
/* #include smtp_sasl.h
/*
/* void smtp_sasl_initialize()
/*
/* void smtp_sasl_connect(session)
/* SMTP_SESSION *session;
/*
/* void smtp_sasl_start(session, sasl_opts_name, sasl_opts_val)
/* SMTP_SESSION *session;
/*
/* int     smtp_sasl_passwd_lookup(session)
/* SMTP_SESSION *session;
/*
/* int smtp_sasl_authenticate(session, why)
/* SMTP_SESSION *session;
/* DSN_BUF *why;
/*
/* void smtp_sasl_cleanup(session)
/* SMTP_SESSION *session;
/*
/* void smtp_sasl_passivate(session, buf)
/* SMTP_SESSION *session;
/* VSTRING *buf;
/*
/* int smtp_sasl_activate(session, buf)
/* SMTP_SESSION *session;
/* char *buf;
/* DESCRIPTION
/* smtp_sasl_initialize() initializes the SASL library. This
/* routine must be called once at process startup, before any
/* chroot operations.
/*
/* smtp_sasl_connect() performs per-session initialization. This
/* routine must be called once at the start of each connection.
/*
/* smtp_sasl_start() performs per-session initialization. This
/* routine must be called once per session before doing any SASL
/* authentication. The sasl_opts_name and sasl_opts_val parameters are
/* the postfix configuration parameters setting the security
/* policy of the SASL authentication.
/*
/* smtp_sasl_passwd_lookup() looks up the username/password
/* for the current SMTP server. The result is zero in case
/* of failure, a long jump in case of error.
/*
/* smtp_sasl_authenticate() implements the SASL authentication
/* dialog. The result is < 0 in case of protocol failure, zero in
/* case of unsuccessful authentication, > 0 in case of success.
/* The why argument is updated with a reason for failure.
/* This routine must be called only when smtp_sasl_passwd_lookup()
/* succeeds.
/*
/* smtp_sasl_cleanup() cleans up. It must be called at the
/* end of every SMTP session that uses SASL authentication.
/* This routine is a noop for non-SASL sessions.
/*
/* smtp_sasl_passivate() appends flattened SASL attributes to the
/* specified buffer. The SASL attributes are not destroyed.
/*
/* smtp_sasl_activate() restores SASL attributes from the
/* specified buffer. The buffer is modified. A result < 0
/* means there was an error.
/*
/* Arguments:
/* .IP session
/* Session context.
/* .IP mech_list
/* String of SASL mechanisms (separated by blanks)
/* DIAGNOSTICS
/* All errors are fatal.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Original author:
/* Till Franke
/* SuSE Rhein/Main AG
/* 65760 Eschborn, Germany
/*
/* Adopted by:
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/


 /*
  * System library.
  */

#include <sys_defs.h>
#include <stdlib.h>
#include <string.h>

 /*
  * Utility library
  */

#include <msg.h>
#include <mymalloc.h>
#include <stringops.h>
#include <split_at.h>

 /*
  * Global library
  */

#include <mail_params.h>
#include <string_list.h>
#include <maps.h>
#include <mail_addr_find.h>
#include <smtp_stream.h>

 /*
  * XSASL library.
  */

#include <xsasl.h>

 /*
  * Application-specific
  */

#include "smtp.h"
#include "smtp_sasl.h"
#include "smtp_sasl_auth_cache.h"

#ifdef USE_SASL_AUTH

 /*
  * Per-host login/password information.
  */

static MAPS *smtp_sasl_passwd_map;

 /*
  * Supported SASL mechanisms.
  */

STRING_LIST *smtp_sasl_mechs;

 /*
  * SASL implementation handle.
  */

static XSASL_CLIENT_IMPL *smtp_sasl_impl;

 /*
  * The 535 SASL authentication failure cache.
  */

#ifdef HAVE_SASL_AUTH_CACHE
static SMTP_SASL_AUTH_CACHE *smtp_sasl_auth_cache;

#endif

/* smtp_sasl_passwd_lookup - password lookup routine */

int     smtp_sasl_passwd_lookup(SMTP_SESSION *session)
{
    const char *myname = "smtp_sasl_passwd_lookup";
    SMTP_STATE *state = session->state;
    SMTP_ITERATOR *iter = session->iterator;
    const char *value;
    char   *passwd;

    /*
     * Sanity check.
     */

    if (smtp_sasl_passwd_map == 0)
 msg_panic("%s: passwd map not initialized", myname);

    /*
     * Look up the per-server password information. Try the hostname first,
     * then try the destination.
     * 
     * XXX Instead of using nexthop (the intended destination) we use dest
     * (either the intended destination, or a fall-back destination).
     * 
     * XXX SASL authentication currently depends on the host/domain but not on
     * the TCP port. If the port is not :25, we should append it to the table
     * lookup key. Code for this was briefly introduced into 2.2 snapshots,
     * but didn't canonicalize the TCP port, and did not append the port to
     * the MX hostname.
     */

    smtp_sasl_passwd_map->error = 0;
    if ((smtp_mode
  && var_smtp_sender_auth && state->request->sender[0]
  && (value = mail_addr_find(smtp_sasl_passwd_map,
     state->request->sender, (char **) 0)) != 0)
 || (smtp_sasl_passwd_map->error == 0
     && (value = maps_find(smtp_sasl_passwd_map,
      STR(iter->host), 0)) != 0)
 || (smtp_sasl_passwd_map->error == 0
     && (value = maps_find(smtp_sasl_passwd_map,
      STR(iter->dest), 0)) != 0)) {
 if (session->sasl_username)
     myfree(session->sasl_username);
 session->sasl_username = mystrdup(value);
 /* Historically, the delimiter may appear in the password. */
 passwd = split_at(session->sasl_username,
     *var_smtp_sasl_passwd_res_delim);
 if (session->sasl_passwd)
     myfree(session->sasl_passwd);
 session->sasl_passwd = mystrdup(passwd ? passwd : "");
 if (msg_verbose)
     msg_info("%s: host `%s' user `%s' pass `%s'",
       myname, STR(iter->host),
       session->sasl_username, session->sasl_passwd);
 return (1);
    } else if (smtp_sasl_passwd_map->error) {
 msg_warn("%s: %s lookup error",
   state->request->queue_id, smtp_sasl_passwd_map->title);
 vstream_longjmp(session->stream, SMTP_ERR_DATA);
    } else {
 if (msg_verbose)
     msg_info("%s: no auth info found (sender=`%s', host=`%s')",
       myname, state->request->sender, STR(iter->host));
 return (0);
    }
}

/* smtp_sasl_initialize - per-process initialization (pre jail) */

void    smtp_sasl_initialize(void)
{

    /*
     * Sanity check.
     */

    if (smtp_sasl_passwd_map || smtp_sasl_impl)
 msg_panic("smtp_sasl_initialize: repeated call");
    if (*var_smtp_sasl_passwd == 0)
 msg_fatal("specify a password table via the `%s' configuration parameter",
    VAR_LMTP_SMTP(SASL_PASSWD));

    /*
     * Open the per-host password table and initialize the SASL library. Use
     * shared locks for reading, just in case someone updates the table.
     */

    smtp_sasl_passwd_map = maps_create(VAR_LMTP_SMTP(SASL_PASSWD),
           var_smtp_sasl_passwd,
           DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
           | DICT_FLAG_UTF8_REQUEST);
    if ((smtp_sasl_impl = xsasl_client_init(var_smtp_sasl_type,
         var_smtp_sasl_path)) == 0)
 msg_fatal("SASL library initialization");

    /*
     * Initialize optional supported mechanism matchlist
     */

    if (*var_smtp_sasl_mechs)
 smtp_sasl_mechs = string_list_init(VAR_SMTP_SASL_MECHS,
        MATCH_FLAG_NONE,
        var_smtp_sasl_mechs);

    /*
     * Initialize the 535 SASL authentication failure cache.
     */

    if (*var_smtp_sasl_auth_cache_name) {
#ifdef HAVE_SASL_AUTH_CACHE
 smtp_sasl_auth_cache =
     smtp_sasl_auth_cache_init(var_smtp_sasl_auth_cache_name,
          var_smtp_sasl_auth_cache_time);
#else
 msg_warn("not compiled with TLS support -- "
     "ignoring the %s setting", VAR_LMTP_SMTP(SASL_AUTH_CACHE_NAME));
#endif
    }
}

/* smtp_sasl_connect - per-session client initialization */

void    smtp_sasl_connect(SMTP_SESSION *session)
{

    /*
     * This initialization happens whenever we instantiate an SMTP session
     * object. We don't instantiate a SASL client until we actually need one.
     */

    session->sasl_mechanism_list = 0;
    session->sasl_username = 0;
    session->sasl_passwd = 0;
    session->sasl_client = 0;
    session->sasl_reply = 0;
}

/* smtp_sasl_start - per-session SASL initialization */

void    smtp_sasl_start(SMTP_SESSION *session, const char *sasl_opts_name,
           const char *sasl_opts_val)
{
    XSASL_CLIENT_CREATE_ARGS create_args;
    SMTP_ITERATOR *iter = session->iterator;

    if (msg_verbose)
 msg_info("starting new SASL client");
    if ((session->sasl_client =
  XSASL_CLIENT_CREATE(smtp_sasl_impl, &create_args,
        stream = session->stream,
        service = var_procname,
        server_name = STR(iter->host),
        security_options = sasl_opts_val)) == 0)
 msg_fatal("SASL per-connection initialization failed");
    session->sasl_reply = vstring_alloc(20);
}

/* smtp_sasl_authenticate - run authentication protocol */

int     smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
{
    const char *myname = "smtp_sasl_authenticate";
    SMTP_ITERATOR *iter = session->iterator;
    SMTP_RESP *resp;
    const char *mechanism;
    int     result;
    char   *line;
    int     steps = 0;

    /*
     * Sanity check.
     */

    if (session->sasl_mechanism_list == 0)
 msg_panic("%s: no mechanism list", myname);

    if (msg_verbose)
 msg_info("%s: %s: SASL mechanisms %s",
   myname, session->namaddrport, session->sasl_mechanism_list);

    /*
     * Avoid repeated login failures after a recent 535 error.
     */

#ifdef HAVE_SASL_AUTH_CACHE
    if (smtp_sasl_auth_cache
 && smtp_sasl_auth_cache_find(smtp_sasl_auth_cache, session)) {
 char   *resp_dsn = smtp_sasl_auth_cache_dsn(smtp_sasl_auth_cache);
 char   *resp_str = smtp_sasl_auth_cache_text(smtp_sasl_auth_cache);

 if (var_smtp_sasl_auth_soft_bounce && resp_dsn[0] == '5')
     resp_dsn[0] = '4';
 dsb_update(why, resp_dsn, DSB_DEF_ACTION, DSB_MTYPE_DNS,
     STR(iter->host), var_procname, resp_str,
     "SASL [CACHED] authentication failed; server %s said: %s",
     STR(iter->host), resp_str);
 return (0);
    }
#endif

    /*
     * Start the client side authentication protocol.
     */

    result = xsasl_client_first(session->sasl_client,
    session->sasl_mechanism_list,
    session->sasl_username,
    session->sasl_passwd,
    &mechanism, session->sasl_reply);
    if (result != XSASL_AUTH_OK) {
 dsb_update(why, "4.7.0", DSB_DEF_ACTION, DSB_SKIP_RMTA,
     DSB_DTYPE_SASL, STR(session->sasl_reply),
     "SASL authentication failed; "
     "cannot authenticate to server %s: %s",
     session->namaddr, STR(session->sasl_reply));
 return (-1);
    }
    /*-
     * Send the AUTH command and the optional initial client response.
     *
     * https://tools.ietf.org/html/rfc4954#page-4
     * Note that the AUTH command is still subject to the line length
     * limitations defined in [SMTP].  If use of the initial response argument
     * would cause the AUTH command to exceed this length, the client MUST NOT
     * use the initial response parameter...
     *
     * https://tools.ietf.org/html/rfc5321#section-4.5.3.1.4
     * The maximum total length of a command line including the command word
     * and the <CRLF> is 512 octets.
     *
     * Defer the initial response if the resulting command exceeds the limit.
     */

    if (LEN(session->sasl_reply) > 0
 && strlen(mechanism) + LEN(session->sasl_reply) + 8 <= 512) {
 smtp_chat_cmd(session, "AUTH %s %s", mechanism,
        STR(session->sasl_reply));
 VSTRING_RESET(session->sasl_reply); /* no deferred initial reply */
    } else {
 smtp_chat_cmd(session, "AUTH %s", mechanism);
    }

    /*
     * Step through the authentication protocol until the server tells us
     * that we are done.  If session->sasl_reply is non-empty we have a
     * deferred initial reply and expect an empty initial challenge from the
     * server. If the server's initial challenge is non-empty we have a SASL
     * protocol violation with both sides wanting to go first.
     */

    while ((resp = smtp_chat_resp(session))->code / 100 == 3) {

 /*
  * Sanity check.
 */

 if (++steps > 100) {
     dsb_simple(why, "4.3.0""SASL authentication failed; "
         "authentication protocol loop with server %s",
         session->namaddr);
     return (-1);
 }

 /*
  * Process a server challenge.
 */

 line = resp->str;
 (void) mystrtok(&line, "- \t\n"); /* skip over result code */

 if (LEN(session->sasl_reply) > 0) {

     /*
      * Deferred initial response, the server challenge must be empty.
      * Cleared after actual transmission to the server.
     */

     if (*line) {
  dsb_update(why, "4.7.0", DSB_DEF_ACTION,
      DSB_SKIP_RMTA, DSB_DTYPE_SASL, "protocol error",
      "SASL authentication failed; non-empty initial "
      "%s challenge from server %s: %s", mechanism,
      session->namaddr, STR(session->sasl_reply));
  return (-1);
     }
 } else {
     result = xsasl_client_next(session->sasl_client, line,
           session->sasl_reply);
     if (result != XSASL_AUTH_OK) {
  dsb_update(why, "4.7.0", DSB_DEF_ACTION, /* Fix 200512 */
      DSB_SKIP_RMTA, DSB_DTYPE_SASL, STR(session->sasl_reply),
      "SASL authentication failed; "
      "cannot authenticate to server %s: %s",
      session->namaddr, STR(session->sasl_reply));
  return (-1);   /* Fix 200512 */
     }
 }

 /*
  * Send a client response.
 */

 smtp_chat_cmd(session, "%s", STR(session->sasl_reply));
 VSTRING_RESET(session->sasl_reply); /* clear initial reply */
    }

    /*
     * We completed the authentication protocol.
     */

    if (resp->code / 100 != 2) {
#ifdef HAVE_SASL_AUTH_CACHE
 /* Update the 535 authentication failure cache. */
 if (smtp_sasl_auth_cache && resp->code == 535)
     smtp_sasl_auth_cache_store(smtp_sasl_auth_cache, session, resp);
#endif
 if (var_smtp_sasl_auth_soft_bounce && resp->code / 100 == 5)
     STR(resp->dsn_buf)[0] = '4';
 dsb_update(why, resp->dsn, DSB_DEF_ACTION,
     DSB_MTYPE_DNS, STR(iter->host),
     var_procname, resp->str,
     "SASL authentication failed; server %s said: %s",
     session->namaddr, resp->str);
 return (0);
    }
    return (1);
}

/* smtp_sasl_cleanup - per-session cleanup */

void    smtp_sasl_cleanup(SMTP_SESSION *session)
{
    if (session->sasl_username) {
 myfree(session->sasl_username);
 session->sasl_username = 0;
    }
    if (session->sasl_passwd) {
 myfree(session->sasl_passwd);
 session->sasl_passwd = 0;
    }
    if (session->sasl_mechanism_list) {
 /* allocated in smtp_sasl_helo_auth */
 myfree(session->sasl_mechanism_list);
 session->sasl_mechanism_list = 0;
    }
    if (session->sasl_client) {
 if (msg_verbose)
     msg_info("disposing SASL state information");
 xsasl_client_free(session->sasl_client);
 session->sasl_client = 0;
    }
    if (session->sasl_reply) {
 vstring_free(session->sasl_reply);
 session->sasl_reply = 0;
    }
}

/* smtp_sasl_passivate - append serialized SASL attributes */

void    smtp_sasl_passivate(SMTP_SESSION *session, VSTRING *buf)
{
}

/* smtp_sasl_activate - de-serialize SASL attributes */

int     smtp_sasl_activate(SMTP_SESSION *session, char *buf)
{
    return (0);
}

#endif

Messung V0.5 in Prozent
C=72 H=94 G=83

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=752002