Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postfix/src/global/   (Postfix Mailserver Version 3.11©)  Datei vom 28.1.2024 mit Größe 19 kB image not shown  

Quelle  mail_addr_find.c

  Sprache: C
 

/*++
/* NAME
/* mail_addr_find 3
/* SUMMARY
/* generic address-based lookup
/* SYNOPSIS
/* #include <mail_addr_find.h>
/*
/* const char *mail_addr_find_int_to_ext(maps, address, extension)
/* MAPS *maps;
/* const char *address;
/* char **extension;
/*
/* const char *mail_addr_find_opt(maps, address, extension, in_form,
/* query_form, out_form, strategy)
/* MAPS *maps;
/* const char *address;
/* char **extension;
/* int in_form;
/* int in_form;
/* int out_form;
/* int strategy;
/* LEGACY SUPPORT
/* const char *mail_addr_find(maps, address, extension)
/* MAPS *maps;
/* const char *address;
/* char **extension;
/*
/* const char *mail_addr_find_to_internal(maps, address, extension)
/* MAPS *maps;
/* const char *address;
/* char **extension;
/*
/* const char *mail_addr_find_strategy(maps, address, extension)
/* MAPS *maps;
/* const char *address;
/* char **extension;
/* int strategy;
/* DESCRIPTION
/* mail_addr_find*() searches the specified maps for an entry with as
/* key the specified address, and derivations from that address.
/* It is up to the caller to specify its case sensitivity
/* preferences when it opens the maps.
/* The result is overwritten upon each call.
/*
/* In the lookup table, the key is expected to be in external
/* form (as produced with the postmap command) and the value is
/* expected to be in external (quoted) form if it is an email
/* address. Override these assumptions with the query_form
/* and out_form arguments.
/*
/* With mail_addr_find_int_to_ext(), the specified address is in
/* internal (unquoted) form, the query is made in external (quoted)
/* form, and the result is in the form found in the table (it is
/* not necessarily an email address). This version minimizes
/* internal/external (unquoted/quoted) conversions of the input,
/* query, extension, or result.
/*
/* mail_addr_find_opt() gives more control, at the cost of
/* additional conversions between internal and external forms.
/* In particular, output conversion to internal form assumes
/* that the lookup result is an email address.
/*
/* mail_addr_find() is used by legacy code that historically searched
/* with internal-form queries. The input is in internal form. It
/* searches with external-form queries first, and falls back to
/* internal-form queries if no result was found and the external
/* and internal forms differ. The result is external form (i.e. no
/* conversion).
/*
/* mail_addr_find_to_internal() is like mail_addr_find() but assumes
/* that the lookup result is one external-form email address,
/* and converts it to internal form.
/*
/* mail_addr_find_strategy() is like mail_addr_find() but overrides
/* the default search strategy for full and partial addresses.
/*
/* Arguments:
/* .IP maps
/* Dictionary search path (see maps(3)).
/* .IP address
/* The address to be looked up.
/* .IP extension
/* A null pointer, or the address of a pointer that is set to
/* the address of a dynamic memory copy of the address extension
/* that had to be chopped off in order to match the lookup tables.
/* The copy includes the recipient address delimiter.
/* The copy is in internal (unquoted) form.
/* The caller is expected to pass the copy to myfree().
/* .IP query_form
/* The address form to use for database queries: one of
/* MA_FORM_INTERNAL (unquoted form), MA_FORM_EXTERNAL (quoted form),
/* MA_FORM_EXTERNAL_FIRST (external form, then internal form if the
/* external and internal forms differ), or MA_FORM_INTERNAL_FIRST
/* (internal form, then external form if the internal and external
/* forms differ).
/* .IP in_form
/* .IP out_form
/* Input and output address forms, one of MA_FORM_INTERNAL (unquoted
/* form), or MA_FORM_EXTERNAL (quoted form).
/* .IP strategy
/* The lookup strategy for full and partial addresses, specified
/* as the binary OR of one or more of the following. These lookups
/* are implemented in the order as listed below.
/* .RS
/* .IP MA_FIND_DEFAULT
/* A convenience alias for (MA_FIND_FULL |
/* MA_FIND_NOEXT | MA_FIND_LOCALPART_IF_LOCAL |
/* MA_FIND_AT_DOMAIN).
/* .IP MA_FIND_FULL
/* Look up the full email address.
/* .IP MA_FIND_NOEXT
/* If no match was found, and the address has a localpart extension,
/* look up the address after removing the extension.
/* .IP MA_FIND_LOCALPART_IF_LOCAL
/* If no match was found, and the domain matches myorigin,
/* mydestination, or any inet_interfaces or proxy_interfaces IP
/* address, look up the localpart.  If no match was found, and the
/* address has a localpart extension, repeat the same query after
/* removing the extension unless MA_FIND_NOEXT is specified.
/* .IP MA_FIND_LOCALPART_AT_IF_LOCAL
/* As above, but using the localpart@ instead.
/* .IP MA_FIND_AT_DOMAIN
/* If no match was found, look up the @domain without localpart.
/* .IP MA_FIND_DOMAIN
/* If no match was found, look up the domain without localpart.
/* .IP MA_FIND_PDMS
/* When used with MA_FIND_DOMAIN, the domain also matches subdomains.
/* .IP MA_FIND_PDDMDS
/* When used with MA_FIND_DOMAIN, dot-domain also matches
/* dot-subdomains.
/* .IP MA_FIND_LOCALPART_AT
/* If no match was found, look up the localpart@, regardless of
/* the domain content.
/* .RE
/* DIAGNOSTICS
/* The maps->error value is non-zero when the lookup failed due to
/* a non-permanent error.
/* SEE ALSO
/* maps(3), multi-dictionary search resolve_local(3), recognize
/* local system
/* 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 <name_mask.h>
#include <dict.h>
#include <stringops.h>
#include <mymalloc.h>
#include <vstring.h>

/* Global library. */

