Esempio n. 1
0
int main (void)
{
    int rc;
 
    setup_test_environment();
    //  Create the infrastructure
    void *ctx = zmq_ctx_new ();
    assert (ctx);

    void *rep = zmq_socket (ctx, ZMQ_REP);
    assert (rep);
    void *req = zmq_socket (ctx, ZMQ_REQ);
    assert (req);

    rc = zmq_bind(rep, "tcp://127.0.0.1:5560");
    assert (rc == 0);

    rc = zmq_connect(req, "tcp://127.0.0.1:5560");
    assert (rc == 0);

    char tmp[MSG_SIZE];
    zmq_send(req, tmp, MSG_SIZE, 0);

    zmq_msg_t msg;
    rc = zmq_msg_init(&msg);
    assert (rc == 0);

    zmq_recvmsg(rep, &msg, 0);
    assert(zmq_msg_size(&msg) == MSG_SIZE);
  
	  // get the messages source file descriptor
    int srcFd = zmq_msg_get(&msg, ZMQ_SRCFD);
    assert(srcFd >= 0);

	  // get the remote endpoint
    struct sockaddr_storage ss;
    socklen_t addrlen = sizeof ss;
    rc = getpeername (srcFd, (struct sockaddr*) &ss, &addrlen);
    assert (rc == 0);

    char host [NI_MAXHOST];
    rc = getnameinfo ((struct sockaddr*) &ss, addrlen, host, sizeof host, NULL, 0, NI_NUMERICHOST);
    assert (rc == 0);

	  // assert it is localhost which connected
    assert (strcmp(host, "127.0.0.1") == 0);

    rc = zmq_close (rep);
    assert (rc == 0);
    rc = zmq_close (req);
    assert (rc == 0);

	  // sleep a bit for the socket to be freed
	  usleep(30000);
	
	  // getting name from closed socket will fail
    rc = getpeername (srcFd, (struct sockaddr*) &ss, &addrlen);
    assert (rc == -1);
    assert (errno == EBADF);
    
    rc = zmq_ctx_term (ctx);
    assert (rc == 0);

    return 0 ;
}
Esempio n. 2
0
static char *
get_remote_hostname(int sock, int use_dns)
{
	struct sockaddr_storage from;
	int i;
	socklen_t fromlen;
	struct addrinfo hints, *ai, *aitop;
	char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];

	/* Get IP address of client. */
	fromlen = sizeof(from);
	memset(&from, 0, sizeof(from));
	if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
		debug("getpeername failed: %.100s", strerror(errno));
		cleanup_exit(255);
	}

	if (from.ss_family == AF_INET)
		check_ip_options(sock, ntop);

	ipv64_normalise_mapped(&from, &fromlen);

	if (from.ss_family == AF_INET6)
		fromlen = sizeof(struct sockaddr_in6);

	if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
	    NULL, 0, NI_NUMERICHOST) != 0)
		fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");

	if (!use_dns)
		return xstrdup(ntop);

	debug3("Trying to reverse map address %.100s.", ntop);
	/* Map the IP address to a host name. */
	if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
	    NULL, 0, NI_NAMEREQD) != 0) {
		/* Host name not found.  Use ip address. */
		return xstrdup(ntop);
	}

	/*
	 * if reverse lookup result looks like a numeric hostname,
	 * someone is trying to trick us by PTR record like following:
	 *	1.1.1.10.in-addr.arpa.	IN PTR	2.3.4.5
	 */
	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
	hints.ai_flags = AI_NUMERICHOST;
	if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
		logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
		    name, ntop);
		freeaddrinfo(ai);
		return xstrdup(ntop);
	}

	/*
	 * Convert it to all lowercase (which is expected by the rest
	 * of this software).
	 */
	for (i = 0; name[i]; i++)
		if (isupper(name[i]))
			name[i] = (char)tolower(name[i]);
	/*
	 * Map it back to an IP address and check that the given
	 * address actually is an address of this host.  This is
	 * necessary because anyone with access to a name server can
	 * define arbitrary names for an IP address. Mapping from
	 * name to IP address can be trusted better (but can still be
	 * fooled if the intruder has access to the name server of
	 * the domain).
	 */
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = from.ss_family;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
		logit("reverse mapping checking getaddrinfo for %.700s "
		    "[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop);
		return xstrdup(ntop);
	}
	/* Look for the address from the list of addresses. */
	for (ai = aitop; ai; ai = ai->ai_next) {
		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
		    sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
		    (strcmp(ntop, ntop2) == 0))
				break;
	}
	freeaddrinfo(aitop);
	/* If we reached the end of the list, the address was not there. */
	if (!ai) {
		/* Address not found for the host name. */
		logit("Address %.100s maps to %.600s, but this does not "
		    "map back to the address - POSSIBLE BREAK-IN ATTEMPT!",
		    ntop, name);
		return xstrdup(ntop);
	}
	return xstrdup(name);
}
int main(int argc, char** argv){

	struct addrinfo hints;
	struct addrinfo *res;
	int info, sd;
	int nread;
	char buf[BUF_SIZE];
	char host[NI_MAXHOST];
	char serv[NI_MAXSERV];

	hints.ai_family = AF_UNSPEC; /*ipv4 o ipv6*/
	hints.ai_socktype = SOCK_DGRAM; /*udp*/
	hints.ai_flags = AI_PASSIVE;
	hints.ai_protocol = 0;
	
	if(argc < 1) perror("Error de argumentos.\n");

	info = getaddrinfo("::", argv[1], &hints, &res);
	if(info != 0) perror("Error getaddrinfo.\n");
	
	sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	
	bind(sd, res->ai_addr, res->ai_addrlen);
	int i;
	for(i = 0; i < 2; i++){	
		pid_t pid = fork();
		if(pid == -1) perror("Error de pid.\n");
		else if(pid == 0)
		{
				while(1){
					struct sockaddr_storage sock;
					socklen_t sock_len = sizeof(sock);
				

					nread = recvfrom(sd, buf, BUF_SIZE, 0, (struct sockaddr *) &sock, &sock_len);
					buf[nread] = '\0';

					getnameinfo((struct sockaddr *) &sock, sock_len, host, NI_MAXHOST, serv, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
					if(strcmp(buf, "a") == 0 || strcmp(buf, "a\n") == 0){
						sendto(sd, host, strlen(host), 0, (struct sockaddr *) &sock, sock_len);
					}
					else if(strcmp(buf, "p") == 0 || strcmp(buf, "p\n") == 0)		{
						sendto(sd, serv, strlen(serv), 0, (struct sockaddr *) &sock, sock_len);
					}
					else if(strcmp(buf, "q") == 0 || strcmp(buf, "q\n") == 0)		{
						sendto(sd, "ADIÓS\n", 6, 0, (struct sockaddr *) &sock, sock_len);
						freeaddrinfo(res);
						close(sd);
						return 0;
					}
					printf("[H: %d,%d] Host: %s     Puerto: %s\n", getpid(), i+1, host, serv);
				}
				
		}
	}
	
	i = 0;
	while(i<2){
		int status;
		wait(&status);
		i++;	
	}
	freeaddrinfo(res);
	close(sd);

	return 0;
}
Esempio n. 4
0
int analyze_line(char *line[]) {
  char sec[LINE_COLUMNS];
  struct tm *tm;
  struct sockaddr_in sa;
  char *l[LINE_COLUMNS];
  char date[9];
  char host[30];
  //char cn_host[CN_LENGTH];
  long i_tmp = 0;
  char *c_tmp;
  struct in_addr addr;

  memset(sec, 0, sizeof(sec));
  memset(date, 0, sizeof(date));
  sscanf(line[0], "%[^-]", sec);
  i_tmp = atol(sec);
  tm = localtime(&i_tmp);
  if(tm == NULL) {
    fprintf(stderr, "  Error to parse time %s\n", sec);
    return EXIT_FAILURE;
  }

  if(strftime(date, sizeof(date), "%Y%m%d", tm) == 0) {
    fprintf(stderr, "  Error to change time to human readable strings\n");
    return EXIT_FAILURE;
  }
  l[0] = date;
  
  if(ip4insubnet(line[2], LOCAL_NET, LOCAL_NETBITS) == 1) {
    c_tmp = line[2];
    l[2] = line[3];
    if(line[6] != NULL && strcasecmp(line[4], "TCP") == 0) {
      l[5] = line[6];
    }
  }
  else{
    c_tmp = line[3];
    l[2] = line[2];
    if(line[5] != NULL && strcasecmp(line[4], "TCP") == 0) {
      l[5] = line[5];
    }
  } 
  
  memset(host, 0, sizeof(host));
  bzero(&sa, sizeof(struct sockaddr_in));
  sa.sin_family = AF_INET;
  sa.sin_addr.s_addr = inet_addr(c_tmp);
  getnameinfo((struct sockaddr *)&sa, sizeof(sa), host, sizeof(host), NULL, 0, NI_NOFQDN);
  if(strlen(host) <= 0) l[1] = c_tmp;
  else l[1] = host;

  l[3] = line[4];
  l[4] = line[1];

  l[7] = "\0";
  if(strcasecmp(line[4], "TCP") == 0) {
    if(strcasecmp(line[7], "FA") == 0) l[6] = "1";
    else l[6] = "0";

    for(i_tmp = 8; i_tmp < LINE_COLUMNS; i_tmp++) {
      if(strcmp(line[i_tmp], "\n") == 0) {
        l[i_tmp] = NULL;
        break;  
      }
      l[i_tmp] = line[i_tmp]; 
    }

    /*
    if(i_tmp == 8 && (atoi(l[5]) == 443 || atoi(l[5]) == 8443)) {
      cn_host[0] = '\0';
      pthread_mutex_lock(&mutex);
      get_crt_cn(l[2], l[5], cn_host); 
      pthread_mutex_unlock(&mutex);
      l[7] = cn_host;
    }
    */

  } else {
    l[5] = NULL;
    l[6] = NULL;
  }

  db_save(l);
}
Esempio n. 5
0
/* Map the host name NAME to the actual to be used host name.  This
   allows us to manage round robin DNS names.  We use our own strategy
   to choose one of the hosts.  For example we skip those hosts which
   failed for some time and we stick to one host for a time
   independent of DNS retry times.  */
static char *
map_host (const char *name)
{
  hostinfo_t hi;
  int idx;

  /* No hostname means localhost.  */
  if (!name || !*name)
    return xtrystrdup ("localhost");

  /* See whether the host is in our table.  */
  idx = find_hostinfo (name);
  if (idx == -1)
    {
      /* We never saw this host.  Allocate a new entry.  */
      struct addrinfo hints, *aibuf, *ai;
      int *reftbl;
      size_t reftblsize;
      int refidx;

      reftblsize = 100;
      reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
      if (!reftbl)
        return NULL;
      refidx = 0;

      idx = create_new_hostinfo (name);
      if (idx == -1)
        {
          xfree (reftbl);
          return NULL;
        }
      hi = hosttable[idx];

      /* Find all A records for this entry and put them into the pool
         list - if any.  */
      memset (&hints, 0, sizeof (hints));
      hints.ai_socktype = SOCK_STREAM;
      if (!getaddrinfo (name, NULL, &hints, &aibuf))
        {
          for (ai = aibuf; ai; ai = ai->ai_next)
            {
              char tmphost[NI_MAXHOST];
              int tmpidx;
              int ec;
              int i;

              if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
                continue;

              log_printhex ("getaddrinfo returned", ai->ai_addr,ai->ai_addrlen);
              if ((ec=getnameinfo (ai->ai_addr, ai->ai_addrlen,
                                   tmphost, sizeof tmphost,
                                   NULL, 0, NI_NAMEREQD)))
                log_info ("getnameinfo failed while checking '%s': %s\n",
                          name, gai_strerror (ec));
              else if (refidx+1 >= reftblsize)
                {
                  log_error ("getnameinfo returned for '%s': '%s'"
                            " [index table full - ignored]\n", name, tmphost);
                }
              else
                {

                  if ((tmpidx = find_hostinfo (tmphost)) != -1)
                    {
                      log_info ("getnameinfo returned for '%s': '%s'"
                                " [already known]\n", name, tmphost);
                      if (ai->ai_family == AF_INET)
                        hosttable[tmpidx]->v4 = 1;
                      if (ai->ai_family == AF_INET6)
                        hosttable[tmpidx]->v6 = 1;

                      for (i=0; i < refidx; i++)
                        if (reftbl[i] == tmpidx)
                      break;
                      if (!(i < refidx) && tmpidx != idx)
                        reftbl[refidx++] = tmpidx;
                    }
                  else
                    {
                      log_info ("getnameinfo returned for '%s': '%s'\n",
                                name, tmphost);
                      /* Create a new entry.  */
                      tmpidx = create_new_hostinfo (tmphost);
                      if (tmpidx == -1)
                        log_error ("map_host for '%s' problem: %s - '%s'"
                                   " [ignored]\n",
                                   name, strerror (errno), tmphost);
                      else
                        {
                          if (ai->ai_family == AF_INET)
                            hosttable[tmpidx]->v4 = 1;
                          if (ai->ai_family == AF_INET6)
                            hosttable[tmpidx]->v6 = 1;

                          for (i=0; i < refidx; i++)
                            if (reftbl[i] == tmpidx)
                              break;
                          if (!(i < refidx) && tmpidx != idx)
                            reftbl[refidx++] = tmpidx;
                        }
                    }
                }
            }
        }
      reftbl[refidx] = -1;
      if (refidx)
        {
          assert (!hi->pool);
          hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl);
          if (!hi->pool)
            {
              log_error ("shrinking index table in map_host failed: %s\n",
                         strerror (errno));
              xfree (reftbl);
            }
          qsort (reftbl, refidx, sizeof *reftbl, sort_hostpool);
        }
      else
        xfree (reftbl);
    }

  hi = hosttable[idx];
  if (hi->pool)
    {
      /* If the currently selected host is now marked dead, force a
         re-selection .  */
      if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
          && hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
        hi->poolidx = -1;

      /* Select a host if needed.  */
      if (hi->poolidx == -1)
        {
          hi->poolidx = select_random_host (hi->pool);
          if (hi->poolidx == -1)
            {
              log_error ("no alive host found in pool '%s'\n", name);
              return NULL;
            }
        }

      assert (hi->poolidx >= 0 && hi->poolidx < hosttable_size);
      hi = hosttable[hi->poolidx];
      assert (hi);
    }

  if (hi->dead)
    {
      log_error ("host '%s' marked as dead\n", hi->name);
      return NULL;
    }

  return xtrystrdup (hi->name);
}
Esempio n. 6
0
/*
 * We will eventually be called from inetd or via the rc scripts directly
 * Parse arguments and act appropiately.
 */
