예제 #1
0
int daemon_main()
{
	network_init(); // (WSAStartup())
	register_signals();
	sdns::conf.read_config();
	try {
		tcp_thread tcp;
		eventloop eloop(&tcp);
		tcp.set_pointers(&eloop);
		if(sdns::conf[sdns::SDNS_USER] != "")
			drop_root(sdns::conf[sdns::SDNS_USER]);
		else
			dout() << "SDNS_USER not set, not changing uid/gid";
		std::thread eventloop_th(std::ref(eloop));
		std::thread tcp_th(std::ref(tcp));
		while(true) {
			os_event event = wait_for_os_event();
			if(event == os_event::shutdown) break;
			if(event == os_event::reload) eloop.reread_static_records();
		}
		eloop.stop();
		tcp.stop();
		eventloop_th.join();
		tcp_th.join();
	} catch(const e_exception &e) {
		eout() << "Error at main(): " << e;
		eout() << "errno was: " << errno << ": " << strerror_rp(errno);
		return EXIT_FAILURE;
	}
	return EXIT_SUCCESS;
}
예제 #2
0
int fork_drop_and_exec(int keepperms, cap_t expected_caps)
{

	int pid;
	int ret = 0;
	char buf[200], *p;
	char *capstxt;
	cap_t actual_caps;
	static int seqno;

	pid = fork();
	if (pid < 0)
		tst_brkm(TFAIL | TERRNO, NULL, "%s: failed fork\n", __func__);
	if (pid == 0) {
		drop_root(keepperms);
		print_my_caps();
		sprintf(buf, "%d", seqno);
		ret = execlp(TSTPATH, TSTPATH, buf, NULL);
		capstxt = cap_to_text(expected_caps, NULL);
		snprintf(buf, 200, "failed to run as %s\n", capstxt);
		cap_free(capstxt);
		write_to_fifo(buf);
		tst_brkm(TFAIL, NULL, "%s: exec failed\n", __func__);
	} else {
		p = buf;
		while (1) {
			int c, s;
			read_from_fifo(buf);
			c = sscanf(buf, "%d", &s);
			if (c == 1 && s == seqno)
				break;
			tst_resm(TINFO,
				 "got a bad seqno (c=%d, s=%d, seqno=%d)", c, s,
				 seqno);
		}
		p = index(buf, '.');
		if (!p)
			tst_brkm(TFAIL, NULL,
				 "got a bad message from print_caps\n");
		p += 1;
		actual_caps = cap_from_text(p);
		if (cap_compare(actual_caps, expected_caps) != 0) {
			capstxt = cap_to_text(expected_caps, NULL);
			tst_resm(TINFO,
				 "Expected to run as .%s., ran as .%s..\n",
				 capstxt, p);
			tst_resm(TINFO, "those are not the same\n");
			cap_free(capstxt);
			ret = -1;
		}
		cap_free(actual_caps);
		seqno++;
	}
	return ret;
}
예제 #3
0
void drop_root_and_removesuid(char *fn)
{
	struct stat st;

	if ( (stat(fn, &st) == 0)    &&
	     (st.st_mode & S_ISUID)  &&
	     (st.st_uid == 0)          ) {

		/* We now know that fn is suid-root */
		chmod(fn, (st.st_mode & (~S_ISUID)));
	}

	drop_root();
}
예제 #4
0
파일: mirror.c 프로젝트: guyou/reflektor
Mirror *	mirror_open (char *path) {
/*
 * The calloc() may cause problems with SELinux
 * after dropping root permissions.
 */

	FILE	*fh	=	mirror_fdopen(path);
	drop_root();
	
	Mirror	*m	=	mirror_create();
	m->path		=	path;
	m->fd		=	fh;
	mirror_getid(m);
	return m;
}
예제 #5
0
FILE *fileopen(char *filename, int *err)
{
	/* Open a file */
	FILE *fd;

#ifdef BIG_SECURITY_HOLE
	get_root();
#endif

	fd = fopen(filename, "r");
	if (err) *err = errno;

#ifdef BIG_SECURITY_HOLE
	drop_root();
#endif

	return fd;
}
예제 #6
0
int perms_test(void)
{
	int ret;
	cap_t cap;

	drop_root(DROP_PERMS);
	cap = cap_from_text("all=eip");
	if (!cap) {
		tst_resm(TFAIL, "could not get cap from text for perms test\n");
		return 1;
	}
	ret = cap_set_file(TSTPATH, cap);
	if (ret) {
		tst_resm(TPASS, "could not set capabilities as non-root\n");
		ret = 0;
	} else {
		tst_resm(TFAIL, "could set capabilities as non-root\n");
		ret = 1;
	}

	cap_free(cap);
	return ret;
}
예제 #7
0
/*
 * Here's where it all begins.
 */