#include <mail_params.h>
#include <strip_addr.h>
#include <mail_addr_find.h>
#include <resolve_local.h>
#include <quote_822_local.h>

/* Application-specific. */

#define STR vstring_str

#ifdef TEST

static const NAME_MASK strategy_table[] = {
    "full", MA_FIND_FULL,
    "noext", MA_FIND_NOEXT,
    "localpart_if_local", MA_FIND_LOCALPART_IF_LOCAL,
    "localpart_at_if_local", MA_FIND_LOCALPART_AT_IF_LOCAL,
    "at_domain", MA_FIND_AT_DOMAIN,
    "domain", MA_FIND_DOMAIN,
    "pdms", MA_FIND_PDMS,
    "pddms", MA_FIND_PDDMDS,
    "localpart_at", MA_FIND_LOCALPART_AT,
    "default", MA_FIND_DEFAULT,
    0, -1,
};

/* strategy_from_string - symbolic strategy flags to internal form */

static int strategy_from_string(const char *strategy_string)
{
    return (name_mask_delim_opt("strategy_from_string", strategy_table,
    strategy_string, "|",
    NAME_MASK_WARN | NAME_MASK_ANY_CASE));
}

/* strategy_to_string - internal form to symbolic strategy flags */

static const char *strategy_to_string(VSTRING *res_buf, int strategy_mask)
{
    static VSTRING *my_buf;

    if (res_buf == 0 && (res_buf = my_buf) == 0)
 res_buf = my_buf = vstring_alloc(20);
    return (str_name_mask_opt(res_buf, "strategy_to_string",
         strategy_table, strategy_mask,
         NAME_MASK_WARN | NAME_MASK_PIPE));
}

#endif

 /*
  * Specify what keys are partial or full, to avoid matching partial
  * addresses with regular expressions.
  */

#define FULL 0
#define PARTIAL DICT_FLAG_FIXED

/* find_addr - helper to search maps with the right query form */