int
main(int argc, char **argv)
{
    extern char *optarg;
    FILE *fp;
    int	c, *s, ns;
    struct pollfd *pfds;

#if PROFILE
    moncontrol(0);
#endif

    if ((progname = strrchr(*argv, '/')) != NULL) {
	progname++;
    } else
	progname = *argv;

    /* initialise global session data */
    memset(&session, 0, sizeof(session));
    session.peer = tac_strdup("unknown");


    if (argc <= 1) {
	usage();
	tac_exit(1);
    }

    while ((c = getopt(argc, argv, "B:C:d:hiPp:tGgvSsLw:u:")) != EOF)
	switch (c) {
	case 'B':		/* bind() address*/
	    bind_address = optarg;
	    break;
	case 'L':		/* lookup peer names via DNS */
	    lookup_peer = 1;
	    break;
	case 's':		/* don't respond to sendpass */
	    sendauth_only = 1;
	    break;
	case 'v':		/* print version and exit */
	    vers();
	    tac_exit(1);
	case 't':
	    console = 1;	/* log to console too */
	    break;
	case 'P':		/* Parse config file only */
	    parse_only = 1;
	    break;
	case 'G':		/* foreground */
	    opt_G = 1;
	    break;
	case 'g':		/* single threaded */
	    single = 1;
	    break;
	case 'p':		/* port */
	    port = atoi(optarg);
	    portstr = optarg;
	    break;
	case 'd':		/* debug */
	    debug |= atoi(optarg);
	    break;
	case 'C':		/* config file name */
	    session.cfgfile = tac_strdup(optarg);
	    break;
	case 'h':		/* usage */
	    usage();
	    tac_exit(0);
	case 'i':		/* inetd mode */
	    standalone = 0;
	    break;
	case 'S':		/* enable single-connection */
	    opt_S = 1;
	    break;
#ifdef MAXSESS
	case 'w':		/* wholog file */
	    wholog = tac_strdup(optarg);
	    break;
#endif
	case 'u':
	    wtmpfile = tac_strdup(optarg);
	    break;

	default:
	    fprintf(stderr, "%s: bad switch %c\n", progname, c);
	    usage();
	    tac_exit(1);
	}

    parser_init();

    /* read the configuration/etc */
    init();
#if defined(REAPCHILD) && defined(REAPSIGIGN)
    client_count_init();
#endif
    open_logfile();

    signal(SIGUSR1, handler);
    signal(SIGHUP, handler);
    signal(SIGUSR2, dump_clients_handler);
    signal(SIGTERM, die);
    signal(SIGPIPE, SIG_IGN);

    if (parse_only)
	tac_exit(0);

    if (debug)
	report(LOG_DEBUG, "tac_plus server %s starting", version);

    if (!standalone) {
	/* running under inetd */
	char host[NI_MAXHOST];
	int on;
#ifdef IPV6
	struct sockaddr_in6 name;
#else
  struct sockaddr_in name;
#endif
	socklen_t name_len;

	name_len = sizeof(name);
	session.flags |= SESS_NO_SINGLECONN;

	session.sock = 0;
#ifdef IPV6
	if (getpeername(session.sock, (struct sockaddr6 *)&name, &name_len)) {
	    report(LOG_ERR, "getpeername failure %s", strerror(errno));
#else
	if (getpeername(session.sock, (struct sockaddr *)&name, &name_len)) {
	    report(LOG_ERR, "getpeername failure %s", strerror(errno));
#endif
	} else {
	    if (lookup_peer)
		on = 0;
	    else
		on = NI_NUMERICHOST;
#ifdef IPV6
	    if (getnameinfo((struct sockaddr6 *)&name, name_len, host, 128,
			    NULL, 0, on)) {
#else
	    if (getnameinfo((struct sockaddr *)&name, name_len, host, 128,
			    NULL, 0, on)) {
#endif
		strncpy(host, "unknown", NI_MAXHOST - 1);
		host[NI_MAXHOST - 1] = '\0';
	    }
	    if (session.peer) free(session.peer);
	    session.peer = tac_strdup(host);

	    if (session.peerip) free(session.peerip);
#ifdef IPV6
	    session.peerip = tac_strdup((char *)inet_ntop(name.sin6_family,
					&name.sin6_addr, host, name_len));
#else
	    session.peerip = tac_strdup((char *)inet_ntop(name.sin_family,
					&name.sin_addr, host, name_len));
#endif
	    if (debug & DEBUG_AUTHEN_FLAG)
		report(LOG_INFO, "session.peerip is %s", session.peerip);
	}
#ifdef FIONBIO
	on = 1;
	if (ioctl(session.sock, FIONBIO, &on) < 0) {
	    report(LOG_ERR, "ioctl(FIONBIO) %s", strerror(errno));
	    tac_exit(1);
	}
#endif
	start_session();
	tac_exit(0);
 }

    if (single) {
	session.flags |= SESS_NO_SINGLECONN;
    } else {
	/*
	 * Running standalone; background ourselves and release controlling
	 * tty, unless -G option was specified to keep the parent in the
	 * foreground.
	 */
#ifdef SIGTTOU
	signal(SIGTTOU, SIG_IGN);
#endif
#ifdef SIGTTIN
	signal(SIGTTIN, SIG_IGN);
#endif
#ifdef SIGTSTP
	signal(SIGTSTP, SIG_IGN);
#endif
	if (!opt_S)
	    session.flags |= SESS_NO_SINGLECONN;

	if (!opt_G) {
	    if ((childpid = fork()) < 0)
		report(LOG_ERR, "Can't fork first child");
	    else if (childpid > 0)
		exit(0);		/* parent */

	    if (debug)
		report(LOG_DEBUG, "Backgrounded");

#if SETPGRP_VOID
	    if (setpgrp() == -1)
#else
	    if (setpgrp(0, getpid()) == -1)
#endif /* SETPGRP_VOID */
		report(LOG_ERR, "Can't change process group: %s",
		       strerror(errno));

	    /* XXX What does "REAPCHILD" have to do with TIOCNOTTY? */
#ifndef REAPCHILD
	    c = open("/dev/tty", O_RDWR);
	    if (c >= 0) {
		ioctl(c, TIOCNOTTY, (char *)0);
		(void) close(c);
	    }
#else /* REAPCHILD */
	    if ((childpid = fork()) < 0)
		report(LOG_ERR, "Can't fork second child");
	    else if (childpid > 0)
		exit(0);

	    if (debug & DEBUG_FORK_FLAG)
		report(LOG_DEBUG, "Forked grandchild");

#endif /* REAPCHILD */

	    /* some systems require this */
	    closelog();

	    for (c = getdtablesize(); c >= 0; c--)
		(void)close(c);

	    /*
	     * make sure we can still log to syslog now that we have closed
	     * everything
	     */
	    open_logfile();
	}
    }
#if REAPCHILD
#if REAPSIGIGN
    signal(SIGCHLD, reapchild);
#else
    signal(SIGCHLD, SIG_IGN);
#endif
#endif

    ostream = NULL;
    /* chdir("/"); */
    umask(022);
    errno = 0;

    get_socket(&s, &ns);

#ifndef SOMAXCONN
#define SOMAXCONN 5
#endif

    for (c = 0; c < ns; c++) {
	if (listen(s[c], SOMAXCONN) < 0) {
	    console = 1;
	report(LOG_ERR, "listen: %s", strerror(errno));
	tac_exit(1);
    }
    }

    if (port == TAC_PLUS_PORT) {
	if (bind_address == NULL) {
	    strncpy(pidfilebuf, TACPLUS_PIDFILE, PIDSZ);
	    if (pidfilebuf[PIDSZ - 1] != '\0')
		c = PIDSZ;
	    else
		c = PIDSZ - 1;
	} else
	    c = snprintf(pidfilebuf, PIDSZ, "%s.%s", TACPLUS_PIDFILE,
			 bind_address);
    } else {
	if (bind_address == NULL)
	    c = snprintf(pidfilebuf, PIDSZ, "%s.%d", TACPLUS_PIDFILE, port);
	else
	    c = snprintf(pidfilebuf, PIDSZ, "%s.%s.%d", TACPLUS_PIDFILE,
			 bind_address, port);
    }
    if (c >= PIDSZ) {
	pidfilebuf[PIDSZ - 1] = '\0';
	report(LOG_ERR, "pid filename truncated: %s", pidfilebuf);
	childpid = 0;
    } else {
	/* write process id to pidfile */
	if ((fp = fopen(pidfilebuf, "w")) != NULL) {
	    fprintf(fp, "%d\n", (int)getpid());
	    fclose(fp);
	    /*
	     * After forking to disassociate; make sure we know we're the
	     * mother so that we remove our pid file upon exit in die().
	     */
	    childpid = 1;
	} else {
	    report(LOG_ERR, "Cannot write pid to %s %s", pidfilebuf,
		   strerror(errno));
	    childpid = 0;
	}
    }
#ifdef TACPLUS_GROUPID
    if (setgid(TACPLUS_GROUPID))
	report(LOG_ERR, "Cannot set group id to %d %s",
	       TACPLUS_GROUPID, strerror(errno));
#endif

#ifdef TACPLUS_USERID
    if (setuid(TACPLUS_USERID))
	report(LOG_ERR, "Cannot set user id to %d %s",
	       TACPLUS_USERID, strerror(errno));
#endif

#ifdef MAXSESS
    maxsess_loginit();
#endif /* MAXSESS */

    report(LOG_DEBUG, "uid=%d euid=%d gid=%d egid=%d s=%d",
	   getuid(), geteuid(), getgid(), getegid(), s);

    pfds = malloc(sizeof(struct pollfd) * ns);
    if (pfds == NULL) {
	report(LOG_ERR, "malloc failure: %s", strerror(errno));
	tac_exit(1);
    }
    for (c = 0; c < ns; c++) {
	pfds[c].fd = s[c];
	pfds[c].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
    }

    for (;;) {
#if HAVE_PID_T
	pid_t pid;
#else
	int pid;
#endif
	char host[NI_MAXHOST];
#ifdef IPV6
	struct sockaddr_in6 from;
#else
	struct sockaddr_in from;
#endif
	socklen_t from_len;
	int newsockfd, status;
	int flags;
  int procs_for_client;

#if defined(REAPCHILD) && defined(REAPSIGIGN)
  if (reap_children)
    reapchildren();
#endif

	if (reinitialize)
	    init();

  if (dump_client_table) {
    report(LOG_ALERT, "Dumping Client Tables");
    dump_client_tables();
    dump_client_table = 0;
  }

	status = poll(pfds, ns, cfg_get_accepttimeout() * 1000);
	if (status == 0)
	    continue;
	if (status == -1)
	    if (errno == EINTR)
		continue;

	from_len = sizeof(from);
	memset((char *)&from, 0, from_len);
	for (c = 0; c < ns; c++) {
	    if (pfds[c].revents & POLLIN)
  #ifdef IPV6
		newsockfd = accept(s[c], (struct sockaddr6 *)&from, &from_len);
  #else
		newsockfd = accept(s[c], (struct sockaddr *)&from, &from_len);
  #endif
	    else if (pfds[c].revents & (POLLERR | POLLHUP | POLLNVAL)) {
		report(LOG_ERR, "exception on listen FD %d", s[c]);
		tac_exit(1);
	    }
	}

	if (newsockfd < 0) {
	    if (errno == EINTR)
		continue;

	    report(LOG_ERR, "accept: %s", strerror(errno));
	    continue;
	}

	if (lookup_peer)
	    flags = 0;
	else
	    flags = NI_NUMERICHOST;
#ifdef IPV6
	if (getnameinfo((struct sockaddr_in6 *)&from, from_len, host, 128, NULL, 0,
			flags)) {
#else
	if (getnameinfo((struct sockaddr_in *)&from, from_len, host, 128, NULL, 0,
			flags)) {
#endif
	    strncpy(host, "unknown", NI_MAXHOST - 1);
	    host[NI_MAXHOST - 1] = '\0';
	}

	if (session.peer) free(session.peer);
	session.peer = tac_strdup(host);

	if (session.peerip) free(session.peerip);
#ifdef IPV6
	session.peerip = tac_strdup((char *)inet_ntop(from.sin6_family,
          &from.sin6_addr, host, INET6_ADDRSTRLEN));
#else
	session.peerip = tac_strdup((char *)inet_ntop(from.sin_family,
          &from.sin_addr, host, INET_ADDRSTRLEN));
#endif
	if (debug & DEBUG_PACKET_FLAG)
	    report(LOG_DEBUG, "session request from %s sock=%d",
		   session.peer, newsockfd);

	if (!single) {
#if defined(REAPCHILD) && defined(REAPSIGIGN)
      /* first we check the tocal process count to see if we are at the limit */
      if (total_child_count >= cfg_get_maxprocs()) {
        report(LOG_ALERT, "refused connection from %s [%s] at global max procs [%d]",
          session.peer, session.peerip, total_child_count);
        shutdown(newsockfd, 2);
        close(newsockfd);
        continue;
      }
      /* no we check the process count per client */
      procs_for_client = get_client_count(session.peerip);
      report(LOG_ALERT, "connection [%d] from %s [%s]", procs_for_client + 1, session.peer, session.peerip);
      if (procs_for_client >= cfg_get_maxprocsperclt()) {
        report(LOG_ALERT, "refused connection from %s [%s] at client max procs [%d]",
          session.peer, session.peerip, procs_for_client);
        shutdown(newsockfd, 2);
        close(newsockfd);
        continue;
      }
#endif
	    pid = fork();
	    if (pid < 0) {
		    report(LOG_ERR, "fork error");
		    tac_exit(1);
	    }
	} else {
	    pid = 0;
	}
	if (pid == 0) {
	  /* child */
	  if (!single) {
            if (ns > 1) {
              for (c = 0; c < ns; c++) {
                close(s[c]);
              }
            }
          }
	  session.sock = newsockfd;
#ifdef LIBWRAP
	  if (! hosts_ctl(progname,session.peer,session.peerip,progname)) {
		  report(LOG_ALERT, "refused connection from %s [%s]",
		       session.peer, session.peerip);
      shutdown(session.sock, 2);
      close(session.sock);
      if (!single) {
          tac_exit(0);
      } else {
          close(session.sock);
          continue;
      }
    }
    if (debug)
      report(LOG_DEBUG, "connect from %s [%s]", session.peer, session.peerip);
#endif
#if PROFILE
	    moncontrol(1);
#endif

	    start_session();
	    shutdown(session.sock, 2);
	    close(session.sock);
	    if (!single)
		    tac_exit(0);
	} else {
	    /* parent */
#if defined(REAPCHILD) && defined(REAPSIGIGN)
      total_child_count++;
      procs_for_client = increment_client_count_for_proc(pid, session.peerip);
      snprintf(msgbuf, MSGBUFSZ, "forked %lu for %s, procs %d, procs for client %d",
            (long)pid, session.peerip, total_child_count, procs_for_client);
		    report(LOG_DEBUG, msgbuf);
#endif
	    close(newsockfd);
	}
    }
}
Esempio n. 7
0
char *
NET_BaseAdrToString(netadr_t a)
{
	static char s[64], tmp[64];
	struct sockaddr_storage ss;
	struct sockaddr_in6 *s6;

	switch (a.type)
	{
		case NA_IP:
		case NA_LOOPBACK:
			Com_sprintf(s, sizeof(s), "%i.%i.%i.%i", a.ip[0],
				a.ip[1], a.ip[2], a.ip[3]);
			break;

		case NA_BROADCAST:
			Com_sprintf(s, sizeof(s), "255.255.255.255");
			break;

		case NA_IP6:
		case NA_MULTICAST6:
			memset(&ss, 0, sizeof(ss));
			s6 = (struct sockaddr_in6 *)&ss;

			if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)a.ip))
			{
#ifdef __FreeBSD__
				ss.ss_len = sizeof(struct sockaddr_in);
#endif
				ss.ss_family = AF_INET;
				memcpy(&((struct sockaddr_in *)&ss)->sin_addr,
						&((struct in6_addr *)a.ip)->s6_addr[12],
						sizeof(struct in_addr));
			}
			else
			{
#ifdef __FreeBSD__
				s6->sin6_len = sizeof(struct sockaddr_in6);
#endif
				s6->sin6_scope_id = a.scope_id;
				s6->sin6_family = AF_INET6;
				memcpy(&s6->sin6_addr, a.ip, sizeof(struct in6_addr));
			}

#ifdef __FreeBSD__
			socklen_t const salen = ss.ss_len;
#else
			socklen_t const salen = sizeof(ss);
#endif
			if (getnameinfo((struct sockaddr*)&ss, salen, s, sizeof(s), NULL, 0, NI_NUMERICHOST))
			{
				Com_sprintf(s, sizeof(s), "<invalid>");
			}

			else
			{
				if ((a.type == NA_MULTICAST6) ||
					IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&ss)-> sin6_addr))
				{
					/* If the address is multicast (link) or a
					   link-local, need to carry the scope. The string
					   format of the IPv6 address is used by the
					   client to extablish the connect to the
					   server. */
					Com_sprintf(tmp, sizeof(tmp), "%s%%%d", s,
							s6->sin6_scope_id);
					memcpy(s, tmp, sizeof(s));
				}
			}

			break;

		default:
			Com_sprintf(s, sizeof(s), "invalid IP address family type");
			break;
	}

	return s;
}
Esempio n. 8
0
LWS_VISIBLE int
libwebsockets_get_addresses(struct libwebsocket_context *context,
			    void *ads, char *name, int name_len,
			    char *rip, int rip_len)
{
	struct addrinfo ai, *res;
	void *p = NULL;

	rip[0] = '\0';
	name[0] = '\0';

#ifdef LWS_USE_IPV6
	if (LWS_IPV6_ENABLED(context)) {
		if (!lws_plat_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)ads)->sin6_addr, rip, rip_len)) {
			lwsl_err("inet_ntop", strerror(LWS_ERRNO));
			return -1;
		}

		// Strip off the IPv4 to IPv6 header if one exists
		if (strncmp(rip, "::ffff:", 7) == 0)
			memmove(rip, rip + 7, strlen(rip) - 6);

		getnameinfo((struct sockaddr *)ads,
				sizeof(struct sockaddr_in6), name,
							name_len, NULL, 0, 0);
		
		return 0;
	} else
