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

Quelle  spawn.c

  Sprache: C
 

/*++
/* NAME
/* spawn 8
/* SUMMARY
/* Postfix external command spawner
/* SYNOPSIS
/* \fBspawn\fR [generic Postfix daemon options] command_attributes...
/* DESCRIPTION
/* The \fBspawn\fR(8) daemon monitors a TCP or UNIX-domain stream
/* socket, configured in \fBmaster.cf\fR with a service type
/* \fBinet\fR or \fBunix\fR.
/*
/* This daemon spawns an external command whenever a connection
/* is established, with the standard input, output and error file
/* descriptors connected to the remote client.
/*
/* The command process is subject to the time limit specified
/* with the parameter \fItransport\fR_time_limit (default:
/* command_time_limit) where \fItransport\fR equals the service
/* name field in master.cf. A process that exceeds the time limit
/* will receive a SIGKILL signal.
/*
/* The \fBspawn\fR(8) daemon service typically has a process limit >
/* 1 in its \fBmaster.cf\fR service definition, so that the number
/* of processes can scale with demand.
/* COMMAND ATTRIBUTE SYNTAX
/* .ad
/* .fi
/* The external command attributes are given in the \fBmaster.cf\fR
/* file at the end of a service definition.  The syntax is as follows:
/* .IP "\fBuser\fR=\fIusername\fR (required)"
/* .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR"
/* The external command is executed with the rights of the
/* specified \fIusername\fR.  The software refuses to execute
/* commands with root privileges, or with the privileges of the
/* mail system owner. If \fIgroupname\fR is specified, the
/* corresponding group ID is used instead of the group ID
/* of \fIusername\fR.
/* .IP "\fBargv\fR=\fIcommand\fR... (required)"
/* The command to be executed. This must be specified as the
/* last command attribute.
/* The command is executed directly, i.e. without interpretation of
/* shell meta characters by a shell command interpreter.
/* .sp
/* If a command argument must contain whitespace, or if a command
/* argument must begin with "{", enclose the argument with "{" and
/* "}". This form will ignore whitespace after the outer "{" and
/* before the outer "}". Example:
/* .sp
/* .fi
/*     argv=/bin/sh -c { shell syntax here }
/* DIAGNOSTICS
/* The \fBspawn\fR(8) daemon reports abnormal child exits.
/* Problems are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8).
/* SECURITY
/* .fi
/* .ad
/* The \fBspawn\fR(8) daemon needs root privilege in order to
/* execute external commands as the specified user. It is therefore
/* security sensitive.
/*
/* However, the \fBspawn\fR(8) daemon does not receive data from
/* or about service clients or external commands, and thus is not
/* vulnerable to data-driven attacks.
/* CONFIGURATION PARAMETERS
/* .ad
/* .fi
/* Changes to \fBmain.cf\fR are picked up automatically as \fBspawn\fR(8)
/* processes run for only a limited amount of time. Use the command
/* "\fBpostfix reload\fR" to speed up a change.
/*
/* The text below provides only a parameter summary. See
/* \fBpostconf\fR(5) for more details including examples.
/*
/* In the text below, \fItransport\fR is the first field of the entry
/* in the \fBmaster.cf\fR file.
/* RESOURCE AND RATE CONTROL
/* .ad
/* .fi
/* .IP "\fBtransport_time_limit ($command_time_limit)\fR"
/* A transport-specific override for the command_time_limit parameter
/* value, where \fItransport\fR is the master.cf name of the message
/* delivery transport.
/* MISCELLANEOUS
/* .ad
/* .fi
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
/* The default location of the Postfix main.cf and master.cf
/* configuration files.
/* .IP "\fBdaemon_timeout (18000s)\fR"
/* How much time a Postfix daemon process may take to handle a
/* request before it is terminated by a built-in watchdog timer.
/* .IP "\fBexport_environment (see 'postconf -d' output)\fR"
/* The list of environment variables that a Postfix process will export
/* to non-Postfix processes.
/* .IP "\fBipc_timeout (3600s)\fR"
/* The time limit for sending or receiving information over an internal
/* communication channel.
/* .IP "\fBmail_owner (postfix)\fR"
/* The UNIX system account that owns the Postfix queue and most Postfix
/* daemon processes.
/* .IP "\fBmax_idle (100s)\fR"
/* The maximum amount of time that an idle Postfix daemon process waits
/* for an incoming connection before terminating voluntarily.
/* .IP "\fBmax_use (100)\fR"
/* The maximal number of incoming connections that a Postfix daemon
/* process will service before terminating voluntarily.
/* .IP "\fBprocess_id (read-only)\fR"
/* The process ID of a Postfix command or daemon process.
/* .IP "\fBprocess_name (read-only)\fR"
/* The process name of a Postfix command or daemon process.
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
/* The location of the Postfix top-level queue directory.
/* .IP "\fBsyslog_facility (mail)\fR"
/* The syslog facility of Postfix logging.
/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
/* A prefix that is prepended to the process name in syslog
/* records, so that, for example, "smtpd" becomes "prefix/smtpd".
/* .PP
/* Available in Postfix 3.3 and later:
/* .IP "\fBservice_name (read-only)\fR"
/* The master.cf service name of a Postfix daemon process.
/* SEE ALSO
/* postconf(5), configuration parameters
/* master(8), process manager
/* postlogd(8), Postfix logging
/* syslogd(8), system logging
/* 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 <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <fcntl.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif

/* Utility library. */

