/* * The main guy. */ int main(int argc, char *argv[]) { int rcode = EXIT_SUCCESS; int argval; const char *input_file = NULL; const char *output_file = NULL; const char *filter_file = NULL; FILE *fp; REQUEST *request; VALUE_PAIR *filter_vps = NULL; if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) progname = argv[0]; else progname++; debug_flag = 0; radius_dir = talloc_strdup(NULL, RADIUS_DIR); /* * Ensure that the configuration is initialized. */ memset(&mainconfig, 0, sizeof(mainconfig)); mainconfig.myip.af = AF_UNSPEC; mainconfig.port = -1; mainconfig.name = "radiusd"; /* * We always log to stdout. */ fr_log_fp = stdout; default_log.dest = L_DST_STDOUT; default_log.fd = STDOUT_FILENO; /* Process the options. */ while ((argval = getopt(argc, argv, "d:D:f:hi:mMn:o:xX")) != EOF) { switch(argval) { case 'd': if (radius_dir) { rad_const_free(radius_dir); } radius_dir = talloc_strdup(NULL, optarg); break; case 'D': mainconfig.dictionary_dir = talloc_strdup(NULL, optarg); break; case 'f': filter_file = optarg; break; case 'h': usage(0); break; case 'i': input_file = optarg; break; case 'm': mainconfig.debug_memory = 1; break; case 'M': memory_report = 1; mainconfig.debug_memory = 1; break; case 'n': mainconfig.name = optarg; break; case 'o': output_file = optarg; break; case 'X': debug_flag += 2; mainconfig.log_auth = true; mainconfig.log_auth_badpass = true; mainconfig.log_auth_goodpass = true; break; case 'x': debug_flag++; break; default: usage(1); break; } } if (memory_report) { talloc_enable_null_tracking(); #ifdef WITH_VERIFY_PTR talloc_set_abort_fn(die_horribly); #endif } talloc_set_log_fn(log_talloc); if (debug_flag) { version(); } fr_debug_flag = debug_flag; /* Read the configuration files, BEFORE doing anything else. */ if (read_mainconfig(0) < 0) { exit(EXIT_FAILURE); } setlinebuf(stdout); /* unbuffered output */ if (!input_file || (strcmp(input_file, "-") == 0)) { fp = stdin; } else { fp = fopen(input_file, "r"); if (!fp) { fprintf(stderr, "Failed reading %s: %s\n", input_file, strerror(errno)); exit(EXIT_FAILURE); } } /* * Grab the VPs from stdin, or from the file. */ request = request_setup(fp); if (!request) { fprintf(stderr, "Failed reading input: %s\n", fr_strerror()); exit(EXIT_FAILURE); } /* * No filter file, OR there's no more input, OR we're * reading from a file, and it's different from the * filter file. */ if (!filter_file || filedone || ((input_file != NULL) && (strcmp(filter_file, input_file) != 0))) { if (output_file) { fclose(fp); fp = NULL; } filedone = 0; } /* * There is a filter file. If necessary, open it. If we * already are reading it via "input_file", then we don't * need to re-open it. */ if (filter_file) { if (!fp) { fp = fopen(filter_file, "r"); if (!fp) { fprintf(stderr, "Failed reading %s: %s\n", filter_file, strerror(errno)); exit(EXIT_FAILURE); } } filter_vps = readvp2(request, fp, &filedone, "radiusd"); if (!filter_vps) { fprintf(stderr, "Failed reading attributes from %s: %s\n", filter_file, fr_strerror()); exit(EXIT_FAILURE); } /* * FIXME: loop over input packets. */ fclose(fp); } rad_virtual_server(request); if (!output_file || (strcmp(output_file, "-") == 0)) { fp = stdout; } else { fp = fopen(output_file, "w"); if (!fp) { fprintf(stderr, "Failed writing %s: %s\n", output_file, strerror(errno)); exit(EXIT_FAILURE); } } print_packet(fp, request->reply); if (output_file) fclose(fp); if (filter_vps && !pairvalidate(filter_vps, request->reply->vps)) { fprintf(stderr, "Output file %s does not match attributes in filter %s\n", output_file, filter_file); exit(EXIT_FAILURE); } talloc_free(request); INFO("Exiting normally."); /* * Detach any modules. */ detach_modules(); xlat_free(); /* modules may have xlat's */ /* * Free the configuration items. */ free_mainconfig(); rad_const_free(radius_dir); if (memory_report) { INFO("Allocated memory at time of report:"); log_talloc_report(NULL); } return rcode; }
/* * The main guy. */ int main(int argc, char *argv[]) { int rcode = EXIT_SUCCESS; int status; int argval; int spawn_flag = true; int dont_fork = false; int write_pid = false; int flag = 0; #ifdef HAVE_SIGACTION struct sigaction act; #endif #ifdef OSFC2 set_auth_parameters(argc,argv); #endif if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) progname = argv[0]; else progname++; #ifdef WIN32 { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { fprintf(stderr, "%s: Unable to initialize socket library.\n", progname); return 1; } } #endif debug_flag = 0; spawn_flag = true; radius_dir = talloc_strdup(NULL, RADIUS_DIR); /* * Ensure that the configuration is initialized. */ memset(&mainconfig, 0, sizeof(mainconfig)); mainconfig.myip.af = AF_UNSPEC; mainconfig.port = -1; mainconfig.name = "radiusd"; #ifdef HAVE_SIGACTION memset(&act, 0, sizeof(act)); act.sa_flags = 0 ; sigemptyset( &act.sa_mask ) ; #endif /* * Don't put output anywhere until we get told a little * more. */ default_log.dest = L_DST_NULL; default_log.fd = -1; mainconfig.log_file = NULL; /* Process the options. */ while ((argval = getopt(argc, argv, "Cd:D:fhi:l:mMn:p:PstvxX")) != EOF) { switch(argval) { case 'C': check_config = true; spawn_flag = false; dont_fork = true; break; case 'd': if (radius_dir) { rad_const_free(radius_dir); } radius_dir = talloc_strdup(NULL, optarg); break; case 'D': mainconfig.dictionary_dir = talloc_strdup(NULL, optarg); break; case 'f': dont_fork = true; break; case 'h': usage(0); break; case 'l': if (strcmp(optarg, "stdout") == 0) { goto do_stdout; } mainconfig.log_file = strdup(optarg); default_log.dest = L_DST_FILES; default_log.fd = open(mainconfig.log_file, O_WRONLY | O_APPEND | O_CREAT, 0640); if (default_log.fd < 0) { fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, fr_syserror(errno)); exit(EXIT_FAILURE); } fr_log_fp = fdopen(default_log.fd, "a"); break; case 'i': if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) { fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg); exit(EXIT_FAILURE); } flag |= 1; break; case 'n': mainconfig.name = optarg; break; case 'm': mainconfig.debug_memory = 1; break; case 'M': memory_report = 1; mainconfig.debug_memory = 1; break; case 'p': mainconfig.port = atoi(optarg); if ((mainconfig.port <= 0) || (mainconfig.port >= 65536)) { fprintf(stderr, "radiusd: Invalid port number %s\n", optarg); exit(EXIT_FAILURE); } flag |= 2; break; case 'P': /* Force the PID to be written, even in -f mode */ write_pid = true; break; case 's': /* Single process mode */ spawn_flag = false; dont_fork = true; break; case 't': /* no child threads */ spawn_flag = false; break; case 'v': /* Don't print timestamps */ debug_flag += 2; fr_log_fp = stdout; default_log.dest = L_DST_STDOUT; default_log.fd = STDOUT_FILENO; version(); exit(EXIT_SUCCESS); case 'X': spawn_flag = false; dont_fork = true; debug_flag += 2; mainconfig.log_auth = true; mainconfig.log_auth_badpass = true; mainconfig.log_auth_goodpass = true; do_stdout: fr_log_fp = stdout; default_log.dest = L_DST_STDOUT; default_log.fd = STDOUT_FILENO; break; case 'x': debug_flag++; break; default: usage(1); break; } } if (memory_report) { talloc_enable_null_tracking(); #ifdef WITH_VERIFY_PTR talloc_set_abort_fn(die_horribly); #endif } talloc_set_log_fn(log_talloc); /* * Mismatch between build time OpenSSL and linked SSL, * better to die here than segfault later. */ #ifdef HAVE_OPENSSL_CRYPTO_H if (ssl_check_version() < 0) { exit(EXIT_FAILURE); } #endif if (flag && (flag != 0x03)) { fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n"); exit(EXIT_FAILURE); } if (debug_flag) { version(); } /* Read the configuration files, BEFORE doing anything else. */ if (read_mainconfig(0) < 0) { exit(EXIT_FAILURE); } #ifndef __MINGW32__ /* * Disconnect from session */ if (dont_fork == false) { pid_t pid = fork(); if (pid < 0) { ERROR("Couldn't fork: %s", fr_syserror(errno)); exit(EXIT_FAILURE); } /* * The parent exits, so the child can run in the background. */ if (pid > 0) { exit(EXIT_SUCCESS); } #ifdef HAVE_SETSID setsid(); #endif } #endif /* * Ensure that we're using the CORRECT pid after forking, * NOT the one we started with. */ radius_pid = getpid(); /* * If we're running as a daemon, close the default file * descriptors, AFTER forking. */ if (!debug_flag) { int devnull; devnull = open("/dev/null", O_RDWR); if (devnull < 0) { ERROR("Failed opening /dev/null: %s\n", fr_syserror(errno)); exit(EXIT_FAILURE); } dup2(devnull, STDIN_FILENO); if (default_log.dest == L_DST_STDOUT) { setlinebuf(stdout); default_log.fd = STDOUT_FILENO; } else { dup2(devnull, STDOUT_FILENO); } if (default_log.dest == L_DST_STDERR) { setlinebuf(stderr); default_log.fd = STDERR_FILENO; } else { dup2(devnull, STDERR_FILENO); } close(devnull); } else { setlinebuf(stdout); /* unbuffered output */ } /* * Now we have logging check that the OpenSSL */ /* * Initialize the event pool, including threads. */ radius_event_init(mainconfig.config, spawn_flag); /* * Now that we've set everything up, we can install the signal * handlers. Before this, if we get any signal, we don't know * what to do, so we might as well do the default, and die. */ #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif #ifdef HAVE_SIGACTION act.sa_handler = sig_hup; sigaction(SIGHUP, &act, NULL); act.sa_handler = sig_fatal; sigaction(SIGTERM, &act, NULL); #else #ifdef SIGHUP signal(SIGHUP, sig_hup); #endif signal(SIGTERM, sig_fatal); #endif /* * If we're debugging, then a CTRL-C will cause the * server to die immediately. Use SIGTERM to shut down * the server cleanly in that case. */ if ((mainconfig.debug_memory == 1) || (debug_flag == 0)) { #ifdef HAVE_SIGACTION act.sa_handler = sig_fatal; sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); #else signal(SIGINT, sig_fatal); #ifdef SIGQUIT signal(SIGQUIT, sig_fatal); #endif #endif } /* * Everything seems to have loaded OK, exit gracefully. */ if (check_config) { DEBUG("Configuration appears to be OK"); /* for -C -m|-M */ if (mainconfig.debug_memory) { goto cleanup; } exit(EXIT_SUCCESS); } #ifdef WITH_STATS radius_stats_init(0); #endif /* * Write out the PID anyway if were in foreground mode. */ if (!dont_fork) write_pid = true; /* * Only write the PID file if we're running as a daemon. * * And write it AFTER we've forked, so that we write the * correct PID. */ if (write_pid) { FILE *fp; fp = fopen(mainconfig.pid_file, "w"); if (fp != NULL) { /* * FIXME: What about following symlinks, * and having it over-write a normal file? */ fprintf(fp, "%d\n", (int) radius_pid); fclose(fp); } else { ERROR("Failed creating PID file %s: %s\n", mainconfig.pid_file, fr_syserror(errno)); exit(EXIT_FAILURE); } } exec_trigger(NULL, NULL, "server.start", false); /* * Process requests until HUP or exit. */ while ((status = radius_event_process()) == 0x80) { #ifdef WITH_STATS radius_stats_init(1); #endif hup_mainconfig(); } if (status < 0) { ERROR("Exiting due to internal error: %s", fr_strerror()); rcode = EXIT_FAILURE; } else { INFO("Exiting normally"); } exec_trigger(NULL, NULL, "server.stop", false); /* * Ignore the TERM signal: we're * about to die. */ signal(SIGTERM, SIG_IGN); /* * Send a TERM signal to all * associated processes * (including us, which gets * ignored.) */ #ifndef __MINGW32__ if (spawn_flag) kill(-radius_pid, SIGTERM); #endif /* * We're exiting, so we can delete the PID * file. (If it doesn't exist, we can ignore * the error returned by unlink) */ if (dont_fork == false) { unlink(mainconfig.pid_file); } radius_event_free(); cleanup: /* * Detach any modules. */ detach_modules(); xlat_free(); /* modules may have xlat's */ /* * Free the configuration items. */ free_mainconfig(); rad_const_free(radius_dir); #ifdef WIN32 WSACleanup(); #endif if (memory_report) { INFO("Allocated memory at time of report:"); log_talloc_report(NULL); } return rcode; }
/* * The main guy. */ int main(int argc, char *argv[]) { int rcode; int argval; int spawn_flag = TRUE; int dont_fork = FALSE; int flag = 0; #ifdef HAVE_SIGACTION struct sigaction act; #endif #ifdef OSFC2 set_auth_parameters(argc,argv); #endif if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) progname = argv[0]; else progname++; #ifdef WIN32 { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { fprintf(stderr, "%s: Unable to initialize socket library.\n"); return 1; } } #endif debug_flag = 0; spawn_flag = TRUE; radius_dir = strdup(RADIUS_DIR); /* * Ensure that the configuration is initialized. */ memset(&mainconfig, 0, sizeof(mainconfig)); mainconfig.myip.af = AF_UNSPEC; mainconfig.port = -1; mainconfig.name = "radiusd"; #ifdef HAVE_SIGACTION memset(&act, 0, sizeof(act)); act.sa_flags = 0 ; sigemptyset( &act.sa_mask ) ; #endif /* * Don't put output anywhere until we get told a little * more. */ mainconfig.radlog_dest = RADLOG_NULL; mainconfig.radlog_fd = -1; mainconfig.log_file = NULL; /* Process the options. */ while ((argval = getopt(argc, argv, "Cd:fhi:l:mn:p:stvxX")) != EOF) { switch(argval) { case 'C': check_config = TRUE; spawn_flag = FALSE; dont_fork = TRUE; break; case 'd': if (radius_dir) free(radius_dir); radius_dir = strdup(optarg); break; case 'f': dont_fork = TRUE; break; case 'h': usage(0); break; case 'l': if (strcmp(optarg, "stdout") == 0) { goto do_stdout; } mainconfig.log_file = strdup(optarg); mainconfig.radlog_dest = RADLOG_FILES; mainconfig.radlog_fd = open(mainconfig.log_file, O_WRONLY | O_APPEND | O_CREAT, 0640); if (mainconfig.radlog_fd < 0) { fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, strerror(errno)); exit(1); } break; case 'i': if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) { fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg); exit(1); } flag |= 1; break; case 'n': mainconfig.name = optarg; break; case 'm': debug_memory = 1; break; case 'p': mainconfig.port = atoi(optarg); if ((mainconfig.port <= 0) || (mainconfig.port >= 65536)) { fprintf(stderr, "radiusd: Invalid port number %s\n", optarg); exit(1); } flag |= 2; break; case 's': /* Single process mode */ spawn_flag = FALSE; dont_fork = TRUE; break; case 't': /* no child threads */ spawn_flag = FALSE; break; case 'v': version(); break; case 'X': spawn_flag = FALSE; dont_fork = TRUE; debug_flag += 2; mainconfig.log_auth = TRUE; mainconfig.log_auth_badpass = TRUE; mainconfig.log_auth_goodpass = TRUE; fr_log_fp = stdout; do_stdout: mainconfig.radlog_dest = RADLOG_STDOUT; mainconfig.radlog_fd = STDOUT_FILENO; break; case 'x': debug_flag++; break; default: usage(1); break; } } if (flag && (flag != 0x03)) { fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n"); exit(1); } if (debug_flag) { radlog(L_INFO, "%s", radiusd_version); radlog(L_INFO, "Copyright (C) 1999-2009 The FreeRADIUS server project and contributors.\n"); radlog(L_INFO, "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"); radlog(L_INFO, "PARTICULAR PURPOSE.\n"); radlog(L_INFO, "You may redistribute copies of FreeRADIUS under the terms of the\n"); radlog(L_INFO, "GNU General Public License v2.\n"); fflush(NULL); } /* Read the configuration files, BEFORE doing anything else. */ if (read_mainconfig(0) < 0) { exit(1); } #ifndef __MINGW32__ /* * Disconnect from session */ if (dont_fork == FALSE) { pid_t pid = fork(); if (pid < 0) { radlog(L_ERR, "Couldn't fork: %s", strerror(errno)); exit(1); } /* * The parent exits, so the child can run in the background. */ if (pid > 0) { exit(0); } #ifdef HAVE_SETSID setsid(); #endif } #endif /* * Ensure that we're using the CORRECT pid after forking, * NOT the one we started with. */ radius_pid = getpid(); /* * If we're running as a daemon, close the default file * descriptors, AFTER forking. */ if (!debug_flag) { int devnull; devnull = open("/dev/null", O_RDWR); if (devnull < 0) { radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n", strerror(errno)); exit(1); } dup2(devnull, STDIN_FILENO); if (mainconfig.radlog_dest == RADLOG_STDOUT) { setlinebuf(stdout); mainconfig.radlog_fd = STDOUT_FILENO; } else { dup2(devnull, STDOUT_FILENO); } if (mainconfig.radlog_dest == RADLOG_STDERR) { setlinebuf(stderr); mainconfig.radlog_fd = STDERR_FILENO; } else { dup2(devnull, STDERR_FILENO); } close(devnull); } else { setlinebuf(stdout); /* unbuffered output */ } /* * Initialize the event pool, including threads. */ radius_event_init(mainconfig.config, spawn_flag); /* * Now that we've set everything up, we can install the signal * handlers. Before this, if we get any signal, we don't know * what to do, so we might as well do the default, and die. */ #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif #ifdef HAVE_SIGACTION act.sa_handler = sig_hup; sigaction(SIGHUP, &act, NULL); act.sa_handler = sig_fatal; sigaction(SIGTERM, &act, NULL); #else #ifdef SIGHUP signal(SIGHUP, sig_hup); #endif signal(SIGTERM, sig_fatal); #endif /* * If we're debugging, then a CTRL-C will cause the * server to die immediately. Use SIGTERM to shut down * the server cleanly in that case. */ if ((debug_memory == 1) || (debug_flag == 0)) { #ifdef HAVE_SIGACTION act.sa_handler = sig_fatal; sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); #else signal(SIGINT, sig_fatal); #ifdef SIGQUIT signal(SIGQUIT, sig_fatal); #endif #endif } /* * Everything seems to have loaded OK, exit gracefully. */ if (check_config) { DEBUG("Configuration appears to be OK."); exit(0); } radius_stats_init(0); /* * Only write the PID file if we're running as a daemon. * * And write it AFTER we've forked, so that we write the * correct PID. */ if (dont_fork == FALSE) { FILE *fp; fp = fopen(mainconfig.pid_file, "w"); if (fp != NULL) { /* * FIXME: What about following symlinks, * and having it over-write a normal file? */ fprintf(fp, "%d\n", (int) radius_pid); fclose(fp); } else { radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n", mainconfig.pid_file, strerror(errno)); exit(1); } } /* * Process requests until HUP or exit. */ while ((rcode = radius_event_process()) == 0x80) { radius_stats_init(1); hup_mainconfig(); } if (rcode < 0) { radlog(L_ERR, "Exiting due to internal error: %s", fr_strerror()); rcode = 2; } else { radlog(L_INFO, "Exiting normally."); } /* * Ignore the TERM signal: we're * about to die. */ signal(SIGTERM, SIG_IGN); /* * Send a TERM signal to all * associated processes * (including us, which gets * ignored.) */ #ifndef __MINGW32__ if (spawn_flag) kill(-radius_pid, SIGTERM); #endif /* * We're exiting, so we can delete the PID * file. (If it doesn't exist, we can ignore * the error returned by unlink) */ if (dont_fork == FALSE) { unlink(mainconfig.pid_file); } radius_event_free(); /* * Free the configuration items. */ free_mainconfig(); /* * Detach any modules. */ detach_modules(); xlat_free(); /* modules may have xlat's */ free(radius_dir); #ifdef WIN32 WSACleanup(); #endif return (rcode - 1); }
/* * Zap a user from the radutmp and radwtmp file. */ int main(int argc, char **argv) { CONF_SECTION *cs; NAS *nas; uint32_t ip = 0; uint32_t nas_port = ~0; char *user = NULL; char *s; char buf[256]; struct radutmp u; int argval; progname = argv[0]; radius_dir = strdup(RADIUS_DIR); /* Process the options. */ while ((argval = getopt(argc, argv, "d:p:r:")) != EOF) { switch(argval) { case 'd': if (radius_dir) free(radius_dir); radius_dir = strdup(optarg); break; case 'p': acct_port = atoi(optarg); break; case 'r': if ((radiusip = ip_getaddr(optarg)) == INADDR_NONE) { fprintf(stderr, "%s: %s: radius server unknown\n", progname, optarg); exit(1); } break; default: usage(); exit(1); } } if (argc == optind) { /* no terminal server specified */ usage(); exit(1); } if (argc > optind + 1) { /* NAS port given */ s = argv[optind+1]; if (*s == 's' || *s == 'S') s++; nas_port = strtoul(s, NULL, 10); } if (argc > optind + 2) { /* username (login) given */ user = argv[optind+2]; } /* * Find the IP address of the terminal server. */ if ((nas = nas_findbyname(argv[optind])) == NULL && argv[optind][0] != 0) { if ((ip = ip_getaddr(argv[optind])) == INADDR_NONE) { fprintf(stderr, "%s: host not found.\n", argv[optind]); exit(1); } } if (nas != NULL) ip = nas->ipaddr; /* * Ensure that the configuration is initialized. */ memset(&mainconfig, 0, sizeof(mainconfig)); /* Read radiusd.conf */ if (read_mainconfig(0) < 0) { fprintf(stderr, "%s: Error reading radiusd.conf.\n", argv[0]); exit(1); } /* Read the radutmp section of radiusd.conf */ cs = cf_section_sub_find(cf_section_find("modules"), "radutmp"); if(!cs) { fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n", argv[0]); exit(1); } cf_section_parse(cs, NULL, module_config); printf("%s: zapping termserver %s, port %u", progname, ip_hostname(buf, sizeof(buf), ip), nas_port); if (user != NULL) printf(", user %s", user); printf("\n"); if (nas_port == ~0) { return do_accton_packet(ip); } if (!radutmp_lookup(&u, ip, nas_port, user)) { fprintf(stderr, "Entry not found\n"); return 1; } return do_stop_packet(&u); }