Beispiel #1
0
static void postmap_seq(const char *map_type, const char *map_name,
			        int dict_flags)
{
    DICT   *dict;
    const char *key;
    const char *value;
    int     func;

    if (strcmp(map_type, DICT_TYPE_PROXY) == 0)
	msg_fatal("can't sequence maps via the proxy service");
    dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags);
    for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) {
	if (dict_seq(dict, func, &key, &value) != 0)
	    break;
	if (*key == 0) {
	    msg_warn("table %s:%s: empty lookup key value is not allowed",
		     map_type, map_name);
	} else if (*value == 0) {
	    msg_warn("table %s:%s: key %s: empty string result is not allowed",
		     map_type, map_name, key);
	    msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
		     map_type, map_name);
	}
	vstream_printf("%s	%s\n", key, value);
    }
    if (dict->error)
	msg_fatal("table %s:%s: sequence error: %m", dict->type, dict->name);
    vstream_fflush(VSTREAM_OUT);
    dict_close(dict);
}
Beispiel #2
0
void    mkmap_close(MKMAP *mkmap)
{

    /*
     * Close the database.
     */
    dict_close(mkmap->dict);

    /*
     * Do whatever special processing is needed after closing the database,
     * such as releasing a global exclusive lock on the database file.
     * Individual Postfix dict modules implement locking only for individual
     * record operations, because most Postfix applications don't need global
     * exclusive locks.
     */
    if (mkmap->after_close)
	mkmap->after_close(mkmap);

    /*
     * Resume signal delivery.
     */
    if (mkmap->multi_writer == 0)
	sigresume();

    /*
     * Cleanup.
     */
    myfree((char *) mkmap);
}
Beispiel #3
0
static int postmap_deletes(VSTREAM *in, char **maps, const int map_count,
			           int dict_flags)
{
    int     found = 0;
    VSTRING *keybuf = vstring_alloc(100);
    DICT  **dicts;
    const char *map_name;
    int     n;
    int     open_flags;

    /*
     * Sanity check.
     */
    if (map_count <= 0)
	msg_panic("postmap_deletes: bad map count");

    /*
     * Open maps ahead of time.
     */
    dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count);
    for (n = 0; n < map_count; n++) {
	map_name = split_at(maps[n], ':');
	if (map_name && strcmp(maps[n], DICT_TYPE_PROXY) == 0)
	    open_flags = O_RDWR | O_CREAT;	/* XXX */
	else
	    open_flags = O_RDWR;
	dicts[n] = (map_name != 0 ?
		    dict_open3(maps[n], map_name, open_flags, dict_flags) :
		  dict_open3(var_db_type, maps[n], open_flags, dict_flags));
    }

    /*
     * Perform all requests.
     */
    while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
	for (n = 0; n < map_count; n++) {
	    found |= (dict_del(dicts[n], STR(keybuf)) == 0);
	    if (dicts[n]->error)
		msg_fatal("table %s:%s: delete error: %m",
			  dicts[n]->type, dicts[n]->name);
	}
    }

    /*
     * Cleanup.
     */
    for (n = 0; n < map_count; n++)
	if (dicts[n])
	    dict_close(dicts[n]);
    myfree((void *) dicts);
    vstring_free(keybuf);

    return (found);
}
Beispiel #4
0
void    dict_cache_close(DICT_CACHE *cp)
{

    /*
     * Destroy the DICT_CACHE object.
     */
    dict_cache_control(cp, DICT_CACHE_CTL_INTERVAL, 0, DICT_CACHE_CTL_END);
    dict_close(cp->db);
    if (cp->saved_curr_key)
	myfree(cp->saved_curr_key);
    if (cp->saved_curr_val)
	myfree(cp->saved_curr_val);
    myfree((char *) cp);
}
Beispiel #5
0
static int postmap_delete(const char *map_type, const char *map_name,
			          const char *key, int dict_flags)
{
    DICT   *dict;
    int     status;
    int     open_flags;

    if (strcmp(map_type, DICT_TYPE_PROXY) == 0)
	open_flags = O_RDWR | O_CREAT;		/* XXX */
    else
	open_flags = O_RDWR;
    dict = dict_open3(map_type, map_name, open_flags, dict_flags);
    status = dict_del(dict, key);
    if (dict->error)
	msg_fatal("table %s:%s: delete error: %m", dict->type, dict->name);
    dict_close(dict);
    return (status == 0);
}
Beispiel #6
0
static int postmap_query(const char *map_type, const char *map_name,
			         const char *key, int dict_flags)
{
    DICT   *dict;
    const char *value;

    dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags);
    if ((value = dict_get(dict, key)) != 0) {
	if (*value == 0) {
	    msg_warn("table %s:%s: key %s: empty string result is not allowed",
		     map_type, map_name, key);
	    msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
		     map_type, map_name);
	}
	vstream_printf("%s\n", value);
    }
    if (dict->error)
	msg_fatal("table %s:%s: query error: %m", dict->type, dict->name);
    vstream_fflush(VSTREAM_OUT);
    dict_close(dict);
    return (value != 0);
}
Beispiel #7
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);
}
Beispiel #8
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);
}
Beispiel #9
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);
}
Beispiel #10
0
static int postmap_queries(VSTREAM *in, char **maps, const int map_count,
			           const int postmap_flags,
			           const int dict_flags)
{
    int     found = 0;
    VSTRING *keybuf = vstring_alloc(100);
    DICT  **dicts;
    const char *map_name;
    const char *value;
    int     n;

    /*
     * Sanity check.
     */
    if (map_count <= 0)
	msg_panic("postmap_queries: bad map count");

    /*
     * Prepare to open maps lazily.
     */
    dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count);
    for (n = 0; n < map_count; n++)
	dicts[n] = 0;

    /*
     * Perform all queries. Open maps on the fly, to avoid opening unecessary
     * maps.
     */
    if ((postmap_flags & POSTMAP_FLAG_HB_KEY) == 0) {
	while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
	    for (n = 0; n < map_count; n++) {
		if (dicts[n] == 0)
		    dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
		       dict_open3(maps[n], map_name, O_RDONLY, dict_flags) :
		    dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags));
		if ((value = dict_get(dicts[n], STR(keybuf))) != 0) {
		    if (*value == 0) {
			msg_warn("table %s:%s: key %s: empty string result is not allowed",
			       dicts[n]->type, dicts[n]->name, STR(keybuf));
			msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
				 dicts[n]->type, dicts[n]->name);
		    }
		    vstream_printf("%s	%s\n", STR(keybuf), value);
		    found = 1;
		    break;
		}
		if (dicts[n]->error)
		    msg_fatal("table %s:%s: query error: %m",
			      dicts[n]->type, dicts[n]->name);
	    }
	}
    } else {
	POSTMAP_KEY_STATE key_state;
	MIME_STATE *mime_state;
	int     mime_errs = 0;

	/*
	 * Bundle up the request and instantiate a MIME parsing engine.
	 */
	key_state.dicts = dicts;
	key_state.maps = maps;
	key_state.map_count = map_count;
	key_state.dict_flags = dict_flags;
	key_state.header_done = 0;
	key_state.found = 0;
	mime_state =
	    mime_state_alloc((postmap_flags & POSTMAP_FLAG_MIME_KEY) ?
			     0 : MIME_OPT_DISABLE_MIME,
			     (postmap_flags & POSTMAP_FLAG_HEADER_KEY) ?
			     postmap_header : (MIME_STATE_HEAD_OUT) 0,
			     (postmap_flags & POSTMAP_FLAG_FULL_KEY) ?
			     (MIME_STATE_ANY_END) 0 : postmap_head_end,
			     (postmap_flags & POSTMAP_FLAG_BODY_KEY) ?
			     postmap_body : (MIME_STATE_BODY_OUT) 0,
			     (MIME_STATE_ANY_END) 0,
			     (MIME_STATE_ERR_PRINT) 0,
			     (void *) &key_state);

	/*
	 * Process the input message.
	 */
	while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF
	       && key_state.header_done == 0 && mime_errs == 0)
	    mime_errs = mime_state_update(mime_state, REC_TYPE_NORM,
					  STR(keybuf), LEN(keybuf));

	/*
	 * Flush the MIME engine output buffer and tidy up loose ends.
	 */
	if (mime_errs == 0)
	    mime_errs = mime_state_update(mime_state, REC_TYPE_END, "", 0);
	if (mime_errs)
	    msg_fatal("message format error: %s",
		      mime_state_detail(mime_errs)->text);
	mime_state_free(mime_state);
	found = key_state.found;
    }
    if (found)
	vstream_fflush(VSTREAM_OUT);

    /*
     * Cleanup.
     */
    for (n = 0; n < map_count; n++)
	if (dicts[n])
	    dict_close(dicts[n]);
    myfree((void *) dicts);
    vstring_free(keybuf);

    return (found);
}
Beispiel #11
0
static int postalias_queries(VSTREAM *in, char **maps, const int map_count,
			             const int dict_flags)
{
    int     found = 0;
    VSTRING *keybuf = vstring_alloc(100);
    DICT  **dicts;
    const char *map_name;
    const char *value;
    int     n;

    /*
     * Sanity check.
     */
    if (map_count <= 0)
	msg_panic("postalias_queries: bad map count");

    /*
     * Prepare to open maps lazily.
     */
    dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count);
    for (n = 0; n < map_count; n++)
	dicts[n] = 0;

    /*
     * Perform all queries. Open maps on the fly, to avoid opening unecessary
     * maps.
     */
    while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
	for (n = 0; n < map_count; n++) {
	    if (dicts[n] == 0)
		dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
		       dict_open3(maps[n], map_name, O_RDONLY, dict_flags) :
		    dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags));
	    if ((value = dict_get(dicts[n], STR(keybuf))) != 0) {
		if (*value == 0) {
		    msg_warn("table %s:%s: key %s: empty string result is not allowed",
			     dicts[n]->type, dicts[n]->name, STR(keybuf));
		    msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
			     dicts[n]->type, dicts[n]->name);
		}
		vstream_printf("%s:	%s\n", STR(keybuf), value);
		found = 1;
		break;
	    }
	    if (dicts[n]->error)
		msg_fatal("table %s:%s: query error: %m",
			  dicts[n]->type, dicts[n]->name);
	}
    }
    if (found)
	vstream_fflush(VSTREAM_OUT);

    /*
     * Cleanup.
     */
    for (n = 0; n < map_count; n++)
	if (dicts[n])
	    dict_close(dicts[n]);
    myfree((void *) dicts);
    vstring_free(keybuf);

    return (found);
}