Exemplo n.º 1
0
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 = mystrtok(&bp, SERVER_ACL_SEPARATORS)) != 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 {
		if (dict_handle(acl) == 0)
		    dict_register(acl, dict_open(acl, O_RDONLY, DICT_FLAG_LOCK
						 | DICT_FLAG_FOLD_FIX));
	    }
	}
	argv_add(intern_acl, acl, (char *) 0);
    }
    argv_terminate(intern_acl);

    /*
     * Cleanup.
     */
    myfree(saved_acl);
    return (intern_acl);
}
Exemplo n.º 2
0
Arquivo: smtp.c Projeto: robn/postfix
static void pre_init(char *unused_name, char **unused_argv)
{
    int     use_tls;
    static const NAME_CODE addr_pref_map[] = {
        INET_PROTO_NAME_IPV6, SMTP_MISC_FLAG_PREF_IPV6,
        INET_PROTO_NAME_IPV4, SMTP_MISC_FLAG_PREF_IPV4,
        INET_PROTO_NAME_ANY, 0,
        0, -1,
    };

    /*
     * Turn on per-peer debugging.
     */
    debug_peer_init();

    /*
     * SASL initialization.
     */
    if (var_smtp_sasl_enable)
#ifdef USE_SASL_AUTH
        smtp_sasl_initialize();
#else
        msg_warn("%s is true, but SASL support is not compiled in",
                 VAR_SMTP_SASL_ENABLE);
#endif

    if (*var_smtp_tls_level != 0)
        switch (tls_level_lookup(var_smtp_tls_level)) {
        case TLS_LEV_SECURE:
        case TLS_LEV_VERIFY:
        case TLS_LEV_FPRINT:
        case TLS_LEV_ENCRYPT:
            var_smtp_use_tls = var_smtp_enforce_tls = 1;
            break;
        case TLS_LEV_MAY:
            var_smtp_use_tls = 1;
            var_smtp_enforce_tls = 0;
            break;
        case TLS_LEV_NONE:
            var_smtp_use_tls = var_smtp_enforce_tls = 0;
            break;
        default:
            /* tls_level_lookup() logs no warning. */
            /* session_tls_init() assumes that var_smtp_tls_level is sane. */
            msg_fatal("Invalid TLS level \"%s\"", var_smtp_tls_level);
        }
    use_tls = (var_smtp_use_tls || var_smtp_enforce_tls);

    /*
     * Initialize the TLS data before entering the chroot jail
     */
    if (use_tls || var_smtp_tls_per_site[0] || var_smtp_tls_policy[0]) {
#ifdef USE_TLS
        TLS_CLIENT_INIT_PROPS props;
        int     using_smtp = (strcmp(var_procname, "smtp") == 0);

        /*
         * We get stronger type safety and a cleaner interface by combining
         * the various parameters into a single tls_client_props structure.
         *
         * Large parameter lists are error-prone, so we emulate a language
         * feature that C does not have natively: named parameter lists.
         */
        smtp_tls_ctx =
            TLS_CLIENT_INIT(&props,
                            log_param = using_smtp ?
                                        VAR_SMTP_TLS_LOGLEVEL : VAR_LMTP_TLS_LOGLEVEL,
                            log_level = var_smtp_tls_loglevel,
                            verifydepth = var_smtp_tls_scert_vd,
                            cache_type = using_smtp ?
                                         TLS_MGR_SCACHE_SMTP : TLS_MGR_SCACHE_LMTP,
                            cert_file = var_smtp_tls_cert_file,
                            key_file = var_smtp_tls_key_file,
                            dcert_file = var_smtp_tls_dcert_file,
                            dkey_file = var_smtp_tls_dkey_file,
                            eccert_file = var_smtp_tls_eccert_file,
                            eckey_file = var_smtp_tls_eckey_file,
                            CAfile = var_smtp_tls_CAfile,
                            CApath = var_smtp_tls_CApath,
                            fpt_dgst = var_smtp_tls_fpt_dgst);
        smtp_tls_list_init();
#else
        msg_warn("TLS has been selected, but TLS support is not compiled in");
#endif
    }

    /*
     * Flush client.
     */
    flush_init();

    /*
     * Session cache domain list.
     */
    if (*var_smtp_cache_dest)
        smtp_cache_dest = string_list_init(MATCH_FLAG_RETURN, var_smtp_cache_dest);

    /*
     * EHLO keyword filter.
     */
    if (*var_smtp_ehlo_dis_maps)
        smtp_ehlo_dis_maps = maps_create(VAR_SMTP_EHLO_DIS_MAPS,
                                         var_smtp_ehlo_dis_maps,
                                         DICT_FLAG_LOCK);

    /*
     * PIX bug workarounds.
     */
    if (*var_smtp_pix_bug_maps)
        smtp_pix_bug_maps = maps_create(VAR_SMTP_PIX_BUG_MAPS,
                                        var_smtp_pix_bug_maps,
                                        DICT_FLAG_LOCK);

    /*
     * Generic maps.
     */
    if (*var_prop_extension)
        smtp_ext_prop_mask =
            ext_prop_mask(VAR_PROP_EXTENSION, var_prop_extension);
    if (*var_smtp_generic_maps)
        smtp_generic_maps =
            maps_create(VAR_SMTP_GENERIC_MAPS, var_smtp_generic_maps,
                        DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);

    /*
     * Header/body checks.
     */
    smtp_header_checks = hbc_header_checks_create(
                             VAR_SMTP_HEAD_CHKS, var_smtp_head_chks,
                             VAR_SMTP_MIME_CHKS, var_smtp_mime_chks,
                             VAR_SMTP_NEST_CHKS, var_smtp_nest_chks,
                             smtp_hbc_callbacks);
    smtp_body_checks = hbc_body_checks_create(
                           VAR_SMTP_BODY_CHKS, var_smtp_body_chks,
                           smtp_hbc_callbacks);

    /*
     * Server reply filter.
     */
    if (*var_smtp_resp_filter)
        smtp_chat_resp_filter =
            dict_open(var_smtp_resp_filter, O_RDONLY,
                      DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);

    /*
     * Address family preference.
     */
    if (*var_smtp_addr_pref) {
        smtp_addr_pref = name_code(addr_pref_map, NAME_CODE_FLAG_NONE,
                                   var_smtp_addr_pref);
        if (smtp_addr_pref < 0)
            msg_fatal("bad %s value: %s", VAR_SMTP_ADDR_PREF, var_smtp_addr_pref);
    }
}
Exemplo n.º 3
0
void    dict_test(int argc, char **argv)
{
    VSTRING *keybuf = vstring_alloc(1);
    VSTRING *inbuf = vstring_alloc(1);
    DICT   *dict;
    char   *dict_name;
    int     open_flags;
    char   *bufp;
    char   *cmd;
    const char *key;
    const char *value;
    int     ch;
    int     dict_flags = 0;
    int     n;
    int     rc;

#define USAGE	"verbose|del key|get key|put key=value|first|next|masks|flags"

    signal(SIGPIPE, SIG_IGN);

    msg_vstream_init(argv[0], VSTREAM_ERR);
    while ((ch = GETOPT(argc, argv, "v")) > 0) {
	switch (ch) {
	default:
	    usage(argv[0]);
	case 'v':
	    msg_verbose++;
	    break;
	}
    }
    optind = OPTIND;
    if (argc - optind < 2)
	usage(argv[0]);
    if (strcasecmp(argv[optind + 1], "create") == 0)
	open_flags = O_CREAT | O_RDWR | O_TRUNC;
    else if (strcasecmp(argv[optind + 1], "write") == 0)
	open_flags = O_RDWR;
    else if (strcasecmp(argv[optind + 1], "read") == 0)
	open_flags = O_RDONLY;
    else
	msg_fatal("unknown access mode: %s", argv[2]);
    for (n = 2; argv[optind + n]; n++)
	dict_flags |= dict_flags_mask(argv[optind + 2]);
    if ((dict_flags & DICT_FLAG_OPEN_LOCK) == 0)
	dict_flags |= DICT_FLAG_LOCK;
    if ((dict_flags & (DICT_FLAG_DUP_WARN | DICT_FLAG_DUP_IGNORE)) == 0)
	dict_flags |= DICT_FLAG_DUP_REPLACE;
    vstream_fflush(VSTREAM_OUT);
    dict_name = argv[optind];
    dict_allow_surrogate = 1;
    dict = dict_open(dict_name, open_flags, dict_flags);
    dict_register(dict_name, dict);
    while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
	bufp = vstring_str(inbuf);
	if (!isatty(0)) {
	    vstream_printf("> %s\n", bufp);
	    vstream_fflush(VSTREAM_OUT);
	}
	if (*bufp == '#')
	    continue;
	if ((cmd = mystrtok(&bufp, " ")) == 0) {
	    vstream_printf("usage: %s\n", USAGE);
	    vstream_fflush(VSTREAM_OUT);
	    continue;
	}
	if (dict_changed_name())
	    msg_warn("dictionary has changed");
	key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0;
	value = mystrtok(&bufp, " =");
	if (strcmp(cmd, "verbose") == 0 && !key) {
	    msg_verbose++;
	} else if (strcmp(cmd, "del") == 0 && key && !value) {
	    if ((rc = dict_del(dict, key)) > 0)
		vstream_printf("%s: not found\n", key);
	    else if (rc < 0)
		vstream_printf("%s: error\n", key);
	    else
		vstream_printf("%s: deleted\n", key);
	} else if (strcmp(cmd, "get") == 0 && key && !value) {
	    if ((value = dict_get(dict, key)) == 0) {
		vstream_printf("%s: %s\n", key, dict->error ?
			       "error" : "not found");
	    } else {
		vstream_printf("%s=%s\n", key, value);
	    }
	} else if (strcmp(cmd, "put") == 0 && key && value) {
	    if (dict_put(dict, key, value) != 0)
		vstream_printf("%s: %s\n", key, dict->error ?
			       "error" : "not updated");
	    else
		vstream_printf("%s=%s\n", key, value);
	} else if (strcmp(cmd, "first") == 0 && !key && !value) {
	    if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0)
		vstream_printf("%s=%s\n", key, value);
	    else
		vstream_printf("%s\n", dict->error ?
			       "error" : "not found");
	} else if (strcmp(cmd, "next") == 0 && !key && !value) {
	    if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0)
		vstream_printf("%s=%s\n", key, value);
	    else
		vstream_printf("%s\n", dict->error ?
			       "error" : "not found");
	} else if (strcmp(cmd, "flags") == 0 && !key && !value) {
	    vstream_printf("dict flags %s\n",
			   dict_flags_str(dict->flags));
	} else if (strcmp(cmd, "masks") == 0 && !key && !value) {
	    vstream_printf("DICT_FLAG_IMPL_MASK %s\n",
			   dict_flags_str(DICT_FLAG_IMPL_MASK));
	    vstream_printf("DICT_FLAG_PARANOID %s\n",
			   dict_flags_str(DICT_FLAG_PARANOID));
	    vstream_printf("DICT_FLAG_RQST_MASK %s\n",
			   dict_flags_str(DICT_FLAG_RQST_MASK));
	    vstream_printf("DICT_FLAG_INST_MASK %s\n",
			   dict_flags_str(DICT_FLAG_INST_MASK));
	} else {
	    vstream_printf("usage: %s\n", USAGE);
	}
	vstream_fflush(VSTREAM_OUT);
    }
    vstring_free(keybuf);
    vstring_free(inbuf);
    dict_close(dict);
}
Exemplo n.º 4
0
int     main(int argc, char **argv)
{
    VSTRING *keybuf = vstring_alloc(1);
    VSTRING *inbuf = vstring_alloc(1);
    DICT   *dict;
    char   *dict_name;
    int     open_flags;
    char   *bufp;
    char   *cmd;
    const char *key;
    const char *value;
    int     ch;
    int     dict_flags = DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE;
    int     n;

    signal(SIGPIPE, SIG_IGN);

    msg_vstream_init(argv[0], VSTREAM_ERR);
    while ((ch = GETOPT(argc, argv, "v")) > 0) {
	switch (ch) {
	default:
	    usage(argv[0]);
	case 'v':
	    msg_verbose++;
	    break;
	}
    }
    optind = OPTIND;
    if (argc - optind < 2)
	usage(argv[0]);
    if (strcasecmp(argv[optind + 1], "create") == 0)
	open_flags = O_CREAT | O_RDWR | O_TRUNC;
    else if (strcasecmp(argv[optind + 1], "write") == 0)
	open_flags = O_RDWR;
    else if (strcasecmp(argv[optind + 1], "read") == 0)
	open_flags = O_RDONLY;
    else
	msg_fatal("unknown access mode: %s", argv[2]);
    for (n = 2; argv[optind + n]; n++) {
	if (strcasecmp(argv[optind + 2], "fold") == 0)
	    dict_flags |= DICT_FLAG_FOLD_ANY;
	else if (strcasecmp(argv[optind + 2], "sync") == 0)
	    dict_flags |= DICT_FLAG_SYNC_UPDATE;
	else
	    usage(argv[0]);
    }
    dict_name = argv[optind];
    dict = dict_open(dict_name, open_flags, dict_flags);
    dict_register(dict_name, dict);
    while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
	bufp = vstring_str(inbuf);
	if (!isatty(0)) {
	    vstream_printf("> %s\n", bufp);
	    vstream_fflush(VSTREAM_OUT);
	}
	if (*bufp == '#')
	    continue;
	if ((cmd = mystrtok(&bufp, " ")) == 0) {
	    vstream_printf("usage: del key|get key|put key=value|first|next\n");
	    vstream_fflush(VSTREAM_OUT);
	    continue;
	}
	if (dict_changed_name())
	    msg_warn("dictionary has changed");
	key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0;
	value = mystrtok(&bufp, " =");
	if (strcmp(cmd, "del") == 0 && key && !value) {
	    if (dict_del(dict, key))
		vstream_printf("%s: not found\n", key);
	    else
		vstream_printf("%s: deleted\n", key);
	} else if (strcmp(cmd, "get") == 0 && key && !value) {
	    if ((value = dict_get(dict, key)) == 0) {
		vstream_printf("%s: %s\n", key,
			       dict_errno == DICT_ERR_RETRY ?
			       "soft error" : "not found");
	    } else {
		vstream_printf("%s=%s\n", key, value);
	    }
	} else if (strcmp(cmd, "put") == 0 && key && value) {
	    dict_put(dict, key, value);
	    vstream_printf("%s=%s\n", key, value);
	} else if (strcmp(cmd, "first") == 0 && !key && !value) {
	    if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0)
		vstream_printf("%s=%s\n", key, value);
	    else
		vstream_printf("%s\n",
			       dict_errno == DICT_ERR_RETRY ?
			       "soft error" : "not found");
	} else if (strcmp(cmd, "next") == 0 && !key && !value) {
	    if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0)
		vstream_printf("%s=%s\n", key, value);
	    else
		vstream_printf("%s\n",
			       dict_errno == DICT_ERR_RETRY ?
			       "soft error" : "not found");
	} else {
	    vstream_printf("usage: del key|get key|put key=value|first|next\n");
	}
	vstream_fflush(VSTREAM_OUT);
    }
    vstring_free(keybuf);
    vstring_free(inbuf);
    dict_close(dict);
    return (0);
}
Exemplo n.º 5
0
int main(int argc, char** argv) {
    int            c;
    char*          p;
    uid_t          uid, gid, client_gid, root_gid;
    struct passwd* pw;
    struct group*  gr;
    struct stat    st;
    int            localsocket = 1;


    /*
     * compilerwarnung: "client_gid may be used uninitialized"
     * sowas will man ja nun wirklich nicht ...
     */
    uid = gid = client_gid = root_gid = 0;

    while ((c = getopt(argc, argv, "bc:d:hfg:k:m:n:s:t:u:vx")) > 0) {
        switch (c) {
        case 'b': /* break contentheader */
            logmsg(LOG_INFO, "option -b is ignored for compatibily reasons, you may remove it safely");
            break;
        case 'c': /* clientgroup */
            opt_clientgroup = optarg;
            if ((gr = getgrnam(opt_clientgroup)) == NULL) {
                logmsg(LOG_ERR, "unknown clientgroup: getgrnam(%s) failed", opt_group);
                exit(EX_DATAERR);
            }
            client_gid = gr->gr_gid;
            break;
        case 'd': /* Loglevel */
            opt_loglevel = (int) strtoul(optarg, &p, 10);
            if (p != NULL && *p != '\0') {
                printf("debug-level is not valid integer: %s\n", optarg);
                exit(EX_DATAERR);
            }
            p = NULL;
            if (opt_loglevel < 0 || opt_loglevel > 7) {
                printf("loglevel out of range 0..7: %i\n", opt_loglevel);
                exit(EX_DATAERR);
            }
            break;
        case 'f': /* signer from header, not from envelope */
            opt_signerfromheader = 1;
            break;
        case 'g': /* group */
            opt_group = optarg;
            if ((gr = getgrnam(opt_group)) == NULL) {
                printf("unknown group: getgrnam(%s) failed", opt_group);
                exit(EX_DATAERR);
            }
            break;
        case 'k': /* keepdir */
            opt_keepdir = optarg;
            if (stat(opt_keepdir, &st) < 0) {
                printf("directory to keep data: %s: %s", opt_keepdir, strerror(errno));
                exit(EX_DATAERR);
            }
            if (!S_ISDIR(st.st_mode)) {
                printf("directory to keep data: %s is not a directory", opt_keepdir);
                exit(EX_DATAERR);
            }
            /* Zugriffsrechte werden spaeter geprueft, wenn zur richtigen uid gewechselt wurde */
            break;
        case '?': /* help */
        case 'h':
            usage();
            exit(EX_OK);
        case 'm': /* Signingtable cdbfilename */
            opt_signingtable = optarg;
            break;
        case 'n': /* Modetable cdbfilename */
            opt_modetable = optarg;
            break;
        case 's': /* Miltersocket */
            opt_miltersocket = optarg;
            break;
        case 't': /* Timeout */
            opt_timeout = (int) strtoul(optarg, &p, 10);
            if (p != NULL && *p != '\0') {
                printf("timeout is not valid integer: %s\n", optarg);
                exit(EX_DATAERR);
            }
            p = NULL;
            if (opt_timeout < 0 ) {
                printf("negative milter connection timeout: %i\n", opt_timeout);
                exit(EX_DATAERR);
            }
            break;
        case 'u': /* user */
            opt_user = optarg;
            /* get passwd/group entries for opt_user and opt_group */
            if ((pw = getpwnam(opt_user)) == NULL) {
                logmsg(LOG_ERR, "unknown user: getpwnam(%s) failed", opt_user);
                exit(EX_DATAERR);
            }
            break;
        case 'v': /* Version */
            version();
            exit(EX_OK);
        case 'x': /* add X-Header */
            opt_addxheader = (int) !opt_addxheader;
            break;
        default:
            usage();
            exit(EX_USAGE);
        }
    }

    /* open syslog an say helo */
    openlog(STR_PROGNAME, LOG_PID, LOG_MAIL);
    logmsg(LOG_NOTICE, "starting %s %s listening on %s, loglevel %i",
               STR_PROGNAME, STR_PROGVERSION, opt_miltersocket, opt_loglevel);

    /* force a new processgroup */
    if ((setsid() == -1))
        logmsg(LOG_DEBUG, "ignoring that setsid() failed");

    if (opt_timeout > 0 && smfi_settimeout(opt_timeout) != MI_SUCCESS) {
        logmsg(LOG_ERR, "could not set milter timeout");
        exit(EX_SOFTWARE);
    }
    logmsg(LOG_INFO, "miltertimeout set to %i", opt_timeout);

    if (smfi_setconn(opt_miltersocket) != MI_SUCCESS) {
        logmsg(LOG_ERR, "could not set milter socket");
        exit(EX_SOFTWARE);
    }

    if (smfi_register(callbacks) != MI_SUCCESS) {
        logmsg(LOG_ERR, "could not register milter");
        exit(EX_SOFTWARE);
    }

    /*
     * User- und Gruppennamen stehen nun fest. Testen, ob es diese gibt
     * und uid / gid ermitteln
     */
    if ((pw = getpwnam(opt_user)) == NULL) {
        logmsg(LOG_ERR, "unknown user: getpwnam(%s) failed", opt_user);
        exit(EX_DATAERR);
    }
    uid = pw->pw_uid;
    if ((gr = getgrnam(opt_group)) == NULL) {
        logmsg(LOG_ERR, "unknown group: getgrnam(%s) failed", opt_group);
        exit(EX_SOFTWARE);
    }
    gid = gr->gr_gid;

    /* wenn nicht als Parameter angegeben, gehört ein Unix-Socket erstmal der gleichen Gruppe */
    if (opt_clientgroup == NULL)
        client_gid = gid;

    /* wenn inet in optarg gefunden wird *und* das auch noch direkt am Anfang
     * dann ist's kein lokaler socket */
    if (((p = strstr(opt_miltersocket, "inet")) != NULL) && opt_miltersocket == p)
        localsocket = 0;

    if (localsocket == 1) {
        /* den Socket oeffnen */
        if (smfi_opensocket(REMOVE_EXISTING_SOCKETS) != MI_SUCCESS) {
            logmsg(LOG_ERR, "could not open milter socket %s", opt_miltersocket);
            exit(EX_SOFTWARE);
        }
        /* testen, ob's den Socket nun gibt */
        p = opt_miltersocket + strlen("local:");
        if (stat(p, &st) < 0) {
            p = opt_miltersocket + strlen("unix:");
            if (stat(p, &st) < 0) {
                logmsg(LOG_ERR, "miltersocket does not exist: %m", strerror(errno));
                exit(EX_DATAERR);
            }
        }

        /* gid der Gruppe root */
        if ((gr = getgrnam("root")) == NULL) {
            logmsg(LOG_ERR, "unknown rootgroup: getgrnam(root) failed");
            exit(EX_SOFTWARE);
        }
        root_gid = gr->gr_gid;

        /* clientgroup muss != root und != opt_group sein */
        if ((client_gid == gid) || (client_gid == root_gid)) {
            logmsg(LOG_ERR, "clientgroup %s must be neither %s nor %s", opt_clientgroup, "root", opt_group);
            exit(EX_DATAERR);
        }

        /* nun die Rechte setzen */
        if (chown(p, uid, client_gid) != 0) {
            logmsg(LOG_ERR, "chown(%s, %i, %i) failed: %m", p, uid, client_gid, strerror(errno));
            exit(EX_SOFTWARE);
        }
        if (chmod(p, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) {
            logmsg(LOG_ERR, "chmod(%s, 0660) failed: %m", p, strerror(errno));
            exit(EX_SOFTWARE);
        }

        logmsg(LOG_INFO, "changed socket %s to owner/group: %i/%i, mode: 0660", opt_miltersocket, uid, client_gid);
    }

    /* gid/uid setzen */
    if (setgid(gid) != 0) {
        logmsg(LOG_ERR, "setgid(%i) failed: %s", gr->gr_gid, strerror(errno));
        exit(EX_SOFTWARE);
    }
    if (setuid(uid) != 0) {
        logmsg(LOG_ERR, "setuid(%i) failed: %s", pw->pw_uid, strerror(errno));
        exit(EX_SOFTWARE);
    } 

    /* aktuelle uid/gid pruefen und loggen */
    uid = getuid();
    gid = getgid();
    if (uid == 0 || gid == 0) {
        logmsg(LOG_ERR, "too much priveleges, %s will not start under root", STR_PROGNAME);
        exit(EX_DATAERR);
    }
    logmsg(LOG_INFO, "running as uid: %i, gid: %i", (int) uid, (int) gid);

    if (opt_keepdir != NULL) {
        if (S_IRWXO & st.st_mode) {
            logmsg(LOG_ERR, "directory to keep data: %s: permissions too open: remove any access for other", opt_keepdir);
            exit(EX_DATAERR);
        }
        if (access(opt_keepdir, R_OK) < 0 && errno == EACCES) {
            logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no read access", opt_keepdir);
            exit(EX_DATAERR);
        }
        if (access(opt_keepdir, W_OK) < 0 && errno == EACCES) {
            logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no write access", opt_keepdir);
            exit(EX_DATAERR);
        }
        if (access(opt_keepdir, X_OK) < 0 && errno == EACCES) {
            logmsg(LOG_ERR, "directory to keep data: %s: permissions too strong: no execute access", opt_keepdir);
            exit(EX_DATAERR);
        }
        logmsg(LOG_INFO, "directory to keep data: %s", opt_keepdir);
    }

    dict_open(opt_signingtable, &dict_signingtable);
    if (opt_modetable)
        dict_open(opt_modetable, &dict_modetable);

    /* initialize OpenSSL */
    SSL_library_init();
    OpenSSL_add_all_algorithms();

    /* get meaningful error messages */
    SSL_load_error_strings();
    ERR_load_crypto_strings();

    /* Statistik initialisieren */
    init_stats();

    /* Signal-Handler fuer SIGALRM */
    signal(SIGALRM, sig_handler);

    /* Run milter */
    if ((c = smfi_main()) != MI_SUCCESS)
        logmsg(LOG_ERR, "Milter startup failed");
    else
        logmsg(LOG_NOTICE, "stopping %s %s listening on %s", STR_PROGNAME, STR_PROGVERSION, opt_miltersocket);

    dict_close(&dict_signingtable);
    if (opt_modetable)
        dict_close(&dict_modetable);

    /* cleanup OpenSSL */
    ERR_free_strings();
    EVP_cleanup();

    output_stats();

#ifdef DMALLOC
    dmalloc_log_stats();
    dmalloc_log_unfreed();
    dmalloc_shutdown();
#endif
    exit(c);
}
Exemplo n.º 6
0
static void pre_jail_init(char *unused_name, char **unused_argv)
{
    VSTRING *redirect;

    /*
     * Open read-only maps before dropping privilege, for consistency with
     * other Postfix daemons.
     */
    psc_acl_pre_jail_init(var_mynetworks, VAR_PSC_ACL);
    if (*var_psc_acl)
	psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL);
    /* Ignore smtpd_forbid_cmds lookup errors. Non-critical feature. */
    if (*var_psc_forbid_cmds)
	psc_forbid_cmds = string_list_init(MATCH_FLAG_RETURN,
					   var_psc_forbid_cmds);
    if (*var_psc_dnsbl_reply)
	psc_dnsbl_reply = dict_open(var_psc_dnsbl_reply, O_RDONLY,
				    DICT_FLAG_DUP_WARN);

    /*
     * Never, ever, get killed by a master signal, as that would corrupt the
     * database when we're in the middle of an update.
     */
    if (setsid() < 0)
	msg_warn("setsid: %m");

    /*
     * Security: don't create root-owned files that contain untrusted data.
     * And don't create Postfix-owned files in root-owned directories,
     * either. We want a correct relationship between (file or directory)
     * ownership and (file or directory) content. To open files before going
     * to jail, temporarily drop root privileges.
     */
    SAVE_AND_SET_EUGID(var_owner_uid, var_owner_gid);
    redirect = vstring_alloc(100);

    /*
     * Keep state in persistent external map. As a safety measure we sync the
     * database on each update. This hurts on LINUX file systems that sync
     * all dirty disk blocks whenever any application invokes fsync().
     * 
     * Start the cache maintenance pseudo thread after dropping privileges.
     */
#define PSC_DICT_OPEN_FLAGS (DICT_FLAG_DUP_REPLACE | DICT_FLAG_SYNC_UPDATE | \
	    DICT_FLAG_OPEN_LOCK)

    if (*var_psc_cache_map)
	psc_cache_map =
	    dict_cache_open(data_redirect_map(redirect, var_psc_cache_map),
			    O_CREAT | O_RDWR, PSC_DICT_OPEN_FLAGS);

    /*
     * Clean up and restore privilege.
     */
    vstring_free(redirect);
    RESTORE_SAVED_EUGID();

    /*
     * Initialize the dummy SMTP engine.
     */
    psc_smtpd_pre_jail_init();
}
Exemplo n.º 7
0
static ARGV *match_list_parse(ARGV *list, char *string, int init_match)
{
    const char *myname = "match_list_parse";
    VSTRING *buf = vstring_alloc(10);
    VSTREAM *fp;
    const char *delim = " ,\t\r\n";
    char   *bp = string;
    char   *start;
    char   *item;
    char   *map_type_name_flags;
    int     match;

#define OPEN_FLAGS	O_RDONLY
#define DICT_FLAGS	(DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX)
#define STR(x)		vstring_str(x)

    /*
     * /filename contents are expanded in-line. To support !/filename we
     * prepend the negation operator to each item from the file.
     */
    while ((start = mystrtokq(&bp, delim, "{}")) != 0) {
	if (*start == '#') {
	    msg_warn("%s: comment at end of line is not supported: %s %s",
		     myname, start, bp);
	    break;
	}
	for (match = init_match, item = start; *item == '!'; item++)
	    match = !match;
	if (*item == 0)
	    msg_fatal("%s: no pattern after '!'", myname);
	if (*item == '/') {			/* /file/name */
	    if ((fp = vstream_fopen(item, O_RDONLY, 0)) == 0) {
		vstring_sprintf(buf, "%s:%s", DICT_TYPE_NOFILE, item);
		/* XXX Should increment existing map refcount. */
		if (dict_handle(STR(buf)) == 0)
		    dict_register(STR(buf),
				  dict_surrogate(DICT_TYPE_NOFILE, item,
						 OPEN_FLAGS, DICT_FLAGS,
						 "open file %s: %m", item));
		argv_add(list, STR(buf), (char *) 0);
	    } else {
		while (vstring_fgets(buf, fp))
		    if (vstring_str(buf)[0] != '#')
			list = match_list_parse(list, vstring_str(buf), match);
		if (vstream_fclose(fp))
		    msg_fatal("%s: read file %s: %m", myname, item);
	    }
	} else if (MATCH_DICTIONARY(item)) {	/* type:table */
	    vstring_sprintf(buf, "%s%s(%o,%s)", match ? "" : "!",
			    item, OPEN_FLAGS, dict_flags_str(DICT_FLAGS));
	    map_type_name_flags = STR(buf) + (match == 0);
	    /* XXX Should increment existing map refcount. */
	    if (dict_handle(map_type_name_flags) == 0)
		dict_register(map_type_name_flags,
			      dict_open(item, OPEN_FLAGS, DICT_FLAGS));
	    argv_add(list, STR(buf), (char *) 0);
	} else {				/* other pattern */
	    argv_add(list, match ? item :
		     STR(vstring_sprintf(buf, "!%s", item)), (char *) 0);
	}
    }
    vstring_free(buf);
    return (list);
}
Exemplo n.º 8
0
DICT   *dict_union_open(const char *name, int open_flags, int dict_flags)
{
    static const char myname[] = "dict_union_open";
    DICT_UNION *dict_union;
    char   *saved_name = 0;
    char   *dict_type_name;
    ARGV   *argv = 0;
    char  **cpp;
    DICT   *dict;
    int     match_flags = 0;
    struct DICT_OWNER aggr_owner;
    size_t  len;

    /*
     * Clarity first. Let the optimizer worry about redundant code.
     */
#define DICT_UNION_RETURN(x) do { \
	      if (saved_name != 0) \
	          myfree(saved_name); \
	      if (argv != 0) \
	          argv_free(argv); \
	      return (x); \
	  } while (0)

    /*
     * Sanity checks.
     */
    if (open_flags != O_RDONLY)
	DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name,
					 open_flags, dict_flags,
				  "%s:%s map requires O_RDONLY access mode",
					 DICT_TYPE_UNION, name));

    /*
     * Split the table name into its constituent parts.
     */
    if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0
	|| *(saved_name = mystrndup(name + 1, len - 2)) == 0
	|| ((argv = argv_splitq(saved_name, CHARS_COMMA_SP, CHARS_BRACE)),
	    (argv->argc == 0)))
	DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name,
					 open_flags, dict_flags,
					 "bad syntax: \"%s:%s\"; "
					 "need \"%s:{type:name...}\"",
					 DICT_TYPE_UNION, name,
					 DICT_TYPE_UNION));

    /*
     * The least-trusted table in the set determines the over-all trust
     * level. The first table determines the pattern-matching flags.
     */
    DICT_OWNER_AGGREGATE_INIT(aggr_owner);
    for (cpp = argv->argv; (dict_type_name = *cpp) != 0; cpp++) {
	if (msg_verbose)
	    msg_info("%s: %s", myname, dict_type_name);
	if (strchr(dict_type_name, ':') == 0)
	    DICT_UNION_RETURN(dict_surrogate(DICT_TYPE_UNION, name,
					     open_flags, dict_flags,
					     "bad syntax: \"%s:%s\"; "
					     "need \"%s:{type:name...}\"",
					     DICT_TYPE_UNION, name,
					     DICT_TYPE_UNION));
	if ((dict = dict_handle(dict_type_name)) == 0)
	    dict = dict_open(dict_type_name, open_flags, dict_flags);
	dict_register(dict_type_name, dict);
	DICT_OWNER_AGGREGATE_UPDATE(aggr_owner, dict->owner);
	if (cpp == argv->argv)
	    match_flags = dict->flags & (DICT_FLAG_FIXED | DICT_FLAG_PATTERN);
    }

    /*
     * Bundle up the result.
     */
    dict_union =
	(DICT_UNION *) dict_alloc(DICT_TYPE_UNION, name, sizeof(*dict_union));
    dict_union->dict.lookup = dict_union_lookup;
    dict_union->dict.close = dict_union_close;
    dict_union->dict.flags = dict_flags | match_flags;
    dict_union->dict.owner = aggr_owner;
    dict_union->re_buf = vstring_alloc(100);
    dict_union->map_union = argv;
    argv = 0;
    DICT_UNION_RETURN(DICT_DEBUG (&dict_union->dict));
}