static int seize_index(int index, int size, char *proc) { int mode = 0, key_base = 0; print(LOG_INFO, "Seizing index %d with %s\n", index, proc); proc_entry *entry = get_proc_at_index(index); /* setting up ctr area for my index */ key_base = index * 4 + SEM_CTRL_KEY; entry->key_shm = key_base + 1; entry->key_rlock = key_base + 2; entry->key_wlock = key_base + 3; entry->key_active = key_base + 4; entry->size_shm = size; entry->sent = 0; entry->received = 0; my_index = index; /* map up the cache (mem_entry) */ if ((mem_entry[index].active = create_lock(entry->key_active, 0)) == -1) { return -1; } /* signal active */ if (set_active(mem_entry[index].active)) { return -1; } strncpy(entry->proc_name, proc, PROC_NAME_SIZE - 1); memcpy(mem_entry[index].proc_name, entry->proc_name, PROC_NAME_SIZE); if ((mem_entry[index].rlock = create_lock(entry->key_rlock, 0)) == -1) { return -1; } print(LOG_INFO, "Seize rlock for %s at index %d, key %d, sem %d\n", entry->proc_name, index, entry->key_rlock, mem_entry[index].rlock); if ((mem_entry[index].wlock = create_lock(entry->key_wlock, 1)) == -1) { return -1; } print(LOG_INFO, "Seize wlock for %s at index %d, key %d, sem %d\n", entry->proc_name, index, entry->key_wlock, mem_entry[index].wlock); if ((mem_entry[index].shm = (char *)get_shm(entry->key_shm, entry->size_shm, &mode)) == 0) { return -1; } print(LOG_INFO, "Seize shm for %s at index %d, key %d, sem %p\n", entry->proc_name, index, entry->key_shm, mem_entry[index].shm); return 0; }
void StateRoom::accessRoom() { INetworkRelay *network = this->_world->getSharedObject<INetworkRelay>("NetworkRelay"); if (network) { Remote *remote = NULL; if (this->_textboxRoom->getString() != "") this->_textboxRoom->setString("defaulte"); if (!(remote = network->getRemote(0))) throw RTException("Invalid remote"); IBuffer *buffer = network->getTCPBuffer(); *buffer << static_cast<char>(INetworkRelay::CHANGE_ROOM_QUERY); *buffer << this->_textboxRoom->getString(); remote->sendTCP(buffer); Thread<INetworkRelay> *thread = new Thread<INetworkRelay>(); thread->start(network, &INetworkRelay::start, Any()); while (42) { LockVector<IBuffer *> &recv_buffer = remote->getRecvBufferTCP(); auto guard = create_lock(recv_buffer); for (auto it = recv_buffer.begin(); it != recv_buffer.end();) { if (this->parsePacket(recv_buffer, it)) return ; } } } else { throw RTException("Invalid network"); } }
int main() //@ : main_full(MockKernel) //@ requires module(MockKernel, true); //@ ensures true; { struct server_socket *serverSocket = 0; //@ open_module(); //@ int modulesId = create_ghost_set<struct module *>(); //@ int devicesId = create_ghost_set<struct device *>(); //@ close lseg(0, 0, nil, kernel_module(modulesId, devicesId)); //@ close lseg(0, 0, nil, device(modulesId, devicesId)); //@ close kernel_inv(modulesId, devicesId)(); //@ close create_lock_ghost_args(kernel_inv(modulesId, devicesId), nil, nil); kernelLock = create_lock(); //@ assert pointer(&kernelLock, ?kernelLock_); //@ leak pointer(&kernelLock, kernelLock_); //@ leak lock(kernelLock_, _, kernel_inv(modulesId, devicesId)); serverSocket = create_server_socket(12345); while (true) //@ invariant [_]pointer(&kernelLock, kernelLock_) &*& [_]lock(kernelLock_, _, kernel_inv(modulesId, devicesId)) &*& server_socket(serverSocket); { struct socket *socket = server_socket_accept(serverSocket); //@ close kernel_inv_info(modulesId, devicesId); //@ close thread_run_data(handle_connection)(socket); thread_start(handle_connection, socket); } }
int init_handle (void) { create_lock(handle_mgr_lock); handle_mgr = create_mem_mgr(init_align_up(HANDLE_MGR_ALLOC)); if (!handle_mgr) return -ENOMEM; return 0; }
int check_proc_at_index(int index) { proc_entry *entry = get_proc_at_index(index); int sem; /* Check if this entry has ever been seized or not */ if (entry->key_active) { print(LOG_DEBUG, "key_active for index %d\n", index); /* get sem for the key */ if ((sem = create_lock(entry->key_active, 0)) == -1) { print(LOG_ERR, "Unable to create active lock in check_proc_at_index for key %d\n", entry->key_active); return 0; } /* check if cache is updated with sem */ if (mem_entry[index].active) { /* check if cache contains correct sem for the key */ if (sem != mem_entry[index].active) { print(LOG_DEBUG, "Cache and sem for key %d doesn't match, updating cache\n", entry->key_active); update_cache(index, entry); /*mem_entry[index].active = sem; */ } } else { print(LOG_DEBUG, "Cache empty update sem from key\n"); /*mem_entry[index].active = sem; */ update_cache(index, entry); } /* use sem in cache to check if active */ if (try_lock1(mem_entry[index].active)) { if (!memcmp (mem_entry[index].proc_name, entry->proc_name, PROC_NAME_SIZE)) { print(LOG_DEBUG, "Index %d is occupied by %s and active\n", index, entry->proc_name); } else { print(LOG_DEBUG, "Index %d is occupied by %s, cache is however outdated\n", index, entry->proc_name); update_cache(index, entry); } return 1; } else { print(LOG_DEBUG, "Index %d has been active but isn't any more, reset key_active\n", index); free_index(index); } } else { print(LOG_DEBUG, "Index %d has never been active (or released)\n", index); } return 0; }
int init_ipc_helper (void) { bool need_helper = (atomic_read(&ipc_helper_state) == HELPER_DELAYED); atomic_set(&ipc_helper_state, HELPER_NOTALIVE); create_lock(ipc_helper_lock); create_event(&ipc_helper_event); if (need_helper) create_ipc_helper(); return 0; }
void SQLiteDBManager::resetPrimary() { auto& self = instance(); WriteLock connection_lock(self.mutex_); self.connection_.reset(); { WriteLock create_lock(self.create_mutex_); sqlite3_close(self.db_); self.db_ = nullptr; } }
static int ln_lock( char * res, /* name of resource to lock */ int op) /* true to lock; false to unlock */ { long mypid; char *lockfile = NULL; char *tlockfile = NULL; char *mres = NULL; int rc; char pid_str[NUM_STR_SIZE]; mypid = (long)getpid(); lockfile = g_strjoin(NULL, _lnlock_dir, "/am", res, ".lock", NULL); if (!op) { /* unlock the resource */ assert(read_lock(lockfile) == mypid); (void)delete_lock(lockfile); amfree(lockfile); return 0; } /* lock the resource */ g_snprintf(pid_str, sizeof(pid_str), "%ld", mypid); tlockfile = g_strjoin(NULL, _lnlock_dir, "/am", res, ".", pid_str, NULL); (void)create_lock(tlockfile, mypid); mres = stralloc2(res, "."); while(1) { rc = link_lock(lockfile, tlockfile); if (rc == -1) break; if (rc == 0) break; rc = steal_lock(lockfile, mypid, mres); if (rc == -1) break; if (rc == 0) continue; sleep(1); } (void) delete_lock(tlockfile); amfree(mres); amfree(tlockfile); amfree(lockfile); return rc; }
int main() //@ : main //@ requires true; //@ ensures true; { struct counter *counter = malloc(sizeof(struct counter)); if (counter == 0) { abort(); } counter->count = 0; //@ create_box boxId = counter_box(counter, 0); //@ close counter(counter, boxId)(); //@ close create_lock_ghost_arg(counter(counter, boxId)); struct lock *lock = create_lock(); //@ leak lock(lock, counter(counter, boxId)); counter->lock = lock; //@ leak counter_lock(counter, lock); //@ close incrementor_session(counter, boxId); //@ close thread_run_data(incrementor)(counter); thread_start(incrementor, counter); lock_acquire(lock); //@ open counter(counter, boxId)(); //@ handle h = create_handle counter_box_handle(boxId); /*@ consuming_box_predicate counter_box(boxId, _, _) consuming_handle_predicate counter_box_handle(h) perform_action increase() { @*/ int count0 = counter->count; /*@ } producing_box_predicate counter_box(counter, count0) producing_handle_predicate count_handle(h, count0); @*/ //@ close counter(counter, boxId)(); lock_release(lock); lock_acquire(lock); //@ open counter(counter, boxId)(); /*@ consuming_box_predicate counter_box(boxId, _, _) consuming_handle_predicate count_handle(h, count0) perform_action increase() { @*/ int count1 = counter->count; /*@ } producing_box_predicate counter_box(counter, count1); @*/ //@ close counter(counter, boxId)(); lock_release(lock); assert(count0 <= count1); //@ leak [_]lock(lock, _) &*& [_]counter->lock |-> _ &*& malloc_block_counter(counter); return 0; }
/* create lockfile, or die in the attempt */ static int create_lock(void) { int fd; if (mkdir(ctlbase, 0755) != 0) { if (errno != EEXIST) { fprintf(stderr, "pluto: FATAL: unable to create lock dir: \"%s\": %s\n", ctlbase, strerror(errno)); exit_pluto(PLUTO_EXIT_LOCK_FAIL); } } fd = open(pluto_lock, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IRGRP | S_IROTH); if (fd < 0) { if (errno == EEXIST) { /* * if we did not fork, then we do't really need * the pid to control, so wipe it */ if (!fork_desired) { if (unlink(pluto_lock) == -1) { fprintf(stderr, "pluto: FATAL: lock file \"%s\" already exists and could not be removed (%d %s)\n", pluto_lock, errno, strerror(errno)); exit_pluto(PLUTO_EXIT_LOCK_FAIL); } else { /* * lock file removed, * try creating it again */ return create_lock(); } } else { fprintf(stderr, "pluto: FATAL: lock file \"%s\" already exists\n", pluto_lock); exit_pluto(PLUTO_EXIT_LOCK_FAIL); } } else { fprintf(stderr, "pluto: FATAL: unable to create lock file \"%s\" (%d %s)\n", pluto_lock, errno, strerror(errno)); exit_pluto(PLUTO_EXIT_LOCK_FAIL); } } pluto_lock_created = TRUE; return fd; }
struct shim_handle * get_new_handle (void) { struct shim_handle * new_handle = get_mem_obj_from_mgr_enlarge(handle_mgr, size_align_up(HANDLE_MGR_ALLOC)); if (!new_handle) return NULL; memset(new_handle, 0, sizeof(struct shim_handle)); REF_SET(new_handle->ref_count, 1); create_lock(new_handle->lock); new_handle->owner = cur_process.vmid; return new_handle; }
static int update_cache(int index, proc_entry * entry) { int mode = 0; print(LOG_INFO, "Updating cache for %s at index %d\n", entry->proc_name, index); if ((mem_entry[index].rlock = create_lock(entry->key_rlock, 0)) == -1) { print(LOG_ERR, "Unable to create rlock\n"); return -1; } print(LOG_INFO, "Cache rlock for %s at index %d, key %d, sem %d\n", entry->proc_name, index, entry->key_rlock, mem_entry[index].rlock); if ((mem_entry[index].wlock = create_lock(entry->key_wlock, 0)) == -1) { print(LOG_ERR, "Unable to create wlock\n"); return -1; } print(LOG_INFO, "Cache wlock for %s at index %d, key %d, sem %d\n", entry->proc_name, index, entry->key_wlock, mem_entry[index].wlock); if ((mem_entry[index].shm = (char *)get_shm(entry->key_shm, entry->size_shm, &mode)) == 0) { print(LOG_ERR, "Unable to map shmc\n"); return -1; } print(LOG_INFO, "Cache shm for %s at index %d, key %d, sem &p\n", entry->proc_name, index, entry->key_shm, mem_entry[index].shm); if ((mem_entry[index].active = create_lock(entry->key_active, 0)) == -1) { print(LOG_ERR, "Unable to create active lock\n"); return -1; } memcpy(mem_entry[index].proc_name, entry->proc_name, PROC_NAME_SIZE); return 0; }
struct vicc_ctx * vicc_init(const char *hostname, unsigned short port) { struct vicc_ctx *r = NULL; struct vicc_ctx *ctx = malloc(sizeof *ctx); if (!ctx) { goto err; } ctx->hostname = NULL; ctx->io_lock = NULL; ctx->server_sock = -1; ctx->client_sock = -1; ctx->port = port; #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); #endif ctx->io_lock = create_lock(); if (!ctx->io_lock) { goto err; } if (hostname) { ctx->hostname = strdup(hostname); if (!ctx->hostname) { goto err; } ctx->client_sock = connectsock(hostname, port); } else { ctx->server_sock = opensock(port); if (ctx->server_sock < 0) { goto err; } } r = ctx; err: if (!r) { vicc_exit(ctx); } return r; }
int main(int argc, char **argv) { int ch, debug = 0, uucpstyle = 0; const char *file = NULL; char *endptr; pid_t pid = -1; long tmp_pid; while ((ch = getopt(argc, argv, "df:p:u")) != -1) { switch (ch) { case 'd': debug = 1; break; case 'f': file = optarg; break; case 'p': errno = 0; tmp_pid = strtol(optarg, &endptr, 10); if (*endptr != '\0' || errno || tmp_pid < 1 || (pid = tmp_pid) != tmp_pid) errx(1, "invalid pid specified"); break; case 'u': uucpstyle = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 0) usage(); if (file == NULL) usage(); if (pid != -1) return(create_lock(file, pid, uucpstyle, debug)); else return(check_lock(file, uucpstyle, debug)); }
static struct shim_ipc_port * __get_new_ipc_port (PAL_HANDLE hdl) { struct shim_ipc_port * port = get_mem_obj_from_mgr_enlarge(port_mgr, size_align_up(PORT_MGR_ALLOC)); if (!port) return NULL; memset(port, 0, sizeof(struct shim_ipc_port)); port->pal_handle = hdl; port->update = true; INIT_HLIST_NODE(&port->hlist); INIT_LIST_HEAD(&port->list); INIT_LIST_HEAD(&port->msgs); REF_SET(port->ref_count, 1); create_lock(port->msgs_lock); return port; }
int main() //@ : main //@ requires true; //@ ensures false; { struct room *room = create_room(); //@ close room_ctor(room)(); //@ close create_lock_ghost_args(room_ctor(room), nil, nil); struct lock *roomLock = create_lock(); //@ leak lock(roomLock, _, _); struct server_socket *serverSocket = create_server_socket(12345); for (;;) //@ invariant [_]lock(roomLock, _, room_ctor(room)) &*& server_socket(serverSocket); { struct socket *socket = server_socket_accept(serverSocket); struct session *session = create_session(room, roomLock, socket); //@ close thread_run_data(session_run)(session); thread_start(session_run, session); } }
int main() //@ requires true; //@ ensures true; { struct sum *sumObject = malloc(sizeof(struct sum)); if (sumObject == 0) { abort(); } sumObject->sum = 0; /*@ create_box box1 = contrib_box(0, handle1) and_handle handle1 = contrib_handle(0); @*/ /*@ create_box box2 = contrib_box(0, handle2) and_handle handle2 = contrib_handle(0); @*/ //@ close sum(sumObject, box1, handle1, box2, handle2)(); //@ close create_lock_ghost_args(sum(sumObject, box1, handle1, box2, handle2), nil, nil); struct lock *lock = create_lock(); struct session *session1 = malloc(sizeof(struct session)); if (session1 == 0) { abort(); } session1->sum_object = sumObject; session1->lock = lock; //@ close contribute_pre(session1, box1, handle1, box2, handle2, box1, sumObject, lock); //@ close thread_run_pre(contribute)(session1, contribute_info(box1, handle1, box2, handle2, box1, sumObject, lock)); struct thread *thread1 = thread_start_joinable(contribute, session1); struct session *session2 = malloc(sizeof(struct session)); if (session2 == 0) { abort(); } session2->sum_object = sumObject; session2->lock = lock; //@ close contribute_pre(session2, box1, handle1, box2, handle2, box2, sumObject, lock); //@ close thread_run_pre(contribute)(session2, contribute_info(box1, handle1, box2, handle2, box2, sumObject, lock)); struct thread *thread2 = thread_start_joinable(contribute, session2); thread_join(thread1); //@ open thread_run_post(contribute)(session1, contribute_info(box1, handle1, box2, handle2, box1, sumObject, lock)); thread_join(thread2); //@ open thread_run_post(contribute)(session2, contribute_info(box1, handle1, box2, handle2, box2, sumObject, lock)); lock_dispose(lock); //@ open sum(sumObject, box1, handle1, box2, handle2)(); // The following perform_action statement is only to show contrib_handle(_, box1, 1) /*@ consuming_box_predicate contrib_box(box1, 1, ?owner1) consuming_handle_predicate contrib_handle(?box1handle, _) perform_action set_value(1) {} producing_box_predicate contrib_box(1, owner1) producing_handle_predicate contrib_box_handle(box1handle); @*/ //@ dispose_box contrib_box(box1, _, _); //@ leak contrib_box_handle(_, box1); // The following perform_action statement is only to show contrib_handle(_, box2, 1) /*@ consuming_box_predicate contrib_box(box2, 1, ?owner2) consuming_handle_predicate contrib_handle(?box2handle, _) perform_action set_value(1) {} producing_box_predicate contrib_box(1, owner2) producing_handle_predicate contrib_box_handle(box2handle); @*/ //@ dispose_box contrib_box(box2, _, _); //@ leak contrib_box_handle(_, _); int sum = sumObject->sum; assert(sum == 2); free(sumObject); return 0; }
int main(int argc, char **argv) { char fileext[4]; char *name_p = 0; char *temp_p; char *target = NULL; char *fname; #ifdef USING_GLFTPD char *env_user, *env_group; #else char dirname[PATH_MAX]; #endif char *inc_point[2]; int n, m, ftype = 0; unsigned char empty_dir = 0; unsigned char _incomplete = 0; GLOBAL g; DIR *dir, *parent; #ifdef USING_GLFTPD if (argc == 1) { d_log("postdel: no param specified\n"); return 0; } if ((int)strlen(argv[1]) < 6 || strncmp(argv[1], "DELE ", 5)) { printf("pzs-ng postdel script.\n"); printf(" - this is supposed to be run from glftpd.\n"); printf(" - if you wish to run it yourself from chroot, \n"); printf(" - use /bin/postdel \"DELE <filename>\"\n"); printf(" - thank you. (remember the quotes!)\n"); return 0; } fname = argv[1] + 5; /* This way we simply skip the required * 'DELE'-part of the argument (so we get * filename) */ #else if (argc < 6) { printf("[running in ftpd-agnostic mode]\n"); printf("Missing arguments! Syntax:\n"); printf(" %s <user> <group> <tagline> <section> <filepath>\n", argv[0]); return 0; } fname = strrchr(argv[5], '/'); if (fname == NULL) { fname = argv[5]; strcpy(dirname, "./"); } else { strlcpy(dirname, argv[5], fname - argv[5] + 1); fname++; } chdir(dirname); d_log("postdel: Got a 'DELE %s' in '%s'\n", fname, dirname); #endif d_log("postdel: Project-ZS Next Generation (pzs-ng) %s debug log for postdel.\n", ng_version); d_log("postdel: Postdel executed by: (uid/gid) %d/%d\n", geteuid(), getegid()); #ifdef _ALT_MAX d_log("postdel: PATH_MAX not found - using predefined settings! Please report to the devs!\n"); #endif #ifdef USING_GLFTPD d_log("postdel: Reading user name from env\n"); if ((env_user = getenv("USER")) == NULL) { d_log("postdel: postdel: Could not find environment variable 'USER', setting value to 'Nobody'\n"); env_user = "******"; } d_log("postdel: Reading group name from env\n"); if ((env_group = getenv("GROUP")) == NULL) { d_log("postdel: Could not find environment variable 'GROUP', setting value to 'NoGroup'\n"); env_group = "NoGroup"; } #endif #if ( program_uid > 0 ) d_log("postdel: Trying to change effective gid\n"); setegid(program_gid); d_log("postdel: Trying to change effective uid\n"); seteuid(program_uid); #endif if (!strcmp(fname, "debug")) d_log("postdel: Reading directory structure\n"); dir = opendir("."); parent = opendir(".."); if (fileexists(fname)) { d_log("postdel: File (%s) still exists\n", fname); #if (remove_dot_debug_on_delete == TRUE) if (strcmp(fname, "debug")) unlink(fname); #endif closedir(dir); closedir(parent); return 0; } umask(0666 & 000); d_log("postdel: Clearing arrays\n"); bzero(&g.v.total, sizeof(struct race_total)); g.v.misc.slowest_user[0] = ULONG_MAX; g.v.misc.fastest_user[0] = 0; #ifdef USING_GLFTPD /* YARR; THE PAIN OF MAGIC NUMBERS! */ d_log("postdel: Copying env/predefined username to g.v. (%s)\n", env_user); strlcpy(g.v.user.name, env_user, sizeof(g.v.user.name)); d_log("postdel: Copying env/predefined groupname to g.v. (%s)\n", env_group); strlcpy(g.v.user.group, env_group, sizeof(g.v.user.group)); #else d_log("postdel: Copying argv[1] (username) to g.v. (%s)\n", argv[1]); strlcpy(g.v.user.name, argv[1], sizeof(g.v.user.name)); d_log("postdel: Copying argv[2] (groupname) to g.v. (%s)\n", argv[2]); strlcpy(g.v.user.group, argv[2], sizeof(g.v.user.group)); #endif d_log("postdel: File to remove is: %s\n", fname); if (!*g.v.user.group) memcpy(g.v.user.group, "NoGroup", 8); d_log("postdel: Allocating memory for variables\n"); g.ui = ng_realloc2(g.ui, sizeof(struct USERINFO *) * 30, 1, 1, 1); g.gi = ng_realloc2(g.gi,sizeof(struct GROUPINFO *) * 30, 1, 1, 1); if (!getcwd(g.l.path, PATH_MAX)) { d_log("postdel: Failed to getcwd(): %s\n", strerror(errno)); } if (subcomp(g.l.path, g.l.basepath) && (g.l.basepath[0] == '\0')) strlcpy(g.l.basepath, g.l.path, PATH_MAX); if (strncmp(g.l.path, g.l.basepath, PATH_MAX)) d_log("postdel: We are in subdir of %s\n", g.l.basepath); strncpy(g.v.misc.current_path, g.l.path, sizeof(g.v.misc.current_path)); strncpy(g.v.misc.basepath, g.l.basepath, sizeof(g.v.misc.basepath)); d_log("postdel: Creating directory to store racedata in\n"); maketempdir(g.l.path); d_log("postdel: Locking release\n"); while(1) { if ((m = create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 3, 0))) { d_log("postdel: Failed to lock release.\n"); if (m == 1) { d_log("postdel: version mismatch. Exiting.\n"); exit(EXIT_FAILURE); } if (m == PROGTYPE_RESCAN) { d_log("postdel: Detected rescan running - will try to make it quit.\n"); update_lock(&g.v, 0, 0); } if (m == PROGTYPE_POSTDEL) { n = (signed int)g.v.data_incrementor; d_log("postdel: Detected postdel running - sleeping for one second.\n"); if (!create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 0, g.v.data_queue)) break; usleep(1000000); if (!create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 0, g.v.data_queue)) break; if ( n == (signed int)g.v.data_incrementor) { d_log("postdel: Failed to get lock. Forcing unlock.\n"); if (create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 2, g.v.data_queue)) { d_log("postdel: Failed to force a lock.\n"); d_log("postdel: Exiting with error.\n"); exit(EXIT_FAILURE); } break; } } else { for ( n = 0; n <= max_seconds_wait_for_lock * 10; n++) { d_log("postdel: sleeping for .1 second before trying to get a lock.\n"); usleep(100000); if (!(m = create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 0, g.v.data_queue))) break; } if (n >= max_seconds_wait_for_lock * 10) { if (m == PROGTYPE_RESCAN) { d_log("postdel: Failed to get lock. Forcing unlock.\n"); if (create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 2, g.v.data_queue)) d_log("postdel: Failed to force a lock.\n"); } else d_log("postdel: Failed to get a lock.\n"); if (!g.v.data_in_use && !ignore_lock_timeout) { d_log("postdel: Exiting with error.\n"); exit(EXIT_FAILURE); } } } rewinddir(dir); rewinddir(parent); } usleep(10000); if (update_lock(&g.v, 1, 0) != -1) break; } g.l.race = ng_realloc(g.l.race, n = (int)strlen(g.l.path) + 12 + sizeof(storage), 1, 1, &g.v, 1); g.l.sfv = ng_realloc(g.l.sfv, n, 1, 1, &g.v, 1); g.l.sfvbackup = ng_realloc(g.l.sfvbackup, n, 1, 1, &g.v, 1); g.l.leader = ng_realloc(g.l.leader, n, 1, 1, &g.v, 1); target = ng_realloc(target, 4096, 1, 1, &g.v, 1); if (getenv("SECTION") == NULL) sprintf(g.v.sectionname, "DEFAULT"); else snprintf(g.v.sectionname, 127, "%s", getenv("SECTION")); d_log("postdel: Copying data &g.l into memory\n"); strlcpy(g.v.file.name, fname, NAME_MAX); sprintf(g.l.sfv, storage "/%s/sfvdata", g.l.path); sprintf(g.l.sfvbackup, storage "/%s/sfvbackup", g.l.path); sprintf(g.l.leader, storage "/%s/leader", g.l.path); sprintf(g.l.race, storage "/%s/racedata", g.l.path); g.l.sfv_incomplete = 0; d_log("postdel: Caching release name\n"); getrelname(&g); d_log("postdel: DEBUG 0: incomplete: '%s', path: '%s'\n", g.l.incomplete, g.l.path); if ((matchpath(nocheck_dirs, g.l.path) && rescan_nocheck_dirs_allowed == FALSE) || (!matchpath(zip_dirs, g.l.path) && !matchpath(sfv_dirs, g.l.path) && !matchpath(group_dirs, g.l.path))) { d_log("postdel: Dir matched with nocheck_dirs, or is not in the zip/sfv/group-dirs\n"); d_log("postdel: Freeing memory, removing lock and exiting\n"); ng_free(g.ui); ng_free(g.gi); if (fileexists(g.l.race)) unlink(g.l.race); if (fileexists(g.l.sfv)) unlink(g.l.sfv); if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); if (fileexists(g.l.leader)) unlink(g.l.leader); ng_free(g.l.race); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); if (remove_dot_debug_on_delete) unlink(".debug"); remove_lock(&g.v); return 0; } d_log("postdel: Parsing file extension from filename...\n"); temp_p = find_last_of(g.v.file.name, "."); if (*temp_p != '.') { d_log("postdel: Got: no extension\n"); temp_p = name_p; } else { d_log("postdel: Got: %s\n", temp_p); temp_p++; } name_p++; if (temp_p) { while ((signed)strlen(temp_p) - 4 > 0) temp_p++; snprintf(fileext, 4, "%s", temp_p); } else *fileext = '\0'; g.v.misc.release_type = read_headdata(&g.v); switch (get_filetype_postdel(&g, fileext)) { case 0: ftype = g.v.misc.release_type; d_log("postdel: File type is: ZIP\n"); if (matchpath(zip_dirs, g.l.path)) { if (matchpath(group_dirs, g.l.path)) { g.v.misc.write_log = 0; } else { g.v.misc.write_log = 1; } } else if (matchpath(sfv_dirs, g.l.path) && strict_path_match) { if (matchpath(group_dirs, g.l.path)) { g.v.misc.write_log = 0; } else { d_log("postdel: Directory matched with sfv_dirs\n"); break; } } if (!fileexists("file_id.diz")) { temp_p = findfileext(dir, ".zip"); if (temp_p != NULL) { d_log("postdel: file_id.diz does not exist, trying to extract it from %s\n", temp_p); sprintf(target, "%s -qqjnCLL \"%s\" file_id.diz", unzip_bin, temp_p); execute(target); if (chmod("file_id.diz", 0666)) d_log("postdel: Failed to chmod %s: %s\n", "file_id.diz", strerror(errno)); } } d_log("postdel: Reading diskcount from diz\n"); // g.v.total.files = read_diz("file_id.diz"); g.v.total.files = read_diz(); if (g.v.total.files == 0) { d_log("postdel: Could not get diskcount from diz\n"); g.v.total.files = 1; } g.v.total.files_missing = g.v.total.files; d_log("postdel: Reading race data from file to memory\n"); readrace(g.l.race, &g.v, g.ui, g.gi); d_log("postdel: Caching progress bar\n"); buffer_progress_bar(&g.v); d_log("postdel: Removing old complete bar, if any\n"); removecomplete(g.v.misc.release_type); if (g.v.total.files_missing < 0) { g.v.total.files -= g.v.total.files_missing; g.v.total.files_missing = 0; } if (!g.v.total.files_missing) { d_log("postdel: Creating complete bar\n"); createstatusbar(convert(&g.v, g.ui, g.gi, zip_completebar)); } else if (g.v.total.files_missing < g.v.total.files) { if (g.v.total.files_missing == 1) { d_log("postdel: Writing INCOMPLETE to %s\n", log); writelog(&g, convert(&g.v, g.ui, g.gi, incompletemsg), general_incomplete_type); } _incomplete = 1; } else { empty_dir = 1; } remove_from_race(g.l.race, g.v.file.name, &g.v); break; case 1: /* SFV */ ftype = g.v.misc.release_type; d_log("postdel: Reading file count from sfvdata\n"); readsfv(g.l.sfv, &g.v, 0); if (fileexists(g.l.race)) { d_log("postdel: Reading race data from file to memory\n"); readrace(g.l.race, &g.v, g.ui, g.gi); } d_log("postdel: Caching progress bar\n"); buffer_progress_bar(&g.v); if (g.v.total.files_missing == g.v.total.files) { empty_dir = 1; } d_log("postdel: SFV was removed - removing progressbar/completebar and -missing pointers.\n"); removecomplete(g.v.misc.release_type); d_log("postdel: removing files created\n"); if (fileexists(g.l.sfv)) { delete_sfv(g.l.sfv, &g.v); unlink(g.l.sfv); } if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); if (g.l.nfo_incomplete) unlink(g.l.nfo_incomplete); if (g.l.sample_incomplete) unlink(g.l.sample_incomplete); if (g.l.incomplete) unlink(g.l.incomplete); d_log("postdel: removing progressbar, if any\n"); g.v.misc.release_type = ftype; move_progress_bar(1, &g.v, g.ui, g.gi); break; case 3: ftype = g.v.misc.release_type; d_log("postdel: Removing old complete bar, if any\n"); removecomplete(g.v.misc.release_type); g.v.misc.write_log = matchpath(sfv_dirs, g.l.path) > 0 ? 1 - matchpath(group_dirs, g.l.path) : 0; if (fileexists(g.l.race)) { d_log("postdel: Reading race data from file to memory\n"); readrace(g.l.race, &g.v, g.ui, g.gi); } else { empty_dir = 1; } if (fileexists(g.l.sfv)) { #if ( create_missing_files == TRUE ) #if ( sfv_cleanup_lowercase == TRUE ) strtolower(g.v.file.name); #endif create_missing(g.v.file.name); #endif d_log("postdel: Reading file count from SFV\n"); readsfv(g.l.sfv, &g.v, 0); d_log("postdel: Caching progress bar\n"); buffer_progress_bar(&g.v); } d_log("postdel: g.v.total.files_missing=%d, g.v.total.files=%d\n", g.v.total.files_missing, g.v.total.files); if (g.v.total.files_missing < g.v.total.files) { if (g.v.total.files_missing == 1) { d_log("postdel: Writing INCOMPLETE to %s\n", log); writelog(&g, convert(&g.v, g.ui, g.gi, incompletemsg), general_incomplete_type); } _incomplete = 1; } else { d_log("postdel: Removing old race data\n"); unlink(g.l.race); if (findfileext(dir, ".sfv") == NULL) { empty_dir = 1; } else { _incomplete = 1; } } remove_from_race(g.l.race, g.v.file.name, &g.v); break; case 4: ftype = g.v.misc.release_type; if (!fileexists(g.l.race)) empty_dir = 1; break; case 255: ftype = g.v.misc.release_type; if (!fileexists(g.l.race)) empty_dir = 1; break; case 2: ftype = g.v.misc.release_type; if (!fileexists(g.l.race)) { empty_dir = 1; } else { d_log("postdel: Reading race data from file to memory\n"); readrace(g.l.race, &g.v, g.ui, g.gi); d_log("postdel: Caching progress bar\n"); buffer_progress_bar(&g.v); if (g.v.total.files_missing == g.v.total.files) empty_dir = 1; } break; } if (empty_dir == 1 && !findfileext(dir, ".sfv")) { d_log("postdel: Removing all files and directories created by zipscript\n"); removecomplete(g.v.misc.release_type); if (fileexists(g.l.sfv)) delete_sfv(g.l.sfv, &g.v); if (g.l.nfo_incomplete) unlink(g.l.nfo_incomplete); if (g.l.incomplete) unlink(g.l.incomplete); if (fileexists("file_id.diz")) unlink("file_id.diz"); if (fileexists(g.l.race)) unlink(g.l.race); if (fileexists(g.l.sfv)) unlink(g.l.sfv); if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); if (fileexists(g.l.leader)) unlink(g.l.leader); g.v.misc.release_type = ftype; move_progress_bar(1, &g.v, g.ui, g.gi); #if (remove_dot_files_on_delete == TRUE) removedotfiles(dir); #endif } if (_incomplete == 1 && g.v.total.files > 0) { g.v.misc.data_completed = 0; getrelname(&g); if (g.l.nfo_incomplete) { if (findfileext(dir, ".nfo")) { d_log("postdel: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else if (matchpath(check_for_missing_nfo_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("postdel: Creating missing-nfo indicator %s.\n", g.l.nfo_incomplete); if (create_incomplete_nfo()) { d_log("postdel: Warning: create_incomplete_nfo() returned something.\n"); } } else { if (findfileextparent(parent, ".nfo")) { d_log("postdel: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else { d_log("postdel: Creating missing-nfo indicator (base) %s.\n", g.l.nfo_incomplete); /* This is not pretty, but should be functional. */ if ((inc_point[0] = find_last_of(g.l.path, "/")) != g.l.path) *inc_point[0] = '\0'; if ((inc_point[1] = find_last_of(g.v.misc.release_name, "/")) != g.v.misc.release_name) *inc_point[1] = '\0'; if (create_incomplete_nfo()) { d_log("postdel: Warning: create_incomplete_nfo() returned something.\n"); } if (*inc_point[0] == '\0') *inc_point[0] = '/'; if (*inc_point[1] == '\0') *inc_point[1] = '/'; } } } } #if (create_missing_sample_link) if (g.l.sample_incomplete) { if (findfileextsub(".", sample_types, sample_list) || matchpartialdirname(missing_sample_check_ignore_list, g.v.misc.release_name, missing_sample_check_ignore_dividers)) { d_log("postdel: Removing missing-sample indicator (if any)\n"); remove_sample_indicator(&g); } else if (matchpath(check_for_missing_sample_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("postdel: Creating missing-sample indicator %s.\n", g.l.sample_incomplete); if (create_incomplete_sample()) { d_log("postdel: Warning: create_incomplete_sample() returned something.\n"); } } else { if (findfileextsub("..", sample_types, sample_list)) { d_log("postdel: Removing missing-sample indicator (if any)\n"); remove_sample_indicator(&g); } else { d_log("postdel: Creating missing-sample indicator (base) %s.\n", g.l.sample_incomplete); /* This is not pretty, but should be functional. */ if ((inc_point[0] = find_last_of(g.l.path, "/")) != g.l.path) *inc_point[0] = '\0'; if ((inc_point[1] = find_last_of(g.v.misc.release_name, "/")) != g.v.misc.release_name) *inc_point[1] = '\0'; if (create_incomplete_sample()) { d_log("postdel: Warning: create_incomplete_sample() returned something.\n"); } if (*inc_point[0] == '\0') *inc_point[0] = '/'; if (*inc_point[1] == '\0') *inc_point[1] = '/'; } } } } #endif if (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs) { d_log("postdel: Creating incomplete indicator\n"); d_log("postdel: incomplete: '%s', path: '%s'\n", g.l.incomplete, g.l.path); if (create_incomplete()) { d_log("postdel: Warning: create_incomplete() returned something.\n"); } } d_log("postdel: Moving progress bar (%d)\n", g.v.misc.release_type); g.v.misc.release_type = ftype; move_progress_bar(0, &g.v, g.ui, g.gi); } d_log("postdel: Releasing memory and removing lock.\n"); closedir(dir); closedir(parent); updatestats_free(&g); ng_free(target); ng_free(g.l.race); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); remove_lock(&g.v); if (empty_dir) { d_log("postdel: Removing missing-sfv indicator (if any)\n"); unlink(g.l.sfv_incomplete); if (fileexists(".debug") && remove_dot_debug_on_delete) unlink(".debug"); } d_log("postdel: Exit 0\n"); return 0; }
int main(int argc, char **argv) { bool fork_desired = TRUE; int lockfd; char* ocspuri = NULL; int nhelpers = -1; char *coredir; const struct osw_conf_options *oco; #ifdef NAT_TRAVERSAL /** Overridden by nat_traversal= in ipsec.conf */ bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; #endif /** Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; #ifdef LEAK_DETECTIVE leak_detective=1; #else leak_detective=0; #endif #ifdef HAVE_LIBCAP_NG /* Drop capabilities */ capng_clear(CAPNG_SELECT_BOTH); capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW, CAP_IPC_LOCK, -1); /* our children must be able to CAP_NET_ADMIN to change routes. */ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, -1); capng_apply(CAPNG_SELECT_BOTH); #endif global_argv = argv; global_argc = argc; #ifdef DEBUG openswan_passert_fail = passert_fail; #endif /* see if there is an environment variable */ coredir = getenv("PLUTO_CORE_DIR"); if(getenv("PLUTO_WAIT_FOR_GDB")) { sleep(120); } /* handle arguments */ for (;;) { # define DBG_OFFSET 256 static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "noklips", no_argument, NULL, 'n' }, { "use-nostack", no_argument, NULL, 'n' }, { "use-none", no_argument, NULL, 'n' }, { "force_busy", no_argument, NULL, 'D' }, { "nocrsend", no_argument, NULL, 'c' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "ocsprequestcert", required_argument, NULL, 'q'}, { "ocspuri", required_argument, NULL, 'o'}, { "uniqueids", no_argument, NULL, 'u' }, { "useklips", no_argument, NULL, 'k' }, { "use-klips", no_argument, NULL, 'k' }, { "use-auto", no_argument, NULL, 'G' }, { "usenetkey", no_argument, NULL, 'K' }, { "use-netkey", no_argument, NULL, 'K' }, { "use-mast", no_argument, NULL, 'M' }, { "use-mastklips", no_argument, NULL, 'M' }, { "use-bsdkame", no_argument, NULL, 'F' }, { "interface", required_argument, NULL, 'i' }, { "listen", required_argument, NULL, 'L' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "noretransmits", no_argument, NULL, 'R' }, { "coredir", required_argument, NULL, 'C' }, { "ipsecdir", required_argument, NULL, 'f' }, { "ipsec_dir", required_argument, NULL, 'f' }, #ifdef USE_LWRES { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-nat_t", no_argument, NULL, '5' }, { "debug-nattraversal", no_argument, NULL, '5' }, { "debug-nat-t", no_argument, NULL, '5' }, #endif { "virtual_private", required_argument, NULL, '6' }, { "nhelpers", required_argument, NULL, 'j' }, #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-crypto", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, { "debug-netkey", no_argument, NULL, DBG_NETKEY + DBG_OFFSET }, { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, { "debug-oppoinfo", no_argument, NULL, DBG_OPPOINFO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-dpd", no_argument, NULL, DBG_DPD + DBG_OFFSET }, { "debug-x509", no_argument, NULL, DBG_X509 + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, { "impair-sa-creation", no_argument, NULL, IMPAIR_SA_CREATION + DBG_OFFSET }, { "impair-die-oninfo", no_argument, NULL, IMPAIR_DIE_ONINFO + DBG_OFFSET }, { "impair-jacob-two-two", no_argument, NULL, IMPAIR_JACOB_TWO_TWO + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int c = getopt_long(argc, argv, "", long_opts, NULL); /** Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'C': coredir = clone_str(optarg, "coredir"); break; case 'v': /* --version */ { const char **sp = ipsec_copyright_notice(); printf("%s%s\n", ipsec_version_string(), compile_time_interop_options); for (; *sp != NULL; sp++) puts(*sp); } exit(0); /* not exit_pluto because we are not initialized yet */ break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* does not return on error */ continue; case 'j': /* --nhelpers */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing number of pluto helpers"); { char *endptr; long count = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || count < -1) usage("<nhelpers> must be a positive number, 0 or -1"); nhelpers = count; } continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'G': /* --use-auto */ kern_interface = AUTO_PICK; continue; case 'k': /* --use-klips */ kern_interface = USE_KLIPS; continue; case 'L': /* --listen ip_addr */ { ip_address lip; err_t e = ttoaddr(optarg,0,0,&lip); if(e) { openswan_log("invalid listen argument ignored: %s\n",e); } else { pluto_listen = clone_str(optarg, "pluto_listen"); openswan_log("bind() will be filtered for %s\n",pluto_listen); } } continue; case 'M': /* --use-mast */ kern_interface = USE_MASTKLIPS; continue; case 'F': /* --use-bsdkame */ kern_interface = USE_BSDKAME; continue; case 'K': /* --use-netkey */ kern_interface = USE_NETKEY; continue; case 'n': /* --use-nostack */ kern_interface = NO_KERNEL; continue; case 'D': /* --force_busy */ force_busy = TRUE; continue ; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue ; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue ; case 'R': no_retransmits = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue ; case 'o': /* --ocspuri */ ocspuri = optarg; continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname|ifaddr> */ if (!use_interface(optarg)) usage("too many --interface specifications"); continue; /* * This option does not really work, as this is the "left" * site only, you also need --to --ikeport again later on * It will result in: yourport -> 500, still not bypassing filters */ case 'p': /* --ikeport <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ ctlbase = optarg; if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", ctlbase, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", ctlbase, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", ctlbase, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ pluto_shared_secrets_file = optarg; continue; case 'f': /* --ipsecdir <ipsec-dir> */ (void)osw_init_ipsecdir(optarg); continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; #ifdef DEBUG case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; #endif #endif case '6': /* --virtual_private */ virtual_private = optarg; continue; default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); #ifdef HAVE_NO_FORK fork_desired = FALSE; nhelpers = 0; #endif /* if a core dir was set, chdir there */ if(coredir) if(chdir(coredir) == -1) { int e = errno; openswan_log("pluto: chdir() do dumpdir failed (%d %s)\n", e, strerror(e)); } oco = osw_init_options(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) log_to_syslog = FALSE; else log_to_stderr = FALSE; #ifdef DEBUG #if 0 if(kernel_ops->set_debug) { (*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log); } #endif #endif /** create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } #ifdef IPSECPOLICY /* create info socket. */ { err_t ugh = init_info_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } #endif /* If not suppressed, do daemon fork */ if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(1); } if (pid != 0) { /* parent: die, after filling PID into lock file. * must not use exit_pluto: lock would be removed! */ exit(fill_lock(lockfd, pid)? 0 : 1); } } if (setsid() < 0) { int e = errno; fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(1); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } /** Close everything but ctl_fd and (if needed) stderr. * There is some danger that a library that we don't know * about is using some fd that we don't know about. * I guess we'll soon find out. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ if ((!log_to_stderr || i != 2) #ifdef IPSECPOLICY && i != info_fd #endif && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) osw_abort(); if (dup2(0, 1) != 1) osw_abort(); if (!log_to_stderr && dup2(0, 2) != 2) osw_abort(); } init_constants(); pluto_init_log(); #ifdef HAVE_LIBNSS char buf[100]; snprintf(buf, sizeof(buf), "%s",oco->confddir); loglog(RC_LOG_SERIOUS,"nss directory plutomain: %s",buf); SECStatus nss_init_status= NSS_InitReadWrite(buf); if (nss_init_status != SECSuccess) { loglog(RC_LOG_SERIOUS, "NSS initialization failed (err %d)\n", PR_GetError()); exit_pluto(10); } else { loglog(RC_LOG_SERIOUS, "NSS Initialized"); PK11_SetPasswordFunc(getNSSPassword); #ifdef FIPS_CHECK const char *package_files[]= { IPSECLIBDIR"/setup", IPSECLIBDIR"/addconn", IPSECLIBDIR"/auto", IPSECLIBDIR"/barf", IPSECLIBDIR"/_copyright", IPSECLIBDIR"/eroute", IPSECLIBDIR"/ikeping", IPSECLIBDIR"/_include", IPSECLIBDIR"/_keycensor", IPSECLIBDIR"/klipsdebug", IPSECLIBDIR"/look", IPSECLIBDIR"/newhostkey", IPSECLIBDIR"/pf_key", IPSECLIBDIR"/_pluto_adns", IPSECLIBDIR"/_plutoload", IPSECLIBDIR"/_plutorun", IPSECLIBDIR"/ranbits", IPSECLIBDIR"/_realsetup", IPSECLIBDIR"/rsasigkey", IPSECLIBDIR"/pluto", IPSECLIBDIR"/_secretcensor", IPSECLIBDIR"/secrets", IPSECLIBDIR"/showdefaults", IPSECLIBDIR"/showhostkey", IPSECLIBDIR"/showpolicy", IPSECLIBDIR"/spi", IPSECLIBDIR"/spigrp", IPSECLIBDIR"/_startklips", IPSECLIBDIR"/_startnetkey", IPSECLIBDIR"/tncfg", IPSECLIBDIR"/_updown", IPSECLIBDIR"/_updown.klips", IPSECLIBDIR"/_updown.mast", IPSECLIBDIR"/_updown.netkey", IPSECLIBDIR"/verify", IPSECLIBDIR"/whack", IPSECSBINDIR"/ipsec", NULL }; if (Pluto_IsFIPS() && !FIPSCHECK_verify_files(package_files)) { loglog(RC_LOG_SERIOUS, "FIPS integrity verification test failed"); exit_pluto(10); } #endif } #endif /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ { const char *vc = ipsec_version_code(); #ifdef PLUTO_SENDS_VENDORID const char *v = init_pluto_vendorid(); openswan_log("Starting Pluto (Openswan Version %s%s; Vendor ID %s) pid:%u" , vc, compile_time_interop_options, v, getpid()); #else openswan_log("Starting Pluto (Openswan Version %s%s) pid:%u" , vc, compile_time_interop_options, getpid()); #endif #ifdef HAVE_LIBNSS if(Pluto_IsFIPS()) { openswan_log("Pluto is running in FIPS mode"); } #endif if((vc[0]=='c' && vc[1]=='v' && vc[2]=='s') || (vc[2]=='g' && vc[3]=='i' && vc[4]=='t')) { /* * when people build RPMs from CVS or GIT, make sure they * get blamed appropriately, and that we get some way to * identify who did it, and when they did it. Use string concat, * so that strings the binary can or classic SCCS "what", will find * stuff too. */ openswan_log("@(#) built on "__DATE__":" __TIME__ " by " BUILDER); } #if defined(USE_1DES) openswan_log("WARNING: 1DES is enabled"); #endif } if(coredir) { openswan_log("core dump dir: %s", coredir); } #ifdef LEAK_DETECTIVE openswan_log("LEAK_DETECTIVE support [enabled]"); #else openswan_log("LEAK_DETECTIVE support [disabled]"); #endif #ifdef HAVE_OCF { struct stat buf; errno=0; if( stat("/dev/crypto",&buf) != -1) openswan_log("OCF support for IKE via /dev/crypto [enabled]"); else openswan_log("OCF support for IKE via /dev/crypto [failed:%s]", strerror(errno)); } #else openswan_log("OCF support for IKE [disabled]"); #endif /* Check for SAREF support */ #ifdef KLIPS_MAST #include <ipsec_saref.h> { int e, sk, saref; saref = 1; errno=0; sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_REFINFO, &saref, sizeof(saref)); if (e == -1 ) { openswan_log("SAref support [disabled]: %s" , strerror(errno)); } else { openswan_log("SAref support [enabled]"); } errno=0; e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref)); if (e == -1 ) { openswan_log("SAbind support [disabled]: %s" , strerror(errno)); } else { openswan_log("SAbind support [enabled]"); } close(sk); } #endif #ifdef HAVE_LIBNSS openswan_log("NSS support [enabled]"); #else openswan_log("NSS support [disabled]"); #endif #ifdef HAVE_STATSD openswan_log("HAVE_STATSD notification via /bin/openswan-statsd enabled"); #else openswan_log("HAVE_STATSD notification support not compiled in"); #endif /** Log various impair-* functions if they were enabled */ if(DBGP(IMPAIR_BUST_MI2)) openswan_log("Warning: IMPAIR_BUST_MI2 enabled"); if(DBGP(IMPAIR_BUST_MR2)) openswan_log("Warning: IMPAIR_BUST_MR2 enabled"); if(DBGP(IMPAIR_SA_CREATION)) openswan_log("Warning: IMPAIR_SA_CREATION enabled"); if(DBGP(IMPAIR_JACOB_TWO_TWO)) openswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled"); if(DBGP(IMPAIR_DIE_ONINFO)) openswan_log("Warning: IMPAIR_DIE_ONINFO enabled"); if(DBGP(IMPAIR_DELAY_ADNS_KEY_ANSWER)) openswan_log("Warning: IMPAIR_DELAY_ADNS_KEY_ANSWER enabled"); if(DBGP(IMPAIR_DELAY_ADNS_TXT_ANSWER)) openswan_log("Warning: IMPAIR_DELAY_ADNS_TXT_ANSWER enabled"); /** Initialize all of the various features */ #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); #endif init_virtual_ip(virtual_private); init_rnd_pool(); init_timer(); init_secret(); init_states(); init_connections(); init_crypto(); init_crypto_helpers(nhelpers); load_oswcrypto(); init_demux(); init_kernel(); init_adns(); init_id(); #ifdef TPM init_tpm(); #endif #ifdef HAVE_THREADS init_fetch(); #endif ocsp_set_default_uri(ocspuri); /* loading X.509 CA certificates */ load_authcerts("CA cert", oco->cacerts_dir, AUTH_CA); /* loading X.509 AA certificates */ load_authcerts("AA cert", oco->aacerts_dir, AUTH_AA); /* loading X.509 OCSP certificates */ load_authcerts("OCSP cert", oco->ocspcerts_dir, AUTH_OCSP); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ load_acerts(); #ifdef HAVE_LIBNSS /*Loading CA certs from NSS DB*/ load_authcerts_from_nss("CA cert", AUTH_CA); #endif daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char **argv) { bool fork_desired = TRUE; bool log_to_stderr_desired = FALSE; bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; char *virtual_private = NULL; int lockfd; #ifdef CAPABILITIES cap_t caps; int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE }; #endif /* CAPABILITIES */ /* initialize library and optionsfrom */ if (!library_init(NULL)) { library_deinit(); exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); } if (!libhydra_init("pluto")) { libhydra_deinit(); library_deinit(); exit(SS_RC_INITIALIZATION_FAILED); } if (!pluto_init(argv[0])) { pluto_deinit(); libhydra_deinit(); library_deinit(); exit(SS_RC_DAEMON_INTEGRITY); } options = options_create(); ha_mcast_addr.s_addr = inet_addr(SA_SYNC_MULTICAST); /* handle arguments */ for (;;) { # define DBG_OFFSET 256 static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "noklips", no_argument, NULL, 'n' }, { "nocrsend", no_argument, NULL, 'c' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "cachecrls", no_argument, NULL, 'C' }, { "probe-psk", no_argument, NULL, 'o' }, { "uniqueids", no_argument, NULL, 'u' }, { "interface", required_argument, NULL, 'i' }, { "ha_interface", required_argument, NULL, 'H' }, { "ha_multicast", required_argument, NULL, 'M' }, { "ha_vips", required_argument, NULL, 'V' }, { "ha_seqdiff_in", required_argument, NULL, 'S' }, { "ha_seqdiff_out", required_argument, NULL, 'O' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "policygroupsdir", required_argument, NULL, 'f' }, #ifdef USE_LWRES { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ { "pkcs11module", required_argument, NULL, 'm' }, { "pkcs11keepstate", no_argument, NULL, 'k' }, { "pkcs11initargs", required_argument, NULL, 'z' }, { "pkcs11proxy", no_argument, NULL, 'y' }, { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-natt", no_argument, NULL, '5' }, { "virtual_private", required_argument, NULL, '6' }, #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-ha", no_argument, NULL, DBG_HA + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int c = getopt_long(argc, argv, "", long_opts, NULL); /* Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'v': /* --version */ { const char **sp = ipsec_copyright_notice(); printf("strongSwan "VERSION"%s\n", compile_time_interop_options); for (; *sp != NULL; sp++) puts(*sp); } exit_pluto(0); break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ if (!options->from(options, optarg, &argc, &argv, optind)) { exit_pluto(1); } continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'n': /* --noklips */ no_klips = TRUE; continue; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue; case 'C': /* --cachecrls */ cache_crls = TRUE; continue; case 'o': /* --probe-psk */ probe_psk = TRUE; continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname> */ if (!use_interface(optarg)) usage("too many --interface specifications"); continue; case 'H': /* --ha_interface <ifname> */ if (optarg && strcmp(optarg, "none") != 0) ha_interface = optarg; continue; case 'M': /* --ha_multicast <ip> */ ha_mcast_addr.s_addr = inet_addr(optarg); if (ha_mcast_addr.s_addr == INADDR_NONE || (((unsigned char *) &ha_mcast_addr.s_addr)[0] & 0xF0) != 0xE0) ha_mcast_addr.s_addr = inet_addr(SA_SYNC_MULTICAST); continue; case 'V': /* --ha_vips <ip addresses> */ if(add_ha_vips(optarg)) usage("misconfigured ha_vip addresses"); continue; case 'S': /* --ha_seqdiff_in <diff> */ ha_seqdiff_in = strtoul(optarg, NULL, 0); continue; case 'O': /* --ha_seqdiff_out <diff> */ ha_seqdiff_out = strtoul(optarg, NULL, 0); continue; case 'p': /* --port <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", optarg, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", optarg, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", optarg, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ shared_secrets_file = optarg; continue; case 'f': /* --policygroupsdir <policygroups-dir> */ policygroups_dir = optarg; continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; case 'm': /* --pkcs11module <pathname> */ pkcs11_module_path = optarg; continue; case 'k': /* --pkcs11keepstate */ pkcs11_keep_state = TRUE; continue; case 'y': /* --pkcs11proxy */ pkcs11_proxy = TRUE; continue; case 'z': /* --pkcs11initargs */ pkcs11_init_args = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; case '6': /* --virtual_private */ virtual_private = optarg; continue; default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) { log_to_syslog = FALSE; } else { log_to_stderr = FALSE; } /* set the logging function of pfkey debugging */ #ifdef DEBUG pfkey_debug_func = DBG_log; #else pfkey_debug_func = NULL; #endif /* create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } /* If not suppressed, do daemon fork */ if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(1); } if (pid != 0) { /* parent: die, after filling PID into lock file. * must not use exit_pluto: lock would be removed! */ exit(fill_lock(lockfd, pid)? 0 : 1); } } if (setsid() < 0) { int e = errno; fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(1); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } /* Close everything but ctl_fd and (if needed) stderr. * There is some danger that a library that we don't know * about is using some fd that we don't know about. * I guess we'll soon find out. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ { if ((!log_to_stderr || i != 2) && i != ctl_fd) close(i); } /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) abort(); if (dup2(0, 1) != 1) abort(); if (!log_to_stderr && dup2(0, 2) != 2) abort(); } init_constants(); init_log("pluto"); /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ plog("Starting IKEv1 pluto daemon (strongSwan "VERSION")%s", compile_time_interop_options); if (lib->integrity) { plog("integrity tests enabled:"); plog("lib 'libstrongswan': passed file and segment integrity tests"); plog("lib 'libhydra': passed file and segment integrity tests"); plog("daemon 'pluto': passed file integrity test"); } /* load plugins, further infrastructure may need it */ if (!lib->plugins->load(lib->plugins, NULL, lib->settings->get_str(lib->settings, "pluto.load", PLUGINS))) { exit(SS_RC_INITIALIZATION_FAILED); } print_plugins(); init_builder(); if (!init_secret() || !init_crypto()) { plog("initialization failed - aborting pluto"); exit_pluto(SS_RC_INITIALIZATION_FAILED); } init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); init_virtual_ip(virtual_private); scx_init(pkcs11_module_path, pkcs11_init_args); init_states(); init_demux(); init_kernel(); init_adns(); init_myid(); fetch_initialize(); ac_initialize(); whack_attribute_initialize(); /* HA System: set sequence number delta and open HA interface */ if (ha_interface != NULL) { int version; if (kernel_ops->type == KERNEL_TYPE_LINUX && (version = xfrm_aevent_version()) != XFRM_AEVENT_VERSION) { if (version == 0) plog("HA system: XFRM sequence number updates only " "supported with kernel version 2.6.17 and later."); else if (version == -1) plog("HA system: error reading kernel version. " "Sequence number updates disabled."); else plog("HA system: Strongswan compiled for wrong kernel " "AEVENT version! Please set XFRM_AEVENT_VERSION " "to %d in src/include/linux/xfrm.h", version); ha_seqdiff_in = 0; ha_seqdiff_out = 0; } else { FILE *etime = fopen("/proc/sys/net/core/xfrm_aevent_etime", "w"); FILE *rseqth = fopen("/proc/sys/net/core/xfrm_aevent_rseqth", "w"); if (etime == NULL || rseqth == NULL) { plog("HA System: no sequence number support in Kernel! " "Please use at least kernel 2.6.17."); ha_seqdiff_in = 0; ha_seqdiff_out = 0; } else { /* * Disable etime (otherwise set to a multiple of 100ms, * e.g. 300 for 30 seconds). Using ha_seqdiff_out. */ fprintf(etime, "0"); fprintf(rseqth, "%d", ha_seqdiff_out); } fclose(etime); fclose(rseqth); } if (open_ha_iface() >= 0) { plog("HA system enabled and listening on interface %s", ha_interface); if (access("/var/master", F_OK) == 0) { plog("Initial HA switch to master mode"); ha_master = 1; event_schedule(EVENT_SA_SYNC_UPDATE, 30, NULL); } } else { plog("HA system failed to listen on interface %s. " "HA system disabled.", ha_interface); ha_interface = NULL; } } /* drop unneeded capabilities and change UID/GID */ prctl(PR_SET_KEEPCAPS, 1); #ifdef IPSEC_GROUP { struct group group, *grp; char buf[1024]; if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 || grp == NULL || setgid(grp->gr_gid) != 0) { plog("unable to change daemon group"); abort(); } } #endif #ifdef IPSEC_USER { struct passwd passwd, *pwp; char buf[1024]; if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 || pwp == NULL || setuid(pwp->pw_uid) != 0) { plog("unable to change daemon user"); abort(); } } #endif #ifdef CAPABILITIES caps = cap_init(); cap_set_flag(caps, CAP_EFFECTIVE, 2, keep, CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, 2, keep, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, 2, keep, CAP_SET); if (cap_set_proc(caps) != 0) { plog("unable to drop daemon capabilities"); abort(); } cap_free(caps); #endif /* CAPABILITIES */ /* loading X.509 CA certificates */ load_authcerts("ca", CA_CERT_PATH, X509_CA); /* loading X.509 AA certificates */ load_authcerts("aa", AA_CERT_PATH, X509_AA); /* loading X.509 OCSP certificates */ load_authcerts("ocsp", OCSP_CERT_PATH, X509_OCSP_SIGNER); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ ac_load_certs(); daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char **argv) { int lockfd; int nhelpers = -1; char *coredir; const struct lsw_conf_options *oco; /* * We read the intentions for how to log from command line options * and the config file. Then we prepare to be able to log, but until * then log to stderr (better then nothing). Once we are ready to * actually do loggin according to the methods desired, we set the * variables for those methods */ bool log_to_stderr_desired = FALSE; bool log_to_file_desired = FALSE; coredir = NULL; /* set up initial defaults that need a cast */ pluto_shared_secrets_file = DISCARD_CONST(char *, SHARED_SECRETS_FILE); #ifdef NAT_TRAVERSAL /** Overridden by nat_traversal= in ipsec.conf */ bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; #endif /** Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; #ifdef LEAK_DETECTIVE leak_detective=1; #else leak_detective=0; #endif #ifdef HAVE_LIBCAP_NG /* Drop capabilities */ capng_clear(CAPNG_SELECT_BOTH); capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW, CAP_IPC_LOCK, CAP_AUDIT_WRITE, -1); /* our children must be able to CAP_NET_ADMIN to change routes. */ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, -1); capng_apply(CAPNG_SELECT_BOTH); #endif #ifdef DEBUG libreswan_passert_fail = passert_fail; #endif if(getenv("PLUTO_WAIT_FOR_GDB")) { sleep(120); } /* handle arguments */ for (;;) { # define DBG_OFFSET 256 static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "config", required_argument, NULL, 'z' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "logfile", required_argument, NULL, 'g' }, { "plutostderrlogtime", no_argument, NULL, 't' }, { "noklips", no_argument, NULL, 'n' }, { "use-nostack", no_argument, NULL, 'n' }, { "use-none", no_argument, NULL, 'n' }, { "force_busy", no_argument, NULL, 'D' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "uniqueids", no_argument, NULL, 'u' }, { "useklips", no_argument, NULL, 'k' }, { "use-klips", no_argument, NULL, 'k' }, { "use-auto", no_argument, NULL, 'G' }, { "usenetkey", no_argument, NULL, 'K' }, { "use-netkey", no_argument, NULL, 'K' }, { "use-mast", no_argument, NULL, 'M' }, { "use-mastklips", no_argument, NULL, 'M' }, { "use-bsdkame", no_argument, NULL, 'F' }, { "interface", required_argument, NULL, 'i' }, { "listen", required_argument, NULL, 'L' }, { "ikeport", required_argument, NULL, 'p' }, { "natikeport", required_argument, NULL, 'q' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "noretransmits", no_argument, NULL, 'R' }, { "coredir", required_argument, NULL, 'C' }, { "ipsecdir", required_argument, NULL, 'f' }, { "ipsec_dir", required_argument, NULL, 'f' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "adns", required_argument, NULL, 'a' }, #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-nat_t", no_argument, NULL, '5' }, { "debug-nattraversal", no_argument, NULL, '5' }, { "debug-nat-t", no_argument, NULL, '5' }, #endif { "virtual_private", required_argument, NULL, '6' }, { "nhelpers", required_argument, NULL, 'j' }, #ifdef HAVE_LABELED_IPSEC { "secctx_attr_value", required_argument, NULL, 'w' }, #endif #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-crypto", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, { "debug-netkey", no_argument, NULL, DBG_NETKEY + DBG_OFFSET }, { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, { "debug-oppoinfo", no_argument, NULL, DBG_OPPOINFO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-dpd", no_argument, NULL, DBG_DPD + DBG_OFFSET }, { "debug-x509", no_argument, NULL, DBG_X509 + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, { "impair-sa-creation", no_argument, NULL, IMPAIR_SA_CREATION + DBG_OFFSET }, { "impair-die-oninfo", no_argument, NULL, IMPAIR_DIE_ONINFO + DBG_OFFSET }, { "impair-jacob-two-two", no_argument, NULL, IMPAIR_JACOB_TWO_TWO + DBG_OFFSET }, { "impair-major-version-bump", no_argument, NULL, IMPAIR_MAJOR_VERSION_BUMP + DBG_OFFSET }, { "impair-minor-version-bump", no_argument, NULL, IMPAIR_MINOR_VERSION_BUMP + DBG_OFFSET }, { "impair-retransmits", no_argument, NULL, IMPAIR_RETRANSMITS + DBG_OFFSET }, { "impair-send-bogus-isakmp-flag", no_argument, NULL, IMPAIR_SEND_BOGUS_ISAKMP_FLAG + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int c = getopt_long(argc, argv, "", long_opts, NULL); /** Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'C': coredir = clone_str(optarg, "coredir"); continue; case 'v': /* --version */ { printf("%s%s\n", ipsec_version_string(), compile_time_interop_options); } exit(0); /* not exit_pluto because we are not initialized yet */ break; /* not actually reached */ case 'j': /* --nhelpers */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing number of pluto helpers"); { char *endptr; long count = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || count < -1) usage("<nhelpers> must be a positive number, 0 or -1"); nhelpers = count; } continue; #ifdef HAVE_LABELED_IPSEC case 'w': /* --secctx_attr_value*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing (positive integer) value of secctx_attr_value (needed only if using labeled ipsec)"); { char *endptr; long value = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || (value != SECCTX && value !=10) ) usage("<secctx_attr_value> must be a positive number (32001 by default, 10 for backward compatibility, or any other future number assigned by IANA)"); secctx_attr_value = (u_int16_t)value; } continue; #endif case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'g': /* --logfile */ pluto_log_file = optarg; log_to_file_desired = TRUE; continue; case 't': /* --plutostderrlogtime */ log_with_timestamp = TRUE; continue; case 'G': /* --use-auto */ libreswan_log("The option --use-auto is obsoleted, falling back to --use-netkey\n"); kern_interface = USE_NETKEY; continue; case 'k': /* --use-klips */ kern_interface = USE_KLIPS; continue; case 'L': /* --listen ip_addr */ { ip_address lip; err_t e = ttoaddr(optarg,0,0,&lip); if(e) { libreswan_log("invalid listen argument ignored: %s\n",e); } else { pluto_listen = clone_str(optarg, "pluto_listen"); libreswan_log("bind() will be filtered for %s\n",pluto_listen); } } continue; case 'M': /* --use-mast */ kern_interface = USE_MASTKLIPS; continue; case 'F': /* --use-bsdkame */ kern_interface = USE_BSDKAME; continue; case 'K': /* --use-netkey */ kern_interface = USE_NETKEY; continue; case 'n': /* --use-nostack */ kern_interface = NO_KERNEL; continue; case 'D': /* --force_busy */ force_busy = TRUE; continue ; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue ; case 'R': no_retransmits = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue ; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname|ifaddr> */ if (!use_interface(optarg)) usage("too many --interface specifications"); continue; /* * This option does not really work, as this is the "left" * site only, you also need --to --ikeport again later on * It will result in: yourport -> 500, still not bypassing filters */ case 'p': /* --ikeport <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; #ifdef NAT_TRAVERSAL case 'q': /* --natikeport <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_natt_float_port = port; } continue; #endif case 'b': /* --ctlbase <path> */ ctlbase = optarg; if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", ctlbase, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", ctlbase, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", ctlbase, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ pluto_shared_secrets_file = optarg; continue; case 'f': /* --ipsecdir <ipsec-dir> */ (void)lsw_init_ipsecdir(optarg); continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; #ifdef DEBUG case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; #endif #endif case '6': /* --virtual_private */ virtual_private = optarg; continue; case 'z': /* --config */ ; /* Config struct to variables mapper. This will overwrite */ /* all previously set options. Keep this in the same order than */ /* long_opts[] is. */ struct starter_config *cfg = read_cfg_file(optarg); set_cfg_string(&pluto_log_file, cfg->setup.strings[KSF_PLUTOSTDERRLOG]); fork_desired = cfg->setup.options[KBF_PLUTOFORK]; /* plutofork= */ log_with_timestamp = cfg->setup.options[KBF_PLUTOSTDERRLOGTIME]; force_busy = cfg->setup.options[KBF_FORCEBUSY]; strict_crl_policy = cfg->setup.options[KBF_STRICTCRLPOLICY]; crl_check_interval = cfg->setup.options[KBF_CRLCHECKINTERVAL]; uniqueIDs = cfg->setup.options[KBF_UNIQUEIDS]; /* * We don't check interfaces= here because that part has been dealt * with in _stackmanager before we started */ set_cfg_string(&pluto_listen, cfg->setup.strings[KSF_LISTEN]); pluto_port = cfg->setup.options[KBF_IKEPORT]; /* --ikeport */ /* no config option: ctlbase */ set_cfg_string(&pluto_shared_secrets_file, cfg->setup.strings[KSF_SECRETSFILE]); /* --secrets */ if(cfg->setup.strings[KSF_IPSECDIR] != NULL && *cfg->setup.strings[KSF_IPSECDIR] != 0) { lsw_init_ipsecdir(cfg->setup.strings[KSF_IPSECDIR]); /* --ipsecdir */ } set_cfg_string(&base_perpeer_logdir, cfg->setup.strings[KSF_PERPEERDIR]); /* --perpeerlogbase */ log_to_perpeer = cfg->setup.options[KBF_PERPEERLOG]; /* --perpeerlog */ no_retransmits = !cfg->setup.options[KBF_RETRANSMITS]; /* --noretransmits */ set_cfg_string(&coredir, cfg->setup.strings[KSF_DUMPDIR]); /* --dumpdir */ /* no config option: pluto_adns_option */ #ifdef NAT_TRAVERSAL pluto_natt_float_port = cfg->setup.options[KBF_NATIKEPORT]; nat_traversal = cfg->setup.options[KBF_NATTRAVERSAL]; keep_alive = cfg->setup.options[KBF_KEEPALIVE]; force_keepalive = cfg->setup.options[KBF_FORCE_KEEPALIVE]; nat_t_spf = !cfg->setup.options[KBF_DISABLEPORTFLOATING]; #endif set_cfg_string(&virtual_private, cfg->setup.strings[KSF_VIRTUALPRIVATE]); nhelpers = cfg->setup.options[KBF_NHELPERS]; #ifdef HAVE_LABELED_IPSEC secctx_attr_value = cfg->setup.options[KBF_SECCTX]; #endif #ifdef DEBUG base_debugging = cfg->setup.options[KBF_PLUTODEBUG]; #endif char *protostack = cfg->setup.strings[KSF_PROTOSTACK]; if (protostack == NULL || *protostack == 0) kern_interface = USE_NETKEY; else if (strcmp(protostack, "none") == 0) kern_interface = NO_KERNEL; else if (strcmp(protostack, "auto") == 0) { libreswan_log("The option protostack=auto is obsoleted, falling back to protostack=netkey\n"); kern_interface = USE_NETKEY; } else if (strcmp(protostack, "klips") == 0) kern_interface = USE_KLIPS; else if (strcmp(protostack, "mast") == 0) kern_interface = USE_MASTKLIPS; else if (strcmp(protostack, "netkey") == 0 || strcmp(protostack, "native") == 0) kern_interface = USE_NETKEY; else if (strcmp(protostack, "bsd") == 0 || strcmp(protostack, "kame") == 0 || strcmp(protostack, "bsdkame") == 0) kern_interface = USE_BSDKAME; else if (strcmp(protostack, "win2k") == 0) kern_interface = USE_WIN2K; confread_free(cfg); continue; default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); #ifdef HAVE_NO_FORK fork_desired = FALSE; nhelpers = 0; #endif /* default coredir to location compatible with SElinux */ if(!coredir) { coredir = clone_str("/var/run/pluto", "coredir"); } if(chdir(coredir) == -1) { int e = errno; libreswan_log("pluto: chdir() do dumpdir failed (%d: %s)\n", e, strerror(e)); } oco = lsw_init_options(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired || log_to_file_desired) { log_to_syslog = FALSE; } if (!log_to_stderr_desired) log_to_stderr = FALSE; #ifdef DEBUG #if 0 if(kernel_ops->set_debug) { (*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log); } #endif #endif /** create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } /* If not suppressed, do daemon fork */ if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(1); } if (pid != 0) { /* parent: die, after filling PID into lock file. * must not use exit_pluto: lock would be removed! */ exit(fill_lock(lockfd, pid)? 0 : 1); } } if (setsid() < 0) { int e = errno; fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(1); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); if (isatty(fileno(stdout))) { fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } } /** Close everything but ctl_fd and (if needed) stderr. * There is some danger that a library that we don't know * about is using some fd that we don't know about. * I guess we'll soon find out. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ if ((!log_to_stderr || i != 2) && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) lsw_abort(); if (dup2(0, 1) != 1) lsw_abort(); if (!log_to_stderr && dup2(0, 2) != 2) lsw_abort(); } init_constants(); pluto_init_log(); pluto_init_nss(oco->confddir); #ifdef FIPS_CHECK const char *package_files[]= { IPSECLIBDIR"/setup", IPSECLIBDIR"/addconn", IPSECLIBDIR"/auto", IPSECLIBDIR"/barf", IPSECLIBDIR"/eroute", IPSECLIBDIR"/ikeping", IPSECLIBDIR"/readwriteconf", IPSECLIBDIR"/_keycensor", IPSECLIBDIR"/klipsdebug", IPSECLIBDIR"/look", IPSECLIBDIR"/newhostkey", IPSECLIBDIR"/pf_key", IPSECLIBDIR"/_pluto_adns", IPSECLIBDIR"/_plutorun", IPSECLIBDIR"/ranbits", IPSECLIBDIR"/_realsetup", IPSECLIBDIR"/rsasigkey", IPSECLIBDIR"/pluto", IPSECLIBDIR"/_secretcensor", IPSECLIBDIR"/secrets", IPSECLIBDIR"/showhostkey", IPSECLIBDIR"/spi", IPSECLIBDIR"/spigrp", IPSECLIBDIR"/_stackmanager", IPSECLIBDIR"/tncfg", IPSECLIBDIR"/_updown", IPSECLIBDIR"/_updown.klips", IPSECLIBDIR"/_updown.mast", IPSECLIBDIR"/_updown.netkey", IPSECLIBDIR"/verify", IPSECLIBDIR"/whack", IPSECSBINDIR"/ipsec", NULL }; if (Pluto_IsFIPS() && !FIPSCHECK_verify_files(package_files)) { loglog(RC_LOG_SERIOUS, "FATAL: FIPS integrity verification test failed"); exit_pluto(10); } #else libreswan_log("FIPS integrity support [disabled]"); #endif #ifdef HAVE_LIBCAP_NG libreswan_log("libcap-ng support [enabled]"); #else libreswan_log("libcap-ng support [disabled]"); #endif #ifdef USE_LINUX_AUDIT libreswan_log("Linux audit support [enabled]"); /* test and log if audit is enabled on the system */ int audit_fd, rc; audit_fd = audit_open(); if (audit_fd < 0) { if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) { loglog(RC_LOG_SERIOUS, "Warning: kernel has no audit support"); } else { loglog(RC_LOG_SERIOUS, "FATAL (SOON): audit_open() failed : %s", strerror(errno)); /* temp disabled exit_pluto(10); */ } } rc = audit_log_acct_message(audit_fd, AUDIT_USER_START, NULL, "starting pluto daemon", NULL, -1, NULL, NULL, NULL, 1); close(audit_fd); if (rc < 0) { loglog(RC_LOG_SERIOUS, "FATAL: audit_log_acct_message failed: %s", strerror(errno)); exit_pluto(10); } #else libreswan_log("Linux audit support [disabled]"); #endif /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ { const char *vc = ipsec_version_code(); #ifdef PLUTO_SENDS_VENDORID const char *v = init_pluto_vendorid(); libreswan_log("Starting Pluto (Libreswan Version %s%s; Vendor ID %s) pid:%u" , vc, compile_time_interop_options, v, getpid()); #else libreswan_log("Starting Pluto (Libreswan Version %s%s) pid:%u" , vc, compile_time_interop_options, getpid()); #endif if(Pluto_IsFIPS()) { libreswan_log("Pluto is running in FIPS mode"); } else { libreswan_log("Pluto is NOT running in FIPS mode"); } if((vc[0]=='c' && vc[1]=='v' && vc[2]=='s') || (vc[2]=='g' && vc[3]=='i' && vc[4]=='t')) { /* * when people build RPMs from CVS or GIT, make sure they * get blamed appropriately, and that we get some way to * identify who did it, and when they did it. Use string concat, * so that strings the binary can or classic SCCS "what", will find * stuff too. */ libreswan_log("@(#) built on "__DATE__":" __TIME__ " by " BUILDER); } #if defined(USE_1DES) libreswan_log("WARNING: 1DES is enabled"); #endif } if(coredir) { libreswan_log("core dump dir: %s", coredir); } if(pluto_shared_secrets_file) { libreswan_log("secrets file: %s", pluto_shared_secrets_file); } #ifdef LEAK_DETECTIVE libreswan_log("LEAK_DETECTIVE support [enabled]"); #else libreswan_log("LEAK_DETECTIVE support [disabled]"); #endif #ifdef HAVE_OCF { struct stat buf; errno=0; if( stat("/dev/crypto",&buf) != -1) libreswan_log("OCF support for IKE via /dev/crypto [enabled]"); else libreswan_log("OCF support for IKE via /dev/crypto [failed:%s]", strerror(errno)); } #else libreswan_log("OCF support for IKE [disabled]"); #endif /* Check for SAREF support */ #ifdef KLIPS_MAST #include <ipsec_saref.h> { int e, sk, saref; saref = 1; errno=0; sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_REFINFO, &saref, sizeof(saref)); if (e == -1 ) { libreswan_log("SAref support [disabled]: %s" , strerror(errno)); } else { libreswan_log("SAref support [enabled]"); } errno=0; e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref)); if (e == -1 ) { libreswan_log("SAbind support [disabled]: %s" , strerror(errno)); } else { libreswan_log("SAbind support [enabled]"); } close(sk); } #endif libreswan_log("NSS crypto [enabled]"); #ifdef XAUTH_HAVE_PAM libreswan_log("XAUTH PAM support [enabled]"); #else libreswan_log("XAUTH PAM support [disabled]"); #endif #ifdef HAVE_STATSD libreswan_log("HAVE_STATSD notification via /bin/libreswan-statsd enabled"); #else libreswan_log("HAVE_STATSD notification support [disabled]"); #endif /** Log various impair-* functions if they were enabled */ if(DBGP(IMPAIR_BUST_MI2)) libreswan_log("Warning: IMPAIR_BUST_MI2 enabled"); if(DBGP(IMPAIR_BUST_MR2)) libreswan_log("Warning: IMPAIR_BUST_MR2 enabled"); if(DBGP(IMPAIR_SA_CREATION)) libreswan_log("Warning: IMPAIR_SA_CREATION enabled"); if(DBGP(IMPAIR_JACOB_TWO_TWO)) libreswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled"); if(DBGP(IMPAIR_DIE_ONINFO)) libreswan_log("Warning: IMPAIR_DIE_ONINFO enabled"); if(DBGP(IMPAIR_MAJOR_VERSION_BUMP)) libreswan_log("Warning: IMPAIR_MAJOR_VERSION_BUMP enabled"); if(DBGP(IMPAIR_MINOR_VERSION_BUMP)) libreswan_log("Warning: IMPAIR_MINOR_VERSION_BUMP enabled"); if(DBGP(IMPAIR_RETRANSMITS)) libreswan_log("Warning: IMPAIR_RETRANSMITS enabled"); if(DBGP(IMPAIR_SEND_BOGUS_ISAKMP_FLAG)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_ISAKMP_FLAG enabled"); if(DBGP(IMPAIR_DELAY_ADNS_KEY_ANSWER)) libreswan_log("Warning: IMPAIR_DELAY_ADNS_KEY_ANSWER enabled"); if(DBGP(IMPAIR_DELAY_ADNS_TXT_ANSWER)) libreswan_log("Warning: IMPAIR_DELAY_ADNS_TXT_ANSWER enabled"); /** Initialize all of the various features */ #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); #endif init_virtual_ip(virtual_private); /* obsoletd by nss code init_rnd_pool(); */ init_timer(); init_secret(); init_states(); init_connections(); init_crypto(); init_crypto_helpers(nhelpers); load_lswcrypto(); init_demux(); init_kernel(); init_adns(); init_id(); #ifdef TPM init_tpm(); #endif #if defined(LIBCURL) || defined(LDAP_VER) init_fetch(); #endif /* loading X.509 CA certificates */ load_authcerts("CA cert", oco->cacerts_dir, AUTH_CA); #if 0 /* unused */ /* loading X.509 AA certificates */ load_authcerts("AA cert", oco->aacerts_dir, AUTH_AA); #endif /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ load_acerts(); /*Loading CA certs from NSS DB*/ load_authcerts_from_nss("CA cert", AUTH_CA); #ifdef HAVE_LABELED_IPSEC init_avc(); #endif daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }
int init_memshare(char *proc_name, int size, int qsize) { int ctrl_mode = 1; int retvalue = 0, index; print(LOG_INFO, "Init_memshare start for %s with size %d\n", proc_name, size); if (initialized) return 1; /* a source proc is a must */ if (proc_name == NULL) return 2; memset(my_proc, 0, PROC_NAME_SIZE); strncpy(my_proc, proc_name, PROC_NAME_SIZE - 1); /* If I don't set a qsize I'm considered to be a send proc only */ if (size) send_only = 0; if (!send_only) { init_queues(); seize_queue(&queue_index, "memshare", qsize); } /* clear the cache */ init_mem_proc(); /* start off by locking the ctrl lock */ if ((lock_ctrl_sem = create_lock(SEM_CTRL_KEY, 1)) == -1) { print(LOG_ERR, "Unable to create ctrl lock\n"); return 3; } while (lock(lock_ctrl_sem) < 0) ; print(LOG_DEBUG, "Ctrl locked (init) by %s, %d\n\n", proc_name, lock_ctrl_sem); /*print(LOG_ERR, "%d trylock (init) key=%d, sem=%d\n", try_lock1(lock_ctrl_sem), SEM_CTRL_KEY, lock_ctrl_sem); */ /* map up the ctrl area */ if ((shm_ctrl_ptr = get_shm(SHM_CTRL_KEY, CTRL_SIZE, &ctrl_mode)) == 0) { print(LOG_ERR, "Unable to alloc shared mem\n"); while (unlock(lock_ctrl_sem) < 0) ; return 6; } if (get_index_for_proc(my_proc) != -1) { print(LOG_ERR, "Procname %s already exists\n", my_proc); while (unlock(lock_ctrl_sem) < 0) ; return 4; } if (!send_only) { if ((index = get_first_free()) < 0) { while (unlock(lock_ctrl_sem) < 0) ; print(LOG_ERR, "Max num of processes registered\n"); return 4; } print(LOG_DEBUG, "Next free index is %d\n", index); retvalue = seize_index(index, size, my_proc); if (retvalue == -1) { while (unlock(lock_ctrl_sem) < 0) ; return 6; } } else { print(LOG_INFO, "%s is a send only proc\n", my_proc); } print(LOG_DEBUG, "Ctrl unlocked by %s\n\n", proc_name); while (unlock(lock_ctrl_sem) < 0) ; if (!send_only) start_listen_thread(); print(LOG_DEBUG, "Init_memshare done for %s\n", my_proc); initialized = 1; return 0; }
int main(int argc, char **argv) { bool fork_desired = TRUE; bool log_to_stderr_desired = FALSE; int lockfd; char* ocspuri = NULL; #ifdef NAT_TRAVERSAL /** Overridden by nat_traversal= in ipsec.conf */ bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; #endif #ifdef VIRTUAL_IP /** Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; #endif /* handle arguments */ for (;;) { # define DBG_OFFSET 256 static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "noklips", no_argument, NULL, 'n' }, { "nocrsend", no_argument, NULL, 'c' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "ocsprequestcert", required_argument, NULL, 'q'}, { "ocspuri", required_argument, NULL, 'o'}, { "uniqueids", no_argument, NULL, 'u' }, { "interface", required_argument, NULL, 'i' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "noretransmits", no_argument, NULL, 'R' }, { "ipsecdir", required_argument, NULL, 'f' }, { "ipsec_dir", required_argument, NULL, 'f' }, #ifdef USE_LWRES { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-nat_t", no_argument, NULL, '5' }, #endif #ifdef VIRTUAL_IP { "virtual_private", required_argument, NULL, '6' }, #endif #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all]", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int c = getopt_long(argc, argv, "", long_opts, NULL); /** Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'v': /* --version */ { const char **sp = ipsec_copyright_notice(); printf("%s%s\n", ipsec_version_string(), compile_time_interop_options); for (; *sp != NULL; sp++) puts(*sp); } exit(0); /* not exit_pluto because we are not initialized yet */ break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* does not return on error */ continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'n': /* --noklips */ no_klips = TRUE; continue; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue ; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue ; case 'R': no_retransmits = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue ; case 'o': /* --ocspuri */ ocspuri = optarg; continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname> */ if (!use_interface(optarg)) usage("too many --interface specifications"); continue; case 'p': /* --port <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", optarg, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", optarg, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", optarg, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ shared_secrets_file = optarg; continue; case 'f': /* --ipsecdir <ipsec-dir> */ ipsec_dir = optarg; continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; #endif #ifdef VIRTUAL_IP case '6': /* --virtual_private */ virtual_private = optarg; continue; #endif default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) log_to_syslog = FALSE; else log_to_stderr = FALSE; /* set the logging function of pfkey debugging */ #ifdef DEBUG pfkey_debug_func = DBG_log; pfkey_error_func = DBG_log; #else pfkey_debug_func = NULL; pfkey_error_func = NULL; #endif /** create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } #ifdef IPSECPOLICY /* create info socket. */ { err_t ugh = init_info_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } #endif /* If not suppressed, do daemon fork */ if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(1); } if (pid != 0) { /* parent: die, after filling PID into lock file. * must not use exit_pluto: lock would be removed! */ exit(fill_lock(lockfd, pid)? 0 : 1); } } if (setsid() < 0) { int e = errno; fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(1); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } /** Close everything but ctl_fd and (if needed) stderr. * There is some danger that a library that we don't know * about is using some fd that we don't know about. * I guess we'll soon find out. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ if ((!log_to_stderr || i != 2) #ifdef IPSECPOLICY && i != info_fd #endif && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) abort(); if (dup2(0, 1) != 1) abort(); if (!log_to_stderr && dup2(0, 2) != 2) abort(); } init_constants(); pluto_init_log(); /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ { #ifdef PLUTO_SENDS_VENDORID const char *v = init_pluto_vendorid(); openswan_log("Starting Pluto (Openswan Version %s%s; Vendor ID %s)" , ipsec_version_code() , compile_time_interop_options , v); #else openswan_log("Starting Pluto (Openswan Version %s%s)" , ipsec_version_code() , compile_time_interop_options); #endif } /** Initialize all of the various features */ #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); #endif #ifdef VIRTUAL_IP init_virtual_ip(virtual_private); #endif init_rnd_pool(); init_secret(); init_states(); init_crypto(); init_demux(); init_kernel(); init_adns(); init_id(); #ifdef HAVE_THREADS init_fetch(); #endif ocsp_set_default_uri(ocspuri); /* loading X.509 CA certificates */ load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA); /* loading X.509 AA certificates */ load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA); /* loading X.509 OCSP certificates */ load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ load_acerts(); daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char **argv) { int lockfd; bool restore_vrf_pluto = 0; /*此开关必须放在所有动态内存分配之前*/ leak_detective=0; debug_info_control* dic=alloc_bytes(sizeof(debug_info_control), "malloc debug_info_control in main"); openswan_passert_fail = passert_fail; /*设备类型初始化*/ ipsec_device_type_init(); { u32 pseudo_start_pluto = 0; for (;;) { #define DBG_OFFSET 256 static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "start", no_argument, NULL, 'B' }, { "quit", no_argument, NULL, 'D' }, { "user", no_argument, NULL, 'u' }, { "krl", no_argument, NULL, 'K' }, { "debug-nat", no_argument, NULL, '5' }, { "debug-none", no_argument, NULL, 'N' }, { "debug-all", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypto", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET }, { "debug-netkey", no_argument, NULL, DBG_NETKEY + DBG_OFFSET }, { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppoinfo", no_argument, NULL, DBG_OPPOINFO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-dpd", no_argument, NULL, DBG_DPD + DBG_OFFSET }, { "debug-xauth", no_argument, NULL, DBG_XAUTH+ DBG_OFFSET }, { "debug-x509", no_argument, NULL, DBG_X509 + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET }, { "debug-ifchange", no_argument, NULL, DBG_IF_CHANGE + DBG_OFFSET }, { "log-openinfo", no_argument, NULL, 'i' }, { "log-openwar", no_argument, NULL, 'w' }, { "log-openerr", no_argument, NULL, 'r' }, { "log-openuserlog", no_argument, NULL, 'e' }, { "log-openradiuslog", no_argument, NULL, 'c' }, { "log-openpri", no_argument, NULL, 'p' }, { "log-opensyserr", no_argument, NULL, 'q' }, { "log-closeall", no_argument, NULL, 'a' }, { "debug-connection", required_argument, NULL, 'O' }, { "debug-host", required_argument, NULL, 'H' }, { "debug-stop", no_argument, NULL, 'S' }, { "counter", no_argument, NULL, 'b' }, { "isa-counter", no_argument, NULL, 'x' }, { "krc", no_argument, NULL, 'E'}, { "kss", required_argument, NULL, 'F'}, { "kpc", no_argument, NULL, 'G'}, { "kprt", required_argument, NULL, 'L'}, { "kspi", required_argument, NULL, 'M' }, { "kdst", required_argument, NULL, 'P' }, { "kdnet", required_argument, NULL, 'R' }, { "kid", required_argument, NULL, 'Q' }, { "restore-vrf", no_argument, NULL, 'V' }, { 0,0,0,0 } }; int c = getopt_long(argc, argv, "", long_opts, NULL); ip_address dst_tmp; ip_subnet subnet_tmp; switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; case 'h': usage(NULL); break; case 'v': { const char **sp = ipsec_copyright_notice(); printf("%s%s\n", ipsec_version_string(),compile_time_interop_options); for (; *sp != NULL; sp++) { puts(*sp); } } exit(0); break; case 'i': dic->public_info.log_falg = 1; dic->public_info.log_level_info |= IPSEC_LOGLEVEL_INFO; continue; case 'w': dic->public_info.log_falg = 1; dic->public_info.log_level_info |= IPSEC_LOGLEVEL_WARNING; continue; case 'r': dic->public_info.log_falg = 1; dic->public_info.log_level_info |= IPSEC_LOGLEVEL_ERROR; continue; case 'e': dic->public_info.log_falg = 1; dic->public_info.log_level_info |= IPSEC_LOGLEVEL_USER_LOG; continue; case 'c': dic->public_info.log_falg = 1; dic->public_info.log_level_info |= IPSEC_LOGLEVEL_RADIUS_LOG; continue; case 'p': dic->public_info.log_falg = 1; dic->public_info.log_level_info |= IPSEC_LOGLEVEL_PRIVATE; continue; case 'q': dic->public_info.log_falg = 1; dic->public_info.log_level_info |= IPSEC_LOGLEVEL_SYSERROR; continue; case 'a': dic->public_info.log_falg = 1; dic->public_info.log_level_info=IPSEC_LOGLEVEL_CLOSE; continue; case 'B': dic->com_type=IPSEC_DEBUG_STAR_HANDLE; continue; case 'D': dic->com_type=IPSEC_DEBUG_QUIT_HANDLE; continue; case 'u': dic->com_type=IPSEC_DEBUG_USER_HANDLE; continue; case 'K': dic->com_type=IPSEC_DEBUG_KERNEL_HANDLE; continue; case 'N': /* --debug-none */ dic->public_info.public_info_flag=1; dic->public_info.public_info_value=DBG_NONE; continue; case 'A': /* --debug-all */ dic->public_info.public_info_flag=1; dic->public_info.public_info_value=DBG_ALL; continue; case 'O': if(optarg != NULL) { strcpy(dic->child_info.child_info_optarg,optarg); dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_CON_NAME; } else { return 0; } break; case 'H': if(optarg != NULL) { strcpy(dic->child_info.child_info_optarg,optarg); dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_HOST; } else { return 0; } break; case 'S': dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_STOP; break; case 'b': dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_PRINT_COUNTER; break; case 'x': dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_PRINT_ISA_COUNTER; break; case 'E': pseudo_start_pluto = 1; dic->kernel_info.flag= IPSEC_RESET_COUNTER; continue; case 'F': pseudo_start_pluto = 1; dic->kernel_info.flag = IPSEC_SET_DEBUG_SIP; dic->kernel_info.sip =inet_addr(optarg); continue; case 'G': pseudo_start_pluto = 1; dic->kernel_info.flag = IPSEC_DUMP_COUNTER; continue; case 'L': pseudo_start_pluto = 1; dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP; if_get_index_by_name(optarg, (s32*)(&dic->kernel_info.ifindex)); continue; case 'M': pseudo_start_pluto = 1; dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP; dic->kernel_info.spi = (u32)chartoint(optarg,strlen(optarg)); if((int)dic->kernel_info.spi < 0) { fprintf(stderr,"%s IS ERROR INPUT(For Example:0x123...)\n",optarg); pfree(dic); return 0; } continue; case 'P': pseudo_start_pluto = 1; dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP; if(ttoaddr(optarg, 0, AF_INET, &dst_tmp)) { fprintf(stderr,"you must input right IP\n"); pfree(dic); return 0; } else{ dic->kernel_info.dsc.a4 = dst_tmp.u.v4.sin_addr.s_addr; continue; } case 'R': pseudo_start_pluto = 1; dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP; if(ttosubnet(optarg, 0, AF_INET, &subnet_tmp)) { fprintf(stderr,"you must input right subnet\n"); pfree(dic); return 0; } else{ dic->kernel_info.net.a4 = subnet_tmp.addr.u.v4.sin_addr.s_addr; continue; } case 'Q': pseudo_start_pluto = 1; dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP; dic->kernel_info.connid = atoi(optarg); continue; case 'V': { restore_vrf_pluto = 1; } continue; default: if (c >= DBG_OFFSET) { dic->public_info.public_info_flag=1; dic->public_info.public_info_value |= c - DBG_OFFSET; } continue; bad_case(c); } break; } /** if(restore_vrf_pluto) { ipsec_restore_vrf_pluto(); } **/ ipsec_restore_vrf_pluto(); { u32 err; conplat_syscall(MODULEID_OSBASIC, OSBASIC_GET_VRF_ID, &g_ipsec_vrf_id, sizeof(g_ipsec_vrf_id), (s32*)(&err)); if(err != 0) { g_ipsec_vrf_id = 0; } sprintf(pluto_lock + strlen(pluto_lock), "_%d", g_ipsec_vrf_id); sprintf(ctl_addr.sun_path+ strlen(ctl_addr.sun_path), "_%d", g_ipsec_vrf_id); sprintf(ws_ctl_addr.sun_path+ strlen(ws_ctl_addr.sun_path), "_%d", g_ipsec_vrf_id); } switch(dic->com_type) { case IPSEC_DEBUG_STAR_HANDLE: if(dic->public_info.public_info_flag) { cur_debugging = dic->public_info.public_info_value; } if(dic->public_info.log_falg) { g_log_level = dic->public_info.log_level_info; } break; case IPSEC_DEBUG_USER_HANDLE: send_connection_debug(dic, IPSEC_DEBUG_USER_HANDLE); pfree(dic); return 0; case IPSEC_DEBUG_KERNEL_HANDLE: if(pseudo_start_pluto == 1) { u32 syscall_result = 0; if((dic->kernel_info.flag==IPSEC_PRINT_INTERFACE_TEMP)&&(0 == dic->kernel_info.ifindex)) { fprintf(stderr,"you must input the if name\n"); pfree(dic); return 0; } conplat_syscall(MODULEID_IPSEC_POLICY, IPSEC_MODULE_DEBUG_PART, (void *)(&dic->kernel_info), sizeof(struct ipsec_user_debug_info), (s32 *)(&syscall_result)); if(g_ipsec_device_is_dpx) { (u32)conplat_syscall(FW_MODULEID_IPSEC | FW_BOARD, IPSEC_MODULE_DEBUG_PART, (void *)(&dic->kernel_info), sizeof(struct ipsec_user_debug_info), (s32 *)(&syscall_result)); } } else { fprintf(stderr,"after --kernel ,you must input the right command\n"); } pfree(dic); return 0; case IPSEC_DEBUG_QUIT_HANDLE: send_connection_debug(dic, IPSEC_DEBUG_QUIT_HANDLE); pfree(dic); return 0; default: fprintf(stderr,"you must input --start --quit --user or --kernel\n"); exit(0); } pfree(dic); } if (optind != argc) { usage("unexpected argument"); } //如果你想再重启设备后默认打开调试开关 #if 0 cur_debugging = DBG_ALL; #endif lockfd = create_lock(); g_log_level |= ws_get_log_level(); //获得显示级别 g_ipsec_multiout = ws_get_multiOut(); //获取多接口转发标志位 if(g_ipsec_multiout) { int res; conplat_syscall(MODULEID_IPSEC_POLICY, IPSEC_MODULE_MULTI_OUT, &(g_ipsec_multiout), sizeof(g_ipsec_multiout), &res); } ipsec_restore_tunnel_ipsec(); ipsec_init_lv2_switch(); ipsec_init_route_mode(); ipsec_init_user_syn(); ipsec_init_compress_enable(); ipsec_init_udp_checksum_switch(); ipsec_init_cookie(); ipsec_esp_alg_init(); init_vendorid(); //daemon之前销毁缓冲池中的数据库句柄,使用make_daemon不用加此函数 sqlite3_clear_buffer_ex(); { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n",errno, strerror(e)); exit_pluto(1); } if (pid != 0) { /* parent: die, after filling PID into lock file. * must not use exit_pluto: lock would be removed! */ exit(fill_lock(lockfd, pid)? 0 : 1); } } if (setsid() < 0) { int e = errno; fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",errno, strerror(e)); exit_pluto(1); } } /** Close everything but and (if needed) stderr. * There is some danger that a library that we don't know * about is using some fd that we don't know about. * I guess we'll soon find out. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ { close(i); } /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) { IPSEC_abort(); } if (dup2(0, 1) != 1) { IPSEC_abort(); } } init_constants(); init_pluto_vendorid(); ipsec_version_code(); ipsec_get_slot_bit(); // 需要放在ipsec_template_delete_all 前面 ipsec_template_delete_all(); ipsec_enable_flag(1); ipsec_init_nat_traversal(); init_rnd_pool(); init_states(); init_connections();//添加到elist链中phase2 pending timer init_crypto(); ipsec_drv_rsa_para_init(); //初始化使用硬件模幂运算时的固定参数 load_oswcrypto(); init_demux(); /* loading X.509 CA certificates */ load_authcerts("CA cert", "/config/sys/certificate/cacerts", AUTH_CA); /* loading X.509 CRLs */ load_crls(); fflush(stderr); fflush(stdout); IPSEC_dbg("listening for IKE messages"); init_ws_ctl_socket(); /*初始化dpdns守护进程*/ ipsec_dpdns_init_helper(); /*读取DPVPN相关配置并初始化*/ //ipsec_dpvpn_init_cfg(); /*该操作放在操作数据库之后的主进程处理不能再数据操作*/ sqlite3_clear_buffer_ex(); /*初始化子进程*/ ipsec_child_init_helpers(); ipsec_main_call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char **argv) { #if 0 NSS_NoDB_Init("."); if (!test_aes_cbc(&algo_aes_cbc)) { printf("aes-cbc failed\n"); } if (!test_camellia_cbc(&algo_camellia_cbc)) { printf("camellia-cbc failed\n"); } if (!test_aes_ctr(&algo_aes_ctr)) { printf("aes-ctr failed\n"); } exit(0); #endif int lockfd; /* * We read the intentions for how to log from command line options * and the config file. Then we prepare to be able to log, but until * then log to stderr (better then nothing). Once we are ready to * actually do loggin according to the methods desired, we set the * variables for those methods */ bool log_to_stderr_desired = FALSE; bool log_to_file_desired = FALSE; { int i; /* MUST BE BEFORE ANY allocs */ for (i = 1; i < argc; ++i) { if (streq(argv[i], "--leak-detective")) leak_detective = TRUE; } } pluto_name = argv[0]; coredir = clone_str("/var/run/pluto", "coredir in main()"); pluto_vendorid = clone_str(ipsec_version_vendorid(), "vendorid in main()"); unsigned int keep_alive = 0; /* Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; libreswan_passert_fail = passert_fail; /* handle arguments */ for (;; ) { /* * Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int longindex = -1; int c = getopt_long(argc, argv, "", long_opts, &longindex); const char *optname = NULL; err_t ugh = NULL; /* complaint from case */ unsigned long u = 0; /* scratch for case */ if (longindex != -1) { const char *optmeta; optname = long_opts[longindex].name; optmeta = optname + strlen(optname) + 1; /* after '\0' */ switch (optmeta[0]) { case '_': libreswan_log("warning: option \"--%s\" with '_' in its name is obsolete; use '-'", optname); break; case '>': libreswan_log("warning: option \"--%s\" is obsolete; use \"--%s\"", optname, optmeta + 1); break; case '!': libreswan_log("warning: option \"--%s\" is obsolete; ignored", optname); continue; /* ignore it! */ } } /* Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* * Long option already handled by getopt_long. * Not currently used since we always set flag to NULL. */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ invocation_fail(NULL); break; case 'h': /* --help */ usage(); break; /* not actually reached */ case 'X': /* --leak-detective */ /* * This flag was already processed at the start of main() * because leak_detective must be immutable from before * the first alloc(). * If this option is specified, we must have already * set it at the start of main(), so assert it. */ passert(leak_detective); continue; case 'C': /* --coredir */ pfree(coredir); coredir = clone_str(optarg, "coredir via getopt"); continue; case 'V': /* --vendorid */ pfree(pluto_vendorid); coredir = clone_str(optarg, "pluto_vendorid via getopt"); continue; case 'S': /* --statsdir */ pfreeany(pluto_stats_binary); pluto_stats_binary = clone_str(optarg, "statsbin"); continue; case 'v': /* --version */ printf("%s%s\n", ipsec_version_string(), compile_time_interop_options); /* not exit_pluto because we are not initialized yet */ exit(0); break; /* not actually reached */ case 'j': /* --nhelpers */ if (streq(optarg, "-1")) { nhelpers = -1; } else { ugh = ttoulb(optarg, 0, 10, 1000, &u); if (ugh != NULL) break; nhelpers = u; } continue; case 'c': /* --seedbits */ pluto_nss_seedbits = atoi(optarg); if (pluto_nss_seedbits == 0) { printf("pluto: seedbits must be an integer > 0"); /* not exit_pluto because we are not initialized yet */ exit(PLUTO_EXIT_NSS_FAIL); } continue; #ifdef HAVE_LABELED_IPSEC case 'w': /* --secctx-attr-type */ ugh = ttoulb(optarg, 0, 0, 0xFFFF, &u); if (ugh != NULL) break; if (u != SECCTX && u != ECN_TUNNEL_or_old_SECCTX) { ugh = "must be a positive 32001 (default) or 10 (for backward compatibility)"; break; } secctx_attr_type = u; continue; #endif case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'g': /* --logfile */ pluto_log_file = optarg; log_to_file_desired = TRUE; continue; case 't': /* --log-no-time */ log_with_timestamp = FALSE; continue; case '7': /* --log-no-append */ log_append = FALSE; continue; case '8': /* --drop-oppo-null */ pluto_drop_oppo_null = TRUE; continue; case '9': /* --expire-bare-shunt <interval> */ ugh = ttoulb(optarg, 0, 10, 1000, &u); if (ugh != NULL) break; bare_shunt_interval = u; continue; case 'k': /* --use-klips */ kern_interface = USE_KLIPS; continue; case 'L': /* --listen ip_addr */ { ip_address lip; err_t e = ttoaddr(optarg, 0, AF_UNSPEC, &lip); if (e != NULL) { /* *??? should we continue on failure? * If not, use ugh mechanism. */ libreswan_log( "invalid listen argument ignored: %s\n", e); } else { pluto_listen = clone_str(optarg, "pluto_listen"); libreswan_log( "bind() will be filtered for %s\n", pluto_listen); } } continue; case 'M': /* --use-mast */ kern_interface = USE_MASTKLIPS; continue; case 'F': /* --use-bsdkame */ kern_interface = USE_BSDKAME; continue; case 'K': /* --use-netkey */ kern_interface = USE_NETKEY; continue; case 'n': /* --use-nostack */ kern_interface = NO_KERNEL; continue; case 'D': /* --force-busy */ pluto_ddos_mode = DDOS_FORCE_BUSY; continue; case 'U': /* --force-unlimited */ pluto_ddos_mode = DDOS_FORCE_UNLIMITED; continue; case 'Z': /* --curl-iface */ curl_iface = optarg; continue; case 'I': /* --curl-timeout */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u <= 0) { ugh = "must not be < 1"; break; } curl_timeout = u; continue; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue; case 'o': strict_ocsp_policy = TRUE; continue; case 'O': ocsp_enable = TRUE; continue; case 'Y': ocsp_default_uri = optarg; continue; case 'J': ocsp_trust_name = optarg; continue; case 'T': /* --ocsp_timeout <seconds> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } ocsp_timeout = u; continue; case 'x': /* --crlcheckinterval <seconds> */ ugh = ttoulb(optarg, 0, 10, TIME_T_MAX, &u); if (ugh != NULL) break; crl_check_interval = deltatime(u); continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname|ifaddr> */ if (!use_interface(optarg)) { ugh = "too many --interface specifications"; break; } continue; /* * This option does not really work, as this is the "left" * site only, you also need --to --ikeport again later on * It will result in: yourport -> 500, still not bypassing * filters */ case 'p': /* --ikeport <portnumber> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } pluto_port = u; continue; case 'q': /* --natikeport <portnumber> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } pluto_nat_port = u; continue; case 'b': /* --ctlbase <path> */ /* * ??? work to be done here: * * snprintf returns the required space if there * isn't enough, not -1. * -1 indicates another kind of error. * * This appears to be the only place where the * ctlbase value is used yet it is set elsewhere. * (This isn't clear -- it may be OK.) */ ctlbase = optarg; if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path), "%s%s", ctlbase, CTL_SUFFIX) == -1) { ugh = "<path>" CTL_SUFFIX " too long for sun_path"; break; } if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path), "%s%s", ctlbase, INFO_SUFFIX) == -1) { ugh = "<path>" INFO_SUFFIX " too long for sun_path"; break; } if (snprintf(pluto_lock, sizeof(pluto_lock), "%s%s", ctlbase, LOCK_SUFFIX) == -1) { ugh = "<path>" LOCK_SUFFIX " must fit"; break; } continue; case 's': /* --secretsfile <secrets-file> */ lsw_conf_secretsfile(optarg); continue; case 'f': /* --ipsecdir <ipsec-dir> */ lsw_init_ipsecdir(optarg); continue; case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': /* --perpeerlog */ log_to_perpeer = TRUE; continue; case '2': /* --keep-alive <delay_secs> */ ugh = ttoulb(optarg, 0, 10, secs_per_day, &u); if (ugh != NULL) break; keep_alive = u; continue; case '5': /* --debug-nat-t */ base_debugging |= DBG_NATT; continue; case '6': /* --virtual-private */ virtual_private = optarg; continue; case 'z': /* --config */ { /* * Config struct to variables mapper. This will * overwrite all previously set options. Keep this * in the same order as long_opts[] is. */ struct starter_config *cfg = read_cfg_file(optarg); /* leak */ set_cfg_string(&pluto_log_file, cfg->setup.strings[KSF_PLUTOSTDERRLOG]); if (pluto_log_file != NULL) log_to_syslog = FALSE; /* plutofork= no longer supported via config file */ log_with_timestamp = cfg->setup.options[KBF_PLUTOSTDERRLOGTIME]; log_append = cfg->setup.options[KBF_PLUTOSTDERRLOGAPPEND]; pluto_drop_oppo_null = cfg->setup.options[KBF_DROP_OPPO_NULL]; pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE]; if (cfg->setup.options[KBF_FORCEBUSY]) { /* force-busy is obsoleted, translate to ddos-mode= */ pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE] = DDOS_FORCE_BUSY; } /* ddos-ike-threshold and max-halfopen-ike */ pluto_ddos_threshold = cfg->setup.options[KBF_DDOS_IKE_THRESHOLD]; pluto_max_halfopen = cfg->setup.options[KBF_MAX_HALFOPEN_IKE]; strict_crl_policy = cfg->setup.options[KBF_STRICTCRLPOLICY]; pluto_shunt_lifetime = deltatime(cfg->setup.options[KBF_SHUNTLIFETIME]); strict_ocsp_policy = cfg->setup.options[KBF_STRICTOCSPPOLICY]; ocsp_enable = cfg->setup.options[KBF_OCSPENABLE]; set_cfg_string(&ocsp_default_uri, cfg->setup.strings[KSF_OCSPURI]); ocsp_timeout = cfg->setup.options[KBF_OCSPTIMEOUT]; set_cfg_string(&ocsp_trust_name, cfg->setup.strings[KSF_OCSPTRUSTNAME]); crl_check_interval = deltatime( cfg->setup.options[KBF_CRLCHECKINTERVAL]); uniqueIDs = cfg->setup.options[KBF_UNIQUEIDS]; /* * We don't check interfaces= here because that part * has been dealt with in _stackmanager before we * started */ set_cfg_string(&pluto_listen, cfg->setup.strings[KSF_LISTEN]); /* --ikeport */ pluto_port = cfg->setup.options[KBF_IKEPORT]; /* --nflog-all */ /* only causes nflog nmber to show in ipsec status */ pluto_nflog_group = cfg->setup.options[KBF_NFLOG_ALL]; /* only causes nflog nmber to show in ipsec status */ pluto_xfrmlifetime = cfg->setup.options[KBF_XFRMLIFETIME]; /* no config option: ctlbase */ /* --secrets */ if (cfg->setup.strings[KSF_SECRETSFILE] && *cfg->setup.strings[KSF_SECRETSFILE]) { lsw_conf_secretsfile(cfg->setup.strings[KSF_SECRETSFILE]); } if (cfg->setup.strings[KSF_IPSECDIR] != NULL && *cfg->setup.strings[KSF_IPSECDIR] != 0) { /* --ipsecdir */ lsw_init_ipsecdir(cfg->setup.strings[KSF_IPSECDIR]); } /* --perpeerlog */ log_to_perpeer = cfg->setup.options[KBF_PERPEERLOG]; if (log_to_perpeer) { /* --perpeerlogbase */ if (cfg->setup.strings[KSF_PERPEERDIR]) { set_cfg_string(&base_perpeer_logdir, cfg->setup.strings[KSF_PERPEERDIR]); } else { base_perpeer_logdir = clone_str("/var/log/pluto/", "perpeer_logdir"); } } if (cfg->setup.strings[KSF_CURLIFACE]) { pfreeany(curl_iface); /* curl-iface= */ curl_iface = clone_str(cfg->setup.strings[KSF_CURLIFACE], "curl-iface= via --config"); } if (cfg->setup.options[KBF_CURLTIMEOUT]) curl_timeout = cfg->setup.options[KBF_CURLTIMEOUT]; if (cfg->setup.strings[KSF_DUMPDIR]) { pfree(coredir); /* dumpdir= */ coredir = clone_str(cfg->setup.strings[KSF_DUMPDIR], "coredir via --config"); } /* --vendorid */ if (cfg->setup.strings[KSF_MYVENDORID]) { pfree(pluto_vendorid); pluto_vendorid = clone_str(cfg->setup.strings[KSF_MYVENDORID], "pluto_vendorid via --config"); } /* no config option: pluto_adns_option */ if (cfg->setup.strings[KSF_STATSBINARY] != NULL) { if (access(cfg->setup.strings[KSF_STATSBINARY], X_OK) == 0) { pfreeany(pluto_stats_binary); /* statsbin= */ pluto_stats_binary = clone_str(cfg->setup.strings[KSF_STATSBINARY], "statsbin via --config"); libreswan_log("statsbinary set to %s", pluto_stats_binary); } else { libreswan_log("statsbinary= '%s' ignored - file does not exist or is not executable", pluto_stats_binary); } } pluto_nss_seedbits = cfg->setup.options[KBF_SEEDBITS]; pluto_nat_port = cfg->setup.options[KBF_NATIKEPORT]; keep_alive = cfg->setup.options[KBF_KEEPALIVE]; set_cfg_string(&virtual_private, cfg->setup.strings[KSF_VIRTUALPRIVATE]); nhelpers = cfg->setup.options[KBF_NHELPERS]; #ifdef HAVE_LABELED_IPSEC secctx_attr_type = cfg->setup.options[KBF_SECCTX]; #endif base_debugging = cfg->setup.options[KBF_PLUTODEBUG]; char *protostack = cfg->setup.strings[KSF_PROTOSTACK]; if (protostack == NULL || *protostack == '\0') { kern_interface = USE_NETKEY; } else if (streq(protostack, "none")) { kern_interface = NO_KERNEL; } else if (streq(protostack, "auto")) { libreswan_log( "The option protostack=auto is obsoleted, falling back to protostack=netkey\n"); kern_interface = USE_NETKEY; } else if (streq(protostack, "klips")) { kern_interface = USE_KLIPS; } else if (streq(protostack, "mast")) { kern_interface = USE_MASTKLIPS; } else if (streq(protostack, "netkey") || streq(protostack, "native")) { kern_interface = USE_NETKEY; } else if (streq(protostack, "bsd") || streq(protostack, "kame") || streq(protostack, "bsdkame")) { kern_interface = USE_BSDKAME; } else if (streq(protostack, "win2k")) { kern_interface = USE_WIN2K; } confread_free(cfg); continue; } default: if (DBG_OFFSET <= c && c < DBG_OFFSET + IMPAIR_roof_IX) { base_debugging |= LELEM(c - DBG_OFFSET); continue; } bad_case(c); } /* if ugh is set, bail with diagnostic */ if (ugh != NULL) { char mess[200]; if (longindex == -1) { snprintf(mess, sizeof(mess), "unknown option: %s", ugh); } else if (optarg == NULL) { snprintf(mess, sizeof(mess), "--%s option: %s", optname, ugh); } else { snprintf(mess, sizeof(mess), "--%s \"%s\" option: %s", optname, optarg, ugh); } invocation_fail(mess); } break; } if (optind != argc) invocation_fail("unexpected argument"); reset_debugging(); if (chdir(coredir) == -1) { int e = errno; libreswan_log("pluto: warning: chdir(\"%s\") to dumpdir failed (%d: %s)", coredir, e, strerror(e)); } oco = lsw_init_options(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired || log_to_file_desired) log_to_syslog = FALSE; if (!log_to_stderr_desired) log_to_stderr = FALSE; #if 0 if (kernel_ops->set_debug != NULL) (*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log); #endif /* * create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: FATAL: %s", ugh); exit_pluto(PLUTO_EXIT_SOCKET_FAIL); } } /* If not suppressed, do daemon fork */ if (fork_desired) { #if USE_DAEMON if (daemon(TRUE, TRUE) < 0) { fprintf(stderr, "pluto: FATAL: daemon failed (%d %s)\n", errno, strerror(errno)); exit_pluto(PLUTO_EXIT_FORK_FAIL); } /* * Parent just exits, so need to fill in our own PID * file. This is racy, since the file won't be * created until after the parent has exited. * * Since "ipsec start" invokes pluto with --nofork, it * is probably safer to leave this feature disabled * then implement it using the daemon call. */ (void) fill_lock(lockfd, getpid()); #elif USE_FORK { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: FATAL: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(PLUTO_EXIT_FORK_FAIL); } if (pid != 0) { /* * parent: die, after filling PID into lock * file. * must not use exit_pluto: lock would be * removed! */ exit(fill_lock(lockfd, pid) ? 0 : 1); } } #else fprintf(stderr, "pluto: FATAL: fork/daemon not supported\n"); exit_pluto(PLUTO_EXIT_FORK_FAIL); #endif if (setsid() < 0) { int e = errno; fprintf(stderr, "FATAL: setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(PLUTO_EXIT_FAIL); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); if (isatty(fileno(stdout))) { fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } } /* * Close everything but ctl_fd and (if needed) stderr. * There is some danger that a library that we don't know * about is using some fd that we don't know about. * I guess we'll soon find out. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ if ((!log_to_stderr || i != 2) && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) lsw_abort(); if (dup2(0, 1) != 1) lsw_abort(); if (!log_to_stderr && dup2(0, 2) != 2) lsw_abort(); } init_constants(); init_pluto_constants(); pluto_init_log(); if (!pluto_init_nss(oco->nssdb)) { loglog(RC_LOG_SERIOUS, "FATAL: NSS initialization failure"); exit_pluto(PLUTO_EXIT_NSS_FAIL); } libreswan_log("NSS crypto library initialized"); if (ocsp_enable) { if (!init_nss_ocsp(ocsp_default_uri, ocsp_trust_name, ocsp_timeout, strict_ocsp_policy)) { loglog(RC_LOG_SERIOUS, "Initializing NSS OCSP failed"); exit_pluto(PLUTO_EXIT_NSS_FAIL); } else { libreswan_log("NSS OCSP Enabled"); } } #ifdef HAVE_LIBCAP_NG /* * Drop capabilities - this generates a false positive valgrind warning * See: http://marc.info/?l=linux-security-module&m=125895232029657 * * We drop these after creating the pluto socket or else we can't * create a socket if the parent dir is non-root (eg openstack) */ capng_clear(CAPNG_SELECT_BOTH); capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW, CAP_IPC_LOCK, CAP_AUDIT_WRITE, /* for google authenticator pam */ CAP_SETGID, CAP_SETUID, CAP_DAC_READ_SEARCH, -1); /* * We need to retain some capabilities for our children (updown): * CAP_NET_ADMIN to change routes * CAP_NET_RAW for iptables -t mangle * CAP_DAC_READ_SEARCH for pam / google authenticator */ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, CAP_NET_RAW, CAP_DAC_READ_SEARCH, -1); capng_apply(CAPNG_SELECT_BOTH); libreswan_log("libcap-ng support [enabled]"); #else libreswan_log("libcap-ng support [disabled]"); #endif #ifdef FIPS_CHECK libreswan_log("FIPS HMAC integrity support [enabled]"); /* * FIPS mode requires two conditions to be true: * - FIPS Kernel mode: fips=1 kernel boot parameter * - FIPS Product mode: See FIPSPRODUCTCHECK in Makefile.inc * (in RHEL/Fedora, dracut-fips installs $FIPSPRODUCTCHECK) * * When FIPS mode, abort on self-check hmac failure. Otherwise, complain */ { if (DBGP(IMPAIR_FORCE_FIPS)) { libreswan_log("Forcing FIPS checks to true to emulate FIPS mode"); lsw_set_fips_mode(LSW_FIPS_ON); } enum lsw_fips_mode pluto_fips_mode = lsw_get_fips_mode(); bool nss_fips_mode = PK11_IsFIPS(); /* * Now verify the consequences. Always run the tests * as combinations such as NSS in fips mode but as out * of it could be bad. */ switch (pluto_fips_mode) { case LSW_FIPS_UNKNOWN: loglog(RC_LOG_SERIOUS, "ABORT: pluto FIPS mode could not be determined"); exit_pluto(PLUTO_EXIT_FIPS_FAIL); break; case LSW_FIPS_ON: libreswan_log("FIPS mode enabled for pluto daemon"); if (nss_fips_mode) { libreswan_log("NSS library is running in FIPS mode"); } else { loglog(RC_LOG_SERIOUS, "ABORT: pluto in FIPS mode but NSS library is not"); exit_pluto(PLUTO_EXIT_FIPS_FAIL); } break; case LSW_FIPS_OFF: libreswan_log("FIPS mode disabled for pluto daemon"); if (nss_fips_mode) { loglog(RC_LOG_SERIOUS, "Warning: NSS library is running in FIPS mode"); } break; case LSW_FIPS_UNSET: default: bad_case(pluto_fips_mode); } /* always run hmac check so we can print diagnostic */ bool fips_files = FIPSCHECK_verify_files(fips_package_files); if (fips_files) { libreswan_log("FIPS HMAC integrity verification self-test passed"); } else { loglog(RC_LOG_SERIOUS, "FIPS HMAC integrity verification self-test FAILED"); } if (pluto_fips_mode == LSW_FIPS_ON && !fips_files) { exit_pluto(PLUTO_EXIT_FIPS_FAIL); } } #else libreswan_log("FIPS HMAC integrity support [disabled]"); #endif #ifdef USE_LINUX_AUDIT linux_audit_init(); #else libreswan_log("Linux audit support [disabled]"); #endif { const char *vc = ipsec_version_code(); libreswan_log("Starting Pluto (Libreswan Version %s%s) pid:%u", vc, compile_time_interop_options, getpid()); } libreswan_log("core dump dir: %s", coredir); if (oco->secretsfile && *oco->secretsfile) libreswan_log("secrets file: %s", oco->secretsfile); libreswan_log(leak_detective ? "leak-detective enabled" : "leak-detective disabled"); /* Check for SAREF support */ #ifdef KLIPS_MAST #include <ipsec_saref.h> { int e, sk, saref; saref = 1; errno = 0; sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_REFINFO, &saref, sizeof(saref)); if (e == -1 ) libreswan_log("SAref support [disabled]: %s", strerror(errno)); else libreswan_log("SAref support [enabled]"); errno = 0; e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref)); if (e == -1 ) libreswan_log("SAbind support [disabled]: %s", strerror(errno)); else libreswan_log("SAbind support [enabled]"); close(sk); } #endif libreswan_log("NSS crypto [enabled]"); #ifdef XAUTH_HAVE_PAM libreswan_log("XAUTH PAM support [enabled]"); #else libreswan_log("XAUTH PAM support [disabled]"); #endif /* Log various impair-* functions if they were enabled */ if (DBGP(IMPAIR_BUST_MI2)) libreswan_log("Warning: IMPAIR_BUST_MI2 enabled"); if (DBGP(IMPAIR_BUST_MR2)) libreswan_log("Warning: IMPAIR_BUST_MR2 enabled"); if (DBGP(IMPAIR_SA_CREATION)) libreswan_log("Warning: IMPAIR_SA_CREATION enabled"); if (DBGP(IMPAIR_JACOB_TWO_TWO)) libreswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled"); if (DBGP(IMPAIR_DIE_ONINFO)) libreswan_log("Warning: IMPAIR_DIE_ONINFO enabled"); if (DBGP(IMPAIR_MAJOR_VERSION_BUMP)) libreswan_log("Warning: IMPAIR_MAJOR_VERSION_BUMP enabled"); if (DBGP(IMPAIR_MINOR_VERSION_BUMP)) libreswan_log("Warning: IMPAIR_MINOR_VERSION_BUMP enabled"); if (DBGP(IMPAIR_RETRANSMITS)) libreswan_log("Warning: IMPAIR_RETRANSMITS enabled"); if (DBGP(IMPAIR_SEND_BOGUS_ISAKMP_FLAG)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_ISAKMP_FLAG enabled"); if (DBGP(IMPAIR_SEND_BOGUS_PAYLOAD_FLAG)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_PAYLOAD_FLAG enabled"); if (DBGP(IMPAIR_SEND_IKEv2_KE)) libreswan_log("Warning: IMPAIR_SEND_IKEv2_KE enabled"); if (DBGP(IMPAIR_SEND_KEY_SIZE_CHECK)) libreswan_log("Warning: IMPAIR_SEND_KEY_SIZE_CHECK enabled"); if (DBGP(IMPAIR_SEND_NO_DELETE)) libreswan_log("Warning: IMPAIR_SEND_NO_DELETE enabled"); if (DBGP(IMPAIR_FORCE_FIPS)) libreswan_log("Warning: IMPAIR_FORCE_FIPS enabled"); if (DBGP(IMPAIR_SEND_NO_IKEV2_AUTH)) libreswan_log("Warning: IMPAIR_SEND_NO_IKEV2_AUTH enabled"); if (DBGP(IMPAIR_SEND_ZERO_GX)) libreswan_log("Warning: IMPAIR_SEND_ZERO_GX enabled"); if (DBGP(IMPAIR_SEND_BOGUS_DCOOKIE)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_DCOOKIE enabled"); /* Initialize all of the various features */ init_nat_traversal(keep_alive); init_virtual_ip(virtual_private); /* obsoleted by nss code init_rnd_pool(); */ init_event_base(); init_secret(); init_states(); init_connections(); init_crypto(); init_crypto_helpers(nhelpers); init_demux(); init_kernel(); init_id(); init_vendorid(); #if defined(LIBCURL) || defined(LDAP_VER) init_fetch(); #endif load_crls(); #ifdef HAVE_LABELED_IPSEC init_avc(); #endif daily_log_event(); #ifdef USE_SYSTEMD_WATCHDOG pluto_sd_init(); #endif call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char *argv[]) { int n, l, complete_type = 0, not_allowed = 0, argv_mode = 0; #ifdef USING_GLFTPD int gnum = 0, unum = 0; char myflags[20]; #endif char *ext, exec[4096], *complete_bar = 0, *inc_point[2]; unsigned int crc; struct stat fileinfo; uid_t f_uid; gid_t f_gid; double temp_time = 0; DIR *dir, *parent; struct dirent *dp; long loc; time_t timenow; #if (test_for_password || extract_nfo || zip_clean) off_t tempstream; #endif short rescan_quick = rescan_default_to_quick; char one_name[NAME_MAX]; char *temp_p = NULL; int chdir_allowed = 0, argnum = 0; GLOBAL g; #if (enable_rescan_script) char target[PATH_MAX+NAME_MAX]; #endif #if ( program_uid > 0 ) setegid(program_gid); seteuid(program_uid); #endif umask(0666 & 000); d_log("rescan: PZS-NG (rescan v2) %s debug log.\n", ng_version); d_log("rescan: Rescan executed by: (uid/gid) %d/%d\n", geteuid(), getegid()); #ifdef _ALT_MAX d_log("rescan: PATH_MAX not found - using predefined settings! Please report to the devs!\n"); #endif d_log("rescan: Allocating memory for variables\n"); g.ui = ng_realloc2(g.ui, sizeof(*g.ui) * 30, 1, 1, 1); g.gi = ng_realloc2(g.gi, sizeof(*g.gi) * 30, 1, 1, 1); bzero(one_name, NAME_MAX); #ifdef USING_GLFTPD if (getenv("FLAGS")) { strlcpy(myflags, getenv("FLAGS"), sizeof(myflags)); n = strlen(myflags); while (n > 0) { --n; l = strlen(rescan_chdir_flags); while(l > 0) { --l; if (myflags[n] == rescan_chdir_flags[l]) chdir_allowed = 1; } } } if (!geteuid()) chdir_allowed = 1; #endif /* With glftpd we can use env vars, rest of the world: commandline. */ #ifndef USING_GLFTPD if (argc < 7) { print_syntax(chdir_allowed); ng_free(g.ui); ng_free(g.gi); return 0; } argnum = 6; if (chdir(argv[5]) != 0) { printf("Could not chdir to <cwd = '%s'>, ftpd agnostic mode: %s\n", argv[5], strerror(errno)); d_log("rescan: Could not chdir to <cwd = '%s'>, ftpd agnostic mode: %s\n", argv[5], strerror(errno)); ng_free(g.ui); ng_free(g.gi); return 1; } #else argnum = 1; #endif while ((argnum < argc) && argc > 1) { if (!strncasecmp(argv[argnum], "--quick", 7)) rescan_quick = TRUE; else if (!strncasecmp(argv[argnum], "--normal", 8)) rescan_quick = FALSE; else if (!strncasecmp(argv[argnum], "--dir=", 6) && (strlen(argv[argnum]) > 7) && chdir_allowed) { temp_p = argv[argnum] + 6; if ((!matchpath(nocheck_dirs, temp_p)) && (matchpath(zip_dirs, temp_p) || matchpath(sfv_dirs, temp_p)) && !matchpath(group_dirs, temp_p)) { if (chdir(temp_p)) { d_log("rescan: Failed to chdir() to %s : %s\n", temp_p, strerror(errno)); not_allowed = 1; } } else { printf("Not allowed to chdir() to %s\n", temp_p); ng_free(g.ui); ng_free(g.gi); return 1; } printf("PZS-NG Rescan %s: Rescanning %s\n", ng_version, temp_p); argv_mode = 1; } else if (!strncasecmp(argv[argnum], "--chroot=", 9) && (strlen(argv[argnum]) > 10) && chdir_allowed) { if (temp_p == NULL) { temp_p = argv[argnum] + 9; if (chroot(temp_p) == -1) { d_log("rescan: Failed to chroot() to %s : %s\n", temp_p, strerror(errno)); not_allowed = 1; } } else { temp_p = argv[argnum] + 9; printf("Not allowed to chroot() to %s\n", temp_p); ng_free(g.ui); ng_free(g.gi); return 1; } printf("PZS-NG Rescan %s: Chroot'ing to %s\n", ng_version, temp_p); argv_mode = 1; } else if (!strncasecmp(argv[argnum], "--help", 6) || !strncasecmp(argv[argnum], "/?", 2) || !strncasecmp(argv[argnum], "--?", 3)) { print_syntax(chdir_allowed); ng_free(g.ui); ng_free(g.gi); return 0; } else { strlcpy(one_name, argv[argnum], sizeof(one_name)); rescan_quick = FALSE; printf("PZS-NG Rescan %s: Rescanning in FILE mode\n", ng_version); if (one_name[strlen(one_name) - 1] == '*') { one_name[strlen(one_name) - 1] = '\0'; } else if (!fileexists(one_name)) { d_log("PZS-NG Rescan: No file named '%s' exists.\n", one_name); one_name[0] = '\0'; not_allowed = 1; } argv_mode = 1; } argnum++; } if (one_name[0] == '\0') { if (rescan_quick == TRUE) { printf("PZS-NG Rescan %s: Rescanning in QUICK mode.\n", ng_version); } else { printf("PZS-NG Rescan %s: Rescanning in NORMAL mode.\n", ng_version); } } printf("PZS-NG Rescan %s: Use --help for options.\n\n", ng_version); if (not_allowed) { ng_free(g.ui); ng_free(g.gi); return 1; } if (!getcwd(g.l.path, PATH_MAX)) { d_log("rescan: getcwd() failed: %s\n", strerror(errno)); } if (subcomp(g.l.path, g.l.basepath) && (g.l.basepath[0] == '\0')) strlcpy(g.l.basepath, g.l.path, sizeof(g.l.basepath)); if (strncmp(g.l.path, g.l.basepath, PATH_MAX)) d_log("rescan: We are in subdir of %s\n", g.l.basepath); strlcpy(g.v.misc.current_path, g.l.path, sizeof(g.v.misc.current_path)); strlcpy(g.v.misc.basepath, g.l.basepath, sizeof(g.v.misc.basepath)); if ((matchpath(nocheck_dirs, g.l.path) && !rescan_nocheck_dirs_allowed) || (matchpath(group_dirs, g.l.path) && argv_mode) || (!matchpath(nocheck_dirs, g.l.path) && !matchpath(zip_dirs, g.l.path) && !matchpath(sfv_dirs, g.l.path) && !matchpath(group_dirs, g.l.path)) || insampledir(g.l.path)) { d_log("rescan: Dir matched with nocheck_dirs/sample_list, or is not in the zip/sfv/group-dirs.\n"); d_log("rescan: Freeing memory, and exiting.\n"); printf("Notice: Unable to rescan this dir - check config.\n\n"); ng_free(g.ui); ng_free(g.gi); return 0; } g.v.misc.slowest_user[0] = ULONG_MAX; bzero(&g.v.total, sizeof(struct race_total)); g.v.misc.fastest_user[0] = 0; g.v.misc.release_type = RTYPE_NULL; g.v.misc.write_log = 0; #ifdef USING_GLFTPD if (getenv("SECTION") == NULL) { sprintf(g.v.sectionname, "DEFAULT"); } else { snprintf(g.v.sectionname, sizeof(g.v.sectionname), "%s", getenv("SECTION")); } #else snprintf(g.v.sectionname, sizeof(g.v.sectionname), argv[4]); #endif g.l.length_path = (int)strlen(g.l.path); g.l.length_zipdatadir = sizeof(storage); n = g.l.length_path + g.l.length_zipdatadir + 11; g.l.race = ng_realloc2(g.l.race, n, 1, 1, 1); g.l.sfv = ng_realloc2(g.l.sfv, n - 1, 1, 1, 1); g.l.sfvbackup = ng_realloc2(g.l.sfvbackup, n + 1, 1, 1, 1); g.l.leader = ng_realloc2(g.l.leader, n - 2, 1, 1, 1); g.l.sfv_incomplete = 0; getrelname(&g); #ifdef USING_GLFTPD gnum = buffer_groups(GROUPFILE, 0); unum = buffer_users(PASSWDFILE, 0); #endif sprintf(g.l.sfv, storage "/%s/sfvdata", g.l.path); sprintf(g.l.sfvbackup, storage "/%s/sfvbackup", g.l.path); sprintf(g.l.leader, storage "/%s/leader", g.l.path); sprintf(g.l.race, storage "/%s/racedata", g.l.path); d_log("rescan: Creating directory to store racedata in\n"); maketempdir(g.l.path); d_log("rescan: Locking release\n"); while (1) { if ((l = create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 3, 0))) { d_log("rescan: Failed to lock release.\n"); if (l == 1) { d_log("rescan: version mismatch. Exiting.\n"); printf("Error. You need to rm -fR ftp-data/pzs-ng/* before rescan will work.\n"); /* */ ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif exit(EXIT_FAILURE); } if (l == PROGTYPE_POSTDEL) { n = (signed int)g.v.data_incrementor; d_log("rescan: Detected postdel running - sleeping for one second.\n"); if (!create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 0, g.v.data_queue)) break; usleep(1000000); if (!create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 0, g.v.data_queue)) break; if ( n == (signed int)g.v.data_incrementor) { d_log("rescan: Failed to get lock. Forcing unlock.\n"); if (create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 2, g.v.data_queue)) { d_log("rescan: Failed to force a lock.\n"); d_log("rescan: Exiting with error.\n"); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif exit(EXIT_FAILURE); } break; } } else { for (l = 0; l <= max_seconds_wait_for_lock * 10; ++l) { d_log("rescan: sleeping for .1 second before trying to get a lock (queue: %d).\n", g.v.data_queue); usleep(100000); if (!create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 0, g.v.data_queue)) break; } if (l >= max_seconds_wait_for_lock * 10) { d_log("rescan: Failed to get lock. Will not force unlock.\n"); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif exit(EXIT_FAILURE); } } } usleep(10000); if (update_lock(&g.v, 1, 0) != -1) break; } move_progress_bar(1, &g.v, g.ui, g.gi); if (g.l.incomplete) unlink(g.l.incomplete); if (del_completebar) removecomplete(); dir = opendir("."); parent = opendir(".."); if (!((rescan_quick && findfileext(dir, ".sfv")) || *one_name)) { if (g.l.sfv) unlink(g.l.sfv); if (g.l.race) unlink(g.l.race); } printf("Rescanning files...\n"); if (findfileext(dir, ".zip")) { if (!fileexists(unzip_bin)) { printf("rescan: ERROR! Not able to check zip-files - %s does not exist!\n", unzip_bin); closedir(dir); closedir(parent); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif remove_lock(&g.v); exit(EXIT_FAILURE); } else { crc = 0; rewinddir(dir); timenow = time(NULL); while ((dp = readdir(dir))) { ext = find_last_of(dp->d_name, "."); if (*ext == '.') ext++; if (!strcasecmp(ext, "zip")) { stat(dp->d_name, &fileinfo); f_uid = fileinfo.st_uid; f_gid = fileinfo.st_gid; if ((timenow == fileinfo.st_ctime) && (fileinfo.st_mode & 0111)) { d_log("rescan.c: Seems this file (%s) is in the process of being uploaded. Ignoring for now.\n", dp->d_name); continue; } #ifdef USING_GLFTPD strlcpy(g.v.user.name, get_u_name(f_uid), sizeof(g.v.user.name)); strlcpy(g.v.user.group, get_g_name(f_gid), sizeof(g.v.user.group)); #else strlcpy(g.v.user.name, argv[1], sizeof(g.v.user.name)); strlcpy(g.v.user.group, argv[2], sizeof(g.v.user.group)); #endif strlcpy(g.v.file.name, dp->d_name, sizeof(g.v.file.name)); g.v.file.speed = 2005 * 1024; g.v.file.size = fileinfo.st_size; g.v.total.start_time = 0; #if (test_for_password || extract_nfo) tempstream = telldir(dir); if ((!findfileextcount(dir, ".nfo") || findfileextcount(dir, ".zip")) && !mkdir(".unzipped", 0777)) snprintf(exec, sizeof(exec), "%s -qqjo \"%s\" -d .unzipped 2>.delme", unzip_bin, g.v.file.name); else snprintf(exec, sizeof(exec), "%s -qqt \"%s\" 2>.delme", unzip_bin, g.v.file.name); seekdir(dir, tempstream); #else snprintf(exec, sizeof(exec), "%s -qqt \"%s\" 2>.delme", unzip_bin, g.v.file.name); #endif if (system(exec) == 0 || (allow_error2_in_unzip == TRUE && errno < 3 )) { writerace(g.l.race, &g.v, crc, F_CHECKED); } else { writerace(g.l.race, &g.v, crc, F_BAD); if (g.v.file.name) unlink(g.v.file.name); removedir(".unzipped"); continue; } #if (test_for_password || extract_nfo || zip_clean) tempstream = telldir(dir); if ((!findfileextcount(dir, ".nfo") || findfileextcount(dir, ".zip")) && check_zipfile(".unzipped", g.v.file.name, findfileextcount(dir, ".nfo"))) { d_log("rescan: File %s is password protected.\n", g.v.file.name); writerace(g.l.race, &g.v, crc, F_BAD); if (g.v.file.name) unlink(g.v.file.name); seekdir(dir, tempstream); continue; } seekdir(dir, tempstream); #endif if (!fileexists("file_id.diz")) { snprintf(exec, sizeof(exec), "%s -qqjnCLL \"%s\" file_id.diz 2>.delme", unzip_bin, g.v.file.name); if (execute(exec) != 0) { d_log("rescan: No file_id.diz found (#%d): %s\n", errno, strerror(errno)); } else { if (fileexists("file_id.diz.bad")) { loc = findfile(dir, "file_id.diz.bad"); seekdir(dir, loc); dp = readdir(dir); unlink(dp->d_name); } if (chmod("file_id.diz", 0666)) d_log("rescan: Failed to chmod %s: %s\n", "file_id.diz", strerror(errno)); } } } } if (fileexists(".delme")) unlink(".delme"); g.v.total.files = read_diz(); if (!g.v.total.files) { g.v.total.files = 1; unlink("file_id.diz"); } g.v.total.files_missing = g.v.total.files; readrace(g.l.race, &g.v, g.ui, g.gi); sortstats(&g.v, g.ui, g.gi); if (g.v.total.files_missing < 0) { g.v.total.files -= g.v.total.files_missing; g.v.total.files_missing = 0; } buffer_progress_bar(&g.v); if (g.v.total.files_missing == 0) { complete(&g, complete_type); createstatusbar(convert(&g.v, g.ui, g.gi, zip_completebar)); #if (chmod_completebar) if (!matchpath(group_dirs, g.l.path)) { if (chmod_each(convert(&g.v, g.ui, g.gi, zip_completebar), 0222)) d_log("rescan: Failed to chmod a statusbar: %s\n", strerror(errno)); } #endif } else { if (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs) { if (create_incomplete()) { d_log("rescan: create_incomplete() returned something\n"); } } move_progress_bar(0, &g.v, g.ui, g.gi); } if (g.l.nfo_incomplete) { if (findfileext(dir, ".nfo")) { d_log("rescan: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else if (matchpath(check_for_missing_nfo_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("rescan: Creating missing-nfo indicator %s.\n", g.l.nfo_incomplete); if (create_incomplete_nfo()) { d_log("rescan: create_incomplete_nfo() returned something\n"); } } else { if (findfileextparent(parent, ".nfo")) { d_log("rescan: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else { d_log("rescan: Creating missing-nfo indicator (base) %s.\n", g.l.nfo_incomplete); if (create_incomplete_nfo()) { d_log("rescan: create_incomplete_nfo() returned something\n"); } } } } } } } else if ((temp_p = findfileext(dir, ".sfv")) || (create_missing_sfv && file_count(dir))) { if (!temp_p && create_missing_sfv && file_count(dir)) { d_log("rescan: No sfv found - creating one.\n"); make_sfv(g.l.path); if (!(temp_p = findfileext(dir, ".sfv"))) { d_log("rescan: Freeing memory, removing lock and exiting.\n"); unlink(g.l.sfv); if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); unlink(g.l.race); closedir(dir); closedir(parent); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif remove_lock(&g.v); return 0; } } #if ( create_missing_sfv_link == TRUE ) d_log("rescan: Removing missing-sfv indicator (if any)\n"); unlink(g.l.sfv_incomplete); #endif strlcpy(g.v.file.name, temp_p, sizeof(g.v.file.name)); maketempdir(g.l.path); stat(g.v.file.name, &fileinfo); if (copysfv(g.v.file.name, g.l.sfv, &g.v)) { printf("Found invalid entries in SFV - Exiting.\n"); while ((dp = readdir(dir))) { ext = find_last_of(dp->d_name, "-"); if (!strcasecmp(ext, "-missing")) unlink(dp->d_name); } d_log("rescan: Freeing memory, removing lock and exiting\n"); unlink(g.l.sfv); if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); unlink(g.l.race); closedir(dir); closedir(parent); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif remove_lock(&g.v); return 0; } g.v.total.start_time = 0; rewinddir(dir); while ((dp = readdir(dir))) { if (*one_name && strncasecmp(one_name, dp->d_name, strlen(one_name))) continue; l = (int)strlen(dp->d_name); ext = find_last_of(dp->d_name, ".-"); if (*ext == '.') ext++; if (!update_lock(&g.v, 1, 0)) { d_log("rescan: Another process wants the lock - will comply and remove lock, then exit.\n"); closedir(dir); closedir(parent); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif remove_lock(&g.v); exit(EXIT_FAILURE); } if ( !strcomp(ignored_types, ext) && (!(strcomp(allowed_types, ext) && !matchpath(allowed_types_exemption_dirs, g.l.path))) && strcasecmp("sfv", ext) && strcasecmp("nfo", ext) && strcasecmp("bad", ext) && strcasecmp("-missing", ext) && strncmp(dp->d_name, ".", 1) ) { stat(dp->d_name, &fileinfo); if (S_ISDIR(fileinfo.st_mode)) continue; if (ignore_zero_sized_on_rescan && !fileinfo.st_size) continue; f_uid = fileinfo.st_uid; f_gid = fileinfo.st_gid; #ifdef USING_GLFTPD strlcpy(g.v.user.name, get_u_name(f_uid), sizeof(g.v.user.name)); strlcpy(g.v.user.group, get_g_name(f_gid), sizeof(g.v.user.group)); #else strlcpy(g.v.user.name, argv[1], sizeof(g.v.user.name)); strlcpy(g.v.user.group, argv[2], sizeof(g.v.user.group)); #endif strlcpy(g.v.file.name, dp->d_name, sizeof(g.v.file.name)); g.v.file.speed = 2005 * 1024; g.v.file.size = fileinfo.st_size; temp_time = fileinfo.st_mtime; if (g.v.total.start_time == 0) g.v.total.start_time = temp_time; else g.v.total.start_time = (g.v.total.start_time < temp_time ? g.v.total.start_time : temp_time); g.v.total.stop_time = (temp_time > g.v.total.stop_time ? temp_time : g.v.total.stop_time); /* Hide users in group_dirs */ if (matchpath(group_dirs, g.l.path) && (hide_group_uploaders == TRUE)) { d_log("rescan: Hiding user in group-dir:\n"); if ((int)strlen(hide_gname) > 0) { snprintf(g.v.user.group, sizeof(g.v.user.group), "%s", hide_gname); d_log("rescan: Changing groupname\n"); } if ((int)strlen(hide_uname) > 0) { snprintf(g.v.user.name, sizeof(g.v.user.name), "%s", hide_uname); d_log("rescan: Changing username\n"); } #if (show_users_in_group_dirs == FALSE) if ((int)strlen(hide_uname) == 0) { d_log("rescan: Making username = groupname\n"); snprintf(g.v.user.name, sizeof(g.v.user.name), "%s", g.v.user.group); } #endif } if (!rescan_quick || (g.l.race && !match_file(g.l.race, dp->d_name))) crc = calc_crc32(dp->d_name); else crc = 1; if (!S_ISDIR(fileinfo.st_mode)) { if (g.v.file.name) unlink_missing(g.v.file.name); if (l > 44) { if (crc == 1) printf("\nFile: %s CHECKED", dp->d_name + l - 44); else printf("\nFile: %s %.8x", dp->d_name + l - 44, crc); } else { if (crc == 1) printf("\nFile: %-44s CHECKED", dp->d_name); else printf("\nFile: %-44s %.8x", dp->d_name, crc); } } if(fflush(stdout)) d_log("rescan: ERROR: %s\n", strerror(errno)); if (!rescan_quick || (g.l.race && !match_file(g.l.race, dp->d_name)) || !fileexists(dp->d_name)) writerace(g.l.race, &g.v, crc, F_NOTCHECKED); } } printf("\n"); testfiles(&g.l, &g.v, 1); printf("\n"); readsfv(g.l.sfv, &g.v, 0); readrace(g.l.race, &g.v, g.ui, g.gi); sortstats(&g.v, g.ui, g.gi); buffer_progress_bar(&g.v); if (g.l.nfo_incomplete) { if (findfileext(dir, ".nfo")) { d_log("rescan: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else if (matchpath(check_for_missing_nfo_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("rescan: Creating missing-nfo indicator %s.\n", g.l.nfo_incomplete); if (create_incomplete_nfo()) { d_log("rescan: create_incomplete_nfo() returned something\n"); } } else { if (findfileextparent(parent, ".nfo")) { d_log("rescan: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else { d_log("rescan: Creating missing-nfo indicator (base) %s.\n", g.l.nfo_incomplete); /* This is not pretty, but should be functional. */ if ((inc_point[0] = find_last_of(g.l.path, "/")) != g.l.path) *inc_point[0] = '\0'; if ((inc_point[1] = find_last_of(g.v.misc.release_name, "/")) != g.v.misc.release_name) *inc_point[1] = '\0'; if (create_incomplete_nfo()) { d_log("rescan: create_incomplete_nfo() returned something\n"); } if (*inc_point[0] == '\0') *inc_point[0] = '/'; if (*inc_point[1] == '\0') *inc_point[1] = '/'; } } } } #if (create_missing_sample_link) if (g.l.sample_incomplete) { if (findfileextsub(dir) || matchpartialdirname(missing_sample_check_ignore_list, g.v.misc.release_name, missing_sample_check_ignore_dividers)) { d_log("rescan: Removing missing-sample indicator (if any)\n"); remove_sample_indicator(&g); } else if (matchpath(check_for_missing_sample_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("rescan: Creating missing-sample indicator %s.\n", g.l.sample_incomplete); if (create_incomplete_sample()) { d_log("rescan: create_incomplete_sample() returned something\n"); } } else { if (findfileextsubp(dir)) { d_log("rescan: Removing missing-sample indicator (if any)\n"); remove_sample_indicator(&g); } else { d_log("rescan: Creating missing-sample indicator (base) %s.\n", g.l.sample_incomplete); /* This is not pretty, but should be functional. */ if ((inc_point[0] = find_last_of(g.l.path, "/")) != g.l.path) *inc_point[0] = '\0'; if ((inc_point[1] = find_last_of(g.v.misc.release_name, "/")) != g.v.misc.release_name) *inc_point[1] = '\0'; if (create_incomplete_sample()) { d_log("rescan: create_incomplete_sample() returned something\n"); } if (*inc_point[0] == '\0') *inc_point[0] = '/'; if (*inc_point[1] == '\0') *inc_point[1] = '/'; } } } } #endif if (g.v.misc.release_type == RTYPE_AUDIO) { get_audio_info(findfileextfromlist(dir, audio_types), &g.v.audio); /* Sort if we're not in a group-dir/nosort-dir. */ if (!matchpath(group_dirs, g.l.path) && !matchpath(audio_nosort_dirs, g.l.path)) { printf(" Resorting release.\n"); audioSort(&g.v.audio, g.l.link_source, g.l.link_target); } } if ((g.v.total.files_missing == 0) && (g.v.total.files > 0)) { switch (g.v.misc.release_type) { case RTYPE_RAR: complete_bar = rar_completebar; break; case RTYPE_OTHER: complete_bar = other_completebar; break; case RTYPE_AUDIO: complete_bar = audio_completebar; #if ( create_m3u == TRUE ) n = snprintf(exec, sizeof(exec), "%s", findfileext(dir, ".sfv")); strcpy(exec + n - 3, "m3u"); create_indexfile(g.l.race, &g.v, exec); #endif break; case RTYPE_VIDEO: complete_bar = video_completebar; break; } complete(&g, complete_type); if (complete_bar) { createstatusbar(convert(&g.v, g.ui, g.gi, complete_bar)); #if (chmod_completebar) if (!matchpath(group_dirs, g.l.path)) { if (chmod_each(convert(&g.v, g.ui, g.gi, complete_bar), 0222)) d_log("rescan: Failed to chmod a statusbar: %s\n", strerror(errno)); } #endif } #if (enable_rescan_script) d_log("rescan: Executing rescan_script script\n"); if (!fileexists(rescan_script)) { d_log("rescan: Warning - rescan_script (%s) - file does not exist!\n", rescan_script); } else { snprintf(target, sizeof(target), rescan_script " \"%s\"", g.v.file.name); if (execute(target) != 0) d_log("rescan: Failed to execute rescan_script: %s\n", strerror(errno)); } #endif } else { if (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs) { if (create_incomplete()) { d_log("rescan: create_incomplete() returned something\n"); } } move_progress_bar(0, &g.v, g.ui, g.gi); } } else { int empty = 1; #if (create_missing_sfv_link == TRUE) if ((!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs) && g.l.sfv_incomplete && !matchpath(nocheck_dirs, g.l.path) && !matchpath(allowed_types_exemption_dirs, g.l.path)) { rewinddir(dir); while ((dp = readdir(dir))) { stat(dp->d_name, &fileinfo); if (S_ISREG(fileinfo.st_mode)) { ext = find_last_of(dp->d_name, "."); if (*ext == '.') ext++; if (*ext && get_filetype(&g, ext) == 3) { d_log("rescan: Creating missing-sfv indicator %s.\n", g.l.sfv_incomplete); if (create_incomplete_sfv()) d_log("rescan: create_incomplete_sfv() returned something.\n"); empty = 0; break; } } } } #endif if (empty && mark_empty_dirs_as_incomplete_on_rescan) { if (create_incomplete()) { d_log("rescan: create_incomplete() returned something\n"); } printf(" Empty dir - marking as incomplete.\n"); } } printf(" Passed : %i\n", (int)g.v.total.files - (int)g.v.total.files_missing); printf(" Failed : %i\n", (int)g.v.total.files_bad); printf(" Missing: %i\n", (int)g.v.total.files_missing); printf(" Total : %i\n", (int)g.v.total.files); if (g.v.total.files && !g.v.total.files_missing) { g.v.misc.data_completed = 1; } else { g.v.misc.data_completed = 0; } d_log("rescan: Freeing memory and removing lock.\n"); closedir(dir); closedir(parent); ng_free(g.l.race); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); remove_lock(&g.v); updatestats_free(&g); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif exit(0); }
int main(int argc, char** argv) { int i, usealt; const char * pin, * label; #ifdef CTAPI void* mutex; #endif /* Check args */ if (argc < 4) { fprintf(stderr, "Usage: [-a] pin label path...\n"); fprintf(stderr, "Signs the specified file(s) and/or files within the specified directory(ies).\n"); fprintf(stderr, " -a use :p7s instead of .p7s extension (alternate data stream on Windows)\n"); return 1; } usealt = strcmp(argv[1], "-a") == 0; pin = !usealt ? argv[1] : argv[2]; label = !usealt ? argv[2] : argv[3]; sig_ext = !usealt ? ".p7s" : ":p7s"; /* Disable buffering on stdout/stderr to prevent mixing the order of messages to stdout/stderr when redirected to the same log file */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); /* Log the args */ log_inf("pin=****; label='%s'", label); #ifdef CTAPI /* Create a mutex/sem/lock for controlling access to token. CTAPI implementations must NOT allow simultaneous access to token. */ mutex = create_lock(MUTEX_KEY); if ((int)mutex < 0) { log_wrn( "couldn't create mutex; another inst. of '%s' is likely running", argv[0]); return -1; } #endif /* For each path arg, sign either the specified file or all the files in the specified directory */ for (i = !usealt ? 3 : 4; i < argc; i++) { int err; struct stat info; char* path = argv[i]; /* Trim trailing slashes from path (required for Windows stat) */ int j = strlen(path); while (--j >= 0 && (path[j] == '/' || path[j] == '\\')) path[j] = 0; /* Log the path */ log_inf("path='%s'", path); /* Verify the specified path exists */ err = stat(path, &info); if (err) { int e = errno; log_err("error accessing path '%s': %s", path, strerror(e)); continue; } if (S_ISDIR(info.st_mode)) /* DIRECTORY */ sign_files(path, pin, label); /* Sign all files in the specified directory */ else /* FILE */ sign_file(path, pin, label); /* Sign the specified file */ } /* Clean up */ release_template(); #ifdef CTAPI /* Release mutex/sem/lock here. */ release_lock(mutex); #endif #if defined(_WIN32) && defined(DEBUG) _CrtDumpMemoryLeaks(); #endif return 0; }
int main(int argc, char **argv) { bool fork_desired = TRUE; bool log_to_stderr_desired = FALSE; bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; char *virtual_private = NULL; int lockfd; #ifdef CAPABILITIES int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE }; #endif /* CAPABILITIES */ /* initialize library and optionsfrom */ if (!library_init(NULL)) { library_deinit(); exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); } if (!libhydra_init("pluto")) { libhydra_deinit(); library_deinit(); exit(SS_RC_INITIALIZATION_FAILED); } if (!pluto_init(argv[0])) { pluto_deinit(); libhydra_deinit(); library_deinit(); exit(SS_RC_DAEMON_INTEGRITY); } options = options_create(); /* handle arguments */ for (;;) { # define DBG_OFFSET 256 static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "nocrsend", no_argument, NULL, 'c' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "cachecrls", no_argument, NULL, 'C' }, { "uniqueids", no_argument, NULL, 'u' }, { "disableuniqreqids", no_argument, NULL, 'Z'}, { "interface", required_argument, NULL, 'i' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "policygroupsdir", required_argument, NULL, 'f' }, #ifdef USE_LWRES { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ { "pkcs11module", required_argument, NULL, 'm' }, { "pkcs11keepstate", no_argument, NULL, 'k' }, { "pkcs11initargs", required_argument, NULL, 'z' }, { "pkcs11proxy", no_argument, NULL, 'y' }, { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-natt", no_argument, NULL, '5' }, { "virtual_private", required_argument, NULL, '6' }, #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET }, { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET }, { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET }, { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET }, { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET }, { "debug-klips", no_argument, NULL, DBG_KERNEL + DBG_OFFSET }, { "debug-kernel", no_argument, NULL, DBG_KERNEL + DBG_OFFSET }, { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int c = getopt_long(argc, argv, "", long_opts, NULL); /* Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'v': /* --version */ { const char **sp = ipsec_copyright_notice(); printf("strongSwan "VERSION"%s\n", compile_time_interop_options); for (; *sp != NULL; sp++) puts(*sp); } exit_pluto(0); break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ if (!options->from(options, optarg, &argc, &argv, optind)) { exit_pluto(1); } continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue; case 'C': /* --cachecrls */ cache_crls = TRUE; continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'Z': /* --disableuniqreqids */ disable_uniqreqids = TRUE; continue; case 'i': /* --interface <ifname> */ if (!use_interface(optarg)) usage("too many --interface specifications"); continue; case 'p': /* --port <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", optarg, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", optarg, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", optarg, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ shared_secrets_file = optarg; continue; case 'f': /* --policygroupsdir <policygroups-dir> */ policygroups_dir = optarg; continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; case 'm': /* --pkcs11module <pathname> */ pkcs11_module_path = optarg; continue; case 'k': /* --pkcs11keepstate */ pkcs11_keep_state = TRUE; continue; case 'y': /* --pkcs11proxy */ pkcs11_proxy = TRUE; continue; case 'z': /* --pkcs11initargs */ pkcs11_init_args = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; case '6': /* --virtual_private */ virtual_private = optarg; continue; default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) { log_to_syslog = FALSE; } else { log_to_stderr = FALSE; } /* set the logging function of pfkey debugging */ #ifdef DEBUG pfkey_debug_func = DBG_log; #else pfkey_debug_func = NULL; #endif /* create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } /* If not suppressed, do daemon fork */ if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(1); } if (pid != 0) { /* parent: die, after filling PID into lock file. * must not use exit_pluto: lock would be removed! */ exit(fill_lock(lockfd, pid)? 0 : 1); } } if (setsid() < 0) { int e = errno; fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(1); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } /* Redirect stdin, stdout and stderr to /dev/null */ { int fd; if ((fd = open("/dev/null", O_RDWR)) == -1) abort(); if (dup2(fd, 0) != 0) abort(); if (dup2(fd, 1) != 1) abort(); if (!log_to_stderr && dup2(fd, 2) != 2) abort(); close(fd); } init_constants(); init_log("pluto"); /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ plog("Starting IKEv1 pluto daemon (strongSwan "VERSION")%s", compile_time_interop_options); if (lib->integrity) { plog("integrity tests enabled:"); plog("lib 'libstrongswan': passed file and segment integrity tests"); plog("lib 'libhydra': passed file and segment integrity tests"); plog("daemon 'pluto': passed file integrity test"); } /* load plugins, further infrastructure may need it */ if (!lib->plugins->load(lib->plugins, NULL, lib->settings->get_str(lib->settings, "pluto.load", PLUGINS))) { exit(SS_RC_INITIALIZATION_FAILED); } print_plugins(); init_builder(); if (!init_secret() || !init_crypto()) { plog("initialization failed - aborting pluto"); exit_pluto(SS_RC_INITIALIZATION_FAILED); } init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); init_virtual_ip(virtual_private); scx_init(pkcs11_module_path, pkcs11_init_args); init_states(); init_demux(); init_kernel(); init_adns(); init_myid(); fetch_initialize(); ac_initialize(); whack_attribute_initialize(); /* drop unneeded capabilities and change UID/GID */ prctl(PR_SET_KEEPCAPS, 1); #ifdef IPSEC_GROUP { struct group group, *grp; char buf[1024]; if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 || grp == NULL || setgid(grp->gr_gid) != 0) { plog("unable to change daemon group"); abort(); } } #endif #ifdef IPSEC_USER { struct passwd passwd, *pwp; char buf[1024]; if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 || pwp == NULL || setuid(pwp->pw_uid) != 0) { plog("unable to change daemon user"); abort(); } } #endif #ifdef CAPABILITIES_LIBCAP { cap_t caps; caps = cap_init(); cap_set_flag(caps, CAP_EFFECTIVE, countof(keep), keep, CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, countof(keep), keep, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, countof(keep), keep, CAP_SET); if (cap_set_proc(caps) != 0) { plog("unable to drop daemon capabilities"); abort(); } cap_free(caps); } #endif /* CAPABILITIES_LIBCAP */ #ifdef CAPABILITIES_NATIVE { struct __user_cap_data_struct caps = { .effective = 0 }; struct __user_cap_header_struct header = { .version = _LINUX_CAPABILITY_VERSION, }; int i; for (i = 0; i < countof(keep); i++) { caps.effective |= 1 << keep[i]; caps.permitted |= 1 << keep[i]; caps.inheritable |= 1 << keep[i]; } if (capset(&header, &caps) != 0) { plog("unable to drop daemon capabilities"); abort(); } } #endif /* CAPABILITIES_NATIVE */ /* loading X.509 CA certificates */ load_authcerts("ca", CA_CERT_PATH, X509_CA); /* loading X.509 AA certificates */ load_authcerts("aa", AA_CERT_PATH, X509_AA); /* loading X.509 OCSP certificates */ load_authcerts("ocsp", OCSP_CERT_PATH, X509_OCSP_SIGNER); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ ac_load_certs(); lib->processor->set_threads(lib->processor, lib->settings->get_int(lib->settings, "pluto.threads", DEFAULT_THREADS)); daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ } /* leave pluto, with status. * Once child is launched, parent must not exit this way because * the lock would be released. * * 0 OK * 1 general discomfort * 10 lock file exists */ void exit_pluto(int status) { lib->processor->set_threads(lib->processor, 0); reset_globals(); /* needed because we may be called in odd state */ free_preshared_secrets(); free_remembered_public_keys(); delete_every_connection(); whack_attribute_finalize(); /* free in-memory pools */ kernel_finalize(); fetch_finalize(); /* stop fetching thread */ free_crl_fetch(); /* free chain of crl fetch requests */ free_ocsp_fetch(); /* free chain of ocsp fetch requests */ free_authcerts(); /* free chain of X.509 authority certificates */ free_crls(); /* free chain of X.509 CRLs */ free_ca_infos(); /* free chain of X.509 CA information records */ free_ocsp(); /* free ocsp cache */ free_ifaces(); ac_finalize(); /* free X.509 attribute certificates */ scx_finalize(); /* finalize and unload PKCS #11 module */ stop_adns(); free_md_pool(); free_crypto(); free_myid(); /* free myids */ free_events(); /* free remaining events */ free_vendorid(); /* free all vendor id records */ free_builder(); delete_lock(); options->destroy(options); pluto_deinit(); lib->plugins->unload(lib->plugins); libhydra_deinit(); library_deinit(); close_log(); exit(status); }
int main(int argc, char **argv) { bool fork_desired = TRUE; bool log_to_stderr_desired = FALSE; int lockfd; #ifdef NAT_TRAVERSAL bool nat_traversal = FALSE; unsigned int keep_alive = 0; #endif #ifdef VIRTUAL_IP char *virtual_private = NULL; #endif char *ipsec0 = NULL; char *ipsec1 = NULL; char *ipsec2 = NULL; char *ipsec3 = NULL; /* handle arguments */ for (;;) { static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "noklips", no_argument, NULL, 'n' }, { "nocrsend", no_argument, NULL, 'c' }, { "uniqueids", no_argument, NULL, 'u' }, { "interface", required_argument, NULL, 'i' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "adns", required_argument, NULL, 'a' }, #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all]", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, 'R' }, { "debug-crypt", no_argument, NULL, 'X' }, { "debug-parsing", no_argument, NULL, 'P' }, { "debug-emitting", no_argument, NULL, 'E' }, { "debug-control", no_argument, NULL, 'C' }, { "debug-lifecycle", no_argument, NULL, 'L' }, { "debug-klips", no_argument, NULL, 'K' }, { "debug-dns", no_argument, NULL, 'D' }, { "debug-private", no_argument, NULL, 'Z' }, #endif #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, #endif #ifdef VIRTUAL_IP { "virtual_private", required_argument, NULL, '3' }, #endif { "ipsec0", required_argument, NULL, '4' }, { "ipsec1", required_argument, NULL, '5' }, { "ipsec2", required_argument, NULL, '6' }, { "ipsec3", required_argument, NULL, '7' }, { 0,0,0,0 } }; /* Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int c = getopt_long(argc, argv, "", long_opts, NULL); /* Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* long option already handled */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ usage(""); break; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'v': /* --version */ { const char **sp = ipsec_copyright_notice(); printf("%s\n", ipsec_version_string()); for (; *sp != NULL; sp++) puts(*sp); } exit_pluto(0); break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* does not return on error */ continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'n': /* --noklips */ no_klips = TRUE; continue; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue ; case 'u': /* --uniquids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname> */ if (!use_interface(optarg)) usage("too many --interface specifications"); continue; case 'p': /* --port <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", optarg, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", optarg, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ shared_secrets_file = optarg; continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; case 'R': /* --debug-raw */ base_debugging |= DBG_RAW; continue; case 'X': /* --debug-crypt */ base_debugging |= DBG_CRYPT; continue; case 'P': /* --debug-parsing */ base_debugging |= DBG_PARSING; continue; case 'E': /* --debug-emitting */ base_debugging |= DBG_EMITTING; continue; case 'C': /* --debug-control */ base_debugging |= DBG_CONTROL; continue; case 'L': /* --debug-lifecycle */ base_debugging |= DBG_LIFECYCLE; continue; case 'K': /* --debug-klips */ base_debugging |= DBG_KLIPS; continue; case 'D': /* --debug-dns */ base_debugging |= DBG_DNS; continue; case 'Z': /* --debug-private */ base_debugging |= DBG_PRIVATE; continue; #endif #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; #endif #ifdef VIRTUAL_IP case '3': /* --virtual_private */ virtual_private = optarg; continue; #endif case '4': /* --ipsec0 */ ipsec0 = optarg; continue; case '5': /* --ipsec1 */ ipsec1 = optarg; continue; case '6': /* --ipsec2 */ ipsec2 = optarg; continue; case '7': /* --ipsec3 */ ipsec3 = optarg; continue; default: impossible(); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) log_to_syslog = FALSE; else log_to_stderr = FALSE; /* create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } /* If not suppressed, do daemon fork */ #ifndef EMBED if (fork_desired) { { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(1); } if (pid != 0) { /* parent: die, after filling PID into lock file. * must not use exit_pluto: lock would be removed! */ exit(fill_lock(lockfd, pid)? 0 : 1); } } if (setsid() < 0) { int e = errno; fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(1); } /* Close everything but ctl_fd and (if needed) stderr. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ if ((!log_to_stderr || i != 2) && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) abort(); if (dup2(0, 1) != 1) abort(); if (!log_to_stderr && dup2(0, 2) != 2) abort(); } } else #endif { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } init_constants(); init_log(); /* Note: some scripts may look for this exact message -- don't change */ log("Starting Pluto (FreeS/WAN Version %s)", ipsec_version_code()); log(" including X.509 patch (Version %s)", x509patch_version); #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal,keep_alive); #endif #ifdef VIRTUAL_IP init_virtual_ip(virtual_private); #endif init_interfaces(ipsec0, ipsec1, ipsec2, ipsec3); init_rnd_pool(); init_secret(); init_states(); init_crypto(); init_demux(); init_kernel(); init_adns(); /* loading CA certificates */ load_cacerts(); /* loading CRLs */ load_crls(); /* loading my X.509 or OpenPGP certificate */ load_mycert(); call_server(); return -1; /* Shouldn't ever reach this */ }
void cli_lock(int sock, oid_t *pid) { create_lock(*pid); send_reply(sock, NULL, 0); }