Beispiel #1
0
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;
}
Beispiel #2
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");
  }
}
Beispiel #3
0
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);
    }
}
Beispiel #4
0
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;
}
Beispiel #5
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;
}
Beispiel #7
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;
  }
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
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;
}
Beispiel #14
0
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));
}
Beispiel #15
0
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;
}
Beispiel #16
0
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);
    }
}
Beispiel #17
0
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;
}
Beispiel #18
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;
}
Beispiel #19
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 */
}
Beispiel #20
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
	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 */
}
Beispiel #21
0
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 */
}
Beispiel #22
0
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;
}
Beispiel #23
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 */
}
Beispiel #24
0
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 */
}
Beispiel #25
0
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 */
}
Beispiel #26
0
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);
}
Beispiel #29
0
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 */
}
Beispiel #30
0
void cli_lock(int sock, oid_t *pid) {
	create_lock(*pid);
	send_reply(sock, NULL, 0);
}