#endif
	{
		memset(&ai, 0, sizeof ai);
		ai.ai_family = PF_UNSPEC;
		ai.ai_socktype = SOCK_STREAM;
		ai.ai_flags = AI_CANONNAME;

		if (getnameinfo((struct sockaddr *)ads,
				sizeof(struct sockaddr_in),
				name, name_len, NULL, 0, 0))
			return -1;

		if (!rip)
			return 0;

		if (getaddrinfo(name, NULL, &ai, &res))
			return -1;

		while (!p && res) {
			switch (res->ai_family) {
			case AF_INET:
				p = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
				break;
			}

			res = res->ai_next;
		}
	}

	if (!p)
		return -1;

	lws_plat_inet_ntop(AF_INET, p, rip, rip_len);

	return 0;
}
Esempio n. 9
0
void comm(SOCKET &sock)
{
	CHAR rbuf[RBUFSIZE];
	std::string sbuf, ckey, s, res;
	int i, n;
	BOOL recvflag = TRUE;

	while(recvflag)
	{
		ZeroMemory(rbuf, sizeof(rbuf));
		n = recv(sock, rbuf, sizeof(rbuf) - 1, 0);
		if(n == SOCKET_ERROR || n <= 0)
		{
			disconnect(sock);
			return;
		}

		sbuf += rbuf;

		if(sbuf.empty())
		{
			disconnect(sock);
			return;
		}

		switch(sbuf.front())
		{
		case REQ_KEY:
		case REQ_CMP:
			if(rbuf[n - 1] == '\x20')
			{
				recvflag = FALSE;
			}
			break;
		case REQ_END:
		case REQ_VER:
		case REQ_HST:
		default:
			recvflag = FALSE;
			break;
		}
	}

	switch(sbuf.front())
	{
	case REQ_END:
		disconnect(sock);
		return;
		break;

	case REQ_KEY:
		if(sbuf.size() > 2)
		{
			ckey = sbuf.substr(1, sbuf.size() - 2);
			n = (int)vdicinfo.size();
			for(i = 0; i < n; i++)
			{
				s.clear();

				if(vdicinfo[i].path.compare(0, wcslen(INIVAL_SKKSERV), INIVAL_SKKSERV) == 0)
				{
					search_skkserv(vdicinfo[i], ckey, s);
				}
				else if(vdicinfo[i].path.compare(0, wcslen(INIVAL_GOOGLECGIAPI), INIVAL_GOOGLECGIAPI) == 0)
				{
					search_google_cgiapi(vdicinfo[i], ckey, s);
				}
				else
				{
					search_dictionary(vdicinfo[i], ckey, s);
				}

				if(!s.empty())
				{
					if(res.size() >= 2)
					{
						res.pop_back();	// '\n'
						res.pop_back(); // '/'
					}
					res += s;
				}
			}
		}

		if(res.empty())
		{
			res.push_back(REP_NOT_FOUND);
			res.push_back('\n');
		}
		else
		{
			res.insert(res.begin(), REP_FOUND);
		}
		break;

	case REQ_VER:
		res = resver;
		break;

	case REQ_HST:
	{
		CHAR host[NI_MAXHOST];
		SOCKADDR_STORAGE sa;
		int len = sizeof(sa);
		if(getsockname(sock, (LPSOCKADDR)&sa, &len) == 0)
		{
			if(getnameinfo((LPSOCKADDR)&sa, len, host, _countof(host), nullptr, 0, NI_NAMEREQD) == 0)
			{
				res += host;
				res += "/";
			}
			if(getnameinfo((LPSOCKADDR)&sa, len, host, _countof(host), nullptr, 0, NI_NUMERICHOST) == 0)
			{
				if(sa.ss_family == AF_INET6) res += "[";
				res += host;
				if(sa.ss_family == AF_INET6) res += "]";
				res += ":";
				res += WCTOU8(serv_port);
				res += "/\x20";
			}
		}
	}
		break;

	case REQ_CMP:
		res.push_back(REP_NOT_FOUND);
		res.push_back('\n');
		break;

	default:
		return;
		break;
	}

	if(send(sock, res.c_str(), (int)res.size(), 0) == SOCKET_ERROR)
	{
		disconnect(sock);
		return;
	}
}
Esempio n. 10
0
int main(int argc, char **argv)
{
    int sfd = 0, s = 0;
    int efd = 0;
    struct epoll_event event = {};
    struct epoll_event *events = NULL;

    if (argc != 2)
    {
        fprintf(stderr, "usage: %s [port]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    sfd = create_and_bind(argv[1]);
    if (sfd == -1) {abort();}
    fprintf(stdout, "sfd: %d\n", sfd);

    s = make_socket_non_blocking(sfd);
    if (s == -1) {abort();}

    s = listen(sfd, SOMAXCONN);
    if (s == -1)
    {
        perror("listen");
        abort();
    }

    efd = epoll_create(256);
    if (efd == -1)
    {
        perror("epoll_create1");
        abort();
    }

    event.data.fd = sfd;
    event.events = EPOLLIN | EPOLLET;
    s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event);
    if (s == -1)
    {
        perror("epoll_ctl");
        abort();
    }

    //Buffer where events are returned
    events = calloc(MAXEVENTS, sizeof(event));

    fprintf(stdout, "before event loop\n");
    //The event loop
    while (1)
    {
        int n, i;

        n = epoll_wait(efd, events, MAXEVENTS, -1);
        fprintf(stdout, "epoll wait return: %d\n", n);
        for (i=0; i<n; i++)
        {
            fprintf(stdout, "events[%d].data.fd=%d\n", i, events[i].data.fd);
            if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP)
                    || (!(events[i].events & EPOLLIN)))
            {
                //an error has occured on this fd, or the socket is not ready for reading
                fprintf(stderr, "epoll error\n");
                close(events[i].data.fd);
                continue;
            }
            else if (sfd == events[i].data.fd)
            {
                //we have a notification on the listening socket, which means one or more
                //incoming connections
                fprintf(stdout, "sfd == events[i].data.fd\n");
                while (1)
                {
                    struct sockaddr in_addr = {};
                    socklen_t in_len = 0;
                    int infd = 0;
                    char hbuf[NI_MAXHOST] = {}, sbuf[NI_MAXSERV] = {};

                    in_len = sizeof(in_addr);
                    infd = accept(sfd, &in_addr, &in_len);
                    if (infd == -1)
                    {
                        if (errno == EAGAIN || errno == EWOULDBLOCK)
                        {
                            //we have processed all incoming connections
                            fprintf(stderr, "accept error: %d\n", errno);
                            break;
                        }
                        else
                        {
                            perror("accept");
                            break;
                        }
                    }
                    fprintf(stdout, "infd=%d\n", infd);

                    s = getnameinfo(&in_addr, in_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), 
                            NI_NUMERICHOST | NI_NUMERICSERV);
                    if (s == 0)
                    {
                        printf("accepted connection on descriptor %d (host=%s, port=%s)\n", 
                                infd, hbuf, sbuf);
                    }

                    fprintf(stdout, "getnameinfo return s:%d\n", s);
                    //make the incoming socket non-blocking and add it to the list of fds
                    //to monitor
                    s = make_socket_non_blocking(infd);
                    if (s == -1) {abort();}

                    event.data.fd = infd;
                    event.events = EPOLLIN | EPOLLET;
                    s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event);
                    if (s == -1)
                    {
                        perror("epoll_ctl");
                        abort();
                    }
                }
                continue;
            }
            else
            {
                //we have data on the fd waiting to be read. Read and display it. We must read
                //whatever data is available completely, as we are running in edge-triggered 
                //mode and won't get a notification again for the same data
                int done = 0;
                
                fprintf(stdout, "else\n");
                while (1)
                {
                    ssize_t count = 0;
                    char buf[512] = "hello epoll";

                    count  = read(events[i].data.fd, buf, sizeof(buf));
                    fprintf(stdout, "read return count=%d\n", count);
                    if (count == -1)
                    {
                        //if errno == EAGAIN , that means we have read all data.
                        //So go back to the main loop
                        fprintf(stdout, "count==-1, errno:%d\n", errno);
                        if (errno != EAGAIN)
                        {
                            perror("read");
                            done = 1;
                        }
                        break;
                    }
                    else if (count == 0)
                    {
                        //end of file. The remote has closed the connection
                        fprintf(stdout, "count == 0\n");
                        done = -1;
                        break;
                    }

                    printf("read data: %s\n", buf);
                    //write the buffer to standard output
                    s = write(STDOUT_FILENO, buf, count);
                    if (s == -1)
                    {
                        perror("write");
                        abort();
                    }
                }

                if (done)
                {
                    printf("closed connection on descriptor %d\n", events[i].data.fd);

                    //closing the descriptor will make epoll remove it from the set of
                    //descriptors which are monitored
                    close(events[i].data.fd);
                }
            }
        }
    }

    free(events);
    events = NULL;
    close(sfd);

    return EXIT_SUCCESS;
}
Esempio n. 11
0
/* miniwget3() :
 * do all the work.
 * Return NULL if something failed. */
