Beispiel #1
0
/* We don't want to run as root -- drop privileges if required */
void drop_privileges(const char* user_name)
{
    int res;
    struct passwd *pw = getpwnam(user_name);
    if (!pw) {
        fprintf(stderr, "%s: not found\n", user_name);
        exit(2);
    }
    if (verbose)
        fprintf(stderr, "turning into %s\n", user_name);

    set_keepcaps(1);

    /* remove extraneous groups in case we belong to several extra groups that
     * may have unwanted rights. If non-root when calling setgroups(), it
     * fails, which is fine because... we have no unwanted rights 
     * (see POS36-C for security context)
     * */
    setgroups(0, NULL);

    res = setgid(pw->pw_gid);
    CHECK_RES_DIE(res, "setgid");
    res = setuid(pw->pw_uid);
    CHECK_RES_DIE(res, "setuid");

    set_capabilities();
    set_keepcaps(0);
}
Beispiel #2
0
void setup_signals(void)
{
    int res;
    struct sigaction action;

    /* Request no SIGCHLD is sent upon termination of
     * the children */
    memset(&action, 0, sizeof(action));
    action.sa_handler = NULL;
    action.sa_flags = SA_NOCLDWAIT;
    res = sigaction(SIGCHLD, &action, NULL);
    CHECK_RES_DIE(res, "sigaction");

    /* Set SIGTERM to exit. For some reason if it's not set explicitly,
     * coverage information is lost when killing the process */
    memset(&action, 0, sizeof(action));
    action.sa_handler = exit;
    res = sigaction(SIGTERM, &action, NULL);
    CHECK_RES_DIE(res, "sigaction");

    /* Ignore SIGPIPE . */
    action.sa_handler = SIG_IGN;
    res = sigaction(SIGPIPE, &action, NULL);
    CHECK_RES_DIE(res, "sigaction");

}
Beispiel #3
0
void ip_map_init()
{
	ip_map_id = new_shared_map();
	semid = semget(IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0666);
	CHECK_RES_DIE(semid, "semget");
	int res = semctl(semid, 0, SETVAL, 1);
	CHECK_RES_DIE(res, "semctl");
	if (verbose) fprintf(stderr, "Port<->IP map initialized.\n");
}
Beispiel #4
0
int bind_peer(int fd, int fd_from)
{
    struct addrinfo from;
    struct sockaddr_storage ss;
    int res, trans = 1;

    memset(&from, 0, sizeof(from));
    from.ai_addr = (struct sockaddr*)&ss;
    from.ai_addrlen = sizeof(ss);

    /* getpeername can fail with ENOTCONN if connection was dropped before we
     * got here */
    res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen);
    CHECK_RES_RETURN(res, "getpeername");
#ifndef IP_BINDANY /* use IP_TRANSPARENT */
    res = setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &trans, sizeof(trans));
    CHECK_RES_DIE(res, "setsockopt");
#else
    if (from.ai_addr->sa_family==AF_INET) { /* IPv4 */
        res = setsockopt(fd, IPPROTO_IP, IP_BINDANY, &trans, sizeof(trans));
        CHECK_RES_RETURN(res, "setsockopt IP_BINDANY");
#ifdef IPV6_BINDANY
    } else { /* IPv6 */
        res = setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &trans, sizeof(trans));
        CHECK_RES_RETURN(res, "setsockopt IPV6_BINDANY");
#endif /* IPV6_BINDANY */
    }
#endif /* IP_TRANSPARENT / IP_BINDANY */
    res = bind(fd, from.ai_addr, from.ai_addrlen);
    CHECK_RES_RETURN(res, "bind");

    return 0;
}
Beispiel #5
0
/* shovels data from one fd to the other and vice-versa 
   returns after one socket closed
 */
int shovel(struct connection *cnx)
{
   fd_set fds;
   int res, i;
   int max_fd = MAX(cnx->q[0].fd, cnx->q[1].fd) + 1;

   FD_ZERO(&fds);
   while (1) {
      FD_SET(cnx->q[0].fd, &fds);
      FD_SET(cnx->q[1].fd, &fds);

      res = select(
                   max_fd,
                   &fds,
                   NULL,
                   NULL,
                   NULL
                  );
      CHECK_RES_DIE(res, "select");

      for (i = 0; i < 2; i++) {
          if (FD_ISSET(cnx->q[i].fd, &fds)) {
              res = fd2fd(&cnx->q[1-i], &cnx->q[i]);
              if (!res) {
                  if (verbose) 
                      fprintf(stderr, "%s %s", i ? "client" : "server", "socket closed\n");
                  return res;
              }
          }
      }
   }
}
Beispiel #6
0
/* Child process that finds out what to connect to and proxies 
 */