#include <msg.h>
#include <argv.h>
#include <dict.h>
#include <mymalloc.h>
#include <spawn_command.h>
#include <split_at.h>
#include <timed_wait.h>
#include <set_eugid.h>

/* Global library. */

#include <mail_version.h>

/* Single server skeleton. */

#include <mail_params.h>
#include <mail_server.h>
#include <mail_conf.h>
#include <mail_parm_split.h>

/* Application-specific. */

 /*
  * Tunable parameters. Values are taken from the config file, after
  * prepending the service name to _name, and so on.
  */

int     var_command_maxtime;  /* system-wide */

 /*
  * For convenience. Instead of passing around lists of parameters, bundle
  * them up in convenient structures.
  */

typedef struct {
    char  **argv;   /* argument vector */
    uid_t   uid;   /* command privileges */
    gid_t   gid;   /* command privileges */
    int     time_limit;   /* per-service time limit */
} SPAWN_ATTR;

/* get_service_attr - get service attributes */

static void get_service_attr(SPAWN_ATTR *attr, char *service, char **argv)
{
    const char *myname = "get_service_attr";
    struct passwd *pwd;
    struct group *grp;
    char   *user;   /* user name */
    char   *group;   /* group name */

    /*
     * Initialize.
     */

    user = 0;
    group = 0;
    attr->argv = 0;

    /*
     * Figure out the command time limit for this transport.
     */

    attr->time_limit =
 get_mail_conf_time2(service, _MAXTIME, var_command_maxtime, 's'10);

    /*
     * Iterate over the command-line attribute list.
     */

    for ( /* void */ ; *argv != 0; argv++) {

 /*
  * user=username[:groupname]
 */

 if (strncasecmp("user=", *argv, sizeof("user=") - 1) == 0) {
     user = *argv + sizeof("user=") - 1;
     if ((group = split_at(user, ':')) != 0/* XXX clobbers argv */
  if (*group == 0)
      group = 0;
     if ((pwd = getpwnam(user)) == 0)
  msg_fatal("unknown user name: %s", user);
     attr->uid = pwd->pw_uid;
     if (group != 0) {
  if ((grp = getgrnam(group)) == 0)
      msg_fatal("unknown group name: %s", group);
  attr->gid = grp->gr_gid;
     } else {
  attr->gid = pwd->pw_gid;
     }
 }

 /*
  * argv=command...
 */

 else if (strncasecmp("argv=", *argv, sizeof("argv=") - 1) == 0) {
     *argv += sizeof("argv=") - 1/* XXX clobbers argv */
     attr->argv = argv;
     break;
 }

 /*
  * Bad.
 */

 else
     msg_fatal("unknown attribute name: %s", *argv);
    }

    /*
     * Sanity checks. Verify that every member has an acceptable value.
     */

    if (user == 0)
 msg_fatal("missing user= attribute");
    if (attr->argv == 0)
 msg_fatal("missing argv= attribute");
    if (attr->uid == 0)
 msg_fatal("request to deliver as root");
    if (attr->uid == var_owner_uid)
 msg_fatal("request to deliver as mail system owner");
    if (attr->gid == 0)
 msg_fatal("request to use privileged group id %ld", (long) attr->gid);
    if (attr->gid == var_owner_gid)
 msg_fatal("request to use mail system owner group id %ld", (long) attr->gid);
    if (attr->uid == (uid_t) (-1))
 msg_fatal("user must not have user ID -1");
    if (attr->gid == (gid_t) (-1))
 msg_fatal("user must not have group ID -1");

    /*
     * Give the poor tester a clue of what is going on.
     */

    if (msg_verbose)
 msg_info("%s: uid %ld, gid %ld; time %d",
       myname, (long) attr->uid, (long) attr->gid, attr->time_limit);
}

/* spawn_service - perform service for client */

static void spawn_service(VSTREAM *client_stream, char *service, char **argv)
{
    const char *myname = "spawn_service";
    static SPAWN_ATTR attr;
    WAIT_STATUS_T status;
    ARGV   *export_env;

    /*
     * This routine runs whenever a client connects to the UNIX-domain socket
     * dedicated to running an external command.
     */

    if (msg_verbose)
 msg_info("%s: service=%s, command=%s...", myname, service, argv[0]);

    /*
     * Look up service attributes and config information only once. This is
     * safe since the information comes from a trusted source.
     */

    if (attr.argv == 0) {
 get_service_attr(&attr, service, argv);
    }

    /*
     * Execute the command.
     */

    export_env = mail_parm_split(VAR_EXPORT_ENVIRON, var_export_environ);
    status = spawn_command(CA_SPAWN_CMD_STDIN(vstream_fileno(client_stream)),
    CA_SPAWN_CMD_STDOUT(vstream_fileno(client_stream)),
    CA_SPAWN_CMD_STDERR(vstream_fileno(client_stream)),
      CA_SPAWN_CMD_UID(attr.uid),
      CA_SPAWN_CMD_GID(attr.gid),
      CA_SPAWN_CMD_ARGV(attr.argv),
      CA_SPAWN_CMD_TIME_LIMIT(attr.time_limit),
      CA_SPAWN_CMD_EXPORT(export_env->argv),
      CA_SPAWN_CMD_END);
    argv_free(export_env);

    /*
     * Warn about unsuccessful completion.
     */

    if (!NORMAL_EXIT_STATUS(status)) {
 if (WIFEXITED(status))
     msg_warn("command %s exit status %d",
       attr.argv[0], WEXITSTATUS(status));
 if (WIFSIGNALED(status))
     msg_warn("command %s killed by signal %d",
       attr.argv[0], WTERMSIG(status));
    }
}

/* pre_accept - see if tables have changed */

static void pre_accept(char *unused_name, char **unused_argv)
{
    const char *table;

    if ((table = dict_changed_name()) != 0) {
 msg_info("table %s has changed -- restarting", table);
 exit(0);
    }
}

/* drop_privileges - drop privileges most of the time */

static void drop_privileges(char *unused_name, char **unused_argv)
{
    set_eugid(var_owner_uid, var_owner_gid);
}

MAIL_VERSION_STAMP_DECLARE;

/* main - pass control to the single-threaded skeleton */

int     main(int argc, char **argv)
{
    static const CONFIG_TIME_TABLE time_table[] = {
 VAR_COMMAND_MAXTIME, DEF_COMMAND_MAXTIME, &var_command_maxtime, 10,
 0,
    };

    /*
     * Fingerprint executables and core dumps.
     */

    MAIL_VERSION_STAMP_ALLOCATE;

    single_server_main(argc, argv, spawn_service,
         CA_MAIL_SERVER_TIME_TABLE(time_table),
         CA_MAIL_SERVER_POST_INIT(drop_privileges),
         CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
         CA_MAIL_SERVER_PRIVILEGED,
         0);
}

Messung V0.5 in Prozent
C=75 H=88 G=81

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

*© 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.