static const char *find_addr(MAPS *path, const char *address, int flags,
              int with_domain, int query_form, VSTRING *ext_addr_buf)
{
    const char *result;

#define SANS_DOMAIN 0
#define WITH_DOMAIN 1

    switch (query_form) {

 /*
  * Query with external-form (quoted) address. The code looks a bit
  * unusual to emphasize the symmetry with the other cases.
 */

    case MA_FORM_EXTERNAL:
    case MA_FORM_EXTERNAL_FIRST:
 quote_822_local_flags(ext_addr_buf, address,
         with_domain ? QUOTE_FLAG_DEFAULT :
       QUOTE_FLAG_DEFAULT | QUOTE_FLAG_BARE_LOCALPART);
 result = maps_find(path, STR(ext_addr_buf), flags);
 if (result != 0 || path->error != 0
     || query_form != MA_FORM_EXTERNAL_FIRST
     || strcmp(address, STR(ext_addr_buf)) == 0)
     break;
 result = maps_find(path, address, flags);
 break;

 /*
  * Query with internal-form (unquoted) address. The code looks a bit
  * unusual to emphasize the symmetry with the other cases.
 */

    case MA_FORM_INTERNAL:
    case MA_FORM_INTERNAL_FIRST:
 result = maps_find(path, address, flags);
 if (result != 0 || path->error != 0
     || query_form != MA_FORM_INTERNAL_FIRST)
     break;
 quote_822_local_flags(ext_addr_buf, address,
         with_domain ? QUOTE_FLAG_DEFAULT :
       QUOTE_FLAG_DEFAULT | QUOTE_FLAG_BARE_LOCALPART);
 if (strcmp(address, STR(ext_addr_buf)) == 0)
     break;
 result = maps_find(path, STR(ext_addr_buf), flags);
 break;

 /*
  * Can't happen.
 */

    default:
 msg_panic("mail_addr_find: bad query_form: %d", query_form);
    }
    return (result);
}

/* find_local - search on localpart info */

static const char *find_local(MAPS *path, char *ratsign, int rats_offs,
                 char *int_full_key, char *int_bare_key,
                int query_form, char **extp, char **saved_ext,
                 VSTRING *ext_addr_buf)
{
    const char *myname = "mail_addr_find";
    const char *result;
    int     with_domain;
    int     saved_ch;

    /*
     * This code was ripped from the middle of a function so that it can be
     * reused multiple times, that's why the interface makes little sense.
     */

    with_domain = rats_offs ? WITH_DOMAIN : SANS_DOMAIN;

    saved_ch = *(unsigned char *) (ratsign + rats_offs);
    *(ratsign + rats_offs) = 0;
    result = find_addr(path, int_full_key, PARTIAL, with_domain,
         query_form, ext_addr_buf);
    *(ratsign + rats_offs) = saved_ch;
    if (result == 0 && path->error == 0 && int_bare_key != 0) {
 if ((ratsign = strrchr(int_bare_key, '@')) == 0)
     msg_panic("%s: bare key botch", myname);
 saved_ch = *(unsigned char *) (ratsign + rats_offs);
 *(ratsign + rats_offs) = 0;
 if ((result = find_addr(path, int_bare_key, PARTIAL, with_domain,
    query_form, ext_addr_buf)) != 0
     && extp != 0) {
     *extp = *saved_ext;
     *saved_ext = 0;
 }
 *(ratsign + rats_offs) = saved_ch;
    }
    return result;
}

/* mail_addr_find_opt - map a canonical address */

