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

Quelle  server_acl.c

  Sprache: C
 

/*++
/* NAME
/* server_acl 3
/* SUMMARY
/* server access list
/* SYNOPSIS
/* #include <server_acl.h>
/*
/* void server_acl_pre_jail_init(mynetworks, param_name)
/* const char *mynetworks;
/* const char *param_name;
/*
/* SERVER_ACL *server_acl_parse(extern_acl, param_name)
/* const char *extern_acl;
/* const char *param_name;
/*
/* int server_acl_eval(client_addr, intern_acl, param_name)
/* const char *client_addr;
/* SERVER_ACL *intern_acl;
/* const char *param_name;
/* DESCRIPTION
/* This module implements a permanent allow/denylist that
/* is meant to be evaluated immediately after a client connects
/* to a server.
/*
/* server_acl_pre_jail_init() does before-chroot initialization
/* for the permit_mynetworks setting.
/*
/* server_acl_parse() converts an access list from raw string
/* form to binary form. It should also be called as part of
/* before-chroot initialization.
/*
/* server_acl_eval() evaluates an access list for the specified
/* client address.  The result is SERVER_ACL_ACT_PERMIT (permit),
/* SERVER_ACL_ACT_REJECT (reject), SERVER_ACL_ACT_DUNNO (no
/* decision), or SERVER_ACL_ACT_ERROR (error, unknown command
/* or database access error).
/*
/* Arguments:
/* .IP mynetworks
/* Network addresses that match "permit_mynetworks".
/* .IP param_name
/* The configuration parameter name for the access list from
/* main.cf.  The information is used for error reporting (nested
/* table, unknown keyword) and to select the appropriate
/* behavior from parent_domain_matches_subdomains.
/* .IP extern_acl
/* External access list representation.
/* .IP intern_acl
/* Internal access list representation.
/* .IP client_addr
/* The client IP address as printable string (without []).
/* 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
/*
/* Wietse Venema
/* porcupine.org
/*--*/


/* System library. */

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

#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif

/* Utility library. */

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

/* Global library. */

#include <mail_params.h>
#include <addr_match_list.h>
#include <match_parent_style.h>
#include <mynetworks.h>
#include <server_acl.h>

/* Application-specific. */

static ADDR_MATCH_LIST *server_acl_mynetworks;
static ADDR_MATCH_LIST *server_acl_mynetworks_host;

#define STR vstring_str

/* server_acl_pre_jail_init - initialize */

void    server_acl_pre_jail_init(const char *mynetworks, const char *origin)
{
    if (server_acl_mynetworks) {
 addr_match_list_free(server_acl_mynetworks);
 if (server_acl_mynetworks_host)
     addr_match_list_free(server_acl_mynetworks_host);
    }
    server_acl_mynetworks =
 addr_match_list_init(origin, MATCH_FLAG_RETURN
        | match_parent_style(origin), mynetworks);
    if (warn_compat_break_mynetworks_style)
 server_acl_mynetworks_host =
     addr_match_list_init(origin, MATCH_FLAG_RETURN
      | match_parent_style(origin), mynetworks_host());
}

/* server_acl_parse - parse access list */