int main(int argc, char **argv)
{
	uid_t UID = -1;
	size_t basesize = 2;            /* how big should strbufs be on creation? */
	pthread_t SessThread;		/* Thread descriptor */
	pthread_attr_t attr;		/* Thread attributes */
	int a;		        	/* General-purpose variable */
	char ip_addr[256]="*";
	int relh=0;
	int home=0;
	char relhome[PATH_MAX]="";
	char webcitdir[PATH_MAX] = DATADIR;
	char *pidfile = NULL;
	char *hdir;
	const char *basedir = NULL;
	char uds_listen_path[PATH_MAX];	/* listen on a unix domain socket? */
	const char *I18nDumpFile = NULL;

	WildFireInitBacktrace(argv[0], 2);

	start_modules();

#ifdef DBG_PRINNT_HOOKS_AT_START
/*	dbg_PrintHash(HandlerHash, nix, NULL);*/
#endif

	/* Ensure that we are linked to the correct version of libcitadel */
	if (libcitadel_version_number() < LIBCITADEL_VERSION_NUMBER) {
		fprintf(stderr, " You are running libcitadel version %d\n", libcitadel_version_number() );
		fprintf(stderr, "WebCit was compiled against version %d\n", LIBCITADEL_VERSION_NUMBER );
		return(1);
	}

	strcpy(uds_listen_path, "");

	/* Parse command line */
#ifdef HAVE_OPENSSL
	while ((a = getopt(argc, argv, "u:h:i:p:t:T:B:x:g:dD:G:cfsS:Z:v:")) != EOF)
#else
	while ((a = getopt(argc, argv, "u:h:i:p:t:T:B:x:g:dD:G:cfZ:v:")) != EOF)
#endif
		switch (a) {
		case 'u':
			UID = atol(optarg);
			break;
		case 'h':
			hdir = strdup(optarg);
			relh=hdir[0]!='/';
			if (!relh) {
				safestrncpy(webcitdir, hdir, sizeof webcitdir);
			}
			else {
				safestrncpy(relhome, relhome, sizeof relhome);
			}
			/* free(hdir); TODO: SHOULD WE DO THIS? */
			home=1;
			break;
		case 'd':
			running_as_daemon = 1;
			break;
		case 'D':
			pidfile = strdup(optarg);
			running_as_daemon = 1;
			break;
		case 'g':
			default_landing_page = strdup(optarg);
			break;
		case 'B': /* Basesize */
			basesize = atoi(optarg);
			if (basesize > 2)
				StartLibCitadel(basesize);
			break;
		case 'i':
			safestrncpy(ip_addr, optarg, sizeof ip_addr);
			break;
		case 'p':
			http_port = atoi(optarg);
			if (http_port == 0) {
				safestrncpy(uds_listen_path, optarg, sizeof uds_listen_path);
			}
			break;
		case 't':
			/* no longer used, but ignored so old scripts don't break */
			break;
		case 'T':
			LoadTemplates = atoi(optarg);
			dbg_analyze_msg = (LoadTemplates & (1<<1)) != 0;
			dbg_backtrace_template_errors = (LoadTemplates & (1<<2)) != 0;
			break;
		case 'Z':
			DisableGzip = 1;
			break;
		case 'x':
			/* no longer used, but ignored so old scripts don't break */
			break;
		case 'f':
			follow_xff = 1;
			break;
		case 'c':
			server_cookie = malloc(256);
			if (server_cookie != NULL) {
				safestrncpy(server_cookie,
				       "Set-cookie: wcserver=",
					256);
				if (gethostname
				    (&server_cookie[strlen(server_cookie)],
				     200) != 0) {
					syslog(LOG_INFO, "gethostname: %s", strerror(errno));
					free(server_cookie);
				}
			}
			break;
#ifdef HAVE_OPENSSL
		case 's':
			is_https = 1;
			break;
		case 'S':
			is_https = 1;
			ssl_cipher_list = strdup(optarg);
			break;
#endif
		case 'G':
			DumpTemplateI18NStrings = 1;
			I18nDump = NewStrBufPlain(HKEY("int templatestrings(void)\n{\n"));
			I18nDumpFile = optarg;
			break;
		case 'v':
			verbose=1;
			break;
		default:
			fprintf(stderr, "usage:\nwebcit "
				"[-i ip_addr] [-p http_port] "
				"[-c] [-f] "
				"[-T Templatedebuglevel] "
				"[-d] [-Z] [-G i18ndumpfile] "
				"[-u uid] [-h homedirectory] "
				"[-D daemonizepid] [-v] "
				"[-g defaultlandingpage] [-B basesize] "
#ifdef HAVE_OPENSSL
				"[-s] [-S cipher_suites]"
#endif
				"[remotehost [remoteport]]\n");
			return 1;
		}

	/* Start the logger */
	openlog("webcit",
		( running_as_daemon ? (LOG_PID) : (LOG_PID | LOG_PERROR) ),
		LOG_DAEMON
	);

	if (optind < argc) {
		ctdlhost = argv[optind];
		if (++optind < argc)
			ctdlport = argv[optind];
	}

	/* daemonize, if we were asked to */
	if (!DumpTemplateI18NStrings && running_as_daemon) {
		start_daemon(pidfile);
	}
	else {
		signal(SIGINT, graceful_shutdown);
		signal(SIGHUP, graceful_shutdown);
	}

	webcit_calc_dirs_n_files(relh, basedir, home, webcitdir, relhome);
	LoadMimeBlacklist();
	LoadIconDir(static_icon_dir);

	/* Tell 'em who's in da house */
	syslog(LOG_NOTICE, "%s", PACKAGE_STRING);
	syslog(LOG_NOTICE, "Copyright (C) 1996-2015 by the citadel.org team");
	syslog(LOG_NOTICE, " ");
	syslog(LOG_NOTICE, "This program is open source software: you can redistribute it and/or");
	syslog(LOG_NOTICE, "modify it under the terms of the GNU General Public License, version 3.");
	syslog(LOG_NOTICE, " ");
	syslog(LOG_NOTICE, "This program is distributed in the hope that it will be useful,");
	syslog(LOG_NOTICE, "but WITHOUT ANY WARRANTY; without even the implied warranty of");
	syslog(LOG_NOTICE, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the");
	syslog(LOG_NOTICE, "GNU General Public License for more details.");
	syslog(LOG_NOTICE, " ");

	/* initialize various subsystems */

	initialise_modules();
	initialise2_modules();
	InitTemplateCache();
	if (DumpTemplateI18NStrings) {
		FILE *fd;
		StrBufAppendBufPlain(I18nDump, HKEY("}\n"), 0);
	        if (StrLength(I18nDump) < 50) {
			syslog(LOG_INFO, "*******************************************************************\n");
			syslog(LOG_INFO, "*   No strings found in templates!  Are you sure they're there?   *\n");
			syslog(LOG_INFO, "*******************************************************************\n");
			return -1;
		}
		fd = fopen(I18nDumpFile, "w");
	        if (fd == NULL) {
			syslog(LOG_INFO, "***********************************************\n");
			syslog(LOG_INFO, "*   unable to open I18N dumpfile [%s]         *\n", I18nDumpFile);
			syslog(LOG_INFO, "***********************************************\n");
			return -1;
		}
		fwrite(ChrPtr(I18nDump), 1, StrLength(I18nDump), fd);
		fclose(fd);
		return 0;
	}

	/* Tell libical to return an error instead of aborting if it sees badly formed iCalendar data. */
	icalerror_errors_are_fatal = 0;

	/* Use our own prefix on tzid's generated from system tzdata */
	icaltimezone_set_tzid_prefix("/citadel.org/");

	/*
	 * Set up a place to put thread-specific data.
	 * We only need a single pointer per thread - it points to the
	 * wcsession struct to which the thread is currently bound.
	 */
	if (pthread_key_create(&MyConKey, NULL) != 0) {
		syslog(LOG_EMERG, "Can't create TSD key: %s", strerror(errno));
	}
	InitialiseSemaphores();

	/*
	 * Set up a place to put thread-specific SSL data.
	 * We don't stick this in the wcsession struct because SSL starts
	 * up before the session is bound, and it gets torn down between
	 * transactions.
	 */
#ifdef HAVE_OPENSSL
	if (pthread_key_create(&ThreadSSL, NULL) != 0) {
		syslog(LOG_EMERG, "Can't create TSD key: %s", strerror(errno));
	}
#endif

	/*
	 * Bind the server to our favorite port.
	 * There is no need to check for errors, because webcit_tcp_server()
	 * exits if it doesn't succeed.
	 */

	if (!IsEmptyStr(uds_listen_path)) {
		syslog(LOG_DEBUG, "Attempting to create listener socket at %s...", uds_listen_path);
		msock = webcit_uds_server(uds_listen_path, LISTEN_QUEUE_LENGTH);
	}
	else {
		syslog(LOG_DEBUG, "Attempting to bind to port %d...", http_port);
		msock = webcit_tcp_server(ip_addr, http_port, LISTEN_QUEUE_LENGTH);
	}
	if (msock < 0)
	{
		ShutDownWebcit();
		return -msock;
	}

	syslog(LOG_INFO, "Listening on socket %d", msock);
	signal(SIGPIPE, SIG_IGN);

	pthread_mutex_init(&SessionListMutex, NULL);

	/*
	 * Start up the housekeeping thread
	 */
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	pthread_create(&SessThread, &attr, (void *(*)(void *)) housekeeping_loop, NULL);

	/*
	 * If this is an HTTPS server, fire up SSL
	 */
#ifdef HAVE_OPENSSL
	if (is_https) {
		init_ssl();
	}
#endif
	drop_root(UID);

	/* Become a worker thread.  More worker threads will be spawned as they are needed. */
	worker_entry();
	ShutDownLibCitadel();
	return 0;
}
예제 #8
0
파일: main.c 프로젝트: Dessperado/avahi
int main(int argc, char *argv[]) {
    int r = 255;
    int wrote_pid_file = 0;

    avahi_set_log_function(log_function);

    init_rand_seed();

    avahi_server_config_init(&config.server_config);
    config.command = DAEMON_RUN;
    config.daemonize = 0;
    config.config_file = NULL;
#ifdef HAVE_DBUS
    config.enable_dbus = 1;
    config.fail_on_missing_dbus = 1;
    config.n_clients_max = 0;
    config.n_objects_per_client_max = 0;
    config.n_entries_per_entry_group_max = 0;
#endif

    config.drop_root = 1;
    config.set_rlimits = 1;
#ifdef ENABLE_CHROOT
    config.use_chroot = 1;
#endif
    config.modify_proc_title = 1;

    config.disable_user_service_publishing = 0;
    config.publish_dns_servers = NULL;
    config.publish_resolv_conf = 0;
    config.use_syslog = 0;
    config.debug = 0;
    config.rlimit_as_set = 0;
    config.rlimit_core_set = 0;
    config.rlimit_data_set = 0;
    config.rlimit_fsize_set = 0;
    config.rlimit_nofile_set = 0;
    config.rlimit_stack_set = 0;
#ifdef RLIMIT_NPROC
    config.rlimit_nproc_set = 0;
#endif

    if ((argv0 = strrchr(argv[0], '/')))
        argv0 = avahi_strdup(argv0 + 1);
    else
        argv0 = avahi_strdup(argv[0]);

    daemon_pid_file_ident = (const char *) argv0;
    daemon_log_ident = (char*) argv0;
    daemon_pid_file_proc = pid_file_proc;

    if (parse_command_line(&config, argc, argv) < 0)
        goto finish;

    if (config.modify_proc_title)
        avahi_init_proc_title(argc, argv);

#ifdef ENABLE_CHROOT
    config.use_chroot = config.use_chroot && config.drop_root;
#endif

    if (config.command == DAEMON_HELP) {
        help(stdout);
        r = 0;
    } else if (config.command == DAEMON_VERSION) {
        printf("%s "PACKAGE_VERSION"\n", argv0);
        r = 0;
    } else if (config.command == DAEMON_KILL) {
        if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) {
            avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
            goto finish;
        }

        r = 0;

    } else if (config.command == DAEMON_RELOAD) {
        if (daemon_pid_file_kill(SIGHUP) < 0) {
            avahi_log_warn("Failed to kill daemon: %s", strerror(errno));
            goto finish;
        }

        r = 0;

    } else if (config.command == DAEMON_CHECK)
        r = (daemon_pid_file_is_running() >= 0) ? 0 : 1;
    else if (config.command == DAEMON_RUN) {
        pid_t pid;

        if (getuid() != 0 && config.drop_root) {
            avahi_log_error("This program is intended to be run as root.");
            goto finish;
        }

        if ((pid = daemon_pid_file_is_running()) >= 0) {
            avahi_log_error("Daemon already running on PID %u", pid);
            goto finish;
        }

        if (load_config_file(&config) < 0)
            goto finish;

        if (config.daemonize) {
            daemon_retval_init();

            if ((pid = daemon_fork()) < 0)
                goto finish;
            else if (pid != 0) {
                int ret;
                /** Parent **/

                if ((ret = daemon_retval_wait(20)) < 0) {
                    avahi_log_error("Could not receive return value from daemon process.");
                    goto finish;
                }

                r = ret;
                goto finish;
            }

            /* Child */
        }

        if (config.use_syslog || config.daemonize)
            daemon_log_use = DAEMON_LOG_SYSLOG;

        if (sd_listen_fds(0) <= 0)
            if (daemon_close_all(-1) < 0)
                avahi_log_warn("Failed to close all remaining file descriptors: %s", strerror(errno));

        daemon_reset_sigs(-1);
        daemon_unblock_sigs(-1);

        if (make_runtime_dir() < 0)
            goto finish;

        if (config.drop_root) {
#ifdef ENABLE_CHROOT
            if (config.use_chroot)
                if (avahi_caps_reduce() < 0)
                    goto finish;
#endif

            if (drop_root() < 0)
                goto finish;

#ifdef ENABLE_CHROOT
            if (config.use_chroot)
                if (avahi_caps_reduce2() < 0)
                    goto finish;
#endif
        }

        if (daemon_pid_file_create() < 0) {
            avahi_log_error("Failed to create PID file: %s", strerror(errno));

            if (config.daemonize)
                daemon_retval_send(1);
            goto finish;
        } else
            wrote_pid_file = 1;

        if (config.set_rlimits)
            enforce_rlimits();

        chdir("/");

#ifdef ENABLE_CHROOT
        if (config.drop_root && config.use_chroot)
            if (avahi_chroot_helper_start(argv0) < 0) {
                avahi_log_error("failed to start chroot() helper daemon.");
                goto finish;
            }
#endif
        avahi_log_info("%s "PACKAGE_VERSION" starting up.", argv0);
        sd_notifyf(0, "STATUS=%s "PACKAGE_VERSION" starting up.", argv0);
        avahi_set_proc_title(argv0, "%s: starting up", argv0);

        if (run_server(&config) == 0)
            r = 0;

        avahi_log_info("%s "PACKAGE_VERSION" exiting.", argv0);
        sd_notifyf(0, "STATUS=%s "PACKAGE_VERSION" exiting.", argv0);
    }

finish:

    if (config.daemonize)
        daemon_retval_done();

    avahi_server_config_free(&config.server_config);
    avahi_free(config.config_file);
    avahi_strfreev(config.publish_dns_servers);
    avahi_strfreev(resolv_conf_name_servers);
    avahi_strfreev(resolv_conf_search_domains);

    if (wrote_pid_file) {
#ifdef ENABLE_CHROOT
        avahi_chroot_helper_unlink(pid_file_proc());
#else
        daemon_pid_file_remove();
#endif
    }

#ifdef ENABLE_CHROOT
    avahi_chroot_helper_shutdown();
#endif

    avahi_free(argv0);

    return r;
}
예제 #9
0
파일: ndyndns.c 프로젝트: a29888778/ndyndns
int main(int argc, char** argv)
{
    int c, read_cfg = 0;

    init_config();

    while (1) {
        int option_index = 0;
        static struct option long_options[] = {
            {"detach", 0, 0, 'd'},
            {"nodetach", 0, 0, 'n'},
            {"pidfile", 1, 0, 'p'},
            {"quiet", 0, 0, 'q'},
            {"chroot", 1, 0, 'c'},
            {"disable-chroot", 0, 0, 'x'},
            {"file", 1, 0, 'f'},
            {"cfg-stdin", 0, 0, 'F'},
            {"user", 1, 0, 'u'},
            {"group", 1, 0, 'g'},
            {"interface", 1, 0, 'i'},
            {"remote", 0, 0, 'r'},
            {"help", 0, 0, 'h'},
            {"version", 0, 0, 'v'},
            {0, 0, 0, 0}
        };

        c = getopt_long(argc, argv, "rdnp:qc:xf:Fu:g:i:hv", long_options, &option_index);
        if (c == -1) break;

        switch (c) {

            case 'h':
                printf(
"ndyndns " PACKAGE_VERSION ", dyndns update client.  Licensed under 2-clause BSD.\n"
"Copyright (c) 2005-2013 Nicholas J. Kain\n"
"Usage: ndyndns [OPTIONS]\n"
"  -d, --detach                detach from TTY and daemonize\n"
"  -n, --nodetach              stay attached to TTY\n"
"  -q, --quiet                 don't print to std(out|err) or log\n"
"  -c, --chroot                path where ndyndns should chroot\n"
"  -x, --disable-chroot        do not actually chroot (not recommended)\n"
"  -f, --file                  configuration file\n"
"  -F, --cfg-stdin             read configuration file from standard input\n"
"  -p, --pidfile               pidfile path\n"
"  -u, --user                  user name that ndyndns should run as\n"
"  -g, --group                 group name that ndyndns should run as\n"
"  -i, --interface             interface ip to check (default: ppp0)\n"
"  -r, --remote                get ip from remote dyndns host (overrides -i)\n"
"  -h, --help                  print this help and exit\n"
"  -v, --version               print version and license info and exit\n"
                );
                exit(EXIT_FAILURE);
                break;

            case 'v':
                printf("ndyndns %s, dhcp client.\n", PACKAGE_VERSION);
                printf("Copyright (c) 2005-2013 Nicholas J. Kain\n"
                       "All rights reserved.\n\n"
                       "Redistribution and use in source and binary forms, with or without\n"
                       "modification, are permitted provided that the following conditions are met:\n\n"
                       "- Redistributions of source code must retain the above copyright notice,\n"
                       "  this list of conditions and the following disclaimer.\n"
                       "- Redistributions in binary form must reproduce the above copyright notice,\n"
                       "  this list of conditions and the following disclaimer in the documentation\n"
                       "  and/or other materials provided with the distribution.\n\n"
                       "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n"
                       "AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
                       "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
                       "ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n"
                       "LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n"
                       "CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n"
                       "SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n"
                       "INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n"
                       "CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n"
                       "ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
                       "POSSIBILITY OF SUCH DAMAGE.\n");
                exit(EXIT_FAILURE);
                break;

            case 'r':
                cfg_set_remote();
                break;

            case 'd':
                cfg_set_detach();
                break;

            case 'n':
                cfg_set_nodetach();
                break;

            case 'q':
                cfg_set_quiet();
                break;

            case 'x':
                disable_chroot();
                break;

            case 'c':
                update_chroot(optarg);
                break;

            case 'f':
                if (read_cfg) {
                    suicide("FATAL: duplicate configuration file data specified");
                } else {
                    read_cfg = 1;
                    if (parse_config(optarg) != 1)
                        suicide("FATAL: bad configuration data");
                }
                break;

            case 'F':
                if (read_cfg) {
                    suicide("ERROR: duplicate configuration file data specified");
                } else {
                    read_cfg = 1;
                    if (parse_config(NULL) != 1)
                        suicide("FATAL: bad configuration data");
                }
                break;

            case 'p':
                cfg_set_pidfile(optarg);
                break;

            case 'u':
                cfg_set_user(optarg);
                break;

            case 'g':
                cfg_set_group(optarg);
                break;

            case 'i':
                cfg_set_interface(optarg);
                break;
        }
    }

    if (!read_cfg)
        suicide("FATAL - no configuration file, exiting.");

    /* This is tricky -- we *must* use a name that will not be in hosts,
     * otherwise, at least with eglibc, the resolve and NSS libraries will not
     * be properly loaded.  The '.invalid' label is RFC-guaranteed to never
     * be installed into the root zone, so we use that to avoid harassing
     * DNS servers at start.
     */
    (void) gethostbyname("fail.invalid");

    if (chroot_enabled() && getuid())
        suicide("FATAL - I need root for chroot!");

    if (gflags_detach)
        if (daemon(0,0))
            suicide("FATAL - detaching fork failed");

    if (file_exists(pidfile, "w") == -1)
        suicide("FATAL - cannot open pidfile for write");
    write_pid(pidfile);

    umask(077);
    fix_signals();

    if (!chroot_exists())
        suicide("FATAL - No chroot path specified.  Refusing to run.");

    /* Note that failure cases are handled by called fns. */
    imprison(get_chroot());
    drop_root(cfg_uid, cfg_gid);

    /* Cover our tracks... */
    wipe_chroot();
    memset(pidfile, '\0', sizeof pidfile);

    curl_global_init(CURL_GLOBAL_ALL);
    use_ssl = check_ssl();

    do_work();

    exit(EXIT_SUCCESS);
}
예제 #10
0
int
main(int argc, char *argv[])
{
	server_t		 server;
	char const		*control = SDP_LOCAL_PATH;
	char const		*user = "******", *group = "_sdpd";
	char const		*sgroup = NULL;
	int32_t			 detach = 1, opt;
	struct sigaction	 sa;

	while ((opt = getopt(argc, argv, "c:dG:g:hu:")) != -1) {
		switch (opt) {
		case 'c': /* control */
			control = optarg;
			break;

		case 'd': /* do not detach */
			detach = 0;
			break;

		case 'G': /* super group */
			sgroup = optarg;
			break;

		case 'g': /* group */
			group = optarg;
			break;

		case 'u': /* user */
			user = optarg;
			break;

		case 'h':
		default:
			usage();
			/* NOT REACHED */
		}
	}

	log_open(SDPD, !detach);

	/* Become daemon if required */
	if (detach && daemon(0, 0) < 0) {
		log_crit("Could not become daemon. %s (%d)",
			strerror(errno), errno);
		exit(1);
	}

	/* Set signal handlers */
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sighandler;

	if (sigaction(SIGTERM, &sa, NULL) < 0 ||
	    sigaction(SIGHUP,  &sa, NULL) < 0 ||
	    sigaction(SIGINT,  &sa, NULL) < 0) {
		log_crit("Could not install signal handlers. %s (%d)",
			strerror(errno), errno);
		exit(1);
	}

	sa.sa_handler = SIG_IGN;
	if (sigaction(SIGPIPE, &sa, NULL) < 0) {
		log_crit("Could not install signal handlers. %s (%d)",
			strerror(errno), errno);
		exit(1);
	}

	/* Initialize server */
	if (server_init(&server, control, sgroup) < 0)
		exit(1);

	if ((user != NULL || group != NULL) && drop_root(user, group) < 0)
		exit(1);

	for (done = 0; !done; ) {
		if (server_do(&server) != 0)
			done ++;
	}

	server_shutdown(&server);
	log_close();

	return (0);
}
예제 #11
0
int main(int argc, char **argv){
   int i, n, nexthost, port=0, method=M_DEFAULT, addr_len;
   char *p, *pl, *pl2, *listen_addr=LISTEN_ADDR, tmpbuf[TMPLEN];
   unsigned char packet[PACKETLEN];
   unsigned long listenhost;
   struct sockaddr_in my_addr, send_addr, client_addr;

   while((i = getopt(argc, argv, "x:l:m:p:v")) > 0){

      switch(i){
         case 'x' :
                    pl = optarg;

                    do{
                       memset((char *)&hosts[hostnum], 0, sizeof(struct onehost));

                       p = _extract(pl, ',', &tmpbuf[0], TMPLEN-1);

                       if(p){
                          p++;
                          pl = p;
                       }
                       else {
                          strncpy(&tmpbuf[0], pl, TMPLEN-1);
                       }

                       pl2 = strchr(tmpbuf, ':');
                       if(pl2){
                          *pl2 = '\0';
                          pl2++;
                          bogomips[hostnum] = atoi(pl2);
                          if(bogomips[hostnum] == 0)
                             fatal(FORMAT2, "bogomips value must be >= 1", bogomips[hostnum]);
                       }
                       else {
                          bogomips[hostnum] = 0;
                       }

                       strncpy((char *)&hosts[hostnum].host[0], &tmpbuf[0], IPADDRLEN-1);

                       hosts[hostnum].s_addr = resolve_host(hosts[hostnum].host);
                       if(hosts[hostnum].s_addr == 0)
                          fatal(FORMAT3, "invalid host", hosts[hostnum].host);

                       hostnum++;

                       if(hostnum > MAXHOSTS)
                          fatal(FORMAT2, "too many host. max:", MAXHOSTS);

                    } while(p);

                    break;

         case 'l' :
                    listen_addr = optarg;
                    break;

         case 'm' :
                    if(!strcmp(optarg, "roundrobin"))
                       method = M_ROUNDROBIN;

                    if(!strcmp(optarg, "loadbalance"))
                       method = M_LOADBALANCE;

                    if(!strcmp(optarg, "volumebalance"))
                       method = M_VOLUMEBALANCE;

                    break;

         case 'p' :
                    port = atoi(optarg);
                    if(port == 0 || port > 65535)
                       fatal(FORMAT2, "invalid port", port);

                    break;

         case 'v' :
                    v++;
                    break;

         default : 
                    fatal(FORMAT1, USAGE);
                    break;
      }
   }

   if(port == 0)
      fatal(FORMAT2, "invalid port", port);

   listenhost = resolve_host(listen_addr);

   #ifdef USESYSLOG
      (void) openlog(PROGNAME, LOG_PID, LOG_FACILITY);
      syslog(LOG_OPTION, "%s %s is starting on %s:%d", PROGNAME, VERSION, listen_addr, port);
   #endif

   signal(SIGINT, clean_exit);
   signal(SIGQUIT, clean_exit);
   signal(SIGKILL, clean_exit);
   signal(SIGTERM, clean_exit);
   signal(SIGALRM, refresh);

   /* create listener socket */

   if((lsd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
      fatal(FORMAT1, "cannot open listener socket");

   my_addr.sin_family = AF_INET;
   my_addr.sin_port = htons(port);
   my_addr.sin_addr.s_addr = listenhost;
   bzero(&(my_addr.sin_zero), 8);

   if(bind(lsd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1)
      fatal(FORMAT2, "cannot bind to port:", port);

   /* drop root privs if we have */

   if(getuid() == 0 || geteuid() == 0){
      fprintf(stderr, "dropped\n");
      drop_root();
   }

   /* create sender socket */

   if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
      fatal(FORMAT1, "cannot open socket");

   bzero((char *)&send_addr, sizeof(struct sockaddr));
   send_addr.sin_family = AF_INET;
   send_addr.sin_port = htons(port);


   nexthost = -1;
   addr_len = sizeof(struct sockaddr);

   srand(getpid());

   refresh();

   for(;;){

      /* read request from clients */

      if((n = recvfrom(lsd,  &packet[0], PACKETLEN, 0, (struct sockaddr*)&client_addr, &addr_len)) > 0){
         //fprintf(stderr, "%d %s\n", n, inet_ntoa(client_addr.sin_addr));

         /* determine next host to forward request */

         switch(method){
            case M_ROUNDROBIN:
                               nexthost++;
                               nexthost = choose_round_robin_host(nexthost);
                               break;

            case M_VOLUMEBALANCE:
                               nexthost = choose_volume_host();
                               break;

            case M_LOADBALANCE:
                               nexthost = choose_balance_host();
                               break;
         }

         if(nexthost < 0){
            #ifdef USESYSLOG
               syslog(LOG_OPTION, "no available hosts! Refreshing.");
            #endif

            fprintf(stderr, "no available hosts! Refreshing.\n");
            refresh();

            continue;
         }

         /* send request to selected host */

         send_addr.sin_addr.s_addr = hosts[nexthost].s_addr;

         gettimeofday(&senttime, &tz);

         sendto(sd, (char *)&packet, n, 0, (struct sockaddr *)&send_addr, sizeof(struct sockaddr));

         /*
          * read answer 
          * we do not retry instead let the client repeat the request
          */

         n = readudppacket(sd, &packet[0], PACKETLEN, timeout, (struct sockaddr*)&client_addr);

         gettimeofday(&now, &tz);

         if(n > 0){
            hosts[nexthost].counter++;
            hosts[nexthost].rtt += tvdiff(now, senttime);

            if(hosts[nexthost].rtt < 0)
               hosts[nexthost].rtt = INT_MAX - 100;

            // print debug info
            if(v > 2)
               fprintf(stderr, "%s => %s:%d - %d bytes in %ld [usec]\n", inet_ntoa(client_addr.sin_addr), hosts[nexthost].host, port, n, tvdiff(now, senttime));
         }
         else {
            /* one lost packet should not discard our next node */

            hosts[nexthost].lost++;
            if(hosts[nexthost].lost > MAX_LOST_PACKET){
               hosts[nexthost].avail = 0;

               #ifdef USESYSLOG
                  syslog(LOG_OPTION, "%s-(%d) been discarded", hosts[nexthost].host, port);
               #endif

               if(v >= 1)
                  fprintf(stderr, "%s-(%d) been discarded\n", hosts[nexthost].host, port);
            }
         }

         /* send response back to your client */

         sendto(lsd, (char *)&packet, n, 0, (struct sockaddr *)&client_addr, sizeof(struct sockaddr));
      }
   }

   return 0;
}
예제 #12
0
파일: linetd.c 프로젝트: br0ns/inliner
int main(int argc, char **argv)
{
  char *user, *group, *interface, *root, *port, *cmd;
  int niceinc;
  int nofork;
  int timeout;
  int instances;
  int queue;

  int reuse;
  int keepalive;
  int what;
  int value;
  int offset;
  int i, j;
  char c;
  int lfd;
  int nfd;
  struct sigaction sag;
  sigset_t sst;
  int status;
  int hang;
  int busy;
  int tos;
  int ttl;
  int sane;
  int just;
#ifdef USE_IDSA
  int exitcode;
  int killcode;
  int flags;
  unsigned int arisk, crisk, irisk, risk;
#endif

  double limit_load = 0.0;

  port = NULL;
  user = NULL;
  group = NULL;
  root = NULL;
  interface = NULL;
  cmd = NULL;

  just = 0;
  sane = 1;
  reuse = 1;
  keepalive = 1;
  niceinc = 0;
  nofork = 0;
  timeout = 0;
  instances = 0;
  queue = 5;
  tos = 0;
  ttl = 0;
  offset = 0;

#ifdef USE_IDSA
  flags = 0;
  arisk = idsa_risk_make(-0.3,0.8);
  crisk = IDSA_R_UNKNOWN;
  irisk = IDSA_R_PARTIAL;
#endif

  i = j = 1;
  while (i < argc) {
    if (argv[i][0] == '-') {
      c = argv[i][j];
      switch (c) {
      case 'c':
	printf("(c) 2002,2007 Marc Welz: Distributed under the terms of the GNU General Public License\n");
	exit(0);
	break;
      case 'h':		/* print brief help message */
      case '?':
	usage(argv[0]);
	exit(0);
	break;
      case 'v':
#ifdef USE_IDSA
	printf("linetd %s-i\n", VERSION);
#else
	printf("linetd %s\n", VERSION);
#endif
	exit(0);
	break;

	/* flags */
      case 'f':		/* keep in foreground */
	nofork = 1;
	j++;
	break;
      case 'a' :        /* disable reuse of address */
        j++;
	c = argv[i][j];
	switch (c) {
        case 'r':
          reuse = 0;
          break;
	case 'k':
          keepalive = 0;
          break;
	case '\0':
	  fatal_failure(LINET_USAGE, 0, "option -a requires a modifier");
	  break;
	default:
	  fatal_failure(LINET_USAGE, 0, "unknown modifier -a%c", c);
	  break;
        }

	j++;
	if (argv[i][j] == '\0') {
	  j = 1;
	  i++;
	}

        break;
      case 'd' :        /* disable sanity checks */
        sane = 0;
	j++;
        break;

	/* strings */
      case 'u':
      case 'g':
      case 'p':
      case 'r':
      case 'b':
	j++;
	if (argv[i][j] == '\0') {
	  j = 0;
	  i++;
	}
	if (i >= argc) {
	  fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c);
	}
	switch (c) {
	case 'u':
	  user = argv[i] + j;
	  break;
	case 'g':
	  group = argv[i] + j;
	  break;
	case 'p':        
	  port = argv[i] + j;
	  break;
	case 'r':
	  root = argv[i] + j;
	  break;
	case 'b':
	  interface = argv[i] + j;
	  break;
	}
	i++;
	j = 1;
	break;

      case 'l':
	j++;
	if (argv[i][j] == '\0') {
	  j = 0;
	  i++;
	}
	if (i >= argc) {
	  fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c);
	}
	if (!isdigit(argv[i][j])) {
	  fatal_failure(LINET_USAGE, 0, "option -%c requires a floating point value", c);
	}
        load_fd = open(LOADAVG, O_RDONLY);
        if(load_fd < 0){
          fatal_failure(LINET_SYSTEM, errno, "unable to open %s to read load average", LOADAVG);
        }
	limit_load = atof(argv[i] + j);
	i++;
	j = 1;
	break;

      case 'n':
      case 'm':
      case 'i':
      case 'j':
      case 'q':
      case 't':
	j++;
	if (argv[i][j] == '\0') {
	  j = 0;
	  i++;
	}
	if (i >= argc) {
	  fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c);
	}
	if (!isdigit(argv[i][j])) {
	  fatal_failure(LINET_USAGE, 0, "option -%c requires a numeric value", c);
	}
	value = atoi(argv[i] + j);
	switch (c) {
	case 'n':
	  niceinc = value;
	  break;
	case 'm':
	  timeout = value;
	  break;
	case 'i':
	  instances = value;
	  break;
	case 'j':
	  just = value;
	  break;
	case 'q':
	  queue = value;
	  break;
	case 't':
	  ttl = value;
	  break;
	}
	i++;
	j = 1;
	break;

      case 'o':
        j++;
	c = argv[i][j];
	switch (c) {
        case 'c':
          tos = IPTOS_LOWCOST;
          break;
	case 'd':
          tos = IPTOS_LOWDELAY;
          break;
	case 'r':
          tos = IPTOS_RELIABILITY;
          break;
	case 't':
          tos = IPTOS_THROUGHPUT;
          break;

	case '\0':
	  fatal_failure(LINET_USAGE, 0, "option -o requires a modifier");
	  break;
	default:
	  fatal_failure(LINET_USAGE, 0, "unknown modifier -o%c", c);
	  break;
        }

	j++;
	if (argv[i][j] == '\0') {
	  j = 1;
	  i++;
	}

        break;

#ifdef USE_IDSA
      case 'k' : /* risk ratings */
	j++;
	c = argv[i][j];
	j++;
	if (argv[i][j] == '\0') {
	  j = 0;
	  i++;
	}

	if (i >= argc) {
	  fatal_failure(LINET_USAGE, 0, "option -k%c requires a parameter", c);
	}

        risk = idsa_risk_parse(argv[i]+j);

	switch (c) {
	case 'a':
          arisk = risk;
          break;
	case 'c':
          crisk = risk;
          break;
	case 'i':
          irisk = risk;
          break;
        }
	i++;
	j = 1;
        break;

      case 'x':
        j++;
	c = argv[i][j];
	switch (c) {
        case 'e':
	  flags |= IDSA_F_ENV; /* honour IDSA_SOCKET */
          break;
	case 'o':
	  flags |= IDSA_F_FAILOPEN; /* continue on failure */
          break;
	case 'u':
	  flags |= IDSA_F_UPLOAD; /* allow uploading of rules */
          break;
	case '\0':
	  fatal_failure(LINET_USAGE, 0, "option -x requires a modifier");
	  break;
	default:
	  fatal_failure(LINET_USAGE, 0, "unknown modifier -x%c", c);
	  break;
        }
	j++;
	if (argv[i][j] == '\0') {
	  j = 1;
	  i++;
	}
        break;
#endif

      case 's':
	j++;
	c = argv[i][j];
	what = 0;
	switch (c) {
	case 'c':
	  what = RLIMIT_CORE;
	  break;
	case 'd':
	  what = RLIMIT_DATA;
	  break;
	case 'f':
	  what = RLIMIT_FSIZE;
	  break;
	case 'l':
	  what = RLIMIT_MEMLOCK;
	  break;
	case 'm':
	  what = RLIMIT_RSS;
	  break;
	case 'n':
	  what = RLIMIT_NOFILE;
	  break;
	case 's':
	  what = RLIMIT_STACK;
	  break;
	case 't':
	  what = RLIMIT_CPU;
	  break;
	case 'u':
	  what = RLIMIT_NPROC;
	  break;
	case 'v':
	  what = RLIMIT_AS;
	  break;

	case '\0':
	  fatal_failure(LINET_USAGE, 0, "option -s requires a modifier");
	  break;
	default:
	  fatal_failure(LINET_USAGE, 0, "unknown modifier -s%c", c);
	  break;
	}

	j++;
	if (argv[i][j] == '\0') {
	  j = 0;
	  i++;
	}

	if (i >= argc) {
	  fatal_failure(LINET_USAGE, 0, "option -s%c requires a parameter", c);
	}
	if (!isdigit(argv[i][j])) {
	  fatal_failure(LINET_USAGE, 0, "option -s%c requires a numeric value", c);
	}
	value = atoi(argv[i] + j);

        if(resource_count >= LINET_MAXRES){
	  fatal_failure(LINET_USAGE, 0, "too many resource restrictions", c);
        }

        resource_table[resource_count][0] = what;
        resource_table[resource_count][1] = value;
        resource_count++;

	i++;
	j = 1;
	break;

      case '-':
	j++;
	break;
      case '\0':
	j = 1;
	i++;
	break;
      default:
	fatal_failure(LINET_USAGE, 0, "unknown option -%c", argv[i][j]);
	break;
      }
    } else {
      cmd = argv[i];
      offset = i + 1;

      if (sane) {
        if (i + 1 >= argc){
          fprintf(stderr, "%s: warning: zeroth argument should be specified\n", argv[0]);
          offset = i;
        }
      }

      i = argc;
    }
  }

  if (cmd == NULL) {
    fatal_failure(LINET_USAGE, 0, "require a command to run");
  }

  if (!nofork) {
    fork_parent(argv[0]);
  }
#ifdef USE_IDSA
  if (ic == NULL) {
    ic = idsa_open(LINETD, NULL, flags);
  }
  if (ic == NULL) {
    fprintf(stderr, "%s: unable to open idsa connection\n", argv[0]);
    exit(EX_UNAVAILABLE);
  }
#endif

  sigfillset(&(sag.sa_mask));
  sag.sa_flags = 0;

  sag.sa_handler = handle_child;
  if (sigaction(SIGCHLD, &sag, NULL)) {
    fatal_failure(LINET_SYSTEM, errno, "unable to set signal handler");
  }

  sag.sa_handler = handle_stop;
  if (sigaction(SIGTERM, &sag, NULL)) {
    fatal_failure(LINET_SYSTEM, errno, "unable to set signal handler");
  }

  lfd = setup_listener(argv[0], port, interface, queue, ttl, tos, reuse, keepalive);

  drop_root(argv[0], user, group, root);

  if(sane){
    if(access(cmd, X_OK)){
      fatal_failure(LINET_SYSTEM, errno, "\"%s\" %s", cmd, (cmd[0] == '/') ? "appears unavailable" : "might need an absolute path");
    }
  }

  if (niceinc) {
    nice(niceinc);
  }

#ifdef USE_IDSA
  if(idsa_set(ic, LINET_DR, LINET_SCHEME, 1, IDSA_R_SUCCESS, IDSA_R_UNKNOWN, IDSA_R_UNKNOWN, 
        IDSA_SSM,  IDSA_T_STRING, IDSA_SSM_SSTART, 
        "version", IDSA_T_STRING, VERSION, 
        NULL) != IDSA_L_ALLOW){
    fprintf(stderr, "%s: start disallowed\n", LINETD);
    return EX_NOPERM;
  }
#endif

  if (!nofork) {
    close(STDERR_FILENO);
  }

  sigemptyset(&sst);
  sigaddset(&sst, SIGCHLD);
  sigaddset(&sst, SIGTERM);

  sigprocmask(SIG_BLOCK, &sst, NULL);	/* disable child signal for everything execpt accept and sleep */

  while (run) {
#ifdef USE_IDSA
    nfd = accept_connection(lfd, arisk, crisk, irisk);
#else
    nfd = accept_connection(lfd);
#endif
    if (nfd >= 0) {
      run_command(lfd, cmd, &argv[offset], nfd, timeout);
      if(just){
        just--;
        if(just == 0){
          run = 0;
        }
      }
    }

    do{ /* check children and load */
      busy = 0;
      hang = ((instances > 0) && (child_count >= instances)); /* actually wait for child */

      if (zombies || hang) {
        if (waitpid(WAIT_ANY, &status, hang ? 0 : WNOHANG) > 0) {	/* collect pids without risk of EINTR */
#ifdef USE_IDSA

          /* in theory this could parse signals and exit codes. Eg SIG{SEGV,BUS} == ES_INTERNAL etc */

          if (WIFEXITED(status)) {
            exitcode = WEXITSTATUS(status);
            if (exitcode == 0) {
              idsa_set(ic, LINET_JD, LINET_SCHEME, 0, IDSA_R_NONE, IDSA_R_UNKNOWN, IDSA_R_UNKNOWN, 
                  IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WSTOP, 
                  NULL);
            } else {
              idsa_set(ic, LINET_JE, LINET_SCHEME, 0, IDSA_R_PARTIAL, IDSA_R_UNKNOWN, IDSA_R_PARTIAL, 
                  IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WFAIL, 
                  IDSA_ES,  IDSA_T_STRING, IDSA_ES_OTHER, 
                  "exit",   IDSA_T_INT, &exitcode, 
                  NULL);
            }
          } else if (WIFSIGNALED(status)) {
            killcode = WTERMSIG(status);
            idsa_set(ic, LINET_JS, LINET_SCHEME, 0, IDSA_R_PARTIAL, IDSA_R_UNKNOWN, IDSA_R_PARTIAL,
                IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WFAIL, 
                IDSA_ES,  IDSA_T_STRING, IDSA_ES_OTHER, 
                "signal", IDSA_T_INT, &killcode,
                NULL);
          }
#endif
          child_count--;
          busy = ! hang; 
        } else { /* nothing more to collect */
          zombies = 0;
        }
      }

      if((load_fd >= 0) && (zombies == 0)){ /* if zombies then loop will run again, defer load check */
        if(get_load() > limit_load){ /* go to sleep if overloaded */
          sigprocmask(SIG_UNBLOCK, &sst, NULL);	/* enable child|term signal */
          sleep(LINET_SLEEP);
          sigprocmask(SIG_BLOCK, &sst, NULL);	/* disable child|term signal */
          busy = run;
        }
      }
    } while (busy); /* end of child and delay loop */
  } /* end of main loop */

  if(lfd >= 0){
    close(lfd);
  }
  if(load_fd >= 0){
    close(load_fd);
  }

#ifdef USE_IDSA
  idsa_set(ic, LINET_DE, LINET_SCHEME, 0, IDSA_R_TOTAL, IDSA_R_NONE, IDSA_R_UNKNOWN, 
      IDSA_SSM,  IDSA_T_STRING, IDSA_SSM_SSTOP, 
      "version", IDSA_T_STRING, VERSION, 
      NULL);
  idsa_close(ic);
#endif

  return 0;
}
예제 #13
0
파일: addrwatch.c 프로젝트: fln/addrwatch
int main(int argc, char *argv[])
{
	char errbuf[PCAP_ERRBUF_SIZE];
	char *dev;
	struct iface_config *ifc;
	int optind;
	int i;


	bzero(&cfg, sizeof(cfg));

	/* Default configuration */
//	cfg.ratelimit = 0;
	cfg.hashsize = 1;
//	cfg.quiet = 0;
	cfg.promisc_flag = 1;
//	cfg.ratelimit = 0;
//	cfg.sqlite_file = NULL;
//	cfg.uname = NULL;
	cfg.shm_data.size = DEFAULT_SHM_LOG_SIZE;
	cfg.shm_data.name = DEFAULT_SHM_LOG_NAME;
#if HAVE_LIBSQLITE3
	cfg.sqlite_table = PACKAGE;
#endif
	log_open(PACKAGE_NAME);
	argp_parse(&argp, argc, argv, 0, &optind, 0);

	if (!cfg.hostname) {
		cfg.hostname_len = sysconf(_SC_HOST_NAME_MAX);
		cfg.hostname = (char *)calloc(cfg.hostname_len, sizeof(char));
		gethostname(cfg.hostname, cfg.hostname_len);
	}

	daemonize();
	save_pid();

	libevent_init();


	if (cfg.ratelimit > 0)
		log_msg(LOG_DEBUG, "Ratelimiting duplicate entries to 1 per %d seconds", cfg.ratelimit);
	else if (cfg.ratelimit == -1)
		log_msg(LOG_DEBUG, "Duplicate entries supressed indefinitely");
	else
		log_msg(LOG_DEBUG, "Duplicate entries ratelimiting disabled");

	if (cfg.promisc_flag)
		log_msg(LOG_DEBUG, "PROMISC mode enabled");
	else
		log_msg(LOG_DEBUG, "PROMISC mode disabled");

	if (argc > optind) {
		for (i = optind; i < argc; i++)
			add_iface(argv[i]);
	} else {
		dev = pcap_lookupdev(errbuf);
		if (dev != NULL)
			add_iface(dev);
	}

	if (!cfg.interfaces)
		log_msg(LOG_ERR, "No suitable interfaces found!");

	if (cfg.uname)
		drop_root(cfg.uname);

	output_flatfile_init();
	output_sqlite_init();
	output_shm_init();

	/* main loop */
#if HAVE_LIBEVENT2
	event_base_dispatch(cfg.eb);
#else
	event_dispatch();
#endif

	output_shm_close();
	output_sqlite_close();
	output_flatfile_close();

	for (ifc = cfg.interfaces; ifc != NULL; ifc = del_iface(ifc));


	libevent_close();
	log_close();

	del_pid();
	blacklist_free();

	free(cfg.hostname);

	return 0;
}
예제 #14
0
int main(int argc, char *argv[])
{
	int argi;
	char *versionfn, *inprogressfn;
	FILE *versionfd, *tarpipefd;
	char version[1024];
	char *newversion = NULL;
	char *newverreq;
	char *updateparam = NULL;
	int  removeself = 0;
	int talkstat = 0;
	sendreturn_t *sres;

#ifdef BIG_SECURITY_HOLE
	/* Immediately drop all root privs, we'll regain them later when needed */
	drop_root();
#else
	/* We WILL not run as suid-root. */
	drop_root_and_removesuid(argv[0]);
#endif

	versionfn = (char *)malloc(strlen(xgetenv("XYMONHOME")) + strlen(CLIENTVERSIONFILE) + 2);
	sprintf(versionfn, "%s/%s", xgetenv("XYMONHOME"), CLIENTVERSIONFILE);
	inprogressfn = (char *)malloc(strlen(xgetenv("XYMONHOME")) + strlen(INPROGRESSFILE) + 2);
	sprintf(inprogressfn, "%s/%s", xgetenv("XYMONHOME"), INPROGRESSFILE);

	versionfd = fopen(versionfn, "r");
	if (versionfd) {
		char *p;
		if (fgets(version, sizeof(version), versionfd) == NULL) *version = '\0';
		p = strchr(version, '\n'); if (p) *p = '\0';
		fclose(versionfd);
	}
	else {
		*version = '\0';
	}

	if (chdir(xgetenv("XYMONHOME")) != 0) {
		errprintf("Cannot chdir to XYMONHOME\n");
		return 1;
	}

	for (argi=1; (argi < argc); argi++) {
		if (strcmp(argv[argi], "--level") == 0) {
			/* For checking what version we're at */
			printf("%s\n", version);
			return 0;
		}
		else if (strcmp(argv[argi], "--reexec") == 0) {
			/*
			 * First step of the update procedure.
			 *
			 * To avoid problems with unpacking a new clientupdate
			 * on top of the running one (some tar's will abort
			 * if they try this), copy ourself to a temp. file and
			 * re-exec it to carry out the update.
			 */
			char tmpfn[PATH_MAX];
			char *srcfn;
			FILE *tmpfd, *srcfd;
			unsigned char buf[8192];
			long n;
			struct stat st;
			int cperr;

			if (!updateparam) {
				errprintf("clientupdate --reexec called with no update version\n");
				return 1;
			}

			if ( (stat(inprogressfn, &st) == 0) && ((getcurrenttime(NULL) - st.st_mtime) < 3600) ) {
				errprintf("Found update in progress or failed update (started %ld minutes ago)\n",
					(long) (getcurrenttime(NULL)-st.st_mtime)/60);
				return 1;
			}
			unlink(inprogressfn);
			tmpfd = fopen(inprogressfn, "w"); if (tmpfd) fclose(tmpfd);

			/* Copy the executable */
			srcfn = argv[0];
			srcfd = fopen(srcfn, "r"); cperr = errno;

			sprintf(tmpfn, "%s/.update.%s.%ld.tmp", 
				xgetenv("XYMONTMP"), xgetenv("MACHINEDOTS"), (long)getcurrenttime(NULL));

			dbgprintf("Starting update by copying %s to %s\n", srcfn, tmpfn);

			unlink(tmpfn);	/* To avoid symlink attacks */
			if (srcfd) { tmpfd = fopen(tmpfn, "w"); cperr = errno; }

			if (!srcfd || !tmpfd) {
				errprintf("Cannot copy executable: %s\n", strerror(cperr));
				return 1;
			}

			while ((n = fread(buf, 1, sizeof(buf), srcfd)) > 0) fwrite(buf, 1, n, tmpfd);
			fclose(srcfd); fclose(tmpfd);

			/* Make sure the temp. binary has execute permissions set */
			chmod(tmpfn, S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);

			/*
			 * Set the temp. executable suid-root, and exec() it.
			 * If get_root() fails (because clientupdate was installed
			 * without suid-root privs), just carry on and do what we
			 * can without root privs. (It basically just means that
			 * logfetch() and clientupdate() will continue to run without
			 * root privs).
			 */
#ifdef BIG_SECURITY_HOLE
			get_root();
			chown(tmpfn, 0, getgid());
			chmod(tmpfn, S_ISUID|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);
			drop_root();
#endif

			/* Run the temp. executable */
			dbgprintf("Running command '%s %s ..remove-self'\n", tmpfn, updateparam);
			execl(tmpfn, tmpfn, updateparam, "--remove-self", (char *)NULL);

			/* We should never go here */
			errprintf("exec() failed to launch update: %s\n", strerror(errno));
			return 1;
		}

		else if (strncmp(argv[argi], "--update=", 9) == 0) {
			newversion = strdup(argv[argi]+9);
			updateparam = argv[argi];
		}
		else if (strcmp(argv[argi], "--remove-self") == 0) {
			removeself = 1;
		}
		else if (strcmp(argv[argi], "--debug") == 0) {
			debug = 1;
		}

		else if (strcmp(argv[argi], "--suid-setup") == 0) {
			/*
			 * Final step of the update procedure.
			 *
			 * Become root to setup suid-root privs on utils that need it.
			 * Note: If get_root() fails, we're left with normal user privileges. That is
			 * OK, because that is how the client was installed originally, then.
			 */
#ifdef BIG_SECURITY_HOLE
			get_root();
			chown("bin/logfetch", 0, getgid());
			chmod("bin/logfetch", S_ISUID|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);
			drop_root();
#endif

			return 0;
		}
	}

	if (!newversion) {
		errprintf("No new version string!\n");
		cleanup(inprogressfn, (removeself ? argv[0] : NULL));
		return 1;
	}

	/* Update to version "newversion" */
	dbgprintf("Opening pipe to 'tar'\n");
	tarpipefd = popen("tar xf -", "w");
	if (tarpipefd == NULL) {
		errprintf("Cannot launch 'tar xf -': %s\n", strerror(errno));
		cleanup(inprogressfn, (removeself ? argv[0] : NULL));
		return 1;
	}

	sres = newsendreturnbuf(1, tarpipefd);
	newverreq = (char *)malloc(100+strlen(newversion));
	sprintf(newverreq, "download %s.tar", newversion);
	dbgprintf("Sending command to Xymon: %s\n", newverreq);
	if ((talkstat = sendmessage(newverreq, NULL, XYMON_TIMEOUT, sres)) != XYMONSEND_OK) {
		errprintf("Cannot fetch new client tarfile: Status %d\n", talkstat);
		cleanup(inprogressfn, (removeself ? argv[0] : NULL));
		freesendreturnbuf(sres);
		return 1;
	}
	else {
		dbgprintf("Download command completed OK\n");
		freesendreturnbuf(sres);
	}

	dbgprintf("Closing tar pipe\n");
	if ((talkstat = pclose(tarpipefd)) != 0) {
		errprintf("Upgrade failed, tar exited with status %d\n", talkstat);
		cleanup(inprogressfn, (removeself ? argv[0] : NULL));
		return 1;
	}
	else {
		dbgprintf("tar pipe exited with status 0 (OK)\n");
	}

	/* Create the new version file */
	dbgprintf("Creating new version file %s with version %s\n", versionfn, newversion);
	unlink(versionfn);
	versionfd = fopen(versionfn, "w");
	if (versionfd) {
		fprintf(versionfd, "%s", newversion);
		fclose(versionfd);
	}
	else {
		errprintf("Cannot create version file: %s\n", strerror(errno));
	}

	/* Make sure these have execute permissions */
	dbgprintf("Setting execute permissions on xymonclient.sh and clientupdate tools\n");
	chmod("bin/xymonclient.sh", S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);
	chmod("bin/clientupdate", S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);

	/*
	 * Become root to setup suid-root privs on the new clientupdate util.
	 * Note: If get_root() fails, we're left with normal user privileges. That is
	 * OK, because that is how the client was installed originally, then.
	 */
#ifdef BIG_SECURITY_HOLE
	get_root();
	chown("bin/clientupdate", 0, getgid());
	chmod("bin/clientupdate", S_ISUID|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);
	drop_root();
#endif

	dbgprintf("Cleaning up after update\n");
	cleanup(inprogressfn, (removeself ? argv[0] : NULL));

	/*
	 * Exec the new client-update utility to fix suid-root permissions on
	 * the new files.
	 */
	execl("bin/clientupdate", "bin/clientupdate", "--suid-setup", (char *)NULL);

	/* We should never go here */
	errprintf("exec() of clientupdate --suid-setup failed: %s\n", strerror(errno));

	return 0;
}
예제 #15
0
int main(int argc, char *argv[])
{
	char *cfgfn = NULL, *statfn = NULL;
	int i;
	checkdef_t *walk;

#ifdef BIG_SECURITY_HOLE
	drop_root();
#else
	drop_root_and_removesuid(argv[0]);
#endif

	for (i=1; (i<argc); i++) {
		if (strcmp(argv[i], "--clock") == 0) {
			struct timeval tv;
			struct timezone tz;
			struct tm *tm;
			char timestr[50];

			gettimeofday(&tv, &tz);
			printf("epoch: %ld.%06ld\n", (long int)tv.tv_sec, (long int)tv.tv_usec);

			tm = localtime(&tv.tv_sec);
			strftime(timestr, sizeof(timestr), "local: %Y-%m-%d %H:%M:%S %Z", tm);
			printf("%s\n", timestr);

			tm = gmtime(&tv.tv_sec);
			strftime(timestr, sizeof(timestr), "UTC: %Y-%m-%d %H:%M:%S %Z", tm);
			printf("%s\n", timestr);
			return 0;
		}
		else if (i == 1) cfgfn = argv[i];
		else if (i == 2) statfn = argv[i];
	}

	if ((cfgfn == NULL) || (statfn == NULL)) return 1;

	if (loadconfig(cfgfn) != 0) return 1;
	loadlogstatus(statfn);

	for (walk = checklist; (walk); walk = walk->next) {
		char *data;
		checkdef_t *fwalk;

		switch (walk->checktype) {
		  case C_LOG:
			data = logdata(walk->filename, &walk->check.logcheck);
			fprintf(stdout, "[msgs:%s]\n", walk->filename);
			fprintf(stdout, "%s\n", data);

			/* See if there's a special "file:" entry for this logfile */
			for (fwalk = checklist; (fwalk && ((fwalk->checktype != C_FILE) || (strcmp(fwalk->filename, walk->filename) != 0))); fwalk = fwalk->next) ;
			if (fwalk == NULL) {
				/* No specific file: entry, so make sure the logfile metadata is available */
				fprintf(stdout, "[logfile:%s]\n", walk->filename);
				printfiledata(stdout, walk->filename, 0, 0, 0);
			}
			break;

		  case C_FILE:
			fprintf(stdout, "[file:%s]\n", walk->filename);
			printfiledata(stdout, walk->filename, 
					walk->check.filecheck.domd5, 
					walk->check.filecheck.dosha1,
					walk->check.filecheck.dormd160);
			break;

		  case C_DIR:
			fprintf(stdout, "[dir:%s]\n", walk->filename);
			printdirdata(stdout, walk->filename);
			break;

		  case C_COUNT:
			fprintf(stdout, "[linecount:%s]\n", walk->filename);
			printcountdata(stdout, walk);
			break;

		  case C_NONE:
			break;
		}
	}

	savelogstatus(statfn);

	return 0;
}
예제 #16
0
int main(int argc, char *argv[])
{
	command_t *cmd;
	mem_region_t *mr;
	target_context_t *tc;

#if !defined(WIN32)
	cmd = get_commands(argc, argv);
	if(cmd == NULL) return -1;
#endif

	/* open raw ethernet socket if desired, then drop root */
#if !defined(WIN32)
	if (opt_ethernet)
		eth_raw_socket();
#endif
	drop_root();

	/* miscellaneous initialization */

	init_crc32();

	/* open a connection to the target */
	if (!(tc = target_open(opt_port, opt_ethernet ? opt_netif : NULL))){
		panic("couldn't open connection to target");
		return -1;
	}

	while (cmd) {
		command_t *tmp;

		if (opt_verbose)
			print_command(cmd);

		switch (cmd->type) {

#ifdef AJ_FIRMUPDATE_SUPPORT
                case CMD_FIRMUPDATE:
			mr = slurp_file_or_die(cmd->input_path);
			if(require_flags(tc, REQ_MEM_MAP) == -1){
				return -1;
			}
                        firmupdate(tc, mr);
			break;
#endif

		case CMD_DOWNLOAD:
			if (cmd->region && cmd->info.download.have_address){
				panic("can't specify both region and address");
				return -1;
			}

			mr = slurp_file_or_die(cmd->input_path);
			if(require_flags(tc, REQ_MEM_MAP) == -1){
				return -1;
			}
			if (cmd->region)
				download_to_region(tc, mr, cmd->region);
			else if (cmd->info.download.have_address)
				download_to_addr(tc, mr, cmd->addr);
			else{
				warn("download: must specify address or region\n");
				return -1;
			}
			break;

		case CMD_ERASE:
			if (cmd->region && cmd->info.download.have_address){
				panic("can't specify both region and address");
				return -1;
			}

			if(require_flags(tc, REQ_MEM_MAP) == -1){
				return -1;
			}
			if (cmd->region)
				erase_region(tc, cmd->region);
			else if (cmd->info.download.have_address)
				erase_addr(tc, cmd->addr);
			else{
				warn("erase: must specify address or region\n");
				return -1;
			}
			break;

		case CMD_MAP:
			if(require_flags(tc, REQ_MEM_MAP) == -1){
				return -1;
			}
			region_print(tc->memmap);
			return 0;

		case CMD_TERMINAL:
			if(restore_interactive(tc) == -1){
				return -1;
			}
#if !defined(WIN32)
			serial_terminal();
#endif
			return 0;

		case CMD_MD5SUM:
			if (cmd->region && cmd->info.download.have_address){
				panic("md5sum: can't specify both region and address");
				return -1;
			}

			if (cmd->size == 0) {
				warn("md5sum: must specify size\n");
				return -1;
			}

			if (cmd->region){
				if(require_flags(tc, REQ_MEM_MAP) == -1){
					return -1;
				}

				md5sum_region(tc, cmd->region, cmd->size);
			} else if (cmd->info.download.have_address) {
				md5sum_addr(tc, cmd->addr, cmd->size);
			} else{
				warn("md5sum: must specify address or region\n");
				return -1;
			}
			break;

		default:
			warn("unsupported command\n");
			return -1;
		}

		tmp = cmd;
		cmd = cmd->next;
		/*
		 * We don't free paths in the command because we don't
		 * know whether or not they're dynamically allocated.
		 * Thus we leak a little memory.  It's not like this
		 * is a long-running program...
		 */
		free(tmp);
	}

	restore_interactive(tc);
	return 0;
}
/* function: main
 * allocate and setup the tun device, then run the event loop
 */