static void *
miniwget3(const char * url, const char * host,
          unsigned short port, const char * path,
          int * size, char * addr_str, int addr_str_len,
          const char * httpversion)
{
	char buf[2048];
    int s;
	int n;
	int len;
	int sent;
	void * content;

	*size = 0;
	s = connecthostport(host, port);
	if(s < 0)
		return NULL;

	/* get address for caller ! */
	if(addr_str)
	{
		struct sockaddr_storage saddr;
		socklen_t saddrlen;

		saddrlen = sizeof(saddr);
		if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
		{
			perror("getsockname");
		}
		else
		{
#if defined(__amigaos__) && !defined(__amigaos4__)
	/* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
     * But his function make a string with the port :  nn.nn.nn.nn:port */
/*		if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
                            NULL, addr_str, (DWORD *)&addr_str_len))
		{
		    printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
		}*/
			/* the following code is only compatible with ip v4 addresses */
			strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len);
#else
#if 0
			if(saddr.sa_family == AF_INET6) {
				inet_ntop(AF_INET6,
				          &(((struct sockaddr_in6 *)&saddr)->sin6_addr),
				          addr_str, addr_str_len);
			} else {
				inet_ntop(AF_INET,
				          &(((struct sockaddr_in *)&saddr)->sin_addr),
				          addr_str, addr_str_len);
			}
#endif
			/* getnameinfo return ip v6 address with the scope identifier
			 * such as : 2a01:e35:8b2b:7330::%4281128194 */
			n = getnameinfo((const struct sockaddr *)&saddr, saddrlen,
			                addr_str, addr_str_len,
			                NULL, 0,
			                NI_NUMERICHOST | NI_NUMERICSERV);
			if(n != 0) {
#ifdef _WIN32
				fprintf(stderr, "getnameinfo() failed : %d\n", n);
#else
				fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
#endif
			}
#endif
		}
#ifdef DEBUG
		printf("address miniwget : %s\n", addr_str);
#endif
	}

	len = snprintf(buf, sizeof(buf),
                 "GET %s HTTP/%s\r\n"
			     "Host: %s:%d\r\n"
				 "Connection: Close\r\n"
				 "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"

				 "\r\n",
			   path, httpversion, host, port);
	sent = 0;
	/* sending the HTTP request */
	while(sent < len)
	{
		n = send(s, buf+sent, len-sent, 0);
		if(n < 0)
		{
			perror("send");
			closesocket(s);
			return NULL;
		}
		else
		{
			sent += n;
		}
	}
	content = getHTTPResponse(s, size);
	closesocket(s);
	return content;
}
Esempio n. 12
0
/*
 * Creates a listening socket and returns it in saddr_ptr.
 */