SERVER_ACL *server_acl_parse(const char *extern_acl, const char *origin)
{
    char   *saved_acl = mystrdup(extern_acl);
    SERVER_ACL *intern_acl = argv_alloc(1);
    char   *bp = saved_acl;
    char   *acl;

#define STREQ(x,y) (strcasecmp((x), (y)) == 0)
#define STRNE(x,y) (strcasecmp((x), (y)) != 0)

    /*
     * Nested tables are not allowed. Tables are opened before entering the
     * chroot jail, while access lists are evaluated after entering the
     * chroot jail.
     */

    while ((acl = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
 if (strchr(acl, ':') != 0) {
     if (strchr(origin, ':') != 0) {
  msg_warn("table %s: lookup result \"%s\" is not allowed"
    " -- ignoring remainder of access list",
    origin, acl);
  argv_add(intern_acl, SERVER_ACL_NAME_DUNNO, (char *) 0);
  break;
     } else {
  acl = dict_open(acl, O_RDONLY, DICT_FLAG_LOCK
    | DICT_FLAG_FOLD_FIX
    | DICT_FLAG_UTF8_REQUEST)->reg_name;
     }
 }
 argv_add(intern_acl, acl, (char *) 0);
    }
    argv_terminate(intern_acl);

    /*
     * Cleanup.
     */

    myfree(saved_acl);
    return (intern_acl);
}

/* server_acl_eval - evaluate access list */

int     server_acl_eval(const char *client_addr, SERVER_ACL * intern_acl,
           const char *origin)
{
    const char *myname = "server_acl_eval";
    char  **cpp;
    DICT   *dict;
    SERVER_ACL *argv;
    const char *acl;
    const char *dict_val;
    int     ret;

    for (cpp = intern_acl->argv; (acl = *cpp) != 0; cpp++) {
 if (msg_verbose)
     msg_info("source=%s address=%s acl=%s",
       origin, client_addr, acl);
 if (STREQ(acl, SERVER_ACL_NAME_REJECT)) {
     return (SERVER_ACL_ACT_REJECT);
 } else if (STREQ(acl, SERVER_ACL_NAME_PERMIT)) {
     return (SERVER_ACL_ACT_PERMIT);
 } else if (STREQ(acl, SERVER_ACL_NAME_WL_MYNETWORKS)) {
     if (addr_match_list_match(server_acl_mynetworks, client_addr)) {
  if (warn_compat_break_mynetworks_style
      && !addr_match_list_match(server_acl_mynetworks_host,
           client_addr))
      msg_info("using backwards-compatible default setting "
        VAR_MYNETWORKS_STYLE "=%s to permit "
        "request from client \"%s\"",
        var_mynetworks_style, client_addr);
  return (SERVER_ACL_ACT_PERMIT);
     }
     if (server_acl_mynetworks->error != 0) {
  msg_warn("%s: %s: mynetworks lookup error -- ignoring the "
    "remainder of this access list", origin, acl);
  return (SERVER_ACL_ACT_ERROR);
     }
 } else if (strchr(acl, ':') != 0) {
     if ((dict = dict_handle(acl)) == 0)
  msg_panic("%s: unexpected dictionary: %s", myname, acl);
     if ((dict_val = dict_get(dict, client_addr)) != 0) {
  /* Fake up an ARGV to avoid lots of mallocs and frees. */
  if (dict_val[strcspn(dict_val, ":" CHARS_COMMA_SP)] == 0) {
      ARGV_FAKE_BEGIN(fake_argv, dict_val);
      ret = server_acl_eval(client_addr, &fake_argv, acl);
      ARGV_FAKE_END;
  } else {
      argv = server_acl_parse(dict_val, acl);
      ret = server_acl_eval(client_addr, argv, acl);
      argv_free(argv);
  }
  if (ret != SERVER_ACL_ACT_DUNNO)
      return (ret);
     } else if (dict->error != 0) {
  msg_warn("%s: %s:%s: table lookup error -- ignoring the "
    "remainder of this access list", origin, dict->type,
    dict->name);
  return (SERVER_ACL_ACT_ERROR);
     }
 } else if (STREQ(acl, SERVER_ACL_NAME_DUNNO)) {
     return (SERVER_ACL_ACT_DUNNO);
 } else {
     msg_warn("%s: unknown command: %s -- ignoring the remainder "
       "of this access list", origin, acl);
     return (SERVER_ACL_ACT_ERROR);
 }
    }
    if (msg_verbose)
 msg_info("source=%s address=%s - no match",
   origin, client_addr);
    return (SERVER_ACL_ACT_DUNNO);
}

 /*
  * Access lists need testing. Not only with good inputs; error cases must
  * also be handled appropriately.
  */

#ifdef TEST
#include <unistd.h>
#include <stdlib.h>
#include <vstring_vstream.h>
#include <name_code.h>
#include <split_at.h>

char   *var_server_acl = "";

#define UPDATE_VAR(s,v) do { if (*(s)) myfree(s); (s) = mystrdup(v); } while (0)

int     main(void)
{
    VSTRING *buf = vstring_alloc(100);
    SERVER_ACL *argv;
    int     ret;
    int     have_tty = isatty(0);
    char   *bufp;
    char   *cmd;
    char   *value;
    const NAME_CODE acl_map[] = {
 SERVER_ACL_NAME_ERROR, SERVER_ACL_ACT_ERROR,
 SERVER_ACL_NAME_PERMIT, SERVER_ACL_ACT_PERMIT,
 SERVER_ACL_NAME_REJECT, SERVER_ACL_ACT_REJECT,
 SERVER_ACL_NAME_DUNNO, SERVER_ACL_ACT_DUNNO,
 0,
    };

    /*
     * No static initializer because these are owned by a library.
     */

    var_par_dom_match = DEF_PAR_DOM_MATCH;
    var_mynetworks = "";

#define VAR_SERVER_ACL "server_acl"

    while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
 bufp = STR(buf);
 if (have_tty == 0) {
     vstream_printf("> %s\n", bufp);
     vstream_fflush(VSTREAM_OUT);
 }
 if (*bufp == '#')
     continue;
 if ((cmd = mystrtok(&bufp, " =")) == 0 || STREQ(cmd, "?")) {
     vstream_printf("usage: %s=value|%s=value|address=value\n",
      VAR_MYNETWORKS, VAR_SERVER_ACL);
 } else if ((value = mystrtok(&bufp, " =")) == 0) {
     vstream_printf("missing value\n");
 } else if (STREQ(cmd, VAR_MYNETWORKS)) {
     UPDATE_VAR(var_mynetworks, value);
 } else if (STREQ(cmd, VAR_SERVER_ACL)) {
     UPDATE_VAR(var_server_acl, value);
 } else if (STREQ(cmd, "address")) {
     server_acl_pre_jail_init(var_mynetworks, VAR_MYNETWORKS);
     argv = server_acl_parse(var_server_acl, VAR_SERVER_ACL);
     ret = server_acl_eval(value, argv, VAR_SERVER_ACL);
     argv_free(argv);
     vstream_printf("%s: %s\n", value, str_name_code(acl_map, ret));
 } else {
     vstream_printf("unknown command: \"%s\"\n", cmd);
 }
 vstream_fflush(VSTREAM_OUT);
    }
    vstring_free(buf);
    exit(0);
}

#endif

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

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