int main (int argc, char *argv[]) { gint status = MI_SUCCESS; GError *error = NULL; GOptionContext *option_context; unsigned int major, minor, patch_level; #ifdef HAVE_LOCALE_H setlocale(LC_ALL, ""); #endif /* * workaround for memory profiler for GLib memory * profiler, we need to call g_mem_set_vtable prior to * any other GLib functions. smfi_version() calls * g_mem_set_vtable() internally. */ smfi_version(&major, &minor, &patch_level); option_context = g_option_context_new(NULL); g_option_context_add_main_entries(option_context, option_entries, NULL); if (!g_option_context_parse(option_context, &argc, &argv, &error)) { g_print("%s\n", error->message); g_error_free(error); g_option_context_free(option_context); exit(EXIT_FAILURE); } if (verbose) smfi_setdbg(6); status = smfi_setconn(spec); if (status == MI_SUCCESS) status = smfi_register(smfilter); if (status == MI_SUCCESS) return smfi_main() == MI_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE; return EXIT_FAILURE; }
main(int argc, char **argv) { int sts ; // Set up the Milter socket unlink(MILTER_SOCKET) ; smfi_setconn(MILTER_SOCKET) ; openlog(PACKAGE_NAME, LOG_PID, LOG_MAIL) ; syslog(LOG_INFO, "%s Initializing...", PACKAGE_STRING) ; // Register our milter callbacks if(smfi_register(smilter) == MI_FAILURE) { fprintf(stderr, "%s: smfi_register failed\n", argv[0]) ; exit(EX_UNAVAILABLE) ; } // And away we go! sts = smfi_main() ; closelog() ; return sts ; }
int main(int argc, char **argv) { char *my_socket, *pt; const struct optstruct *opt; struct optstruct *opts; time_t currtime; mode_t umsk; int ret; cl_initialize_crypto(); memset(&descr, 0, sizeof(struct smfiDesc)); descr.xxfi_name = "ClamAV"; /* filter name */ descr.xxfi_version = SMFI_VERSION; /* milter version */ descr.xxfi_flags = SMFIF_QUARANTINE; /* flags */ descr.xxfi_connect = clamfi_connect; /* connection info filter */ descr.xxfi_envfrom = clamfi_envfrom; /* envelope sender filter */ descr.xxfi_envrcpt = clamfi_envrcpt; /* envelope recipient filter */ descr.xxfi_header = clamfi_header; /* header filter */ descr.xxfi_body = clamfi_body; /* body block */ descr.xxfi_eom = clamfi_eom; /* end of message */ descr.xxfi_abort = clamfi_abort; /* message aborted */ opts = optparse(NULL, argc, argv, 1, OPT_MILTER, 0, NULL); if (!opts) { mprintf("!Can't parse command line options\n"); return 1; } if(optget(opts, "help")->enabled) { printf("Usage: %s [-c <config-file>]\n\n", argv[0]); printf(" --help -h Show this help\n"); printf(" --version -V Show version and exit\n"); printf(" --config-file <file> -c Read configuration from file\n\n"); optfree(opts); return 0; } if(opts->filename) { int x; for(x = 0; opts->filename[x]; x++) mprintf("^Ignoring option %s\n", opts->filename[x]); } if(optget(opts, "version")->enabled) { printf("clamav-milter %s\n", get_version()); optfree(opts); return 0; } pt = strdup(optget(opts, "config-file")->strarg); if (pt == NULL) { printf("Unable to allocate memory for config file\n"); return 1; } if((opts = optparse(pt, 0, NULL, 1, OPT_MILTER, 0, opts)) == NULL) { printf("%s: cannot parse config file %s\n", argv[0], pt); free(pt); return 1; } free(pt); if((opt = optget(opts, "Chroot"))->enabled) { if(chdir(opt->strarg) != 0) { logg("!Cannot change directory to %s\n", opt->strarg); return 1; } if(chroot(opt->strarg) != 0) { logg("!chroot to %s failed. Are you root?\n", opt->strarg); return 1; } } pt = optget(opts, "AddHeader")->strarg; if (strcasecmp(pt, "No")) { char myname[255]; if (((opt = optget(opts, "ReportHostname"))->enabled && strncpy(myname, opt->strarg, sizeof(myname))) || !gethostname(myname, sizeof(myname))) { myname[sizeof(myname)-1] = '\0'; snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s", get_version(), myname); } else { snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s", get_version()); } xvirushdr[sizeof(xvirushdr)-1] = '\0'; descr.xxfi_flags |= SMFIF_ADDHDRS; if (strcasecmp(pt, "Add")) { /* Replace or Yes */ descr.xxfi_flags |= SMFIF_CHGHDRS; addxvirus = 1; } else { /* Add */ addxvirus = 2; } } if(!(my_socket = optget(opts, "MilterSocket")->strarg)) { logg("!Please configure the MilterSocket directive\n"); logg_close(); optfree(opts); return 1; } if(smfi_setconn(my_socket) == MI_FAILURE) { logg("!smfi_setconn failed\n"); logg_close(); optfree(opts); return 1; } if(smfi_register(descr) == MI_FAILURE) { logg("!smfi_register failed\n"); logg_close(); optfree(opts); return 1; } opt = optget(opts, "FixStaleSocket"); umsk = umask(0777); /* socket is created with 000 to avoid races */ if(smfi_opensocket(opt->enabled) == MI_FAILURE) { logg("!Failed to create socket %s\n", my_socket); logg_close(); optfree(opts); return 1; } umask(umsk); /* restore umask */ if(strncmp(my_socket, "inet:", 5) && strncmp(my_socket, "inet6:", 6)) { /* set group ownership and perms on the local socket */ char *sock_name = my_socket; mode_t sock_mode; if(!strncmp(my_socket, "unix:", 5)) sock_name += 5; if(!strncmp(my_socket, "local:", 6)) sock_name += 6; if(*my_socket == ':') sock_name ++; if(optget(opts, "MilterSocketGroup")->enabled) { char *gname = optget(opts, "MilterSocketGroup")->strarg, *end; gid_t sock_gid = strtol(gname, &end, 10); if(*end) { struct group *pgrp = getgrnam(gname); if(!pgrp) { logg("!Unknown group %s\n", gname); logg_close(); optfree(opts); return 1; } sock_gid = pgrp->gr_gid; } if(chown(sock_name, -1, sock_gid)) { logg("!Failed to change socket ownership to group %s\n", gname); logg_close(); optfree(opts); return 1; } } if ((opt = optget(opts, "User"))->enabled) { struct passwd *user; if ((user = getpwnam(opt->strarg)) == NULL) { logg("ERROR: Can't get information about user %s.\n", opt->strarg); logg_close(); optfree(opts); return 1; } if(chown(sock_name, user->pw_uid, -1)) { logg("!Failed to change socket ownership to user %s\n", user->pw_name); optfree(opts); logg_close(); return 1; } } if(optget(opts, "MilterSocketMode")->enabled) { char *end; sock_mode = strtol(optget(opts, "MilterSocketMode")->strarg, &end, 8); if(*end) { logg("!Invalid MilterSocketMode %s\n", optget(opts, "MilterSocketMode")->strarg); logg_close(); optfree(opts); return 1; } } else sock_mode = 0777 & ~umsk; if(chmod(sock_name, sock_mode & 0666)) { logg("!Cannot set milter socket permission to %s\n", optget(opts, "MilterSocketMode")->strarg); logg_close(); optfree(opts); return 1; } } if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) { struct passwd *user = NULL; if((user = getpwnam(opt->strarg)) == NULL) { fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg); optfree(opts); return 1; } if(optget(opts, "AllowSupplementaryGroups")->enabled) { #ifdef HAVE_INITGROUPS if(initgroups(opt->strarg, user->pw_gid)) { fprintf(stderr, "ERROR: initgroups() failed.\n"); optfree(opts); return 1; } #else mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups\n"); optfree(opts); return 1; #endif } else { #ifdef HAVE_SETGROUPS if(setgroups(1, &user->pw_gid)) { fprintf(stderr, "ERROR: setgroups() failed.\n"); optfree(opts); return 1; } #endif } if(setgid(user->pw_gid)) { fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid); optfree(opts); return 1; } if(setuid(user->pw_uid)) { fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid); optfree(opts); return 1; } } logg_lock = !optget(opts, "LogFileUnlock")->enabled; logg_time = optget(opts, "LogTime")->enabled; logg_size = optget(opts, "LogFileMaxSize")->numarg; logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled; if (logg_size) logg_rotate = optget(opts, "LogRotate")->enabled; if((opt = optget(opts, "LogFile"))->enabled) { logg_file = opt->strarg; if(!cli_is_abspath(logg_file)) { fprintf(stderr, "ERROR: LogFile requires full path.\n"); logg_close(); optfree(opts); return 1; } } else logg_file = NULL; #if defined(USE_SYSLOG) && !defined(C_AIX) if(optget(opts, "LogSyslog")->enabled) { int fac; opt = optget(opts, "LogFacility"); if((fac = logg_facility(opt->strarg)) == -1) { logg("!LogFacility: %s: No such facility.\n", opt->strarg); logg_close(); optfree(opts); return 1; } openlog("clamav-milter", LOG_PID, fac); logg_syslog = 1; } #endif time(&currtime); if(logg("#+++ Started at %s", ctime(&currtime))) { fprintf(stderr, "ERROR: Can't initialize the internal logger\n"); logg_close(); optfree(opts); return 1; } if((opt = optget(opts, "TemporaryDirectory"))->enabled) tempdir = opt->strarg; if(localnets_init(opts) || init_actions(opts)) { logg_close(); optfree(opts); return 1; } if((opt = optget(opts, "Whitelist"))->enabled && whitelist_init(opt->strarg)) { localnets_free(); logg_close(); optfree(opts); return 1; } if((opt = optget(opts, "SkipAuthenticated"))->enabled && smtpauth_init(opt->strarg)) { localnets_free(); whitelist_free(); logg_close(); optfree(opts); return 1; } multircpt = optget(opts, "SupportMultipleRecipients")->enabled; if(!optget(opts, "Foreground")->enabled) { if(daemonize() == -1) { logg("!daemonize() failed\n"); localnets_free(); whitelist_free(); cpool_free(); logg_close(); optfree(opts); return 1; } if(chdir("/") == -1) logg("^Can't change current working directory to root\n"); } maxfilesize = optget(opts, "MaxFileSize")->numarg; if(!maxfilesize) { logg("^Invalid MaxFileSize, using default (%d)\n", CLI_DEFAULT_MAXFILESIZE); maxfilesize = CLI_DEFAULT_MAXFILESIZE; } readtimeout = optget(opts, "ReadTimeout")->numarg; cpool_init(opts); if (!cp) { logg("!Failed to init the socket pool\n"); localnets_free(); whitelist_free(); logg_close(); optfree(opts); return 1; } if((opt = optget(opts, "PidFile"))->enabled) { FILE *fd; mode_t old_umask = umask(0002); if((fd = fopen(opt->strarg, "w")) == NULL) { logg("!Can't save PID in file %s\n", opt->strarg); } else { if (fprintf(fd, "%u\n", (unsigned int)getpid())<0) { logg("!Can't save PID in file %s\n", opt->strarg); } fclose(fd); } umask(old_umask); } ret = smfi_main(); optfree(opts); logg_close(); cpool_free(); localnets_free(); whitelist_free(); return ret; }
/*}}}*/ }; static int usage (const char *pgm) /*{{{*/ { fprintf (stderr, "Usage: %s [-L <loglevel>] [-s <socket name>] [-s <reread in seconds>] [-c <config filename>] [-l]\n", pgm); return 1; }/*}}}*/ int main (int argc, char **argv) /*{{{*/ { int rc; char *ptr; char *sock_name; int reread; int n; lock_t *lock; if (ptr = strrchr (argv[0], '/')) program = ptr + 1; else program = argv[0]; loglevel = "WARNING"; sock_name = NULL; reread = 0; cfgfile = NULL; while ((n = getopt (argc, argv, "L:s:r:c:l")) != -1) switch (n) { case 'L': loglevel = optarg; break; case 's': if (sock_name) free (sock_name); if (! (sock_name = strdup (optarg))) { fprintf (stderr, "Failed to allocate memory for socket name %s (%m).\n", optarg); return 1; } break; case 'r': if ((reread = atoi (optarg)) < 1) { fprintf (stderr, "Reread value must be at least 1.\n"); return 1; } break; case 'c': if (cfgfile) free (cfgfile); if (! (cfgfile = strdup (optarg))) { fprintf (stderr, "Failed to allocate memory for config.filename %s (%m).\n", optarg); return 1; } break; case 'l': break; default: return usage (argv[0]); } if (optind < argc) return usage (argv[0]); if (! (lock = lock_alloc (LOCK_PATH))) { fprintf (stderr, "Failed to allocate memory for locking (%m).\n"); return 1; } if (! lock_lock (lock)) { fprintf (stderr, "Instance seems already to run, aborting.\n"); return 1; } if ((! sock_name) || (! cfgfile)) { const char *home; if (! (home = getenv ("HOME"))) home = ""; if (! sock_name) { if (! (sock_name = malloc (strlen (home) + sizeof (SOCK_PATH) + 16))) { fprintf (stderr, "Failed to allocate socket name %s/%s (%m).\n", home, SOCK_PATH); return 1; } sprintf (sock_name, "unix:%s/%s", home, SOCK_PATH); } if (! cfgfile) { if (! (cfgfile = malloc (strlen (home) + sizeof (CFGFILE) + 1))) { fprintf (stderr, "Failed to allocate config.filename %s/%s (%m).\n", home, CFGFILE); return 1; } sprintf (cfgfile, "%s/%s", home, CFGFILE); } } rc = 1; umask (0); if (smfi_register (bav) == MI_FAILURE) fprintf (stderr, "Failed to register filter.\n"); else if (smfi_setconn (sock_name) == MI_FAILURE) fprintf (stderr, "Failed to register socket name \"%s\".\n", sock_name); else if (smfi_opensocket (1) == MI_FAILURE) fprintf (stderr, "Failed to open socket socket \"%s\".\n", sock_name); else { if (smfi_main () == MI_FAILURE) fprintf (stderr, "Failed to hand over control to milter.\n"); else rc = 0; } unlink (sock_name); lock_unlock (lock); lock_free (lock); free (sock_name); free (cfgfile); return rc; }/*}}}*/
int main(int argc, char **argv) { const char *progname = argv[0]; const char *port; const char *mail_log = DEFAULT_MAIL_LOG; int c; pthread_t tid; struct smfiDesc smfilter = { "blacklist", /* filter name */ SMFI_VERSION, /* version code -- leave untouched */ SMFIF_NONE, /* flags - we only look */ blacklist_connect, /* connection callback */ NULL, /* HELO filter callback */ NULL, /* envelope sender filter callback */ NULL, /* envelope recipient filter callback */ blacklist_header, /* header filter callback */ NULL, /* end of header callback */ blacklist_body, /* body filter callback */ NULL, /* end of message callback */ blacklist_cleanup, /* message aborted callback */ blacklist_cleanup, /* connection cleanup callback */ #if SMFI_VERSION > 2 NULL, /* Unrecognised command */ #endif #if SMFI_VERSION > 3 NULL, /* DATA command callback */ #endif #if SMFI_VERSION >= 0x01000000 NULL, /* Negotiation callback */ #endif }; while((c = getopt(argc, argv, "f:")) != EOF) switch(c) { case 'f': mail_log = optarg; break; default: fprintf(stderr, "Usage: %s [ -f log_file ] socket-addr\n", progname); return EX_USAGE; } if(optind >= argc) { fprintf(stderr, "Usage: %s [ -f log_file ] socket-addr\n", progname); return EX_USAGE; } if(access(mail_log, R_OK) < 0) { perror(mail_log); return EX_NOINPUT; } openlog("blacklist-milter", LOG_CONS|LOG_PID, LOG_MAIL); #ifndef DEBUG switch(fork()) { case -1: perror("fork"); return EX_OSERR; case 0: /* child */ break; default: /* parent */ return EX_OK; } #endif port = argv[optind]; if(strncasecmp(port, "unix:", 5) == 0) { if(unlink(&port[5]) < 0) if(errno != ENOENT) perror(&port[5]); } else if(strncasecmp(port, "local:", 6) == 0) { if(unlink(&port[6]) < 0) if(errno != ENOENT) perror(&port[6]); } else if(port[0] == '/') { if(unlink(port) < 0) if(errno != ENOENT) perror(port); } /* sendmail->milter comms */ if(smfi_setconn(port) == MI_FAILURE) { fprintf(stderr, "%s: smfi_setconn failed\n", progname); return EX_SOFTWARE; } if(smfi_register(smfilter) == MI_FAILURE) { fprintf(stderr, "%s: smfi_register failed\n", progname); return EX_UNAVAILABLE; } if(smfi_opensocket(1) == MI_FAILURE) { fprintf(stderr, "%s: can't open/create %s\n", progname, port); return EX_CONFIG; } syslog(LOG_INFO, "Starting blacklist"); #ifndef DEBUG close(0); close(1); close(2); open("/dev/null", O_RDONLY); open("/dev/console", O_WRONLY); if(dup(1) < 0) { perror("dup"); return EX_OSERR; } #endif setpgrp(); pthread_create(&tid, NULL, watchdog, mail_log); return smfi_main(); }
int main(int argc, char *argv[]) { int c, r; extern int yynerrs; extern FILE *yyin; const char *args = "c:hndv"; char *cfg_file = NULL; FILE *f; pthread_t reload_thr; rmilter_pidfh_t *pfh = NULL; pid_t pid; daemonize = 1; /* Process command line options */ while ((c = getopt (argc, argv, args)) != -1) { switch (c) { case 'c': if (optarg == NULL || *optarg == '\0') { fprintf (stderr, "Illegal config_file: %s\n", optarg); exit (EX_USAGE); } else { cfg_file = strdup (optarg); } break; case 'n': daemonize = 0; break; case 'd': yydebug = 1; break; case 'v': version (); break; case 'h': default: usage (); break; } } openlog ("rmilter.startup", LOG_PID, LOG_MAIL); cfg = (struct config_file*) malloc (sizeof(struct config_file)); if (cfg == NULL) { msg_warn("malloc: %s", strerror (errno)); return -1; } bzero (cfg, sizeof(struct config_file)); init_defaults (cfg); if (cfg_file == NULL) { cfg_file = strdup ("/usr/local/etc/rmilter.conf"); } f = fopen (cfg_file, "r"); if (f == NULL) { msg_warn("cannot open file: %s", cfg_file); return EBADF; } yyin = f; yyrestart (yyin); if (yyparse () != 0 || yynerrs > 0) { msg_warn("yyparse: cannot parse config file, %d errors", yynerrs); return EBADF; } closelog (); openlog (cfg->syslog_name, LOG_PID, LOG_MAIL); if (!cfg->cache_use_redis) { msg_warn("rmilter is configured to work with legacy memcached cache," " please consider switching to redis by adding " "'use_redis = true;' into configuration"); } fclose (f); if (argv[0] && strrchr (argv[0], '/') != NULL) { _rmilter_progname = strrchr (argv[0], '/') + 1; } else { _rmilter_progname = argv[0]; } cfg->cfg_name = strdup (cfg_file); /* Strictly set temp dir */ if (!cfg->temp_dir) { msg_warn("tempdir is not set, trying to use $TMPDIR"); cfg->temp_dir = getenv ("TMPDIR"); if (!cfg->temp_dir) { cfg->temp_dir = strdup ("/tmp"); } } if (cfg->sizelimit == 0) { msg_warn("maxsize is not set, no limits on size of scanned mail"); } #ifdef HAVE_SRANDOMDEV srandomdev(); #else srand (time (NULL)); #endif umask (0); rng_state = get_prng_state (); smfi_setconn (cfg->sock_cred); if (smfi_register (smfilter) == MI_FAILURE) { msg_err("smfi_register failed"); exit (EX_UNAVAILABLE); } if (smfi_opensocket (true) == MI_FAILURE) { msg_err("Unable to open listening socket"); exit (EX_UNAVAILABLE); } if (daemonize && daemon (0, 0) == -1) { msg_err("Unable to daemonize"); exit (EX_UNAVAILABLE); } msg_info("main: starting rmilter version %s, listen on %s", MVERSION, cfg->sock_cred); if (pthread_create (&reload_thr, NULL, reload_thread, NULL)) { msg_warn("main: cannot start reload thread, ignoring error"); } if (cfg->pid_file) { pfh = rmilter_pidfile_open (cfg->pid_file, 0644, &pid); if (pfh == NULL) { msg_err("Unable to open pidfile %s", cfg->pid_file); exit (EX_UNAVAILABLE); } rmilter_pidfile_write (pfh); } r = smfi_main (); if (cfg_file != NULL) free (cfg_file); if (pfh) { rmilter_pidfile_close (pfh); } return r; }
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); }
int main(int argc, char **argv) { int ch; mode_t omask; const char *oconn = OCONN; const char *user = USER; const char *group = ""; sfsistat r = MI_FAILURE; const char *ofile = NULL; tzset(); openlog("sa2scl-milter", LOG_PID | LOG_NDELAY, LOG_DAEMON); while ((ch = getopt(argc, argv, "dg:p:u:")) != -1) { switch (ch) { case 'd': debug = 1; break; case 'g': group = optarg; break; case 'p': oconn = optarg; break; case 'u': user = optarg; break; default: usage(argv[0]); } } if (argc != optind) { fprintf(stderr, "unknown command line argument: %s ...", argv[optind]); usage(argv[0]); } if (!strncmp(oconn, "unix:", 5)) ofile = oconn + 5; else if (!strncmp(oconn, "local:", 6)) ofile = oconn + 6; if (ofile != NULL) unlink(ofile); /* drop privileges */ if (!getuid()) { struct passwd *pw; struct group *gr; if ((pw = getpwnam(user)) == NULL) { fprintf(stderr, "getpwnam: %s: %s\n", user, strerror(errno)); return (1); } if (strlen(group) == 0 || (gr = getgrnam(group)) == NULL) { /* use primary group of user */ setgroups(1, &pw->pw_gid); if (setegid(pw->pw_gid) || setgid(pw->pw_gid)) { fprintf(stderr, "setgid: %s\n", strerror(errno)); return (1); } omask = 0177; } else { /* custom group */ setgroups(1, &gr->gr_gid); if (setegid(gr->gr_gid) || setgid(gr->gr_gid)) { fprintf(stderr, "setgid: %s\n", strerror(errno)); return (1); } omask = 0117; } if ( #if ! ( __linux__ ) seteuid(pw->pw_uid) || #endif setuid(pw->pw_uid)) { fprintf(stderr, "setuid: %s\n", strerror(errno)); return (1); } } if (smfi_setconn((char *)oconn) != MI_SUCCESS) { fprintf(stderr, "smfi_setconn: %s: failed\n", oconn); goto done; } if (smfi_register(smfilter) != MI_SUCCESS) { fprintf(stderr, "smfi_register: failed\n"); goto done; } /* daemonize (detach from controlling terminal) */ if (!debug && daemon(0, 0)) { fprintf(stderr, "daemon: %s\n", strerror(errno)); goto done; } umask(omask); msg(LOG_INFO, NULL, "smfi_main: started"); r = smfi_main(); if (r != MI_SUCCESS) msg(LOG_ERR, NULL, "smfi_main: terminating due to error"); else msg(LOG_INFO, NULL, "smfi_main: terminating without error"); done: return (r); }
int main(int argc, char **argv) { char *my_socket, *pt; const struct optstruct *opt; struct optstruct *opts; time_t currtime; int ret; memset(&descr, 0, sizeof(struct smfiDesc)); descr.xxfi_name = "ClamAV"; /* filter name */ descr.xxfi_version = SMFI_VERSION; /* milter version */ descr.xxfi_flags = SMFIF_QUARANTINE; /* flags */ descr.xxfi_connect = clamfi_connect; /* connection info filter */ descr.xxfi_envfrom = clamfi_envfrom; /* envelope sender filter */ descr.xxfi_envrcpt = clamfi_envrcpt; /* envelope recipient filter */ descr.xxfi_header = clamfi_header; /* header filter */ descr.xxfi_body = clamfi_body; /* body block */ descr.xxfi_eom = clamfi_eom; /* end of message */ descr.xxfi_abort = clamfi_abort; /* message aborted */ opts = optparse(NULL, argc, argv, 1, OPT_MILTER, 0, NULL); if (!opts) { mprintf("!Can't parse command line options\n"); return 1; } if(optget(opts, "help")->enabled) { printf("Usage: %s [-c <config-file>]\n\n", argv[0]); printf(" --help -h Show this help\n"); printf(" --version -V Show version and exit\n"); printf(" --config-file <file> -c Read configuration from file\n\n"); optfree(opts); return 0; } if(opts->filename) { int x; for(x = 0; opts->filename[x]; x++) mprintf("^Ignoring option %s\n", opts->filename[x]); } if(optget(opts, "version")->enabled) { printf("clamav-milter %s\n", get_version()); optfree(opts); return 0; } pt = strdup(optget(opts, "config-file")->strarg); if((opts = optparse(pt, 0, NULL, 1, OPT_MILTER, 0, opts)) == NULL) { printf("%s: cannot parse config file %s\n", argv[0], pt); free(pt); return 1; } free(pt); if((opt = optget(opts, "Chroot"))->enabled) { if(chdir(opt->strarg) != 0) { logg("!Cannot change directory to %s\n", opt->strarg); return 1; } if(chroot(opt->strarg) != 0) { logg("!chroot to %s failed. Are you root?\n", opt->strarg); return 1; } } if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) { struct passwd *user = NULL; if((user = getpwnam(opt->strarg)) == NULL) { fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg); optfree(opts); return 1; } if(optget(opts, "AllowSupplementaryGroups")->enabled) { #ifdef HAVE_INITGROUPS if(initgroups(opt->strarg, user->pw_gid)) { fprintf(stderr, "ERROR: initgroups() failed.\n"); optfree(opts); return 1; } #else mprintf("!AllowSupplementaryGroups: initgroups() is not available, please disable AllowSupplementaryGroups\n"); optfree(opts); return 1; #endif } else { #ifdef HAVE_SETGROUPS if(setgroups(1, &user->pw_gid)) { fprintf(stderr, "ERROR: setgroups() failed.\n"); optfree(opts); return 1; } #endif } if(setgid(user->pw_gid)) { fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid); optfree(opts); return 1; } if(setuid(user->pw_uid)) { fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid); optfree(opts); return 1; } } logg_lock = !optget(opts, "LogFileUnlock")->enabled; logg_time = optget(opts, "LogTime")->enabled; logg_size = optget(opts, "LogFileMaxSize")->numarg; logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled; if((opt = optget(opts, "LogFile"))->enabled) { logg_file = opt->strarg; if(strlen(logg_file) < 2 || logg_file[0] != '/') { fprintf(stderr, "ERROR: LogFile requires full path.\n"); logg_close(); optfree(opts); return 1; } } else logg_file = NULL; #if defined(USE_SYSLOG) && !defined(C_AIX) if(optget(opts, "LogSyslog")->enabled) { int fac; opt = optget(opts, "LogFacility"); if((fac = logg_facility(opt->strarg)) == -1) { logg("!LogFacility: %s: No such facility.\n", opt->strarg); logg_close(); optfree(opts); return 1; } openlog("clamav-milter", LOG_PID, fac); logg_syslog = 1; } #endif time(&currtime); if(logg("#+++ Started at %s", ctime(&currtime))) { fprintf(stderr, "ERROR: Can't initialize the internal logger\n"); logg_close(); optfree(opts); return 1; } if((opt = optget(opts, "TemporaryDirectory"))->enabled) tempdir = opt->strarg; if(localnets_init(opts) || init_actions(opts)) { logg_close(); optfree(opts); return 1; } if((opt = optget(opts, "Whitelist"))->enabled && whitelist_init(opt->strarg)) { localnets_free(); logg_close(); optfree(opts); return 1; } if((opt = optget(opts, "SkipAuthenticated"))->enabled && smtpauth_init(opt->strarg)) { localnets_free(); whitelist_free(); logg_close(); optfree(opts); return 1; } pt = optget(opts, "AddHeader")->strarg; if(strcasecmp(pt, "No")) { char myname[255]; if(!gethostname(myname, sizeof(myname))) { myname[sizeof(myname)-1] = '\0'; snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s", get_version(), myname); xvirushdr[sizeof(xvirushdr)-1] = '\0'; } else { snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s", get_version()); xvirushdr[sizeof(xvirushdr)-1] = '\0'; } descr.xxfi_flags |= SMFIF_ADDHDRS; if(strcasecmp(pt, "Add")) { /* Replace or Yes */ descr.xxfi_flags |= SMFIF_CHGHDRS; addxvirus = 1; } else { /* Add */ addxvirus = 2; } } if(!(my_socket = optget(opts, "MilterSocket")->strarg)) { logg("!Please configure the MilterSocket directive\n"); localnets_free(); whitelist_free(); logg_close(); optfree(opts); return 1; } if(!optget(opts, "Foreground")->enabled) { if(daemonize() == -1) { logg("!daemonize() failed\n"); localnets_free(); whitelist_free(); cpool_free(); logg_close(); optfree(opts); return 1; } if(chdir("/") == -1) logg("^Can't change current working directory to root\n"); } if(smfi_setconn(my_socket) == MI_FAILURE) { logg("!smfi_setconn failed\n"); localnets_free(); whitelist_free(); logg_close(); optfree(opts); return 1; } if(smfi_register(descr) == MI_FAILURE) { logg("!smfi_register failed\n"); localnets_free(); whitelist_free(); logg_close(); optfree(opts); return 1; } opt = optget(opts, "FixStaleSocket"); if(smfi_opensocket(opt->enabled) == MI_FAILURE) { logg("!Failed to create socket %s\n", my_socket); localnets_free(); whitelist_free(); logg_close(); optfree(opts); return 1; } maxfilesize = optget(opts, "MaxFileSize")->numarg; readtimeout = optget(opts, "ReadTimeout")->numarg; cpool_init(opts); if (!cp) { logg("!Failed to init the socket pool\n"); localnets_free(); whitelist_free(); logg_close(); optfree(opts); return 1; } if((opt = optget(opts, "PidFile"))->enabled) { FILE *fd; mode_t old_umask = umask(0006); if((fd = fopen(opt->strarg, "w")) == NULL) { logg("!Can't save PID in file %s\n", opt->strarg); } else { if (fprintf(fd, "%u", (unsigned int)getpid())<0) { logg("!Can't save PID in file %s\n", opt->strarg); } fclose(fd); } umask(old_umask); } ret = smfi_main(); optfree(opts); logg_close(); cpool_free(); localnets_free(); whitelist_free(); return ret; }
int main(int argc, char **argv) { char *action = 0; char *command = 0; const struct command_map *cp; int ch; int code; const char **cpp; char *set_macro_state_arg = 0; char *nosend = 0; char *noreply = 0; const struct noproto_map *np; while ((ch = getopt(argc, argv, "a:A:b:c:C:d:f:h:i:lm:M:n:N:p:rv")) > 0) { switch (ch) { case 'a': action = optarg; break; case 'A': if (rcpt_count >= MAX_RCPT) { fprintf(stderr, "too many -A options\n"); exit(1); } rcpt_addr[rcpt_count++] = optarg; break; case 'b': #ifdef SMFIR_REPLBODY if (body_file) { fprintf(stderr, "too many -b options\n"); exit(1); } body_file = optarg; #else fprintf(stderr, "no libmilter support to replace body\n"); #endif break; case 'c': command = optarg; break; case 'd': if (smfi_setdbg(atoi(optarg)) == MI_FAILURE) { fprintf(stderr, "smfi_setdbg failed\n"); exit(1); } break; case 'f': #ifdef SMFIR_CHGFROM if (chg_from) { fprintf(stderr, "too many -f options\n"); exit(1); } chg_from = optarg; #else fprintf(stderr, "no libmilter support to change sender\n"); exit(1); #endif break; case 'h': #ifdef SMFIR_CHGHEADER if (chg_hdr) { fprintf(stderr, "too many -h options\n"); exit(1); } parse_hdr_info(optarg, &chg_idx, &chg_hdr, &chg_val); #else fprintf(stderr, "no libmilter support to change header\n"); exit(1); #endif break; case 'i': #ifdef SMFIR_INSHEADER if (ins_hdr) { fprintf(stderr, "too many -i options\n"); exit(1); } parse_hdr_info(optarg, &ins_idx, &ins_hdr, &ins_val); #else fprintf(stderr, "no libmilter support to insert header\n"); exit(1); #endif break; case 'l': #if SMFI_VERSION > 5 if (ins_hdr || chg_hdr) { fprintf(stderr, "specify -l before -i or -r\n"); exit(1); } misc_mask |= SMFIP_HDR_LEADSPC; #else fprintf(stderr, "no libmilter support for leading space\n"); exit(1); #endif break; case 'm': #if SMFI_VERSION > 5 if (set_macro_state_arg) { fprintf(stderr, "too many -m options\n"); exit(1); } set_macro_state_arg = optarg; #else fprintf(stderr, "no libmilter support to specify macro list\n"); exit(1); #endif break; case 'M': #if SMFI_VERSION > 5 if (set_macro_list) { fprintf(stderr, "too many -M options\n"); exit(1); } set_macro_list = optarg; #else fprintf(stderr, "no libmilter support to specify macro list\n"); #endif break; case 'n': #if SMFI_VERSION > 5 if (nosend) { fprintf(stderr, "too many -n options\n"); exit(1); } nosend = optarg; #else fprintf(stderr, "no libmilter support for negotiate callback\n"); #endif break; case 'N': #if SMFI_VERSION > 5 if (noreply) { fprintf(stderr, "too many -n options\n"); exit(1); } noreply = optarg; #else fprintf(stderr, "no libmilter support for negotiate callback\n"); #endif break; case 'p': if (smfi_setconn(optarg) == MI_FAILURE) { fprintf(stderr, "smfi_setconn failed\n"); exit(1); } break; case 'r': #ifdef SMFIP_RCPT_REJ misc_mask |= SMFIP_RCPT_REJ; #else fprintf(stderr, "no libmilter support for rejected recipients\n"); #endif break; case 'v': verbose++; break; case 'C': conn_count = atoi(optarg); break; default: fprintf(stderr, "usage: %s [-dv] \n" "\t[-a action] non-default action\n" "\t[-b body_text] replace body\n", "\t[-c command] non-default action trigger\n" "\t[-h 'index label value'] replace header\n" "\t[-i 'index label value'] insert header\n" "\t[-m macro_state] non-default macro state\n" "\t[-M macro_list] non-default macro list\n" "\t[-n events] don't receive these events\n" "\t[-N events] don't reply to these events\n" "\t-p port milter application\n" "\t-r request rejected recipients\n" "\t[-C conn_count] when to exit\n", argv[0]); exit(1); } } if (command) { for (cp = command_map; /* see below */ ; cp++) { if (cp->name == 0) { fprintf(stderr, "bad -c argument: %s\n", command); exit(1); } if (strcmp(command, cp->name) == 0) break; } } if (action) { if (command == 0) cp = command_map; if (strcmp(action, "tempfail") == 0) { cp->reply[0] = SMFIS_TEMPFAIL; } else if (strcmp(action, "reject") == 0) { cp->reply[0] = SMFIS_REJECT; } else if (strcmp(action, "accept") == 0) { cp->reply[0] = SMFIS_ACCEPT; } else if (strcmp(action, "discard") == 0) { cp->reply[0] = SMFIS_DISCARD; #ifdef SMFIS_SKIP } else if (strcmp(action, "skip") == 0) { cp->reply[0] = SMFIS_SKIP; #endif } else if ((code = atoi(action)) >= 400 && code <= 599 && action[3] == ' ') { cp->reply[0] = SMFIR_REPLYCODE; reply_code = action; reply_dsn = action + 3; if (*reply_dsn != 0) { *reply_dsn++ = 0; reply_dsn += strspn(reply_dsn, " "); } if (*reply_dsn == 0) { reply_dsn = reply_message = 0; } else { reply_message = reply_dsn + strcspn(reply_dsn, " "); if (*reply_message != 0) { *reply_message++ = 0; reply_message += strspn(reply_message, " "); } if (*reply_message == 0) reply_message = 0; } } else { fprintf(stderr, "bad -a argument: %s\n", action); exit(1); } if (verbose) { printf("command %s action %d\n", cp->name, cp->reply[0]); if (reply_code) printf("reply code %s dsn %s message %s\n", reply_code, reply_dsn ? reply_dsn : "(null)", reply_message ? reply_message : "(null)"); } } #if SMFI_VERSION > 5 if (set_macro_state_arg) { for (cpp = macro_states; /* see below */ ; cpp++) { if (*cpp == 0) { fprintf(stderr, "bad -m argument: %s\n", set_macro_state_arg); exit(1); } if (strcmp(set_macro_state_arg, *cpp) == 0) break; } set_macro_state = cpp - macro_states; } if (nosend) { for (np = noproto_map; /* see below */ ; np++) { if (np->name == 0) { fprintf(stderr, "bad -n argument: %s\n", nosend); exit(1); } if (strcmp(nosend, np->name) == 0) break; } nosend_mask = np->send_mask; np->action[0] = 0; } if (noreply) { for (np = noproto_map; /* see below */ ; np++) { if (np->name == 0) { fprintf(stderr, "bad -N argument: %s\n", noreply); exit(1); } if (strcmp(noreply, np->name) == 0) break; } noreply_mask = np->reply_mask; *np->reply = SMFIS_NOREPLY; } #endif if (smfi_register(smfilter) == MI_FAILURE) { fprintf(stderr, "smfi_register failed\n"); exit(1); } return (smfi_main()); }
int main(int argc, char **argv) { int ch; const char *oconn = OCONN; const char *user = USER; sfsistat r = MI_FAILURE; const char *ofile = NULL; tzset(); openlog("milter-spamd", LOG_PID | LOG_NDELAY, LOG_DAEMON); while ((ch = getopt(argc, argv, "di:p:u:U:")) != -1) { switch (ch) { case 'd': debug = 1; break; case 'i': { int r; ignore_connect = optarg; r = regcomp(&re_ignore_connect, ignore_connect, REG_EXTENDED | REG_ICASE); if (r) { char e[8192]; regerror(r, &re_ignore_connect, e, sizeof(e)); fprintf(stderr, "regcomp: %s: %s\n", ignore_connect, e); usage(argv[0]); } break; } case 'p': oconn = optarg; break; case 'u': user = optarg; break; case 'U': spamd_user = optarg; break; default: usage(argv[0]); } } if (argc != optind) { fprintf(stderr, "unknown command line argument: %s ...", argv[optind]); usage(argv[0]); } if (!strncmp(oconn, "unix:", 5)) ofile = oconn + 5; else if (!strncmp(oconn, "local:", 6)) ofile = oconn + 6; if (ofile != NULL) unlink(ofile); /* drop privileges */ if (!getuid()) { struct passwd *pw; if ((pw = getpwnam(user)) == NULL) { fprintf(stderr, "getpwnam: %s: %s\n", user, strerror(errno)); return (1); } setgroups(1, &pw->pw_gid); if (setegid(pw->pw_gid) || setgid(pw->pw_gid)) { fprintf(stderr, "setgid: %s\n", strerror(errno)); return (1); } if ( seteuid(pw->pw_uid) || setuid(pw->pw_uid)) { fprintf(stderr, "setuid: %s\n", strerror(errno)); return (1); } } if (smfi_setconn((char *)oconn) != MI_SUCCESS) { fprintf(stderr, "smfi_setconn: %s: failed\n", oconn); goto done; } if (smfi_register(smfilter) != MI_SUCCESS) { fprintf(stderr, "smfi_register: failed\n"); goto done; } /* daemonize (detach from controlling terminal) */ if (!debug && daemon(0, 0)) { fprintf(stderr, "daemon: %s\n", strerror(errno)); goto done; } umask(0177); signal(SIGPIPE, SIG_IGN); msg(LOG_INFO, NULL, "started: %s", rcsid); r = smfi_main(); if (r != MI_SUCCESS) msg(LOG_ERR, NULL, "smfi_main: terminating due to error"); else msg(LOG_INFO, NULL, "smfi_main: terminating without error"); done: return (r); }
/* {{{ main */ int main(int argc, char *argv[]) { char *sock = NULL; int dofork = 0; int exit_status = SUCCESS; int c; /* temporary locals */ int orig_optind=ap_php_optind; char *orig_optarg=ap_php_optarg; int interactive=0; char *param_error=NULL; /* end of temporary locals */ void ***tsrm_ls; #ifdef HAVE_SIGNAL_H #if defined(SIGPIPE) && defined(SIG_IGN) signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so that sockets created via fsockopen() don't kill PHP if the remote site closes it. in apache|apxs mode apache does that for us! [email protected] 20000419 */ #endif #endif tsrm_startup(1, 1, 0, NULL); tsrm_ls = ts_resource(0); sapi_startup(&milter_sapi_module); while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) { switch (c) { case 'c': milter_sapi_module.php_ini_path_override = strdup(ap_php_optarg); break; case 'n': milter_sapi_module.php_ini_ignore = 1; break; } } ap_php_optind = orig_optind; ap_php_optarg = orig_optarg; milter_sapi_module.executable_location = argv[0]; sapi_module.startup(&milter_sapi_module); zend_first_try { while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) { switch (c) { case '?': php_output_tearup(); SG(headers_sent) = 1; php_milter_usage(argv[0]); php_output_teardown(); exit(1); break; } } ap_php_optind = orig_optind; ap_php_optarg = orig_optarg; /* Set some CLI defaults */ SG(options) |= SAPI_OPTION_NO_CHDIR; zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */ while ((c = ap_php_getopt(argc, argv, OPTSTRING)) != -1) { switch (c) { case 'a': /* interactive mode */ printf("Interactive mode enabled\n\n"); interactive=1; break; case 'C': /* don't chdir to the script directory */ /* This is default so NOP */ break; case 'd': /* define ini entries on command line */ define_command_line_ini_entry(ap_php_optarg); break; case 'D': /* daemon */ dofork = 1; break; case 'e': /* enable extended info output */ CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; break; case 'f': /* parse file */ filename = ap_php_optarg; break; case 'h': /* help & quit */ case '?': php_output_tearup(); SG(headers_sent) = 1; php_milter_usage(argv[0]); php_output_teardown(); exit(1); break; case 'p': /* socket */ sock = strdup(ap_php_optarg); break; case 'v': /* show php version & quit */ if (php_request_startup()==FAILURE) { zend_ini_deactivate(); php_module_shutdown(); sapi_shutdown(); tsrm_shutdown(); exit(1); } SG(headers_sent) = 1; SG(request_info).no_headers = 1; php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); php_output_teardown(); exit(1); break; case 'V': /* verbose */ flag_debug = atoi(ap_php_optarg); break; case 'z': /* load extension file */ zend_load_extension(ap_php_optarg); break; default: break; } } if (param_error) { SG(headers_sent) = 1; SG(request_info).no_headers = 1; PUTS(param_error); exit(1); } /* only set script_file if not set already and not in direct mode and not at end of parameter list */ if (argc > ap_php_optind && !filename) { filename=argv[ap_php_optind]; ap_php_optind++; } /* check if file exists, exit else */ if (dofork) { switch(fork()) { case -1: /* Uh-oh, we have a problem forking. */ fprintf(stderr, "Uh-oh, couldn't fork!\n"); exit(errno); break; case 0: /* Child */ break; default: /* Parent */ exit(0); } } if (sock) { struct stat junk; if (stat(sock,&junk) == 0) unlink(sock); } openlog("php-milter", LOG_PID, LOG_MAIL); if ((exit_status = mlfi_init())) { syslog(1, "mlfi_init failed."); closelog(); goto err; } smfi_setconn(sock); if (smfi_register(smfilter) == MI_FAILURE) { syslog(1, "smfi_register failed."); fprintf(stderr, "smfi_register failed\n"); closelog(); goto err; } else { exit_status = smfi_main(); } closelog(); if (milter_sapi_module.php_ini_path_override) { free(milter_sapi_module.php_ini_path_override); } } zend_catch { exit_status = EG(exit_status); } zend_end_try(); err: php_module_shutdown(); sapi_shutdown(); tsrm_shutdown(); exit(exit_status); }
int main(int argc, char **argv) { const char *opts = "b:D:dg:hst:u:H"; #ifdef HAS_LONGOPT static const struct option lopt[] = { {"bind", 1, 0, 'b'}, {"dry", 0, 0, 'H'}, {"debug", 1, 0, 'D'}, {"daemonize", 0, 0, 'd'}, {"group", 1, 0, 'g'}, {"help", 0, 0, 'h'}, {"no-stamp", 0, 0, 's'}, {"timeout", 1, 0, 't'}, {"user", 1, 0, 'u'}, {NULL, 0, 0, 0} }; #endif int c; char *p; char *oconn; int setconn; size_t len; int ret; uint8_t daemon; char *usr; char *grp; char *pidf = "/var/run/milter/dnsbl-milter.pid"; config.pname = argv[0]; p = strrchr(config.pname, '/'); if (p != NULL) config.pname = p + 1; if (argc < 2) { usage(config.pname); exit(EX_USAGE); } setconn = 0; oconn = NULL; config.daemon = 0; daemon = 0; usr = grp = NULL; config.stamp = 1; while ((c = getopt_long(argc, argv, opts, lopt, NULL)) != -1) { switch (c) { case 'b': /* bind address/socket */ if (setconn != 0) { mlog(LOG_ERR, "Bind address/socket already provided, ignoring"); break; } if ((optarg == NULL) || (*optarg == '\0')) { mlog(LOG_ERR, "No bind address/socket provided"); usage(config.pname); exit(EX_USAGE); } if ((strncmp(optarg, "unix:", 5) == 0) || (strncmp(optarg, "local:", 6) == 0) || (strncmp(optarg, "inet:", 5) == 0) || (strncmp(optarg, "inet6:", 6) == 0)) { oconn = optarg; setconn = 1; break; } /* "unix:" + optarg + '\0' */ len = 5 + strlen(optarg) + 1; oconn = malloc(len); if (oconn == NULL) { mlog(LOG_ERR, "Memory allocation failed"); exit(EX_UNAVAILABLE); } snprintf(oconn, len, "unix:%s", optarg); setconn = 2; break; case 'H': config.drymode = 1; // Adds a header instead of rejecting break; case 'D': if ((optarg == NULL) || (*optarg == '\0')) { mlog(LOG_ERR, "No debugging level provided"); usage(config.pname); exit(EX_USAGE); } smfi_setdbg(atoi(optarg)); break; case 'd': daemon = 1; break; case 'g': if ((optarg == NULL) || (*optarg == '\0')) { mlog(LOG_ERR, "No group provided"); usage(config.pname); exit(EX_USAGE); } grp = optarg; break; case 's': config.stamp = 0; break; case 't': if ((optarg == NULL) || (*optarg == '\0')) { mlog(LOG_ERR, "No timeout provided"); usage(config.pname); exit(EX_USAGE); } smfi_settimeout(atoi(optarg)); break; case 'u': if ((optarg == NULL) || (*optarg == '\0')) { mlog(LOG_ERR, "No user provided"); usage(config.pname); exit(EX_USAGE); } usr = optarg; break; case 'h': /* help */ default: usage(config.pname); exit(EX_USAGE); } } if (setconn == 0) { mlog(LOG_ERR, "%s: Missing required bind address/socket\n", config.pname); usage(config.pname); exit(EX_USAGE); } umask(0137); if ((oconn == NULL) || (smfi_setconn(oconn) == MI_FAILURE)) { mlog(LOG_ERR, "smfi_setconn() failed"); exit(EX_UNAVAILABLE); } if (smfi_register(smfilter) == MI_FAILURE) { mlog(LOG_ERR, "smfi_register() failed"); exit(EX_UNAVAILABLE); } /* List of blacklists to use */ list_add(&blacklist, "bl.spamcop.net", "Listed on SpamCop. See http://spamcop.net/w3m?action=checkblock&ip="); list_add(&blacklist, "b.barracudacentral.org", "Listed on Barracuda Reputation Block List (BRBL). See http://www.barracudacentral.org/lookups?ip_address="); list_add(&blacklist, "zen.spamhaus.org", "Listed on The Spamhaus Project. See http://www.spamhaus.org/query/bl?ip="); list_add(&blacklist, "psbl.surriel.com", "Listed on The Passive Spam Block List. See http://psbl.surriel.com/listing?ip="); /* List of whitelists to use */ list_add(&whitelist, "list.dnswl.org", "http://www.dnswl.org"); if ((usr != NULL) || (grp != NULL)) if (drop_privs(usr, grp) != 0) exit(EX_TEMPFAIL); if (daemon != 0) daemonize(); /* write pid file */ pidf_create(pidf); mlog(LOG_INFO, "Starting Sendmail %s filter '%s'", smfilter.xxfi_name, config.pname); ret = smfi_main(); /* remove pid file */ pidf_destroy(pidf); if (ret == MI_SUCCESS) { mlog(LOG_INFO, "Stopping Sendmail %s filter '%s'", smfilter.xxfi_name, config.pname); } else { mlog(LOG_ERR, "Abnormal termination of Sendmail %s filter '%s': %d", smfilter.xxfi_name, config.pname, ret); } list_free(&blacklist); list_free(&whitelist); if (setconn == 2) { free(oconn); oconn = NULL; } if (daemon != 0) closelog(); return ret; }
int main(int argc, char **argv) { int u_flag; int s_flag; int d_flag; int W_flag; int w_flag; int l_flag; int ret; char *user; char *socket; char *ep; int uid; struct passwd *pwd; pid_t pid; int fd; u_flag = s_flag = d_flag = l_flag = w_flag = W_flag = 0; dnsbls = dnswls = wl_domains = NULL; while ((ret = getopt(argc, argv, "hdu:s:l:w:W:")) != -1) { switch(ret) { case 'd': d_flag++; break; case 'u': u_flag++; user = optarg; break; case 's': s_flag++; socket = optarg; break; case 'l': dnsbls = add_list(dnsbls, optarg); l_flag++; break; case 'w': dnswls = add_list(dnswls, optarg); w_flag++; break; case 'W': wl_domains = add_list(wl_domains, optarg); W_flag++; break; case 'h': default: usage(_progname); } } argc -= optind; argv += optind; if (!u_flag) { fprintf(stderr, "You must specify a user!\n"); usage(_progname); } if (!s_flag) { fprintf(stderr, "You must specify a socket!\n"); usage(_progname); } if (w_flag) { printf("Using whitelists:\n"); print_list(dnswls); } if (W_flag) { printf("Whitelisting domains:\n"); print_list(wl_domains); } if (!l_flag) { fprintf(stderr, "You must specify at least one DNSBL!\n"); usage(_progname); } else { printf("Using blacklists:\n"); print_list(dnsbls); } if (getuid() != 0) { fprintf(stderr, "%s: cannot switch to user %s if not started as root!\n", _progname, user); exit(EX_USAGE); } /* OK running as root, now switch to user */ uid = strtol(user, &ep, 0); if (*ep == '\0') { pwd = getpwuid(uid); } else { pwd = getpwnam(user); } if (pwd == NULL) { fprintf(stderr, "%s: unknown user: %s\n", _progname, user); exit(EX_NOUSER); } if (setgroups(0, NULL) < 0) { perror("setgroups()"); exit(1); } if (setgid(pwd->pw_gid) < 0) { perror("setgid()"); exit(1); } if (initgroups(user, pwd->pw_gid) < 0) { perror("initgroups()"); /* not a critical failure */ } if (setuid(pwd->pw_uid) < 0) { perror("setuid()"); exit(1); } openlog(_progname, 0, LOG_MAIL); if (smfi_register(smfilter) == MI_FAILURE) { fprintf(stderr, "smfi_register() failed.\n"); exit(EX_UNAVAILABLE); } if (smfi_setconn(socket) == MI_FAILURE) { fprintf(stderr, "smfi_setconn() %s\n", strerror(errno)); exit(EX_SOFTWARE); } if (smfi_opensocket(1) == MI_FAILURE) { fprintf(stderr, "smfi_opensocket() %s\n", strerror(errno)); exit(EX_SOFTWARE); } (void) smfi_settimeout(7200); if (!d_flag) { fprintf(stderr, "Warning: not starting as daemon"); } else { if (daemon(0, 0) < 0) { perror("daemon()"); exit(1); } } syslog(LOG_INFO, "%s started successfuly!", _progname); return(smfi_main()); /* start doing business */ }