int ft_listen( struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client, char **errptr )
{
	int fd, gret, saddrlen;
	struct addrinfo hints, *rp;
	socklen_t ssize = sizeof( struct sockaddr_storage );
	struct sockaddr_storage saddrs, *saddr = &saddrs;
	static char errmsg[1024];
	char *ftlisten = global.conf->ft_listen;

	if( errptr )
		*errptr = errmsg;

	strcpy( port, "0" );

	/* Format is <IP-A>[:<Port-A>];<IP-B>[:<Port-B>] where
	 * A is for connections with the bitlbee client (DCC)
	 * and B is for connections with IM peers.
	 */
	if( ftlisten )
	{
		char *scolon = strchr( ftlisten, ';' );
		char *colon;

		if( scolon )
		{
			if( for_bitlbee_client )
			{
				*scolon = '\0';
				strncpy( host, ftlisten, HOST_NAME_MAX );
				*scolon = ';';
			}
			else
			{
				strncpy( host, scolon + 1, HOST_NAME_MAX );
			}
		}
		else
		{
			strncpy( host, ftlisten, HOST_NAME_MAX );
		}

		if( ( colon = strchr( host, ':' ) ) )
		{
			*colon = '\0';
			strncpy( port, colon + 1, 5 );
		}
	}
	else if( copy_fd >= 0 && getsockname( copy_fd, (struct sockaddr*) &saddrs, &ssize ) == 0 &&
	         ( saddrs.ss_family == AF_INET || saddrs.ss_family == AF_INET6 ) &&
	         getnameinfo( (struct sockaddr*) &saddrs, ssize, host, HOST_NAME_MAX,
	                      NULL, 0, NI_NUMERICHOST ) == 0 )
	{
		/* We just took our local address on copy_fd, which is likely to be a
		   sensible address from which we can do a file transfer now - the
		   most sensible we can get easily. */
	}
	else
	{
		ASSERTSOCKOP( gethostname( host, HOST_NAME_MAX + 1 ), "gethostname()" );
	}

	memset( &hints, 0, sizeof( struct addrinfo ) );
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_NUMERICSERV;

	if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) != 0 )
	{
		sprintf( errmsg, "getaddrinfo() failed: %s", gai_strerror( gret ) );
		return -1;
	}

	saddrlen = rp->ai_addrlen;

	memcpy( saddr, rp->ai_addr, saddrlen );

	freeaddrinfo( rp );

	ASSERTSOCKOP( fd = socket( saddr->ss_family, SOCK_STREAM, 0 ), "Opening socket" );
	ASSERTSOCKOP( bind( fd, ( struct sockaddr *)saddr, saddrlen ), "Binding socket" );
	ASSERTSOCKOP( listen( fd, 1 ), "Making socket listen" );

	if ( !inet_ntop( saddr->ss_family, saddr->ss_family == AF_INET ?
			( void * )&( ( struct sockaddr_in * ) saddr )->sin_addr.s_addr :
			( void * )&( ( struct sockaddr_in6 * ) saddr )->sin6_addr.s6_addr,
			host, HOST_NAME_MAX ) )
	{
		strcpy( errmsg, "inet_ntop failed on listening socket" );
		return -1;
	}

	ssize = sizeof( struct sockaddr_storage );
	ASSERTSOCKOP( getsockname( fd, ( struct sockaddr *)saddr, &ssize ), "Getting socket name" );

	if( saddr->ss_family == AF_INET )
		g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in *) saddr )->sin_port ) );
	else
		g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in6 *) saddr )->sin6_port ) );

	if( saddr_ptr )
		memcpy( saddr_ptr, saddr, saddrlen );

	/* I hate static-length strings.. */
	host[HOST_NAME_MAX] = '\0';
	port[5] = '\0';
	
	return fd;
}
Esempio n. 13
0
int main(int ac, char *av[])
{
	//initialize a lot of struct and data points needed
    struct addrinfo *in, *pin;
    struct addrinfo start;
    int sockets[10], socket_num = 0;	
	allocatedMemory[0] = 0;
	myStruct *arg;
	pthread_t dthread;
	pthread_mutex_t *mutex;
	//clear the struct data values
	memset(&start, 0, sizeof start);//clear the object and then check for the right number of arguments passed
	
    if (ac < 3) 
	{
		printf("Usage: %s -p <port>\n", av[0]), exit(0);
	}
	if (ac == 4)
	{
		printf("Usage: %s -p <port> -R <path>\n", av[0]), exit(0);
	}
	else if (ac == 5) 
	{
		path = av[4];
	}
	//set the flags for the correct type of server
    start.ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_ADDRCONFIG;
    start.ai_protocol = IPPROTO_TCP; // only interested in TCP
    start.ai_family = AF_INET6;
	
	if (strcmp(av[1],"-p"))
		return -1;
	//gets the port number
    char *nport = av[2];

    int gai = getaddrinfo(NULL, nport, &start, &in);
	
    if (gai != 0)
	{
        gai_strerror(gai);
		exit(-1);
	}

    char printed_addr[1024];
    for (pin = in; pin; pin = pin->ai_next) {
        assert (pin->ai_protocol == IPPROTO_TCP);
        int gai = getnameinfo(pin->ai_addr, pin->ai_addrlen,
                             printed_addr, sizeof printed_addr, NULL, 0,
                             NI_NUMERICHOST);
		
        if (gai != 0)
            gai_strerror(gai), exit(-1);

        printf("%s: %s\n", pin->ai_family == AF_INET ? "AF_INET" :
                           pin->ai_family == AF_INET6 ? "AF_INET6" : "?", 
                           printed_addr);

        int s = socket(pin->ai_family, pin->ai_socktype, pin->ai_protocol);
        if (s == -1)
            perror("socket"), exit(-1);

        int opt = 1;
        setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));

        gai = bind(s, pin->ai_addr, pin->ai_addrlen);
        if (gai == -1 && errno == EADDRINUSE) {
            // ignore Linux limitation
            close(s);
            continue;
        }

        if (gai == -1)
            perror("bind"), exit(-1);
		//begin listening on the socket
        gai = listen(s, 10);
        if (gai == -1)
            perror("listen"), exit(-1);

        assert(socket_num < sizeof(sockets)/sizeof(sockets[0]));
        sockets[socket_num++] = s;
    }
	freeaddrinfo(in);
    assert(socket_num == 1);
	//initialize mutex before accepting
    struct sockaddr_storage rem;
    socklen_t remlen = sizeof (rem);
	
	mutex = malloc(sizeof(pthread_mutex_t));
	pthread_mutex_init(mutex, NULL);
	while(1){
		//accept a connection
		arg = malloc(sizeof(myStruct));
		arg->mutex = mutex;
		//accept the connection
        arg->s = accept (sockets[0], (struct sockaddr *) &rem, &remlen);
		
		//if the connection works
        if (arg->s == -1)
		{
			pthread_mutex_lock(mutex);
            perror ("accept");
			pthread_mutex_unlock(mutex);
			free(arg);
			pthread_mutex_destroy(mutex);
			exit(-1);			
		}
		pthread_mutex_lock(mutex);

        char buffer[200];

		//get information about the connection
        if (getnameinfo ((struct sockaddr *) &rem, remlen, buffer, sizeof (buffer), NULL, 0, 0))
            strcpy (buffer, "???");   // hostname unknown

        char buf2[100];
        (void) getnameinfo ((struct sockaddr *) &rem, remlen, 
                buf2, sizeof (buf2), NULL, 0, NI_NUMERICHOST);
        printf ("connection from %s (%s)\n", buffer, buf2);
		
		
		//create the thread and call the echo functions
		//makes sure to lock and unlock and set the stack size
		pthread_mutex_unlock(mutex);
		arg->attribute = malloc(sizeof(pthread_attr_t));
		pthread_attr_init(arg->attribute);
		pthread_attr_setstacksize(arg->attribute, PTHREAD_STACK_MIN+8192);
		pthread_attr_setdetachstate(arg->attribute, PTHREAD_CREATE_DETACHED);
		pthread_create(&dthread, arg->attribute, echo, arg);
		
    }

    return 0;
}
Esempio n. 14
0
void StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config)
{
    int sd = -1;
    fd_set rset;
    struct timeval timeout;
    int ret_val;
    CfLock thislock;
    time_t last_collect = 0, last_policy_reload = 0;
    extern int COLLECT_WINDOW;

    struct sockaddr_storage cin;
    socklen_t addrlen = sizeof(cin);

    MakeSignalPipe();

    signal(SIGINT, HandleSignalsForDaemon);
    signal(SIGTERM, HandleSignalsForDaemon);
    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGUSR1, HandleSignalsForDaemon);
    signal(SIGUSR2, HandleSignalsForDaemon);

    ServerTLSInitialize();

    sd = SetServerListenState(ctx, QUEUESIZE, SERVER_LISTEN, &InitServer);

    TransactionContext tc = {
        .ifelapsed = 0,
        .expireafter = 1,
    };

    Policy *server_cfengine_policy = PolicyNew();
    Promise *pp = NULL;
    {
        Bundle *bp = PolicyAppendBundle(server_cfengine_policy, NamespaceDefault(), "server_cfengine_bundle", "agent", NULL, NULL);
        PromiseType *tp = BundleAppendPromiseType(bp, "server_cfengine");

        pp = PromiseTypeAppendPromise(tp, config->input_file, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL);
    }
    assert(pp);

    thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false);

    if (thislock.lock == NULL)
    {
        PolicyDestroy(server_cfengine_policy);
        return;
    }

    if (sd != -1)
    {
        Log(LOG_LEVEL_VERBOSE, "Listening for connections ...");
    }

#ifdef __MINGW32__

    if (!NO_FORK)
    {
        Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground");
    }

#else /* !__MINGW32__ */

    if ((!NO_FORK) && (fork() != 0))
    {
        _exit(0);
    }

    if (!NO_FORK)
    {
        ActAsDaemon();
    }

#endif /* !__MINGW32__ */

    WritePID("cf-serverd.pid");

/* Andrew Stribblehill <*****@*****.**> -- close sd on exec */
#ifndef __MINGW32__
    fcntl(sd, F_SETFD, FD_CLOEXEC);