const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
                  int in_form, int query_form,
                  int out_form, int strategy)
{
    const char *myname = "mail_addr_find";
    VSTRING *ext_addr_buf = 0;
    VSTRING *int_addr_buf = 0;
    const char *int_addr;
    static VSTRING *int_result = 0;
    const char *result;
    char   *ratsign = 0;
    char   *int_full_key;
    char   *int_bare_key;
    char   *saved_ext;
    int     rc = 0;

    /*
     * Optionally convert the address from external form.
     */

    if (in_form == MA_FORM_EXTERNAL) {
 int_addr_buf = vstring_alloc(100);
 unquote_822_local(int_addr_buf, address);
 int_addr = STR(int_addr_buf);
    } else {
 int_addr = address;
    }
    if (query_form == MA_FORM_EXTERNAL_FIRST
 || query_form == MA_FORM_EXTERNAL)
 ext_addr_buf = vstring_alloc(100);

    /*
     * Initialize.
     */

    int_full_key = mystrdup(int_addr);
    if (*var_rcpt_delim == 0 || (strategy & MA_FIND_NOEXT) == 0) {
 int_bare_key = saved_ext = 0;
    } else {
 /* XXX This could be done after user+foo@domain fails. */
 int_bare_key =
     strip_addr_internal(int_full_key, &saved_ext, var_rcpt_delim);
    }

    /*
     * Try user+foo@domain and user@domain.
     */

    if ((strategy & MA_FIND_FULL) != 0) {
 result = find_addr(path, int_full_key, FULL, WITH_DOMAIN,
      query_form, ext_addr_buf);
    } else {
 result = 0;
 path->error = 0;
    }

    if (result == 0 && path->error == 0 && int_bare_key != 0
 && (result = find_addr(path, int_bare_key, PARTIAL, WITH_DOMAIN,
          query_form, ext_addr_buf)) != 0
 && extp != 0) {
 *extp = saved_ext;
 saved_ext = 0;
    }

    /*
     * Try user+foo if the domain matches user+foo@$myorigin,
     * user+foo@$mydestination or user+foo@[${proxy,inet}_interfaces]. Then
     * try with +foo stripped off.
     */

    if (result == 0 && path->error == 0
 && (ratsign = strrchr(int_full_key, '@')) != 0
 && (strategy & (MA_FIND_LOCALPART_IF_LOCAL
   | MA_FIND_LOCALPART_AT_IF_LOCAL)) != 0) {
 if (strcasecmp_utf8(ratsign + 1, var_myorigin) == 0
     || (rc = resolve_local(ratsign + 1)) > 0) {
     if ((strategy & MA_FIND_LOCALPART_IF_LOCAL) != 0)
  result = find_local(path, ratsign, 0, int_full_key,
     int_bare_key, query_form, extp, &saved_ext,
        ext_addr_buf);
     if (result == 0 && path->error == 0
  && (strategy & MA_FIND_LOCALPART_AT_IF_LOCAL) != 0)
  result = find_local(path, ratsign, 1, int_full_key,
     int_bare_key, query_form, extp, &saved_ext,
        ext_addr_buf);
 } else if (rc < 0)
     path->error = rc;
    }

    /*
     * Try @domain.
     */

    if (result == 0 && path->error == 0 && ratsign != 0
 && (strategy & MA_FIND_AT_DOMAIN) != 0)
 result = maps_find(path, ratsign, PARTIAL);

    /*
     * Try domain (optionally, subdomains).
     */

    if (result == 0 && path->error == 0 && ratsign != 0
 && (strategy & MA_FIND_DOMAIN) != 0) {
 const char *name;
 const char *next;

 if ((strategy & MA_FIND_PDMS) && (strategy & MA_FIND_PDDMDS))
     msg_warn("mail_addr_find_opt: do not specify both "
       "MA_FIND_PDMS and MA_FIND_PDDMDS");
 for (name = ratsign + 1; *name != 0; name = next) {
     if ((result = maps_find(path, name, PARTIAL)) != 0
  || path->error != 0
  || (strategy & (MA_FIND_PDMS | MA_FIND_PDDMDS)) == 0
  || (next = strchr(name + 1'.')) == 0)
  break;
     if ((strategy & MA_FIND_PDDMDS) == 0)
  next++;
 }
    }

    /*
     * Try localpart@ even if the domain is not local.
     */

    if ((strategy & MA_FIND_LOCALPART_AT) != 0
 && result == 0 && path->error == 0)
 result = find_local(path, ratsign, 1, int_full_key,
       int_bare_key, query_form, extp, &saved_ext,
       ext_addr_buf);

    /*
     * Optionally convert the result to internal form. The lookup result is
     * supposed to be one external-form email address.
     */

    if (result != 0 && out_form == MA_FORM_INTERNAL) {
 if (int_result == 0)
     int_result = vstring_alloc(100);
 unquote_822_local(int_result, result);
 result = STR(int_result);
    }

    /*
     * Clean up.
     */

    if (msg_verbose)
 msg_info("%s: %s -> %s", myname, address,
   result ? result :
   path->error ? "(try again)" :
   "(not found)");
    myfree(int_full_key);
    if (int_bare_key)
 myfree(int_bare_key);
    if (saved_ext)
 myfree(saved_ext);
    if (int_addr_buf)
 vstring_free(int_addr_buf);
    if (ext_addr_buf)
 vstring_free(ext_addr_buf);
    return (result);
}

#ifdef TEST

 /*
  * Proof-of-concept test program. Read an address and expected results from
  * stdin, and warn about any discrepancies.
  */

#include <ctype.h>
#include <stdlib.h>

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

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

