コード例 #1
0
ファイル: ex-serv-dtls.c プロジェクト: nobled/gnutls
static ssize_t
pull_func (gnutls_transport_ptr_t p, void *data, size_t size)
{
    priv_data_st *priv = p;
    struct sockaddr_in cli_addr;
    socklen_t cli_addr_size;
    char buffer[64];
    int ret;

    cli_addr_size = sizeof (cli_addr);
    ret =
        recvfrom (priv->fd, data, size, 0, (struct sockaddr *) &cli_addr,
                  &cli_addr_size);
    if (ret == -1)
        return ret;

    if (cli_addr_size == priv->cli_addr_size
            && memcmp (&cli_addr, priv->cli_addr, sizeof (cli_addr)) == 0)
        return ret;

    printf ("Denied connection from %s\n",
            human_addr ((struct sockaddr *)
                        &cli_addr, sizeof (cli_addr), buffer, sizeof (buffer)));

    gnutls_transport_set_errno (priv->session, EAGAIN);
    return -1;
}
コード例 #2
0
ファイル: ip-lease.c プロジェクト: cernekee/ocserv
int get_ip_leases(main_server_st* s, struct proc_st* proc)
{
int ret;
char buf[128];

	if (proc->ipv4 == NULL) {
		ret = get_ipv4_lease(s, proc);
		if (ret < 0)
			return ret;

		if (proc->ipv4) {
			if (htable_add(&s->ip_leases.ht, rehash(proc->ipv4, NULL), proc->ipv4) == 0) {
				mslog(s, proc, LOG_ERR, "could not add IPv4 lease to hash table.");
				return -1;
			}
		}
	}

	if (proc->ipv6 == NULL) {
		ret = get_ipv6_lease(s, proc);
		if (ret < 0)
			return ret;

		if (proc->ipv6) {
			if (htable_add(&s->ip_leases.ht, rehash(proc->ipv6, NULL), proc->ipv6) == 0) {
				mslog(s, proc, LOG_ERR, "could not add IPv6 lease to hash table.");
				return -1;
			}
		}
	}

	if (proc->ipv4 == 0 && proc->ipv6 == 0) {
		mslog(s, proc, LOG_ERR, "no IPv4 or IPv6 addresses are configured. Cannot obtain lease.");
		return -1;
	}
	
	if (proc->ipv4)
		mslog(s, proc, LOG_INFO, "assigned IPv4 to '%s': %s", proc->username,
			human_addr((void*)&proc->ipv4->rip, proc->ipv4->rip_len, buf, sizeof(buf)));

	if (proc->ipv6)
		mslog(s, proc, LOG_INFO, "assigned IPv6 to '%s': %s", proc->username,
			human_addr((void*)&proc->ipv6->rip, proc->ipv6->rip_len, buf, sizeof(buf)));
		
	return 0;
}
コード例 #3
0
ファイル: log.c プロジェクト: fqtools/ocserv
    _mslog(const main_server_st * s, const struct proc_st* proc,
    	int priority, const char *fmt, ...)
{
	char buf[512];
	char ipbuf[128];
	const char* ip = NULL;
	va_list args;

	if (priority == LOG_DEBUG && s->perm_config->debug < 3)
		return;

	if (priority == LOG_HTTP_DEBUG) {
	    if (s->perm_config->debug < DEBUG_HTTP)
                return;
            else
                priority = LOG_DEBUG;
        } else if (priority == LOG_TRANSFER_DEBUG) {
	    if (s->perm_config->debug < DEBUG_TRANSFERRED)
                return;
            else
                priority = LOG_DEBUG;
        }

	if (proc) {
		ip = human_addr((void*)&proc->remote_addr, proc->remote_addr_len,
			    ipbuf, sizeof(ipbuf));
	}

	va_start(args, fmt);
	vsnprintf(buf, sizeof(buf), fmt, args);
	va_end(args);

	if (ip) {
		if (proc->username[0] == 0)
			syslog(priority, "main: %s %s", ip, buf);
		else
			syslog(priority, "main[%s]: %s %s", proc->username, ip, buf);
	} else {
		syslog(priority, "main: %s", buf);
	}

	return;
}
コード例 #4
0
ファイル: udp-serv.c プロジェクト: intgr/gnutls
void udp_server(const char* name, int port, int mtu)
{
    int sock, ret;
    struct sockaddr_in cli_addr;
    socklen_t cli_addr_size;
    char buffer[MAX_BUFFER];
    priv_data_st priv;
    gnutls_session_t session;
    gnutls_datum_t cookie_key;
    gnutls_dtls_prestate_st prestate;
    unsigned char sequence[8];

    ret = gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE);
    if (ret < 0)
      {
        fprintf(stderr, "Cannot generate key\n");
        exit(1);
      }

    ret = listen_socket (name, port, SOCK_DGRAM);
    if (ret < 0)
      {
        fprintf(stderr, "Cannot listen\n");
        exit (1);
      }

    for (;;)
      {
        printf("Waiting for connection...\n");
        sock = wait_for_connection();
        if (sock < 0)
          continue;

        cli_addr_size = sizeof(cli_addr);
        ret = recvfrom(sock, buffer, sizeof(buffer), MSG_PEEK, (struct sockaddr*)&cli_addr, &cli_addr_size);
        if (ret > 0)
          {
            memset(&prestate, 0, sizeof(prestate));
            ret = gnutls_dtls_cookie_verify(&cookie_key, &cli_addr, sizeof(cli_addr), buffer, ret, &prestate);
            if (ret < 0) /* cookie not valid */
              {
                priv_data_st s;
                
                memset(&s,0,sizeof(s));
                s.fd = sock;
                s.cli_addr = (void*)&cli_addr;
                s.cli_addr_size = sizeof(cli_addr);
                
                printf("Sending hello verify request to %s\n", human_addr ((struct sockaddr *)
                  &cli_addr, sizeof(cli_addr), buffer, sizeof(buffer)));
                gnutls_dtls_cookie_send(&cookie_key, &cli_addr, sizeof(cli_addr), &prestate, (gnutls_transport_ptr_t)&s, push_func);

                /* discard peeked data*/
                recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&cli_addr, &cli_addr_size);
                continue;
              }
            printf ("Accepted connection from %s\n",
                            human_addr ((struct sockaddr *)
                                        &cli_addr, sizeof(cli_addr), buffer,
                                        sizeof (buffer)));
          }
        else
          continue;

        session = initialize_session(1);
        gnutls_dtls_prestate_set(session, &prestate);
        if (mtu) gnutls_dtls_set_mtu(session, mtu);

        priv.session = session;
        priv.fd = sock;
        priv.cli_addr = (struct sockaddr *)&cli_addr;
        priv.cli_addr_size = sizeof(cli_addr);

        gnutls_transport_set_ptr (session, &priv);
        gnutls_transport_set_push_function (session, push_func);
        gnutls_transport_set_pull_function (session, pull_func);
        gnutls_transport_set_pull_timeout_function (session, pull_timeout_func);

        do
          {
            ret = gnutls_handshake(session);
          }
        while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

        if (ret < 0)
          {
            fprintf(stderr, "Error in handshake(): %s\n", gnutls_strerror(ret));
            gnutls_deinit(session);
            continue;
          }

        for(;;)
          {
            do {
              ret = gnutls_record_recv_seq(session, buffer, MAX_BUFFER, sequence);
            } while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

            if (ret == GNUTLS_E_REHANDSHAKE)
              {
                fprintf (stderr, "*** Received hello message\n");
                do
                  {
                    ret = gnutls_handshake (session);
                  }
                while (ret == GNUTLS_E_INTERRUPTED ||
                       ret == GNUTLS_E_AGAIN);
                
                if (ret == 0) continue;
              }
            if (ret < 0)
              {
                fprintf(stderr, "Error in recv(): %s\n", gnutls_strerror(ret));
                break;
              }
            if (ret == 0)
              {
                printf("EOF\n\n");
                break;
              }
              
            buffer[ret] = 0;
            printf("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n", sequence[0], sequence[1], sequence[2],
                   sequence[3], sequence[4], sequence[5], sequence[6], sequence[7], buffer);

            if (check_command(session, buffer) == 0)
              {
                /* reply back */
                ret = gnutls_record_send(session, buffer, ret);
                if (ret < 0)
                  {
                    fprintf(stderr, "Error in send(): %s\n", gnutls_strerror(ret));
                    break;
                  }
              }
          }
      }
    gnutls_deinit(session);
}
コード例 #5
0
ファイル: ex-serv-dtls.c プロジェクト: nobled/gnutls
int
main (void)
{
    int listen_sd;
    int sock, ret;
    struct sockaddr_in sa_serv;
    struct sockaddr_in cli_addr;
    socklen_t cli_addr_size;
    gnutls_session_t session;
    char buffer[MAX_BUFFER];
    priv_data_st priv;
    gnutls_datum_t cookie_key;
    gnutls_dtls_prestate_st prestate;
    int mtu = 1400;
    unsigned char sequence[8];

    /* this must be called once in the program
     */
    gnutls_global_init ();

    gnutls_certificate_allocate_credentials (&x509_cred);
    gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE,
                                            GNUTLS_X509_FMT_PEM);

    gnutls_certificate_set_x509_crl_file (x509_cred, CRLFILE,
                                          GNUTLS_X509_FMT_PEM);

    ret = gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE,
            GNUTLS_X509_FMT_PEM);
    if (ret < 0)
    {
        printf("No certificate or key were found\n");
        exit(1);
    }

    generate_dh_params ();

    gnutls_certificate_set_dh_params (x509_cred, dh_params);

    gnutls_priority_init (&priority_cache,
                          "PERFORMANCE:-VERS-TLS-ALL:+VERS-DTLS1.0:%SERVER_PRECEDENCE",
                          NULL);

    gnutls_key_generate (&cookie_key, GNUTLS_COOKIE_KEY_SIZE);

    /* Socket operations
     */
    listen_sd = socket (AF_INET, SOCK_DGRAM, 0);

    memset (&sa_serv, '\0', sizeof (sa_serv));
    sa_serv.sin_family = AF_INET;
    sa_serv.sin_addr.s_addr = INADDR_ANY;
    sa_serv.sin_port = htons (PORT);

    {   /* DTLS requires the IP don't fragment (DF) bit to be set */
#if defined(IP_DONTFRAG)
        int optval = 1;
        setsockopt (listen_sd, IPPROTO_IP, IP_DONTFRAG,
                    (const void *) &optval, sizeof (optval));
#elif defined(IP_MTU_DISCOVER)
        int optval = IP_PMTUDISC_DO;
        setsockopt(listen_sd, IPPROTO_IP, IP_MTU_DISCOVER,
                   (const void*) &optval, sizeof (optval));
#endif
    }

    bind (listen_sd, (struct sockaddr *) &sa_serv, sizeof (sa_serv));

    printf ("UDP server ready. Listening to port '%d'.\n\n", PORT);

    for (;;)
    {
        printf ("Waiting for connection...\n");
        sock = wait_for_connection (listen_sd);
        if (sock < 0)
            continue;

        cli_addr_size = sizeof (cli_addr);
        ret = recvfrom (sock, buffer, sizeof (buffer), MSG_PEEK,
                        (struct sockaddr *) &cli_addr, &cli_addr_size);
        if (ret > 0)
        {
            memset (&prestate, 0, sizeof (prestate));
            ret = gnutls_dtls_cookie_verify (&cookie_key, &cli_addr,
                                             sizeof (cli_addr), buffer, ret,
                                             &prestate);
            if (ret < 0)          /* cookie not valid */
            {
                priv_data_st s;

                memset (&s, 0, sizeof (s));
                s.fd = sock;
                s.cli_addr = (void *) &cli_addr;
                s.cli_addr_size = sizeof (cli_addr);

                printf ("Sending hello verify request to %s\n",
                        human_addr ((struct sockaddr *) &cli_addr,
                                    sizeof (cli_addr), buffer,
                                    sizeof (buffer)));

                gnutls_dtls_cookie_send (&cookie_key, &cli_addr,
                                         sizeof (cli_addr), &prestate,
                                         (gnutls_transport_ptr_t) & s,
                                         push_func);

                /* discard peeked data */
                recvfrom (sock, buffer, sizeof (buffer), 0,
                          (struct sockaddr *) &cli_addr, &cli_addr_size);
                usleep (100);
                continue;
            }
            printf ("Accepted connection from %s\n",
                    human_addr ((struct sockaddr *)
                                &cli_addr, sizeof (cli_addr), buffer,
                                sizeof (buffer)));
        }
        else
            continue;

        session = initialize_tls_session ();
        gnutls_dtls_prestate_set (session, &prestate);
        gnutls_dtls_set_mtu (session, mtu);

        priv.session = session;
        priv.fd = sock;
        priv.cli_addr = (struct sockaddr *) &cli_addr;
        priv.cli_addr_size = sizeof (cli_addr);

        gnutls_transport_set_ptr (session, &priv);
        gnutls_transport_set_push_function (session, push_func);
        gnutls_transport_set_pull_function (session, pull_func);
        gnutls_transport_set_pull_timeout_function (session, pull_timeout_func);

        do
        {
            ret = gnutls_handshake (session);
        }
        while (ret < 0 && gnutls_error_is_fatal (ret) == 0);

        if (ret < 0)
        {
            fprintf (stderr, "Error in handshake(): %s\n",
                     gnutls_strerror (ret));
            gnutls_deinit (session);
            continue;
        }

        printf ("- Handshake was completed\n");

        for (;;)
        {
            do
            {
                ret = gnutls_record_recv_seq (session, buffer, MAX_BUFFER,
                                              sequence);
            }
            while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

            if (ret < 0)
            {
                fprintf (stderr, "Error in recv(): %s\n",
                         gnutls_strerror (ret));
                break;
            }
            if (ret == 0)
            {
                printf ("EOF\n\n");
                break;
            }
            buffer[ret] = 0;
            printf ("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n",
                    sequence[0], sequence[1], sequence[2], sequence[3],
                    sequence[4], sequence[5], sequence[6], sequence[7], buffer);

            /* reply back */
            ret = gnutls_record_send (session, buffer, ret);
            if (ret < 0)
            {
                fprintf (stderr, "Error in send(): %s\n",
                         gnutls_strerror (ret));
                break;
            }
        }

        gnutls_bye (session, GNUTLS_SHUT_WR);
        gnutls_deinit (session);

    }
    close (listen_sd);

    gnutls_certificate_free_credentials (x509_cred);
    gnutls_priority_deinit (priority_cache);

    gnutls_global_deinit ();

    return 0;

}
コード例 #6
0
ファイル: ip-lease.c プロジェクト: cernekee/ocserv
static
int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
{

	struct sockaddr_storage tmp, mask, network, rnd;
	unsigned i, max_loops = MAX_IP_TRIES;
	int ret;
	const char* c_network, *c_netmask;
	char buf[64];

	if (proc->config.ipv6_network && proc->config.ipv6_netmask) {
		c_network = proc->config.ipv6_network;
		c_netmask = proc->config.ipv6_netmask;
	} else {
		c_network = s->config->network.ipv6;
		c_netmask = s->config->network.ipv6_netmask;
	}

	if (c_network && c_netmask) {
		ret =
		    inet_pton(AF_INET6, c_network, SA_IN6_P(&network));

		if (ret != 1) {
			mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
			return -1;
		}

		ret =
		    inet_pton(AF_INET6, c_netmask, SA_IN6_P(&mask));
	
		if (ret != 1) {
			mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask);
			return -1;
		}
		
		proc->ipv6 = calloc(1, sizeof(*proc->ipv6));
		if (proc->ipv6 == NULL)
			return ERR_MEM;

		/* mask the network */
		for (i=0;i<sizeof(struct in6_addr);i++)
			SA_IN6_U8_P(&network)[i] &= (SA_IN6_U8_P(&mask)[i]);
		((struct sockaddr_in6*)&network)->sin6_family = AF_INET6;
		((struct sockaddr_in6*)&network)->sin6_port = 0;

       		memcpy(&tmp, &network, sizeof(tmp));
        	((struct sockaddr_in6*)&tmp)->sin6_family = AF_INET6;
        	((struct sockaddr_in6*)&tmp)->sin6_port = AF_INET6;

        	((struct sockaddr_in6*)&rnd)->sin6_family = AF_INET6;
        	((struct sockaddr_in6*)&rnd)->sin6_port = AF_INET6;

		do {
			if (max_loops == 0) {
				mslog(s, NULL, LOG_ERR, "could not figure out a valid IPv6 IP.");
				ret = ERR_NO_IP;
				goto fail;
			}
			
			if (max_loops == MAX_IP_TRIES) {
				uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
				memset(SA_IN6_U8_P(&rnd), 0, sizeof(struct in6_addr));
				memcpy(SA_IN6_U8_P(&rnd)+sizeof(struct in6_addr)-5, &t, 4);
			} else
				gnutls_rnd(GNUTLS_RND_NONCE, SA_IN6_U8_P(&rnd), sizeof(struct in6_addr));
			max_loops--;
			
			/* Mask the random number with the netmask */
        		for (i=0;i<sizeof(struct in6_addr);i++)
        			SA_IN6_U8_P(&rnd)[i] &= ~(SA_IN6_U8_P(&mask)[i]);

			SA_IN6_U8_P(&rnd)[sizeof(struct in6_addr)-1] &= 0xFE;

			/* Now add the network to the masked random number */
        		for (i=0;i<sizeof(struct in6_addr);i++)
        			SA_IN6_U8_P(&rnd)[i] |= (SA_IN6_U8_P(&network)[i]);
        			
 			/* check if it exists in the hash table */
			if (ip_lease_exists(s, &rnd, sizeof(struct sockaddr_in6)) != 0) {
				mslog(s, proc, LOG_DEBUG, "cannot assign local IP %s to '%s'; it is in use.", 
				      human_addr((void*)&rnd, sizeof(struct sockaddr_in6), buf, sizeof(buf)), 
				      proc->username);
				continue;
			}

        		proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
        		memcpy(&proc->ipv6->lip, &rnd, proc->ipv6->lip_len);

        		/* RIP = LIP + 1 */
        		memcpy(&tmp, &proc->ipv6->lip, proc->ipv6->rip_len);

	        	bignum_add(SA_IN6_U8_P(&tmp), sizeof(struct in6_addr), 1);

 			/* check if it exists in the hash table */
			if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in6)) != 0) {
				mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s to '%s'; it is in use.", 
				      human_addr((void*)&tmp, sizeof(struct sockaddr_in6), buf, sizeof(buf)), 
				      proc->username);
				continue;
			}

        		proc->ipv6->rip_len = sizeof(struct sockaddr_in6);
        		memcpy(&proc->ipv6->rip, &tmp, proc->ipv6->rip_len);

        		/* mask the last IP with the netmask */
        		for (i=0;i<sizeof(struct in6_addr);i++)
	        		SA_IN6_U8_P(&tmp)[i] &= (SA_IN6_U8_P(&mask)[i]);

        		/* the result should match the network */
	        	if (memcmp(SA_IN6_U8_P(&network), SA_IN6_U8_P(&tmp), sizeof(struct in6_addr)) != 0) {
		        	continue;
	        	}

			mslog(s, proc, LOG_DEBUG, "selected IP for '%s': %s", proc->username,
			      human_addr((void*)&proc->ipv6->lip, proc->ipv6->lip_len, buf, sizeof(buf)));

	        	if (icmp_ping6(s, (void*)&proc->ipv6->lip, (void*)&proc->ipv6->rip) == 0)
	        		break;
                } while(1);
	}

	return 0;