#endif

    while (!IsPendingTermination())
    {
        time_t now = time(NULL);

        /* Note that this loop logic is single threaded, but ACTIVE_THREADS
           might still change in threads pertaining to service handling */

        if (ThreadLock(cft_server_children))
        {
            if (ACTIVE_THREADS == 0)
            {
                CheckFileChanges(ctx, policy, config, &last_policy_reload);
            }
            ThreadUnlock(cft_server_children);
        }

        // Check whether we should try to establish peering with a hub

        if ((COLLECT_INTERVAL > 0) && ((now - last_collect) > COLLECT_INTERVAL))
        {
            TryCollectCall(COLLECT_WINDOW, &ServerEntryPoint);
            last_collect = now;
            continue;
        }

        /* check if listening is working */
        if (sd != -1)
        {
            // Look for normal incoming service requests

            int signal_pipe = GetSignalPipe();
            FD_ZERO(&rset);
            FD_SET(sd, &rset);
            FD_SET(signal_pipe, &rset);

            timeout.tv_sec = 60;
            timeout.tv_usec = 0;

            Log(LOG_LEVEL_DEBUG, "Waiting at incoming select...");

            int max_fd = (sd > signal_pipe) ? (sd + 1) : (signal_pipe + 1);
            ret_val = select(max_fd, &rset, NULL, NULL, &timeout);

            // Empty the signal pipe. We don't need the values.
            unsigned char buf;
            while (recv(signal_pipe, &buf, 1, 0) > 0) {}

            if (ret_val == -1)      /* Error received from call to select */
            {
                if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Log(LOG_LEVEL_ERR, "select failed. (select: %s)", GetErrorStr());
                    exit(1);
                }
            }
            else if (!ret_val) /* No data waiting, we must have timed out! */
            {
                continue;
            }

            if (FD_ISSET(sd, &rset))
            {
                int new_client = accept(sd, (struct sockaddr *)&cin, &addrlen);
                if (new_client == -1)
                {
                    continue;
                }
                /* Just convert IP address to string, no DNS lookup. */
                char ipaddr[CF_MAX_IP_LEN] = "";
                getnameinfo((struct sockaddr *) &cin, addrlen,
                            ipaddr, sizeof(ipaddr),
                            NULL, 0, NI_NUMERICHOST);
                ConnectionInfo *info = ConnectionInfoNew();
                if (info)
                {
                    ConnectionInfoSetSocket(info, new_client);
                    ServerEntryPoint(ctx, ipaddr, info);
                }
            }
        }
    }

    PolicyDestroy(server_cfengine_policy);
}

/*********************************************************************/
/* Level 2                                                           */
/*********************************************************************/

int InitServer(size_t queue_size)
{
    int sd = -1;

    if ((sd = OpenReceiverChannel()) == -1)
    {
        Log(LOG_LEVEL_ERR, "Unable to start server");
        exit(1);
    }

    if (listen(sd, queue_size) == -1)
    {
        Log(LOG_LEVEL_ERR, "listen failed. (listen: %s)", GetErrorStr());
        exit(1);
    }

    return sd;
}
Esempio n. 15
0
void
NET_SendPacket ( netsrc_t sock, int length, void *data, netadr_t to )
{
	int ret;
	struct sockaddr_storage addr;
	int net_socket;
	int addr_size = sizeof(struct sockaddr_in);

	switch (to.type)
	{
		case NA_LOOPBACK:
			NET_SendLoopPacket(sock, length, data, to);
			return;
			break;

		case NA_BROADCAST:
		case NA_IP:
			net_socket = ip_sockets[sock];

			if (!net_socket)
			{
				return;
			}

			break;

		case NA_IP6:
		case NA_MULTICAST6:
			net_socket = ip6_sockets[sock];
			addr_size = sizeof(struct sockaddr_in6);

			if (!net_socket)
			{
				return;
			}

			break;

		case NA_IPX:
		case NA_BROADCAST_IPX:
			net_socket = ipx_sockets[sock];

			if (!net_socket)
			{
				return;
			}

			break;

		default:
			Com_Error(ERR_FATAL, "NET_SendPacket: bad address type");
			return;
			break;
	}

	NetadrToSockadr(&to, &addr);

	/* Re-check the address family. If to.type is NA_IP6 but
	   contains an IPv4 mapped address, NetadrToSockadr will
	   return an AF_INET struct.  If so, switch back to AF_INET
	   socket.*/
	if ((to.type == NA_IP6) && (addr.ss_family == AF_INET))
	{
		net_socket = ip_sockets[sock];
		addr_size = sizeof(struct sockaddr_in);

		if (!net_socket)
		{
			return;
		}
	}

	if (addr.ss_family == AF_INET6)
	{
		struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&addr;

		/* If multicast socket, must specify scope.
		   So multicast_interface must be specified */
		if (IN6_IS_ADDR_MULTICAST(&s6->sin6_addr))
		{
			struct addrinfo hints;
			struct addrinfo *res;
			char tmp[128], mcast_addr[128], mcast_port[10];
			int error;

			if (multicast_interface != NULL)
			{
				/* Do a getnameinfo/getaddrinfo cycle
				   to calculate the scope_id of the
				   multicast address. getaddrinfo is
				   passed a multicast address of the
				   form ff0x::xxx%multicast_interface */
#ifdef __FreeBSD__
				error = getnameinfo((struct sockaddr *)s6, s6->sin6_len, tmp,
						sizeof(tmp), NULL, 0, NI_NUMERICHOST);
#else
				error = getnameinfo((struct sockaddr *)s6, sizeof(struct sockaddr_in6),
							tmp, sizeof(tmp), NULL, 0, NI_NUMERICHOST);
#endif

				if (error)
				{
					Com_Printf("NET_SendPacket: getnameinfo: %s\n", gai_strerror(error));
					return;
				}

				Com_sprintf(mcast_addr, sizeof(mcast_addr), "%s%%%s", tmp,
						multicast_interface);
				Com_sprintf(mcast_port, sizeof(mcast_port), "%d",
						ntohs(s6->sin6_port));
				memset(&hints, 0, sizeof(hints));
				hints.ai_family = AF_INET6;
				hints.ai_socktype = SOCK_DGRAM;
				hints.ai_flags = AI_NUMERICHOST;

				error = getaddrinfo(mcast_addr, mcast_port, &hints, &res);

				if (error)
				{
					Com_Printf("NET_SendPacket: getaddrinfo: %s\n", gai_strerror(error));
					return;
				}

				/* sockaddr_in6 should now have a valid scope_id. */
				memcpy(s6, res->ai_addr, res->ai_addrlen);
			}
			else
			{
				Com_Printf("NET_SendPacket: IPv6 multicast destination but +set multicast not specified: %s\n",
						inet_ntop(AF_INET6, &s6->sin6_addr, tmp, sizeof(tmp)));
				return;
			}
		}
	}

	ret = sendto(net_socket, data, length, 0, (struct sockaddr *)&addr, addr_size);

	if (ret == -1)
	{
		Com_Printf("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(),
				NET_AdrToString(to));
	}
}
Esempio n. 16
0
int OpenReceiverChannel(void)
{
    struct addrinfo *response, *ap;
    struct addrinfo query = {
        .ai_flags = AI_PASSIVE,
        .ai_family = AF_UNSPEC,
        .ai_socktype = SOCK_STREAM
    };

    /* Listen to INADDR(6)_ANY if BINDINTERFACE unset. */
    char *ptr = NULL;
    if (BINDINTERFACE[0] != '\0')
    {
        ptr = BINDINTERFACE;
    }

    char servname[10];
    snprintf(servname, 10, "%d", CFENGINE_PORT);

    /* Resolve listening interface. */
    if (getaddrinfo(ptr, servname, &query, &response) != 0)
    {
        Log(LOG_LEVEL_ERR, "DNS/service lookup failure. (getaddrinfo: %s)", GetErrorStr());
        return -1;
    }

    int sd = -1;
    for (ap = response; ap != NULL; ap = ap->ai_next)
    {
        if ((sd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol)) == -1)
        {
            continue;
        }

        int yes = 1;
        if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
                       &yes, sizeof(yes)) == -1)
        {
            Log(LOG_LEVEL_ERR, "Socket option SO_REUSEADDR was not accepted. (setsockopt: %s)", GetErrorStr());
            exit(1);
        }

        struct linger cflinger = {
            .l_onoff = 1,
            .l_linger = 60
        };
        if (setsockopt(sd, SOL_SOCKET, SO_LINGER,
                       &cflinger, sizeof(cflinger)) == -1)
        {
            Log(LOG_LEVEL_ERR, "Socket option SO_LINGER was not accepted. (setsockopt: %s)", GetErrorStr());
            exit(1);
        }

        if (bind(sd, ap->ai_addr, ap->ai_addrlen) != -1)
        {
            if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
            {
                /* Convert IP address to string, no DNS lookup performed. */
                char txtaddr[CF_MAX_IP_LEN] = "";
                getnameinfo(ap->ai_addr, ap->ai_addrlen,
                            txtaddr, sizeof(txtaddr),
                            NULL, 0, NI_NUMERICHOST);
                Log(LOG_LEVEL_DEBUG, "Bound to address '%s' on '%s' = %d", txtaddr,
                    CLASSTEXT[VSYSTEMHARDCLASS], VSYSTEMHARDCLASS);
            }
            break;
        }
        else
        {
            Log(LOG_LEVEL_ERR, "Could not bind server address. (bind: %s)", GetErrorStr());
            cf_closesocket(sd);
        }
    }

    if (sd < 0)
    {
        Log(LOG_LEVEL_ERR, "Couldn't open/bind a socket");
        exit(1);
    }

    freeaddrinfo(response);
    return sd;
}

/*********************************************************************/
/* Level 3                                                           */
/*********************************************************************/

