Eine aufbereitete Darstellung der Quelle

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

Benutzer

SSL transport.c   Sprache: C

 

/*++
/* NAME
/* transport 3
/* SUMMARY
/* transport mapping
/* SYNOPSIS
/* #include "transport.h"
/*
/* TRANSPORT_INFO *transport_pre_init(maps_name, maps)
/* const char *maps_name;
/* const char *maps;
/*
/* void transport_post_init(info)
/* TRANSPORT_INFO *info;
/*
/* int transport_lookup(info, address, rcpt_domain, channel, nexthop)
/* TRANSPORT_INFO *info;
/* const char *address;
/* const char *rcpt_domain;
/* VSTRING *channel;
/* VSTRING *nexthop;
/*
/* void transport_free(info);
/* TRANSPORT_INFO * info;
/* DESCRIPTION
/* This module implements access to the table that maps transport
/* user@domain addresses to (channel, nexthop) tuples.
/*
/* transport_pre_init() performs initializations that should be
/* done before the process enters the chroot jail, and
/* before calling transport_lookup().
/*
/* transport_post_init() can be invoked after entering the chroot
/* jail, and must be called before calling transport_lookup().
/*
/* transport_lookup() finds the channel and nexthop for the given
/* domain, and returns 1 if something was found. Otherwise, 0
/* is returned.
/* DIAGNOSTICS
/* info->transport_path->error is non-zero when the lookup
/* should be tried again.
/* SEE ALSO
/* maps(3), multi-dictionary search
/* strip_addr(3), strip extension from address
/* transport(5), format of transport map
/* CONFIGURATION PARAMETERS
/* transport_maps, names of maps to be searched.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* 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 <string.h>

/* Utility library. */

#include <msg.h>
#include <stringops.h>
#include <mymalloc.h>
#include <vstring.h>
#include <split_at.h>
#include <dict.h>
#include <events.h>

/* Global library. */

#include <strip_addr.h>
#include <mail_params.h>
#include <mail_addr_find.h>
#include <match_parent_style.h>
#include <mail_proto.h>

/* Application-specific. */

#include "transport.h"

static int transport_match_parent_style;

#define STR(x) vstring_str(x)

static void transport_wildcard_init(TRANSPORT_INFO *);

/* transport_pre_init - pre-jail initialization */

TRANSPORT_INFO *transport_pre_init(const char *transport_maps_name,
               const char *transport_maps)
{
    TRANSPORT_INFO *tp;

    tp = (TRANSPORT_INFO *) mymalloc(sizeof(*tp));
    tp->transport_path = maps_create(transport_maps_name, transport_maps,
         DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
         | DICT_FLAG_NO_REGSUB
         | DICT_FLAG_UTF8_REQUEST);
    tp->wildcard_channel = tp->wildcard_nexthop = 0;
    tp->wildcard_errno = 0;
    tp->expire = 0;
    return (tp);
}

/* transport_post_init - post-jail initialization */

void    transport_post_init(TRANSPORT_INFO *tp)
{
    transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS);
    transport_wildcard_init(tp);
}

/* transport_free - destroy transport info */

void    transport_free(TRANSPORT_INFO *tp)
{
    if (tp->transport_path)
 maps_free(tp->transport_path);
    if (tp->wildcard_channel)
 vstring_free(tp->wildcard_channel);
    if (tp->wildcard_nexthop)
 vstring_free(tp->wildcard_nexthop);
    myfree((void *) tp);
}

/* update_entry - update from transport table entry */

static void update_entry(const char *new_channel, const char *new_nexthop,
            const char *rcpt_domain, VSTRING *channel,
            VSTRING *nexthop)
{

    /*
     * :[nexthop] means don't change the channel, and don't change the
     * nexthop unless a non-default nexthop is specified. Thus, a right-hand
     * side of ":" is the transport table equivalent of a NOOP.
     */

    if (*new_channel == 0) {   /* :[nexthop] */
 if (*new_nexthop != 0)
     vstring_strcpy(nexthop, new_nexthop);
    }

    /*
     * transport[:[nexthop]] means change the channel, and reset the nexthop
     * to the default unless a non-default nexthop is specified.
     */

    else {
 vstring_strcpy(channel, new_channel);
 if (*new_nexthop != 0)
     vstring_strcpy(nexthop, new_nexthop);
 else if (strcmp(STR(channel), MAIL_SERVICE_ERROR) != 0
   && strcmp(STR(channel), MAIL_SERVICE_RETRY) != 0)
     vstring_strcpy(nexthop, rcpt_domain);
 else
     vstring_strcpy(nexthop, "Address is undeliverable");
    }
}

/* parse_transport_entry - parse transport table entry */