fail:
	free(proc->ipv6);
	proc->ipv6 = NULL;

	return ret;

}
コード例 #7
0
ファイル: ip-lease.c プロジェクト: a1ive/ocserv-fork
static
int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
{

	struct sockaddr_storage tmp, mask, network, rnd;
	unsigned i;
	unsigned max_loops = MAX_IP_TRIES;
	int ret;
	const char* c_network, *c_netmask;
	char buf[64];

	/* Our IP accounting */
	if (proc->config.ipv4_network && proc->config.ipv4_netmask) {
		c_network = proc->config.ipv4_network;
		c_netmask = proc->config.ipv4_netmask;
	} else {
		c_network = s->config->network.ipv4;
		c_netmask = s->config->network.ipv4_netmask;
	}

	if (c_network == NULL || c_netmask == NULL) {
		mslog(s, NULL, LOG_DEBUG, "there is no IPv4 network assigned");
		return 0;
	}

	ret =
	    inet_pton(AF_INET, c_network, SA_IN_P(&network));
	if (ret != 1) {
		mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
		return -1;
	}

	ret =
	    inet_pton(AF_INET, c_netmask, SA_IN_P(&mask));
	if (ret != 1) {
		mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask);
		return -1;
	}

	/* mask the network (just in case it is wrong) */
	for (i=0;i<sizeof(struct in_addr);i++)
		SA_IN_U8_P(&network)[i] &= (SA_IN_U8_P(&mask)[i]);
       	((struct sockaddr_in*)&network)->sin_family = AF_INET;
       	((struct sockaddr_in*)&network)->sin_port = 0;

	if (proc->config.explicit_ipv4) {
		/* if an explicit IP is given for that client, then
		 * do implicit IP accounting. Require the address
		 * to be odd, so we use the next even address as PtP. */
		ret =
		    inet_pton(AF_INET, proc->config.explicit_ipv4, SA_IN_P(&tmp));

		if (ret != 1) {
			mslog(s, NULL, LOG_ERR, "error reading explicit IP: %s", proc->config.explicit_ipv4);
			return -1;
		}

		proc->ipv4 = talloc_zero(proc, struct ip_lease_st);
		if (proc->ipv4 == NULL)
			return ERR_MEM;

        	((struct sockaddr_in*)&tmp)->sin_family = AF_INET;
        	((struct sockaddr_in*)&tmp)->sin_port = 0;
		memcpy(&proc->ipv4->rip, &tmp, sizeof(struct sockaddr_in));
       		proc->ipv4->rip_len = sizeof(struct sockaddr_in);

		if (is_ipv4_ok(s, &proc->ipv4->rip, &network, &mask) == 0) {
			mslog(s, proc, LOG_DEBUG, "cannot assign explicit IP %s; it is in use or invalid", 
			      human_addr((void*)&tmp, sizeof(struct sockaddr_in), buf, sizeof(buf)));
			ret = ERR_NO_IP;
			goto fail;
		}

		/* LIP = network address + 1 */
		memcpy(&proc->ipv4->lip, &network, sizeof(struct sockaddr_in));
		proc->ipv4->lip_len = sizeof(struct sockaddr_in);
		SA_IN_U8_P(&proc->ipv4->lip)[3] |= 1;

		if (ip_cmp(&proc->ipv4->lip, &proc->ipv4->rip) == 0) {
			mslog(s, NULL, LOG_ERR, "cannot assign explicit IP %s; network: %s", proc->config.explicit_ipv4, c_network);
			ret = ERR_NO_IP;
			goto fail;
		}

		return 0;
	}