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; }
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; }
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(); }
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; }
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; }
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; }
/* * 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; }
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; }
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); }
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); }
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; }
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; }
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; }
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; }
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; }
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; }