void CheckFileChanges(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, time_t *last_policy_reload)
{
    time_t validated_at;

    Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file);

    validated_at = ReadTimestampFromPolicyValidatedMasterfiles(config);

    if (*last_policy_reload < validated_at)
    {
        *last_policy_reload = validated_at;

        Log(LOG_LEVEL_VERBOSE, "New promises detected...");

        if (GenericAgentArePromisesValid(config))
        {
            Log(LOG_LEVEL_INFO, "Rereading policy file '%s'", config->input_file);

            /* Free & reload -- lock this to avoid access errors during reload */
            
            EvalContextClear(ctx);

            free(SV.allowciphers);
            SV.allowciphers = NULL;

            DeleteItemList(SV.trustkeylist);
            DeleteItemList(SV.attackerlist);
            DeleteItemList(SV.nonattackerlist);
            DeleteItemList(SV.multiconnlist);

            DeleteAuthList(SV.admit);
            DeleteAuthList(SV.deny);

            DeleteAuthList(SV.varadmit);
            DeleteAuthList(SV.vardeny);

            DeleteAuthList(SV.roles);

            strcpy(VDOMAIN, "undefined.domain");

            SV.admit = NULL;
            SV.admittop = NULL;

            SV.varadmit = NULL;
            SV.varadmittop = NULL;

            SV.deny = NULL;
            SV.denytop = NULL;

            SV.vardeny = NULL;
            SV.vardenytop = NULL;

            SV.roles = NULL;
            SV.rolestop = NULL;

            SV.trustkeylist = NULL;
            SV.attackerlist = NULL;
            SV.nonattackerlist = NULL;
            SV.multiconnlist = NULL;

            PolicyDestroy(*policy);
            *policy = NULL;

            {
                char *existing_policy_server = ReadPolicyServerFile(GetWorkDir());
                SetPolicyServer(ctx, existing_policy_server);
                free(existing_policy_server);
            }
            UpdateLastPolicyUpdateTime(ctx);

            DetectEnvironment(ctx);
            KeepHardClasses(ctx);

            EvalContextClassPutHard(ctx, CF_AGENTTYPES[config->agent_type], "cfe_internal,source=agent");

            time_t t = SetReferenceTime();
            UpdateTimeClasses(ctx, t);
            *policy = GenericAgentLoadPolicy(ctx, config);
            KeepPromises(ctx, *policy, config);
            Summarize();
        }
        else
        {
            Log(LOG_LEVEL_INFO, "File changes contain errors -- ignoring");
        }
    }
    else
    {
        Log(LOG_LEVEL_DEBUG, "No new promises found");
    }
}
Esempio n. 17
0
char *
inet6name(const unsigned char *in6)
{
	char *cp;
	static char line[NI_MAXHOST];
	static char domain[MAXHOSTNAMELEN];
	static int first = 1;
#ifdef NETSNMP_ENABLE_IPV6
	struct hostent *hp;
	char hbuf[NI_MAXHOST];
	const int niflag = NI_NUMERICHOST;
	struct sockaddr_in6 sin6;
	const struct in6_addr *in6p = (const struct in6_addr *)in6;
#endif

	if (first && !nflag) {
		first = 0;
		if (gethostname(line, sizeof(line)) == 0 &&
		    (cp = strchr(line, '.')))
			(void) strlcpy(domain, cp + 1, sizeof domain);
		else
			domain[0] = '\0';
	}
#ifdef NETSNMP_ENABLE_IPV6
	cp = NULL;
	if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
		hp = netsnmp_gethostbyaddr((const char *)in6p, sizeof(*in6p),
                                           AF_INET6);
		if (hp) {
			if ((cp = strchr(hp->h_name, '.')) &&
			    !strcmp(cp + 1, domain))
				*cp = 0;
			cp = hp->h_name;
		}
	}
	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
		strlcpy(line, "*", sizeof(line));
	else if (cp)
		strlcpy(line, cp, sizeof(line));
	else {
		memset(&sin6, 0, sizeof(sin6));
/*		sin6.sin6_len = sizeof(sin6);   */
		sin6.sin6_family = AF_INET6;
		sin6.sin6_addr = *in6p;
#ifdef __KAME__
		if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
		    IN6_IS_ADDR_MC_LINKLOCAL(in6p)) {
			sin6.sin6_scope_id =
			    ntohs(*(const uint16_t *)&in6p->s6_addr[2]);
			sin6.sin6_addr.s6_addr[2] = 0;
			sin6.sin6_addr.s6_addr[3] = 0;
		}
#endif
		if (getnameinfo((struct sockaddr *)&sin6, sizeof(sin6),
		    hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
			strlcpy(hbuf, "?", sizeof hbuf);
		strlcpy(line, hbuf, sizeof(line));
	}
#else
	strlcpy(line, "[[XXX - inet6 address]]", sizeof(line));
#endif
	return (line);
}
Esempio n. 18
0
/*
 * Setup to handle new incoming connections
 */