void start_shoveler(int in_socket)
{
   fd_set fds;
   struct timeval tv;
   int res = PROBE_AGAIN;
   int out_socket;
   struct connection cnx;

   init_cnx(&cnx);
   cnx.q[0].fd = in_socket;

   FD_ZERO(&fds);
   FD_SET(in_socket, &fds);
   memset(&tv, 0, sizeof(tv));
   tv.tv_sec = probing_timeout;

   while (res == PROBE_AGAIN) {
       /* POSIX does not guarantee that tv will be updated, but the client can
        * only postpone the inevitable for so long */
       res = select(in_socket + 1, &fds, NULL, NULL, &tv);
       if (res == -1)
           perror("select");

       if (FD_ISSET(in_socket, &fds)) {
           /* Received data: figure out what protocol it is */
           res = probe_client_protocol(&cnx);
       } else {
           /* Timed out: it's necessarily SSH */
           cnx.proto = timeout_protocol();
           break;
       }
   }

   if (cnx.proto->service &&
       check_access_rights(in_socket, cnx.proto->service)) {
       exit(0);
   }

   /* Connect the target socket */
   out_socket = connect_addr(&cnx, in_socket);
   CHECK_RES_DIE(out_socket, "connect");

   cnx.q[1].fd = out_socket;

   log_connection(&cnx);

   flush_deferred(&cnx.q[1]);

   shovel(&cnx);

   close(in_socket);
   close(out_socket);
   
   if (verbose)
      fprintf(stderr, "connection closed down\n");

   exit(0);
}
Beispiel #7
0
int new_shared_map()
{
	int id = shmget(IPC_PRIVATE, sizeof(map_t), IPC_CREAT | IPC_EXCL | 0600);
	CHECK_RES_DIE(id, "shmget");
	map_t *m = shmat(id, NULL, 0);
	m->ip = 0;
	m->port = 0;
	m->next = -1;
	shmdt(m);
	return id;
}
Beispiel #8
0
/* Open syslog connection with appropriate banner; 
 * banner is made up of basename(bin_name)+"[pid]" */
void setup_syslog(const char* bin_name) {
    char *name1, *name2;
    int res;

    name1 = strdup(bin_name);
    res = asprintf(&name2, "%s[%d]", basename(name1), getpid());
    CHECK_RES_DIE(res, "asprintf");
    openlog(name2, LOG_CONS, LOG_AUTH);
    free(name1); 
    /* Don't free name2, as openlog(3) uses it (at least in glibc) */

    log_message(LOG_INFO, "%s %s started\n", server_type, VERSION);
}
Beispiel #9
0
void main_loop(int listen_sockets[], int num_addr_listen)
{
    int in_socket, i, res;
    struct sigaction action;

    listener_pid_number = num_addr_listen;
    listener_pid = malloc(listener_pid_number * sizeof(listener_pid[0]));

    /* Start one process for each listening address */
    for (i = 0; i < num_addr_listen; i++) {
        if (!(listener_pid[i] = fork())) {

            /* Listening process just accepts a connection, forks, and goes
             * back to listening */
            while (1)
            {
                in_socket = accept(listen_sockets[i], 0, 0);
                if (verbose) fprintf(stderr, "accepted fd %d\n", in_socket);

                if (!fork())
                {
                    close(listen_sockets[i]);
                    start_shoveler(in_socket);
                    exit(0);
                }
                close(in_socket);
            }
        }
    }

    /* Set SIGTERM to "stop_listeners" which further kills all listener
     * processes. Note this won't kill processes that listeners forked, which
     * means active connections remain active. */
    memset(&action, 0, sizeof(action));
    action.sa_handler = stop_listeners;
    res = sigaction(SIGTERM, &action, NULL);
    CHECK_RES_DIE(res, "sigaction");

    wait(NULL);
}
Beispiel #10
0
/* set needed capabilities for effective and permitted, clear rest */
void set_capabilities(void) {
#ifdef LIBCAP
    int res;
    cap_t caps;
    cap_value_t cap_list[10];
    int ncap = 0;

    if (transparent)
        cap_list[ncap++] = CAP_NET_ADMIN;

    caps = cap_init();

#define _cap_set_flag(flag) do { \
        res = cap_clear_flag(caps, flag); \
        CHECK_RES_DIE(res, "cap_clear_flag(" #flag ")"); \
        if (ncap > 0) { \
            res = cap_set_flag(caps, flag, ncap, cap_list, CAP_SET); \
            CHECK_RES_DIE(res, "cap_set_flag(" #flag ")"); \
        } \
    } while(0)

    _cap_set_flag(CAP_EFFECTIVE);
    _cap_set_flag(CAP_PERMITTED);

#undef _cap_set_flag

    res = cap_set_proc(caps);
    CHECK_RES_DIE(res, "cap_set_proc");

    res = cap_free(caps);
    if (res) {
        perror("cap_free");
        exit(1);
    }
#endif
}
Beispiel #11
0
/* Sets the protocol name to connect to in case of timeout */
void set_ontimeout(const char* name)
{
    int res = asprintf(&on_timeout, "%s", name);
    CHECK_RES_DIE(res, "asprintf");
}