int main(int argc, char **argv) {
  struct tun_data tunnel;
  int opt;
  char *uplink_interface = NULL, *plat_prefix = NULL;

  strcpy(tunnel.device6, DEVICENAME6);
  strcpy(tunnel.device4, DEVICENAME4);

  while((opt = getopt(argc, argv, "i:p:h")) != -1) {
    switch(opt) {
      case 'i':
        uplink_interface = optarg;
        break;
      case 'p':
        plat_prefix = optarg;
        break;
      case 'h':
      default:
        print_help();
        exit(1);
        break;
    }
  }

  if(uplink_interface == NULL) {
    logmsg(ANDROID_LOG_FATAL, "clatd called without an interface");
    printf("I need an interface\n");
    exit(1);
  }
  logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s", CLATD_VERSION, uplink_interface);

  // open the tunnel device before dropping privs
  tunnel.fd6 = tun_open();
  if(tunnel.fd6 < 0) {
    logmsg(ANDROID_LOG_FATAL, "tun_open failed: %s", strerror(errno));
    exit(1);
  }

  tunnel.fd4 = tun_open();
  if(tunnel.fd4 < 0) {
    logmsg(ANDROID_LOG_FATAL, "tun_open4 failed: %s", strerror(errno));
    exit(1);
  }

  // open the forwarding configuration before dropping privs
  forwarding_fd = open("/proc/sys/net/ipv6/conf/all/forwarding", O_RDWR);
  if(forwarding_fd < 0) {
    logmsg(ANDROID_LOG_FATAL,"open /proc/sys/net/ipv6/conf/all/forwarding failed: %s",
           strerror(errno));
    exit(1);
  }

  // run under a regular user
  drop_root();

  // When run from netd, the environment variable ANDROID_DNS_MODE is set to
  // "local", but that only works for the netd process itself.
  unsetenv("ANDROID_DNS_MODE");

  configure_interface(uplink_interface, plat_prefix, &tunnel);

  set_forwarding(forwarding_fd,"1\n");

  // Loop until someone sends us a signal or brings down the tun interface.
  if(signal(SIGTERM, stop_loop) == SIG_ERR) {
    logmsg(ANDROID_LOG_FATAL, "sigterm handler failed: %s", strerror(errno));
    exit(1);
  }
  event_loop(&tunnel);

  set_forwarding(forwarding_fd,"0\n");
  logmsg(ANDROID_LOG_INFO,"Shutting down clat on %s", uplink_interface);

  return 0;
}