static void
ssl_accept(
    const struct security_driver *driver,
    char *	(*conf_fn)(char *, void *),
    int		in,
    int		out,
    void	(*fn)(security_handle_t *, pkt_t *),
    void       *datap)
{
    sockaddr_union sin;
    socklen_t_equiv len = sizeof(struct sockaddr);
    struct tcp_conn *rc;
    char hostname[NI_MAXHOST];
    int result;
    char *errmsg = NULL;
    int   err;
    X509 *remote_cert;
    char *str;
    X509_NAME *x509_name;
    char *cert_hostname;
    SSL_CTX            *ctx;
    SSL                *ssl;
    int loc;
    char *ssl_dir = getconf_str(CNF_SSL_DIR);
    char *ssl_fingerprint_file = conf_fn("ssl_fingerprint_file", datap);
    char *ssl_cert_file        = conf_fn("ssl_cert_file", datap);
    char *ssl_key_file         = conf_fn("ssl_key_file", datap);
    char *ssl_ca_cert_file     = conf_fn("ssl_ca_cert_file", datap);
    char *ssl_cipher_list      = conf_fn("ssl_cipher_list", datap);
    int   ssl_check_host       = atoi(conf_fn("ssl_check_host", datap));
    int   ssl_check_certificate_host = atoi(conf_fn("ssl_check_certificate_host", datap));

    if (getpeername(in, (struct sockaddr *)&sin, &len) < 0) {
	g_debug(_("getpeername returned: %s"), strerror(errno));
	return;
    }
    if ((result = getnameinfo((struct sockaddr *)&sin, len,
			      hostname, NI_MAXHOST, NULL, 0, 0) != 0)) {
	g_debug(_("getnameinfo failed: %s"),
		  gai_strerror(result));
	return;
    }

    if (ssl_check_host && check_name_give_sockaddr(hostname,
				 (struct sockaddr *)&sin, &errmsg) < 0) {
	amfree(errmsg);
	return;
    }

    if (ssl_dir) {
	if (!ssl_cert_file || ssl_cert_file == '\0') {
	    ssl_cert_file = g_strdup_printf("%s/me/crt.pem", ssl_dir);
	}
	if (!ssl_key_file || ssl_key_file == '\0') {
	    ssl_key_file = g_strdup_printf("%s/me/private/key.pem", ssl_dir);
	}
	if (!ssl_ca_cert_file || ssl_ca_cert_file == '\0') {
	    ssl_ca_cert_file = g_strdup_printf("%s/CA/crt.pem", ssl_dir);
	}
    }

    if (!ssl_cert_file) {
	g_debug(_("ssl-cert-file must be set in amanda-remote.conf"));
	return;
    }

    if (!ssl_key_file) {
	g_debug(_("ssl-key-file must be set in amanda-remote.conf"));
	return;
    }

    if (!ssl_ca_cert_file) {
	g_debug(_("ssl_ca_cert_file must be set in amanda-remote.conf"));
	return;
    }

    len = sizeof(sin);
    init_ssl();

    /* Create a SSL_CTX structure */
#if OPENSSL_VERSION_NUMBER < 0x10100000L
    ctx = SSL_CTX_new(SSLv3_server_method());
#else
    ctx = SSL_CTX_new(TLS_server_method());
#endif
    if (!ctx) {
	g_debug(_("SSL_CTX_new failed: %s"),
		 ERR_error_string(ERR_get_error(), NULL));
	return;
    }
    SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);

    if (ssl_cipher_list) {
	g_debug("Set ssl_cipher_list to %s", ssl_cipher_list);
	if (SSL_CTX_set_cipher_list(ctx, ssl_cipher_list) == 0) {
	    g_debug(_("SSL_CTX_set_cipher_list failed: %s"),
		     ERR_error_string(ERR_get_error(), NULL));
	    return;
	}
    }

    /* Load the me certificate into the SSL_CTX structure */
    g_debug(_("Loading ssl-cert-file certificate %s"), ssl_cert_file);
    if (SSL_CTX_use_certificate_file(ctx, ssl_cert_file,
				     SSL_FILETYPE_PEM) <= 0) {
	g_debug(_("Load ssl-cert-file failed: %s"),
		 ERR_error_string(ERR_get_error(), NULL));
	return;
    }

    /* Load the private-key corresponding to the me certificate */
    g_debug(_("Loading ssl-key-file private-key %s"), ssl_key_file);
    if (SSL_CTX_use_PrivateKey_file(ctx, ssl_key_file,
				    SSL_FILETYPE_PEM) <= 0) {
	g_debug(_("Load ssl-key-file failed: %s"),
		 ERR_error_string(ERR_get_error(), NULL));
	return;
    }

    if (ssl_ca_cert_file) {
        /* Load the RSA CA certificate into the SSL_CTX structure */
	g_debug(_("Loading ssl-ca-cert-file ca certificate %s"),
		 ssl_ca_cert_file);
        if (!SSL_CTX_load_verify_locations(ctx, ssl_ca_cert_file, NULL)) {
	    g_debug(_("Load ssl-ca-cert-file failed: %s"),
		     ERR_error_string(ERR_get_error(), NULL));
	    return;
        }

	/* Set to require peer (remote) certificate verification */
	SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

	/* Set the verification depth to 1 */
	SSL_CTX_set_verify_depth(ctx,1);
    }

    ssl = SSL_new(ctx);
    if (!ssl) {
	g_debug(_("SSL_new failed: %s"),
		 ERR_error_string(ERR_get_error(), NULL));
	return;
    }
    SSL_set_accept_state(ssl);

    /* Assign the socket into the SSL structure (SSL and socket without BIO) */
    SSL_set_fd(ssl, in);

    /* Perform SSL Handshake on the SSL me */
    err = SSL_accept(ssl);
    if (err == -1) {
	g_debug(_("SSL_accept failed: %s"),
		 ERR_error_string(ERR_get_error(), NULL));
	return;
    }

    /* Get the me's certificate (optional) */
    remote_cert = SSL_get_peer_certificate (ssl);

    if (remote_cert == NULL) {
	g_debug(_("remote doesn't sent a certificate"));
	return;
    }

    x509_name = X509_get_subject_name(remote_cert);
    str = X509_NAME_oneline(X509_get_subject_name(remote_cert), 0, 0);
    auth_debug(1, _("\t subject: %s\n"), str);
    amfree (str);

    str = X509_NAME_oneline(X509_get_issuer_name(remote_cert), 0, 0);
    auth_debug(1, _("\t issuer: %s\n"), str);
    amfree(str);

    loc = -1;
    loc = X509_NAME_get_index_by_NID(x509_name, NID_commonName, loc);
    if (loc != -1) {
	X509_NAME_ENTRY *x509_entry = X509_NAME_get_entry(x509_name, loc);
	ASN1_STRING *asn1_string = X509_NAME_ENTRY_get_data(x509_entry);
	cert_hostname = (char *)ASN1_STRING_data(asn1_string);
	auth_debug(1, "common_name: %s\n", cert_hostname);

	if (ssl_check_certificate_host &&
	    check_name_give_sockaddr((char*)cert_hostname,
			 (struct sockaddr *)&sin, &errmsg) < 0) {
	    g_debug("Common name of certicate (%s) doesn't resolv to IP (%s)", cert_hostname, str_sockaddr(&sin));
	    amfree(errmsg);
	    X509_free(remote_cert);
	    return;
	}
    } else {
	g_debug("Certificate have no common name");
	X509_free(remote_cert);
	return;
    }

    if (ssl_dir) {
	if (!ssl_fingerprint_file || ssl_fingerprint_file == '\0') {
	    struct stat  statbuf;
	    ssl_fingerprint_file = g_strdup_printf("%s/remote/%s/fingerprint", ssl_dir, cert_hostname);
	    if (stat(ssl_fingerprint_file, &statbuf) == -1) {
		g_free(ssl_fingerprint_file);
		ssl_fingerprint_file = NULL;
	    }
	}
    }

    if (ssl_fingerprint_file) {
        g_debug(_("Loading ssl-fingerprint-file %s"), ssl_fingerprint_file);
	str = validate_fingerprints(remote_cert, ssl_fingerprint_file);
	if (str) {
	    g_debug("%s", str);
	    amfree(str);
	    X509_free(remote_cert);
	    return;
	}
    }
    X509_free(remote_cert);

    rc = sec_tcp_conn_get(NULL, hostname, 0);
    rc->recv_security_ok = &bsd_recv_security_ok;
    rc->prefix_packet = &bsd_prefix_packet;
    rc->need_priv_port = 0;
    copy_sockaddr(&rc->peer, &sin);
    rc->read = in;
    rc->write = out;
    rc->accept_fn = fn;
    rc->driver = driver;
    rc->conf_fn = conf_fn;
    rc->datap = datap;
    rc->ctx = ctx;
    rc->ssl = ssl;
    strncpy(rc->hostname, cert_hostname, sizeof(rc->hostname)-1);

    g_debug(_("SSL_cipher: %s"), SSL_get_cipher(rc->ssl));

    sec_tcp_conn_read(rc);
}
Esempio n. 19
0
int IdentifyAgent(int sd)
{
    char uname[CF_BUFSIZE], sendbuff[CF_BUFSIZE];
    char dnsname[CF_MAXVARSIZE], localip[CF_MAX_IP_LEN];
    int ret;

    if ((!SKIPIDENTIFY) && (strcmp(VDOMAIN, CF_START_DOMAIN) == 0))
    {
        Log(LOG_LEVEL_ERR, "Undefined domain name");
        return false;
    }

    if (!SKIPIDENTIFY)
    {
        /* First we need to find out the IP address and DNS name of the socket
           we are sending from. This is not necessarily the same as VFQNAME if
           the machine has a different uname from its IP name (!) This can
           happen on poorly set up machines or on hosts with multiple
           interfaces, with different names on each interface ... */
        struct sockaddr_storage myaddr = {0};
        socklen_t myaddr_len = sizeof(myaddr);

        if (getsockname(sd, (struct sockaddr *) &myaddr, &myaddr_len) == -1)
        {
            Log(LOG_LEVEL_ERR, "Couldn't get socket address. (getsockname: %s)", GetErrorStr());
            return false;
        }

        /* No lookup, just convert the bound address to string. */
        ret = getnameinfo((struct sockaddr *) &myaddr, myaddr_len,
                          localip, sizeof(localip),
                          NULL, 0, NI_NUMERICHOST);
        if (ret != 0)
        {
            Log(LOG_LEVEL_ERR,
                "During agent identification. (getnameinfo: %s)",
                  gai_strerror(ret));
            return false;
        }

        /* dnsname: Reverse lookup of the bound IP address. */
        ret = getnameinfo((struct sockaddr *) &myaddr, myaddr_len,
                          dnsname, sizeof(dnsname), NULL, 0, 0);
        if (ret != 0)
        {
            /* getnameinfo doesn't fail on resolution failure, it just prints
             * the IP, so here something else is wrong. */
            Log(LOG_LEVEL_ERR,
                "During agent identification for '%s'. (getnameinfo: %s)",
                  localip, gai_strerror(ret));
            return false;
        }

        /* getnameinfo() should always return FQDN. Some resolvers will not
         * return FQNAME and missing PTR will give numerical result */
        if ((strlen(VDOMAIN) > 0)                      /* TODO true always? */
            && (!IsIPV6Address(dnsname)) && (!strchr(dnsname, '.')))
        {
            strcat(dnsname, ".");
            strncat(dnsname, VDOMAIN, CF_MAXVARSIZE / 2);
        }

        /* Seems to be a bug in some resolvers that adds garbage, when it just
         * returns the input. */
        if (strncmp(dnsname, localip, strlen(localip)) == 0
            && dnsname[strlen(localip)] != '\0')
        {
            dnsname[strlen(localip)] = '\0';
            Log(LOG_LEVEL_WARNING,
                "getnameinfo() seems to append garbage to unresolvable IPs, bug mitigated by CFEngine but please report your platform!");
        }
    }
    else
    {
        assert(sizeof(localip) >= sizeof(VIPADDRESS));
        strcpy(localip, VIPADDRESS);

        Log(LOG_LEVEL_VERBOSE,
            "skipidentify was promised, so we are trusting and simply announcing the identity as '%s' for this host",
            strlen(VFQNAME) > 0 ? VFQNAME : "skipident");
        if (strlen(VFQNAME) > 0)
        {
            strcpy(dnsname, VFQNAME);
        }
        else
        {
            strcpy(dnsname, "skipident");
        }
    }

/* client always identifies as root on windows */
#ifdef __MINGW32__
    snprintf(uname, sizeof(uname), "%s", "root");
#else
    GetCurrentUserName(uname, sizeof(uname));
#endif

    snprintf(sendbuff, sizeof(sendbuff), "CAUTH %s %s %s %d",
             localip, dnsname, uname, 0);

    if (SendTransaction(sd, sendbuff, 0, CF_DONE) == -1)
    {
        Log(LOG_LEVEL_ERR,
              "During identify agent, could not send auth response. (SendTransaction: %s)", GetErrorStr());
        return false;
    }

    return true;
}
Esempio n. 20
0
char *ast_sockaddr_stringify_fmt(const struct ast_sockaddr *sa, int format)
{
	struct ast_sockaddr sa_ipv4;
	const struct ast_sockaddr *sa_tmp;
	char host[NI_MAXHOST];
	char port[NI_MAXSERV];
	struct ast_str *str;
	int e;
	static const size_t size = sizeof(host) - 1 + sizeof(port) - 1 + 4;


	if (ast_sockaddr_isnull(sa)) {
		return "(null)";
	}

	if (!(str = ast_str_thread_get(&ast_sockaddr_stringify_buf, size))) {
		return "";
	}

	if (ast_sockaddr_ipv4_mapped(sa, &sa_ipv4)) {
		sa_tmp = &sa_ipv4;
	} else {
		sa_tmp = sa;
	}

	if ((e = getnameinfo((struct sockaddr *)&sa_tmp->ss, sa_tmp->len,
			     format & AST_SOCKADDR_STR_ADDR ? host : NULL,
			     format & AST_SOCKADDR_STR_ADDR ? sizeof(host) : 0,
			     format & AST_SOCKADDR_STR_PORT ? port : 0,
			     format & AST_SOCKADDR_STR_PORT ? sizeof(port): 0,
			     NI_NUMERICHOST | NI_NUMERICSERV))) {
		ast_log(LOG_ERROR, "getnameinfo(): %s\n", gai_strerror(e));
		return "";
	}

	if ((format & AST_SOCKADDR_STR_REMOTE) == AST_SOCKADDR_STR_REMOTE) {
		char *p;
		if (ast_sockaddr_is_ipv6_link_local(sa) && (p = strchr(host, '%'))) {
			*p = '\0';
		}
	}

	switch ((format & AST_SOCKADDR_STR_FORMAT_MASK))  {
	case AST_SOCKADDR_STR_DEFAULT:
		ast_str_set(&str, 0, sa_tmp->ss.ss_family == AF_INET6 ?
				"[%s]:%s" : "%s:%s", host, port);
		break;
	case AST_SOCKADDR_STR_ADDR:
		ast_str_set(&str, 0, "%s", host);
		break;
	case AST_SOCKADDR_STR_HOST:
		ast_str_set(&str, 0,
			    sa_tmp->ss.ss_family == AF_INET6 ? "[%s]" : "%s", host);
		break;
	case AST_SOCKADDR_STR_PORT:
		ast_str_set(&str, 0, "%s", port);
		break;
	default:
		ast_log(LOG_ERROR, "Invalid format\n");
		return "";
	}

	return ast_str_buffer(str);
}
Esempio n. 21
0
/*
 * Return a socket bound to an appropriate port number/address. Exits
 * the program on failure.
 */
static int
get_socket(int **sa, int *nsa)
{
    char	host[NI_MAXHOST], serv[NI_MAXHOST];
    struct addrinfo hint, *res, *rp;
    u_long inaddr;
    int		ecode,
		flag,
		kalive = 1,
		s;

    memset(&hint, 0, sizeof(struct addrinfo));
    hint.ai_family = AF_UNSPEC;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_protocol = IPPROTO_TCP;
    hint.ai_flags = AI_PASSIVE;
#ifdef AI_ADDRCONFIG
    hint.ai_flags |= AI_ADDRCONFIG;
#endif
    if (bind_address)
	ecode = getaddrinfo(bind_address, portstr, &hint, &res);
    else
	ecode = getaddrinfo(NULL, portstr, &hint, &res);
    if (ecode != 0) {
	report(LOG_ERR, "getaddrinfo: %s\n", gai_strerror(ecode));
	    tac_exit(1);
	}

    *sa = NULL;
    *nsa = 0;
    for (rp = res; rp != NULL; rp = rp->ai_next) {
	s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
	if (s == -1)
	    continue;

	if (1 || debug & DEBUG_PACKET_FLAG)
	    report(LOG_DEBUG, "socket FD %d AF %d", s, rp->ai_family);
	flag = 1;
	if (rp->ai_family == AF_INET6)
	    setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag));
#ifdef SO_REUSEADDR
	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&flag,
		       sizeof(flag)) < 0)
	perror("setsockopt - SO_REUSEADDR");
#endif
    if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *)&kalive,
		   sizeof(kalive)) < 0)
	    perror("setsockopt - SO_KEEPALIVE");
	flag = 0;
	if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
		       sizeof(flag)) < 0)
	    perror("setsockopt - SO_NODELAY");

	if (bind(s, rp->ai_addr, rp->ai_addrlen) < 0) {
	    console = 1;
	    ecode = errno;
	    if (lookup_peer)
		flag = 0;
	    else
		flag = NI_NUMERICHOST | NI_NUMERICSERV;
	    if (getnameinfo(rp->ai_addr, rp->ai_addrlen, host, NI_MAXHOST,
			    serv, NI_MAXHOST, flag)) {
		strncpy(host, "unknown", NI_MAXHOST - 1);
		host[NI_MAXHOST - 1] = '\0';
		strncpy(serv, "unknown", NI_MAXHOST - 1);
		serv[NI_MAXHOST - 1] = '\0';
	    }
	    report(LOG_ERR, "get_socket: bind %s:%s %s", host, serv,
		   strerror(ecode));
	    console = 0;
	    close(s);
	    s = -1;
	    continue;
	}
	if (*sa == NULL)
	    *sa = malloc(sizeof(int) * ++(*nsa));
	else
	    *sa = realloc(*sa, sizeof(int) * ++(*nsa));
	if (*sa == NULL) {
	    report(LOG_ERR, "malloc failure: %s", strerror(errno));
	tac_exit(1);
    }
	(*sa)[*nsa - 1] = s;
    }
    freeaddrinfo(res);

    if (*nsa < 1) {
	console = 1;
	report(LOG_ERR, "get_socket: could not bind a listening socket");
	tac_exit(1);
    }
    return(0);
}