static void parse_transport_entry(const char *value, const char *rcpt_domain,
              VSTRING *channel, VSTRING *nexthop)
{
    char   *saved_value;
    const char *host;

#define FOUND  1
#define NOTFOUND 0

    /*
     * It would be great if we could specify a recipient address in the
     * lookup result. Unfortunately, we cannot simply run the result through
     * a parser that recognizes "transport:user@domain" because the lookup
     * result can have arbitrary content (especially in the case of the error
     * mailer).
     */

    saved_value = mystrdup(value);
    host = split_at(saved_value, ':');
    update_entry(saved_value, host ? host : "", rcpt_domain, channel, nexthop);
    myfree(saved_value);
}

/* transport_wildcard_init - (re) initialize wild-card lookup result */

static void transport_wildcard_init(TRANSPORT_INFO *tp)
{
    VSTRING *channel = vstring_alloc(10);
    VSTRING *nexthop = vstring_alloc(10);
    const char *value;

    /*
     * Both channel and nexthop may be zero-length strings. Therefore we must
     * use something else to represent "wild-card does not exist". We use
     * null VSTRING pointers, for historical reasons.
     */

    if (tp->wildcard_channel)
 vstring_free(tp->wildcard_channel);
    if (tp->wildcard_nexthop)
 vstring_free(tp->wildcard_nexthop);

    /*
     * Technically, the wildcard lookup pattern is redundant. A static map
     * (keys always match, result is fixed string) could achieve the same:
     * 
     * transport_maps = hash:/etc/postfix/transport static:xxx:yyy
     * 
     * But the user interface of such an approach would be less intuitive. We
     * tolerate the continued existence of wildcard lookup patterns because
     * of human interface considerations.
     */

#define WILDCARD "*"
#define FULL  0
#define PARTIAL  DICT_FLAG_FIXED

    if ((value = maps_find(tp->transport_path, WILDCARD, FULL)) != 0) {
 parse_transport_entry(value, "", channel, nexthop);
 tp->wildcard_errno = 0;
 tp->wildcard_channel = channel;
 tp->wildcard_nexthop = nexthop;
 if (msg_verbose)
     msg_info("wildcard_{chan:hop}={%s:%s}",
       vstring_str(channel), vstring_str(nexthop));
    } else {
 tp->wildcard_errno = tp->transport_path->error;
 vstring_free(channel);
 vstring_free(nexthop);
 tp->wildcard_channel = 0;
 tp->wildcard_nexthop = 0;
    }
    tp->expire = event_time() + 30;  /* XXX make configurable */
}

/* transport_lookup - map a transport domain */

int     transport_lookup(TRANSPORT_INFO *tp, const char *addr,
            const char *rcpt_domain,
            VSTRING *channel, VSTRING *nexthop)
{
    char   *ratsign = 0;
    const char *value;

#define STREQ(x,y) (strcmp((x), (y)) == 0)
#define DISCARD_EXTENSION ((char **) 0)

    /*
     * The null recipient is rewritten to the local mailer daemon address.
     */

    if (*addr == 0) {
 msg_warn("transport_lookup: null address - skipping table lookup");
 return (NOTFOUND);
    }

    /*
     * Look up the full and extension-stripped address, then match the domain
     * and subdomains. Try the external form before the backwards-compatible
     * internal form.
     */

#define LOOKUP_STRATEGY \
 (MA_FIND_FULL | MA_FIND_NOEXT | MA_FIND_DOMAIN | \
 (transport_match_parent_style == MATCH_FLAG_PARENT ? \
  MA_FIND_PDMS : MA_FIND_PDDMDS))

    if ((ratsign = strrchr(addr, '@')) == 0 || ratsign[1] == 0)
 msg_panic("transport_lookup: bad address: \"%s\"", addr);

    if ((value = mail_addr_find_strategy(tp->transport_path, addr, (char **) 0,
      LOOKUP_STRATEGY)) != 0) {
 parse_transport_entry(value, rcpt_domain, channel, nexthop);
 return (FOUND);
    }
    if (tp->transport_path->error != 0)
 return (NOTFOUND);

    /*
     * Fall back to the wild-card entry.
     */

    if (tp->wildcard_errno || event_time() > tp->expire)
 transport_wildcard_init(tp);
    if (tp->wildcard_errno) {
 tp->transport_path->error = tp->wildcard_errno;
 return (NOTFOUND);
    } else if (tp->wildcard_channel) {
 update_entry(STR(tp->wildcard_channel), STR(tp->wildcard_nexthop),
       rcpt_domain, channel, nexthop);
 return (FOUND);
    }

    /*
     * We really did not find it.
     */

    return (NOTFOUND);
}