int     main(int argc, char **argv)
{
    VSTRING *buffer = vstring_alloc(100);
    char   *bp;
    MAPS   *path = 0;
    const char *result;
    char   *extent;
    char   *cmd;
    char   *in_field;
    char   *query_field;
    char   *out_field;
    char   *strategy_field;
    char   *key_field;
    char   *expect_res;
    char   *expect_ext;
    int     in_form;
    int     query_form;
    int     out_form;
    int     strategy_flags;
    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)
 usage(argv[0]);

    /*
     * Initialize.
     */

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

    mail_params_init();

    /*
     * TODO: move these assignments into the read/eval loop.
     */

    UPDATE(var_rcpt_delim, "+");
    UPDATE(var_mydomain, "localdomain");
    UPDATE(var_myorigin, "localdomain");
    UPDATE(var_mydest, "localhost.localdomain");
    while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
 bp = STR(buffer);
 if (msg_verbose)
     msg_info("> %s", bp);
 if ((cmd = mystrtok(&bp, CHARS_SPACE)) == 0 || *cmd == '#')
     continue;
 while (ISSPACE(*bp))
     bp++;

 /*
  * Visible comment.
 */

 if (strcmp(cmd, "echo") == 0) {
     vstream_printf("%s\n", bp);
 }

 /*
  * Open maps.
 */

 else if (strcmp(cmd, "maps") == 0) {
     if (path)
  maps_free(path);
     path = maps_create(argv[0], bp, DICT_FLAG_LOCK
        | DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST);
     vstream_printf("%s\n", bp);
     continue;
 }

 /*
  * Lookup and verify.
 */

 else if (path && strcmp(cmd, "test") == 0) {

     /*
      * Parse the input and expectations.
     */

     /* internal, external. */
     if ((in_field = mystrtok(&bp, ":")) == 0)
  msg_fatal("no input form");
     if ((in_form = mail_addr_form_from_string(in_field)) < 0)
  msg_fatal("bad input form: '%s'", in_field);
     if ((query_field = mystrtok(&bp, ":")) == 0)
  msg_fatal("no query form");
     /* internal, external, external-first. */
     if ((query_form = mail_addr_form_from_string(query_field)) < 0)
  msg_fatal("bad query form: '%s'", query_field);
     if ((out_field = mystrtok(&bp, ":")) == 0)
  msg_fatal("no output form");
     /* internal, external. */
     if ((out_form = mail_addr_form_from_string(out_field)) < 0)
  msg_fatal("bad output form: '%s'", out_field);
     if ((strategy_field = mystrtok(&bp, ":")) == 0)
  msg_fatal("no strategy field");
     if ((strategy_flags = strategy_from_string(strategy_field)) < 0)
  msg_fatal("bad strategy field: '%s'", strategy_field);
     if ((key_field = mystrtok(&bp, ":")) == 0)
  msg_fatal("no search key");
     expect_res = mystrtok(&bp, ":");
     expect_ext = mystrtok(&bp, ":");
     if (mystrtok(&bp, ":") != 0)
  msg_fatal("garbage after extension field");

     /*
      * Lookups.
     */

     extent = 0;
     result = mail_addr_find_opt(path, key_field, &extent,
     in_form, query_form, out_form,
     strategy_flags);
     vstream_printf("%s:%s -%s-> %s:%s (%s)\n",
       in_field, key_field, query_field, out_field, result ? result :
      path->error ? "(try again)" :
    "(not found)", extent ? extent : "null extension");
     vstream_fflush(VSTREAM_OUT);

     /*
      * Enforce expectations.
     */

     if (expect_res && result) {
  if (strcmp(expect_res, result) != 0) {
      msg_warn("expect result '%s' but got '%s'", expect_res, result);
      errs = 1;
      if (expect_ext && extent) {
   if (strcmp(expect_ext, extent) != 0)
       msg_warn("expect extension '%s' but got '%s'",
         expect_ext, extent);
   errs = 1;
      } else if (expect_ext && !extent) {
   msg_warn("expect extension '%s' but got none", expect_ext);
   errs = 1;
      } else if (!expect_ext && extent) {
   msg_warn("expect no extension but got '%s'", extent);
   errs = 1;
      }
  }
     } else if (expect_res && !result) {
  msg_warn("expect result '%s' but got none", expect_res);
  errs = 1;
     } else if (!expect_res && result) {
  msg_warn("expected no result but got '%s'", result);
  errs = 1;
     }
     vstream_fflush(VSTREAM_OUT);
     if (extent)
  myfree(extent);
 }

 /*
  * Unknown request.
 */

 else {
     msg_warn("bad request: %s", cmd);
 }
    }
    vstring_free(buffer);

    maps_free(path);
    return (errs != 0);
}

#endif

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

¤ Dauer der Verarbeitung: 0.17 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.