#ifdef TEST

 /*
  * Proof-of-concept test program. Read an address from stdin, and spit out
  * the lookup result.
  */


#include <string.h>

#include <mail_conf.h>
#include <vstream.h>
#include <vstring_vstream.h>

static NORETURN usage(const char *progname)
{
    msg_fatal("usage: %s [-v] database", progname);
}

int     main(int argc, char **argv)
{
    VSTRING *buffer = vstring_alloc(100);
    VSTRING *channel = vstring_alloc(100);
    VSTRING *nexthop = vstring_alloc(100);
    TRANSPORT_INFO *tp;
    char   *bp;
    char   *addr_field;
    char   *rcpt_domain;
    char   *expect_channel;
    char   *expect_nexthop;
    int     status;
    int     ch;
    int     errs = 0;

    /*
     * Parse JCL.
     */

    while ((ch = GETOPT(argc, argv, "v")) > 0) {
 switch (ch) {
 case 'v':
     msg_verbose++;
     break;
 default:
     usage(argv[0]);
 }
    }
    if (argc != optind + 1)
 usage(argv[0]);

    /*
     * Initialize.
     */

#define UPDATE(var, val) do { myfree(var); var = mystrdup(val); } while (0)

    mail_conf_read();    /* XXX eliminate dependency. */
    UPDATE(var_rcpt_delim, "+");
    UPDATE(var_mydomain, "localdomain");
    UPDATE(var_myorigin, "localhost.localdomain");
    UPDATE(var_mydest, "localhost.localdomain");

    tp = transport_pre_init("transport map", argv[optind]);
    transport_post_init(tp);

    while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
 bp = STR(buffer);

 /*
  * Parse the input and expectations. XXX We can't expect empty
  * fields, so require '-' instead.
 */

 if ((addr_field = mystrtok(&bp, ":")) == 0)
     msg_fatal("no address field");
 if ((rcpt_domain = strrchr(addr_field, '@')) == 0)
     msg_fatal("no recipient domain");
 rcpt_domain += 1;
 expect_channel = mystrtok(&bp, ":");
 expect_nexthop = mystrtok(&bp, ":");
 if ((expect_channel != 0) != (expect_nexthop != 0))
     msg_fatal("specify both channel and nexthop, or specify neither");
 if (expect_channel) {
     if (strcmp(expect_channel, "-") == 0)
  *expect_channel = 0;
     if (strcmp(expect_nexthop, "-") == 0)
  *expect_nexthop = 0;
     vstring_strcpy(channel, "DEFAULT");
     vstring_strcpy(nexthop, rcpt_domain);
 }
 if (mystrtok(&bp, ":") != 0)
     msg_fatal("garbage after nexthop field");

 /*
  * Lookups.
 */

 status = transport_lookup(tp, addr_field, rcpt_domain,
      channel, nexthop);

 /*
  * Enforce expectations.
 */

 if (expect_nexthop && status) {
     vstream_printf("%s:%s -> %s:%s \n",
      addr_field, rcpt_domain,
      STR(channel), STR(nexthop));
     vstream_fflush(VSTREAM_OUT);
     if (strcmp(expect_channel, STR(channel)) != 0) {
  msg_warn("expect channel '%s' but got '%s'",
    expect_channel, STR(channel));
  errs = 1;
     }
     if (strcmp(expect_nexthop, STR(nexthop)) != 0) {
  msg_warn("expect nexthop '%s' but got '%s'",
    expect_nexthop, STR(nexthop));
  errs = 1;
     }
 } else if (expect_nexthop && !status) {
     vstream_printf("%s:%s -> %s\n", addr_field, rcpt_domain,
      tp->transport_path->error ?
      "(try again)" : "(not found)");
     vstream_fflush(VSTREAM_OUT);
     msg_warn("expect channel '%s' but got none", expect_channel);
     msg_warn("expect nexthop '%s' but got none", expect_nexthop);
     errs = 1;
 } else if (!status) {
     vstream_printf("%s:%s -> %s\n", addr_field, rcpt_domain,
      tp->transport_path->error ?
      "(try again)" : "(not found)");
 }
    }
    transport_free(tp);
    vstring_free(nexthop);
    vstring_free(channel);
    vstring_free(buffer);
    exit(errs != 0);
}

#endif

Messung V0.5 in Prozent
C=80 H=93 G=86

¤ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet am  2026-09-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Anfrage:

Dauer der Verarbeitung:

Sekunden

sprechenden Kalenders






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

letze Version des Elbe Quellennavigators


Jenseits des Üblichen ....
    

Besucher

Besucher

Statistik
#Sources=1126438
#Domains=1897691