コード例 #1
0
static void connect_handler(nsock_pool nsp, nsock_event evt, void *data)
{
    enum nse_status status = nse_status(evt);
    enum nse_type type = nse_type(evt);

    assert(type == NSE_TYPE_CONNECT || type == NSE_TYPE_CONNECT_SSL);

    if (status == NSE_STATUS_ERROR) {
        loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
        exit(1);
    } else if (status == NSE_STATUS_TIMEOUT) {
        loguser("%s.\n", socket_strerror(ETIMEDOUT));
        exit(1);
    } else {
        assert(status == NSE_STATUS_SUCCESS);
    }

#ifdef HAVE_OPENSSL
    if (nsi_checkssl(cs.sock_nsi)) {
        /* Check the domain name. ssl_post_connect_check prints an
           error message if appropriate. */
        if (!ssl_post_connect_check((SSL *) nsi_getssl(cs.sock_nsi), o.target))
            bye("Certificate verification error.");
    }
#endif

    connect_report(cs.sock_nsi);

    /* Create IOD for nsp->stdin */
    if ((cs.stdin_nsi = nsi_new2(nsp, 0, NULL)) == NULL)
        bye("Failed to create stdin nsiod.");

    post_connect(nsp, nse_iod(evt));
}
コード例 #2
0
/* This callback is called for every certificate in a chain. ok is true if
   OpenSSL's internal verification has verified the certificate. We don't change
   anything about the verification, we only need access to the certificates to
   provide diagnostics. */
static int verify_callback(int ok, X509_STORE_CTX *store)
{
    X509 *cert = X509_STORE_CTX_get_current_cert(store);
    int err = X509_STORE_CTX_get_error(store);

    /* Print the subject, issuer, and fingerprint depending on the verbosity
       level. */
    if ((!ok && o.verbose) || o.debug > 1) {
        char digest_buf[SHA1_STRING_LENGTH + 1];

        loguser("Subject: ");
        X509_NAME_print_ex_fp(stderr, X509_get_subject_name(cert), 0, XN_FLAG_COMPAT);
        loguser_noprefix("\n");
        loguser("Issuer: ");
        X509_NAME_print_ex_fp(stderr, X509_get_issuer_name(cert), 0, XN_FLAG_COMPAT);
        loguser_noprefix("\n");

        assert(ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf)) != NULL);
        loguser("SHA-1 fingerprint: %s\n", digest_buf);
    }

    if (!ok && o.verbose) {
        loguser("Certificate verification failed (%s).\n",
            X509_verify_cert_error_string(err));
    }

    return ok;
}
コード例 #3
0
static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data)
{
    enum nse_status status = nse_status(evt);
    enum nse_type type = nse_type(evt);
    char *buf, *tmp = NULL;
    int nbytes;

    assert(type == NSE_TYPE_READ);

    if (status == NSE_STATUS_EOF) {
        if (o.sendonly) {
            /* In --send-only mode, exit after EOF on stdin. */
            nsock_loop_quit(nsp);
        } else {
            shutdown(nsi_getsd(cs.sock_nsi), SHUT_WR);
        }
        return;
    } else if (status == NSE_STATUS_ERROR) {
        loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
        exit(1);
    } else if (status == NSE_STATUS_TIMEOUT) {
        loguser("%s.\n", socket_strerror(ETIMEDOUT));
        exit(1);
    } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) {
        return;
    } else {
        assert(status == NSE_STATUS_SUCCESS);
    }

    buf = nse_readbuf(evt, &nbytes);

    /* read from stdin */
    if (o.linedelay)
        ncat_delay_timer(o.linedelay);

    if (o.crlf) {
        if (fix_line_endings(buf, &nbytes, &tmp, &cs.crlf_state))
            buf = tmp;
    }

    nsock_write(nsp, cs.sock_nsi, write_socket_handler, -1, NULL, buf, nbytes);
    ncat_log_send(buf, nbytes);

    if (tmp)
        free(tmp);

    refresh_idle_timer(nsp);
}
コード例 #4
0
ファイル: ncat_connect.c プロジェクト: richardlee8681/nmap
static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
{
    enum nse_status status = nse_status(evt);
    enum nse_type type = nse_type(evt);
    char *buf;
    int nbytes;

    ncat_assert(type == NSE_TYPE_READ);

    if (status == NSE_STATUS_EOF) {
        Close(STDOUT_FILENO);
        /* In --recv-only mode or non-TCP mode, exit after EOF on the socket. */
        if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.recvonly))
            nsock_loop_quit(nsp);
        return;
    } else if (status == NSE_STATUS_ERROR) {
        loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
        exit(1);
    } else if (status == NSE_STATUS_TIMEOUT) {
        loguser("%s.\n", socket_strerror(ETIMEDOUT));
        exit(1);
    } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) {
        return;
    } else {
        ncat_assert(status == NSE_STATUS_SUCCESS);
    }

    buf = nse_readbuf(evt, &nbytes);

    if (o.linedelay)
        ncat_delay_timer(o.linedelay);

    if (o.telnet)
        dotelnet(nsi_getsd(nse_iod(evt)), (unsigned char *) buf, nbytes);

    /* Write socket data to stdout */
    Write(STDOUT_FILENO, buf, nbytes);
    ncat_log_recv(buf, nbytes);

    nsock_readbytes(nsp, cs.sock_nsi, read_socket_handler, -1, NULL, 0);

    refresh_idle_timer(nsp);
}
コード例 #5
0
ファイル: rx_server.cpp プロジェクト: hailynch/Beagle_SDR_GPS
void rx_server_remove(conn_t *c)
{
	c->stop_data = TRUE;
	c->mc = NULL;
	if (c->type == STREAM_SOUND) loguser(c, "(LEAVING)");
	webserver_connection_cleanup(c);
	if (c->user) wrx_free("user", c->user);
	if (c->geo) wrx_free("geo", c->geo);
	
	int task = c->task;
	conn_init(c, c->type, c->rx_channel);
	TaskRemove(task);
	panic("shouldn't return");
}
コード例 #6
0
static void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
{
    enum nse_status status = nse_status(evt);
    enum nse_type type = nse_type(evt);

    assert(type == NSE_TYPE_WRITE);

    if (status == NSE_STATUS_ERROR) {
        loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
        exit(1);
    } else if (status == NSE_STATUS_TIMEOUT) {
        loguser("%s.\n", socket_strerror(ETIMEDOUT));
        exit(1);
    } else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) {
        return;
    } else {
        assert(status == NSE_STATUS_SUCCESS);
    }

    /* The write to the socket was successful. Allow reading more from stdin
       now. */
    nsock_readbytes(nsp, cs.stdin_nsi, read_stdin_handler, -1, NULL, 0);
}
コード例 #7
0
static void idle_timer_handler(nsock_pool nsp, nsock_event evt, void *data)
{
    enum nse_status status = nse_status(evt);
    enum nse_type type = nse_type(evt);

    assert(type == NSE_TYPE_TIMER);

    if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL)
        return;

    assert(status == NSE_STATUS_SUCCESS);

    loguser("Idle timeout expired (%d ms).\n", o.idletimeout);

    exit(1);
}
コード例 #8
0
ファイル: ncat_connect.c プロジェクト: richardlee8681/nmap
/* Depending on verbosity, print a message that a connection was established. */
static void connect_report(nsock_iod nsi)
{
    union sockaddr_u peer;
    zmem(&peer, sizeof(peer.storage));

    nsi_getlastcommunicationinfo(nsi, NULL, NULL, NULL,
        &peer.sockaddr, sizeof(peer.storage));

    if (o.verbose) {
#ifdef HAVE_OPENSSL
        if (nsi_checkssl(nsi)) {
            X509 *cert;
            X509_NAME *subject;
            char digest_buf[SHA1_STRING_LENGTH + 1];
            char *fp;

            loguser("SSL connection to %s:%hu.", inet_socktop(&peer), nsi_peerport(nsi));

            cert = SSL_get_peer_certificate((SSL *) nsi_getssl(nsi));
            ncat_assert(cert != NULL);

            subject = X509_get_subject_name(cert);
            if (subject != NULL) {
                char buf[256];
                int n;

                n = X509_NAME_get_text_by_NID(subject, NID_organizationName, buf, sizeof(buf));
                if (n >= 0 && n <= sizeof(buf) - 1)
                    loguser_noprefix(" %s", buf);
            }

            loguser_noprefix("\n");

            fp = ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf));
            ncat_assert(fp == digest_buf);
            loguser("SHA-1 fingerprint: %s\n", digest_buf);
        } else {
#if HAVE_SYS_UN_H
            if (peer.sockaddr.sa_family == AF_UNIX)
                loguser("Connected to %s.\n", peer.un.sun_path);
            else
#endif
                loguser("Connected to %s:%hu.\n", inet_socktop(&peer), nsi_peerport(nsi));
        }
#else
#if HAVE_SYS_UN_H
        if (peer.sockaddr.sa_family == AF_UNIX)
            loguser("Connected to %s.\n", peer.un.sun_path);
        else
#endif
            loguser("Connected to %s:%hu.\n", inet_socktop(&peer), nsi_peerport(nsi));
#endif
    }
}
コード例 #9
0
ファイル: rx_server.cpp プロジェクト: hailynch/Beagle_SDR_GPS
void webserver_print_stats()
{
	int nusers=0;
	conn_t *c;
	
	for (c=conns; c<&conns[RX_CHANS*2]; c++) {
		if (!c->arrived) continue;
		
		#if 0
		if (c->type == STREAM_WATERFALL) {
			printf("WF%d %2d fps %7.3f %7.3f %7.3f\n", c->rx_channel, c->wf_frames,
				(float) c->wf_get / 1000, (float) c->wf_lock / 1000, (float) c->wf_loop / 1000);
			c->wf_frames = 0;
		}
		#endif

		if (c->type == STREAM_SOUND) {
			if ((c->freqHz != c->last_freqHz) || (c->mode != c->last_mode)) loguser(c, NULL);
			nusers++;
		}
	}

	static const float k = 1.0/1000.0/10.0;		// kbytes/sec every 10 secs
	audio_kbps = audio_bytes*k;
	waterfall_kbps = waterfall_bytes*k;
	waterfall_fps = waterfall_frames/10.0;
	http_kbps = http_bytes*k;
	audio_bytes = waterfall_bytes = waterfall_frames = http_bytes = 0;

	time_t t;
	time(&t);
	struct tm tm;
	localtime_r(&t, &tm);
	
	if (tm.tm_hour != last_hour) {
		lprintf("(%d %s)\n", nusers, (nusers==1)? "user":"******");
		last_hour = tm.tm_hour;
	}
}
コード例 #10
0
int ncat_connect(void)
{
    nsock_pool mypool;
    int rc;

    /* Unless explicitely asked not to do so, ncat uses the
     * fallback nsock engine to maximize compatibility between
     * operating systems and the different use cases.
     */
    if (!o.nsock_engine)
        nsock_set_default_engine("select");

    /* Create an nsock pool */
    if ((mypool = nsp_new(NULL)) == NULL)
        bye("Failed to create nsock_pool.");

    if (o.debug >= 6)
        nsock_set_loglevel(mypool, NSOCK_LOG_DBG_ALL);
    else if (o.debug >= 3)
        nsock_set_loglevel(mypool, NSOCK_LOG_DBG);
    else if (o.debug >= 1)
        nsock_set_loglevel(mypool, NSOCK_LOG_INFO);
    else
        nsock_set_loglevel(mypool, NSOCK_LOG_ERROR);

    /* Allow connections to broadcast addresses. */
    nsp_setbroadcast(mypool, 1);

#ifdef HAVE_OPENSSL
    set_ssl_ctx_options((SSL_CTX *) nsp_ssl_init(mypool));
#endif

    if (httpconnect.storage.ss_family == AF_UNSPEC
             && socksconnect.storage.ss_family == AF_UNSPEC) {
        /* A non-proxy connection. Create an iod for a new socket. */
        cs.sock_nsi = nsi_new(mypool, NULL);
        if (cs.sock_nsi == NULL)
            bye("Failed to create nsock_iod.");

        if (nsi_set_hostname(cs.sock_nsi, o.target) == -1)
            bye("Failed to set hostname on iod.");

#if HAVE_SYS_UN_H
        /* For DGRAM UNIX socket we have to use source socket */
        if (o.af == AF_UNIX && o.udp)
        {
            if (srcaddr.storage.ss_family != AF_UNIX) {
                char *tmp_name = NULL;
                /* If no source socket was specified, we have to create temporary one. */
                if ((tmp_name = tempnam(NULL, "ncat.")) == NULL)
                    bye("Failed to create name for temporary DGRAM source Unix domain socket (tempnam).");

                srcaddr.un.sun_family = AF_UNIX;
                strncpy(srcaddr.un.sun_path, tmp_name, sizeof(srcaddr.un.sun_path));
                free (tmp_name);
            }
            nsi_set_localaddr(cs.sock_nsi, &srcaddr.storage, SUN_LEN((struct sockaddr_un *)&srcaddr.storage));

            if (o.verbose)
                loguser("[%s] used as source DGRAM Unix domain socket.\n", srcaddr.un.sun_path);
        }
        else
#endif
        if (srcaddr.storage.ss_family != AF_UNSPEC)
            nsi_set_localaddr(cs.sock_nsi, &srcaddr.storage, sizeof(srcaddr.storage));

        if (o.numsrcrtes) {
            unsigned char *ipopts = NULL;
            size_t ipoptslen = 0;

            if (o.af != AF_INET)
                bye("Sorry, -g can only currently be used with IPv4.");
            ipopts = buildsrcrte(targetss.in.sin_addr, o.srcrtes, o.numsrcrtes, o.srcrteptr, &ipoptslen);

            nsi_set_ipoptions(cs.sock_nsi, ipopts, ipoptslen);
            free(ipopts); /* Nsock has its own copy */
        }

#if HAVE_SYS_UN_H
        if (o.af == AF_UNIX) {
            if (o.udp) {
                nsock_connect_unixsock_datagram(mypool, cs.sock_nsi, connect_handler, NULL,
                                                &targetss.sockaddr,
                                                SUN_LEN((struct sockaddr_un *)&targetss.sockaddr));
            } else {
                nsock_connect_unixsock_stream(mypool, cs.sock_nsi, connect_handler, o.conntimeout,
                                              NULL, &targetss.sockaddr,
                                              SUN_LEN((struct sockaddr_un *)&targetss.sockaddr));
            }
        } else
#endif
        if (o.udp) {
            nsock_connect_udp(mypool, cs.sock_nsi, connect_handler,
                              NULL, &targetss.sockaddr, targetsslen,
                              inet_port(&targetss));
        }
#ifdef HAVE_OPENSSL
        else if (o.sctp && o.ssl) {
            nsock_connect_ssl(mypool, cs.sock_nsi, connect_handler,
                              o.conntimeout, NULL,
                              &targetss.sockaddr, targetsslen,
                              IPPROTO_SCTP, inet_port(&targetss),
                              NULL);
        }
#endif
        else if (o.sctp) {
            nsock_connect_sctp(mypool, cs.sock_nsi, connect_handler,
                              o.conntimeout, NULL,
                              &targetss.sockaddr, targetsslen,
                              inet_port(&targetss));
        }
#ifdef HAVE_OPENSSL
        else if (o.ssl) {
            nsock_connect_ssl(mypool, cs.sock_nsi, connect_handler,
                              o.conntimeout, NULL,
                              &targetss.sockaddr, targetsslen,
                              IPPROTO_TCP, inet_port(&targetss),
                              NULL);
        }
#endif
        else {
            nsock_connect_tcp(mypool, cs.sock_nsi, connect_handler,
                              o.conntimeout, NULL,
                              &targetss.sockaddr, targetsslen,
                              inet_port(&targetss));
        }
    } else {
        /* A proxy connection. */
        static int connect_socket;
        int len;
        char *line;
        size_t n;

        if (httpconnect.storage.ss_family != AF_UNSPEC) {
            connect_socket = do_proxy_http();
            if (connect_socket == -1)
                return 1;
        } else if (socksconnect.storage.ss_family != AF_UNSPEC) {
            struct socket_buffer stateful_buf;
            struct socks4_data socks4msg;
            char socksbuf[8];

            connect_socket = do_connect(SOCK_STREAM);
            if (connect_socket == -1) {
                loguser("Proxy connection failed: %s.\n", socket_strerror(socket_errno()));
                return 1;
            }

            socket_buffer_init(&stateful_buf, connect_socket);

            if (o.verbose) {
                loguser("Connected to proxy %s:%hu\n", inet_socktop(&targetss),
                    inet_port(&targetss));
            }

            /* Fill the socks4_data struct */
            zmem(&socks4msg, sizeof(socks4msg));
            socks4msg.version = SOCKS4_VERSION;
            socks4msg.type = SOCKS_CONNECT;
            socks4msg.port = socksconnect.in.sin_port;
            socks4msg.address = socksconnect.in.sin_addr.s_addr;
            if (o.proxy_auth)
                Strncpy(socks4msg.username, (char *) o.proxy_auth, sizeof(socks4msg.username));

            len = 8 + strlen(socks4msg.username) + 1;

            if (send(connect_socket, (char *) &socks4msg, len, 0) < 0) {
                loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
                return 1;
            }
            /* The size of the socks4 response is 8 bytes. So read exactly
               8 bytes from the buffer */
            if (socket_buffer_readcount(&stateful_buf, socksbuf, 8) < 0) {
                loguser("Error: short reponse from proxy.\n");
                return 1;
            }
            if (socksbuf[1] != 90) {
                loguser("Proxy connection failed.\n");
                return 1;
            }

            /* Clear out whatever is left in the socket buffer which may be
               already sent by proxy server along with http response headers. */
            line = socket_buffer_remainder(&stateful_buf, &n);
            /* Write the leftover data to stdout. */
            Write(STDOUT_FILENO, line, n);
        }

        /* Once the proxy negotiation is done, Nsock takes control of the
           socket. */
        cs.sock_nsi = nsi_new2(mypool, connect_socket, NULL);

        /* Create IOD for nsp->stdin */
        if ((cs.stdin_nsi = nsi_new2(mypool, 0, NULL)) == NULL)
            bye("Failed to create stdin nsiod.");

        post_connect(mypool, cs.sock_nsi);
    }

    /* connect */
    rc = nsock_loop(mypool, -1);

    if (o.verbose) {
        struct timeval end_time;
        double time;
        gettimeofday(&end_time, NULL);
        time = TIMEVAL_MSEC_SUBTRACT(end_time, start_time) / 1000.0;
        loguser("%lu bytes sent, %lu bytes received in %.2f seconds.\n",
            nsi_get_write_count(cs.sock_nsi),
            nsi_get_read_count(cs.sock_nsi), time);
    }

#if HAVE_SYS_UN_H
    if (o.af == AF_UNIX && o.udp) {
        if (o.verbose)
            loguser("Deleting source DGRAM Unix domain socket. [%s]\n", srcaddr.un.sun_path);
        unlink(srcaddr.un.sun_path);
    }
#endif

    nsp_delete(mypool);

    return rc == NSOCK_LOOP_ERROR ? 1 : 0;
}
コード例 #11
0
/* Return a usable socket descriptor after proxy negotiation, or -1 on any
   error. If any bytes are received through the proxy after negotiation, they
   are written to stdout. */
static int do_proxy_http(void)
{
    struct socket_buffer sockbuf;
    char *request;
    char *status_line, *header;
    char *remainder;
    size_t len;
    int sd, code;
    int n;

    sd = do_connect(SOCK_STREAM);
    if (sd == -1) {
        loguser("Proxy connection failed: %s.\n", socket_strerror(socket_errno()));
        return -1;
    }

    status_line = NULL;
    header = NULL;

    /* First try a request with no authentication. */
    request = http_connect_request(&httpconnect, &n);
    if (send(sd, request, n, 0) < 0) {
        loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
        free(request);
        return -1;
    }
    free(request);

    socket_buffer_init(&sockbuf, sd);

    if (http_read_status_line(&sockbuf, &status_line) != 0) {
        loguser("Error reading proxy response Status-Line.\n");
        goto bail;
    }
    code = http_parse_status_line_code(status_line);
    logdebug("Proxy returned status code %d.\n", code);
    free(status_line);
    status_line = NULL;
    if (http_read_header(&sockbuf, &header) != 0) {
        loguser("Error reading proxy response header.\n");
        goto bail;
    }

    if (code == 407 && o.proxy_auth != NULL) {
        struct http_header *h;
        struct http_challenge challenge;

        close(sd);
        sd = -1;

        if (http_parse_header(&h, header) != 0) {
            loguser("Error parsing proxy response header.\n");
            goto bail;
        }
        free(header);
        header = NULL;

        if (http_header_get_proxy_challenge(h, &challenge) == NULL) {
            loguser("Error getting Proxy-Authenticate challenge.\n");
            http_header_free(h);
            goto bail;
        }
        http_header_free(h);

        sd = do_connect(SOCK_STREAM);
        if (sd == -1) {
            loguser("Proxy reconnection failed: %s.\n", socket_strerror(socket_errno()));
            goto bail;
        }

        request = http_connect_request_auth(&httpconnect, &n, &challenge);
        if (request == NULL) {
            loguser("Error building Proxy-Authorization header.\n");
            http_challenge_free(&challenge);
            goto bail;
        }
        logdebug("Reconnection header:\n%s", request);
        if (send(sd, request, n, 0) < 0) {
            loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
            free(request);
            http_challenge_free(&challenge);
            goto bail;
        }
        free(request);
        http_challenge_free(&challenge);

        socket_buffer_init(&sockbuf, sd);

        if (http_read_status_line(&sockbuf, &status_line) != 0) {
            loguser("Error reading proxy response Status-Line.\n");
            goto bail;
        }
        code = http_parse_status_line_code(status_line);
        logdebug("Proxy returned status code %d.\n", code);
        free(status_line);
        status_line = NULL;
        if (http_read_header(&sockbuf, &header) != 0) {
            loguser("Error reading proxy response header.\n");
            goto bail;
        }
    }

    free(header);
    header = NULL;

    if (code != 200) {
        loguser("Proxy returned status code %d.\n", code);
        return -1;
    }

    remainder = socket_buffer_remainder(&sockbuf, &len);
    Write(STDOUT_FILENO, remainder, len);

    return sd;

bail:
    if (sd != -1)
        close(sd);
    if (status_line != NULL)
        free(status_line);
    if (header != NULL)
        free(header);

    return -1;
}
コード例 #12
0
SSL_CTX *setup_ssl_listen(void)
{
    const SSL_METHOD *method;

    if (sslctx)
        goto done;

    SSL_library_init();
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();
    SSL_load_error_strings();

    /* RAND_status initializes the random number generator through a variety of
       platform-dependent methods, then returns 1 if there is enough entropy or
       0 otherwise. This seems to be a good platform-independent way of seeding
       the generator, as well as of refusing to continue without enough
       entropy. */
    if (!RAND_status())
        bye("Failed to seed OpenSSL PRNG (RAND_status returned false).");

    if (!(method = SSLv23_server_method()))
        bye("SSLv23_server_method(): %s.", ERR_error_string(ERR_get_error(), NULL));
    if (!(sslctx = SSL_CTX_new(method)))
        bye("SSL_CTX_new(): %s.", ERR_error_string(ERR_get_error(), NULL));

    SSL_CTX_set_options(sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);

    /* Secure ciphers list taken from Nsock. */
    if (!SSL_CTX_set_cipher_list(sslctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"))
        bye("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL));

    if (o.sslcert == NULL && o.sslkey == NULL) {
        X509 *cert;
        EVP_PKEY *key;
        char digest_buf[SHA1_STRING_LENGTH + 1];

        if (o.verbose)
            loguser("Generating a temporary %d-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.\n", DEFAULT_KEY_BITS);
        if (ssl_gen_cert(&cert, &key) == 0)
            bye("ssl_gen_cert(): %s.", ERR_error_string(ERR_get_error(), NULL));
        if (o.verbose) {
            char *fp;
            fp = ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf));
            ncat_assert(fp == digest_buf);
            loguser("SHA-1 fingerprint: %s\n", digest_buf);
        }
        if (SSL_CTX_use_certificate(sslctx, cert) != 1)
            bye("SSL_CTX_use_certificate(): %s.", ERR_error_string(ERR_get_error(), NULL));
        if (SSL_CTX_use_PrivateKey(sslctx, key) != 1)
            bye("SSL_CTX_use_PrivateKey(): %s.", ERR_error_string(ERR_get_error(), NULL));
        X509_free(cert);
        EVP_PKEY_free(key);
    } else {
        if (o.sslcert == NULL || o.sslkey == NULL)
            bye("The --ssl-key and --ssl-cert options must be used together.");
        if (SSL_CTX_use_certificate_chain_file(sslctx, o.sslcert) != 1)
            bye("SSL_CTX_use_certificate_chain_file(): %s.", ERR_error_string(ERR_get_error(), NULL));
        if (SSL_CTX_use_PrivateKey_file(sslctx, o.sslkey, SSL_FILETYPE_PEM) != 1)
            bye("SSL_CTX_use_Privatekey_file(): %s.", ERR_error_string(ERR_get_error(), NULL));
    }

done:
    return sslctx;
}
コード例 #13
0
/* userpass is a user:pass string (the argument to --proxy-auth). value is the
   value of the Proxy-Authorization header field. Returns 0 on authentication
   failure and nonzero on success. *stale is set to 1 if HTTP Digest credentials
   are valid but out of date. */
static int check_auth(const struct http_request *request,
    const struct http_credentials *credentials, int *stale)
{
    if (o.proxy_auth == NULL)
        return 1;

    *stale = 0;

    if (credentials->scheme == AUTH_BASIC) {
        char *expected;
        int cmp;

        if (credentials->u.basic == NULL)
            return 0;

        /* We don't decode the received password, we encode the expected
           password and compare the encoded strings. */
        expected = b64enc((unsigned char *) o.proxy_auth, strlen(o.proxy_auth));
        cmp = strcmp(expected, credentials->u.basic);
        free(expected);

        return cmp == 0;
    }
#if HAVE_HTTP_DIGEST
    else if (credentials->scheme == AUTH_DIGEST) {
        char *username, *password;
        char *proxy_auth;
        struct timeval nonce_tv, now;
        int nonce_age;
        int ret;

        /* Split up the proxy auth argument. */
        proxy_auth = Strdup(o.proxy_auth);
        username = strtok(proxy_auth, ":");
        password = strtok(NULL, ":");
        if (password == NULL) {
            free(proxy_auth);
            return 0;
        }
        ret = http_digest_check_credentials(username, "Ncat", password,
            request->method, credentials);
        free(proxy_auth);

        if (!ret)
            return 0;

        /* The nonce checks out as one we issued and it matches what we expect
           given the credentials. Now check if it's too old. */
        if (credentials->u.digest.nonce == NULL
            || http_digest_nonce_time(credentials->u.digest.nonce, &nonce_tv) == -1)
            return 0;
        gettimeofday(&now, NULL);
        if (TIMEVAL_AFTER(nonce_tv, now))
            return 0;
        nonce_age = TIMEVAL_SEC_SUBTRACT(now, nonce_tv);

        if (nonce_age > HTTP_DIGEST_NONCE_EXPIRY) {
            if (o.verbose)
                loguser("Nonce is %d seconds old; rejecting.\n", nonce_age);
            *stale = 1;
            return 0;
        }

        /* To prevent replays, here we should additionally check against a list
           of recently used nonces, where "recently used nonce" is one that has
           been used to successfully authenticate within the last
           HTTP_DIGEST_NONCE_EXPIRY seconds. (Older than that and we don't need
           to keep it in the list, because the expiry test above will catch it.
           This isn't supported because the fork-and-process architecture of the
           proxy server makes it hard for us to change state in the parent
           process from here in the child. */

        return 1;
    }
#endif
    else {
        return 0;
    }
}
コード例 #14
0
static void http_server_handler(int c)
{
    int code;
    struct socket_buffer sock;
    struct http_request request;
    char *buf;

    socket_buffer_init(&sock, c);
#if HAVE_OPENSSL
    if (o.ssl) {
        sock.fdn.ssl = new_ssl(sock.fdn.fd);
        if (SSL_accept(sock.fdn.ssl) != 1) {
            loguser("Failed SSL connection: %s\n",
                ERR_error_string(ERR_get_error(), NULL));
            fdinfo_close(&sock.fdn);
            return;
        }
    }
#endif

    code = http_read_request_line(&sock, &buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error reading Request-Line.\n");
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }
    if (o.debug > 1)
        logdebug("Request-Line: %s", buf);
    code = http_parse_request_line(buf, &request);
    free(buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error parsing Request-Line.\n");
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    if (!method_is_known(request.method)) {
        if (o.debug > 1)
            logdebug("Bad method: %s.\n", request.method);
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(405));
        fdinfo_close(&sock.fdn);
        return;
    }

    code = http_read_header(&sock, &buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error reading header.\n");
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }
    if (o.debug > 1)
        logdebug("Header:\n%s", buf);
    code = http_request_parse_header(&request, buf);
    free(buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error parsing header.\n");
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    /* Check authentication. */
    if (o.proxy_auth) {
        struct http_credentials credentials;
        int ret, stale;

        if (http_header_get_proxy_credentials(request.header, &credentials) == NULL) {
            /* No credentials or a parsing error. */
            send_proxy_authenticate(&sock.fdn, 0);
            http_request_free(&request);
            fdinfo_close(&sock.fdn);
            return;
        }

        ret = check_auth(&request, &credentials, &stale);
        http_credentials_free(&credentials);
        if (!ret) {
            /* Password doesn't match. */
            /* RFC 2617, section 1.2: "If a proxy does not accept the
               credentials sent with a request, it SHOULD return a 407 (Proxy
               Authentication Required). */
            send_proxy_authenticate(&sock.fdn, stale);
            http_request_free(&request);
            fdinfo_close(&sock.fdn);
            return;
        }
    }

    if (strcmp(request.method, "CONNECT") == 0) {
        code = handle_connect(&sock, &request);
    } else if (strcmp(request.method, "GET") == 0
        || strcmp(request.method, "HEAD") == 0
        || strcmp(request.method, "POST") == 0) {
        code = handle_method(&sock, &request);
    } else {
        code = 500;
    }
    http_request_free(&request);

    if (code != 0) {
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    fdinfo_close(&sock.fdn);
}
コード例 #15
0
ファイル: acct.c プロジェクト: Babar/tac_plus
static void
account(u_char *pak)
{
    struct acct *acct_pak;
    u_char *p, *argsizep;
    struct acct_rec rec;
    struct identity identity;
    char **cmd_argp;
    int i, errors = 0, status;

    acct_pak = (struct acct *) (pak + TAC_PLUS_HDR_SIZE);

    /* Fill out accounting record structure */
    memset(&rec, 0, sizeof(struct acct_rec));

    if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_WATCHDOG)
	rec.acct_type = ACCT_TYPE_UPDATE;
    if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_START)
	rec.acct_type = ACCT_TYPE_START;
    if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_STOP)
	rec.acct_type = ACCT_TYPE_STOP;

    rec.authen_method  = acct_pak->authen_method;
    rec.authen_type    = acct_pak->authen_type;
    rec.authen_service = acct_pak->authen_service;

    /* start of variable length data is here */
    p = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;

    /* skip arg cnts */
    p += acct_pak->arg_cnt;

    /* zero out identity struct */
    memset(&identity, 0, sizeof(struct identity));

    identity.username = tac_make_string(p, (int)acct_pak->user_len);
    p += acct_pak->user_len;

    identity.NAS_name = tac_strdup(session.peer);

    identity.NAS_port = tac_make_string(p, (int)acct_pak->port_len);
    p += acct_pak->port_len;
    if (acct_pak->port_len <= 0) {
	strcpy(session.port, "unknown-port");
    } else {
	strcpy(session.port, identity.NAS_port);
    }

    identity.NAC_address = tac_make_string(p, (int)acct_pak->rem_addr_len);
    p += acct_pak->rem_addr_len;

    identity.priv_lvl = acct_pak->priv_lvl;

    rec.identity = &identity;

    /* Now process cmd args */
    argsizep = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;

    cmd_argp = (char **)tac_malloc(acct_pak->arg_cnt * sizeof(char *));

    for (i = 0; i < (int)acct_pak->arg_cnt; i++) {
	cmd_argp[i] = tac_make_string(p, *argsizep);
	p += *argsizep++;
    }

    rec.args = cmd_argp;
    rec.num_args = acct_pak->arg_cnt;

#ifdef MAXSESS
    /* Tally for MAXSESS counting */
    loguser(&rec);
#endif

    /* Do accounting */
    if (wtmpfile)
	errors = do_wtmp(&rec);
    if (session.acctfile != NULL)
	errors += do_acct_file(&rec);
    if (session.flags & SESS_FLAG_ACCTSYSL)
	errors += do_acct_syslog(&rec);

    if (errors) {
	status = TAC_PLUS_ACCT_STATUS_ERROR;
    } else {
	status = TAC_PLUS_ACCT_STATUS_SUCCESS;
    }
    send_acct_reply(status, rec.msg, rec.admin_msg);

    free(identity.username);
    free(identity.NAS_name);
    free(identity.NAS_port);
    free(identity.NAC_address);

    for (i = 0; i < (int)acct_pak->arg_cnt; i++) {
	free(cmd_argp[i]);
    }
    free(cmd_argp);

    if (rec.msg)
	free(rec.msg);
    if (rec.admin_msg)
	free(rec.admin_msg);
}
コード例 #16
0
ファイル: ncat_listen.c プロジェクト: Araleii/nmap
/* Accept a connection on a listening socket. Allow or deny the connection.
   Fork a command if o.cmdexec is set. Otherwise, add the new socket to the
   watch set. */
static void handle_connection(int socket_accept)
{
    union sockaddr_u remoteaddr;
    socklen_t ss_len;
    struct fdinfo s = { 0 };
    int conn_count;

    zmem(&s, sizeof(s));
    zmem(&remoteaddr, sizeof(remoteaddr.storage));

    ss_len = sizeof(remoteaddr.storage);

    errno = 0;
    s.fd = accept(socket_accept, &remoteaddr.sockaddr, &ss_len);

    if (s.fd < 0) {
        if (o.debug)
            logdebug("Error in accept: %s\n", strerror(errno));

        close(s.fd);
        return;
    }

    if (o.verbose) {
#if HAVE_SYS_UN_H
        if (remoteaddr.sockaddr.sa_family == AF_UNIX)
            loguser("Connection from a client on Unix domain socket.\n");
        else
#endif
        if (o.chat)
            loguser("Connection from %s on file descriptor %d.\n", inet_socktop(&remoteaddr), s.fd);
        else
            loguser("Connection from %s.\n", inet_socktop(&remoteaddr));
    }

    if (!o.keepopen && !o.broker) {
        int i;
        for (i = 0; i < num_listenaddrs; i++) {
            Close(listen_socket[i]);
            FD_CLR(listen_socket[i], &master_readfds);
            rm_fd(&client_fdlist, listen_socket[i]);
        }
    }

    if (o.verbose) {
#if HAVE_SYS_UN_H
        if (remoteaddr.sockaddr.sa_family == AF_UNIX)
            loguser("Connection from %s.\n", remoteaddr.un.sun_path);
        else
#endif
            loguser("Connection from %s:%hu.\n", inet_socktop(&remoteaddr), inet_port(&remoteaddr));
    }

    /* Check conditions that might cause us to deny the connection. */
    conn_count = get_conn_count();
    if (conn_count >= o.conn_limit) {
        if (o.verbose)
            loguser("New connection denied: connection limit reached (%d)\n", conn_count);
        Close(s.fd);
        return;
    }
    if (!allow_access(&remoteaddr)) {
        if (o.verbose)
            loguser("New connection denied: not allowed\n");
        Close(s.fd);
        return;
    }

    s.remoteaddr = remoteaddr;

    conn_inc++;

    unblock_socket(s.fd);

#ifdef HAVE_OPENSSL
    if (o.ssl) {
        /* Add the socket to the necessary descriptor lists. */
        FD_SET(s.fd, &sslpending_fds);
        FD_SET(s.fd, &master_readfds);
        FD_SET(s.fd, &master_writefds);
        /* Add it to our list of fds too for maintaining maxfd. */
        if (add_fdinfo(&client_fdlist, &s) < 0)
            bye("add_fdinfo() failed.");
    } else
#endif
        post_handle_connection(s);
}
コード例 #17
0
ファイル: ncat_listen.c プロジェクト: Araleii/nmap
/* This is sufficiently different from the TCP code (wrt SSL, etc) that it
 * resides in its own simpler function
 */
static int ncat_listen_dgram(int proto)
{
    struct {
        int fd;
        union sockaddr_u addr;
    } sockfd[NUM_LISTEN_ADDRS];
    int i, fdn = -1;
    int fdmax, nbytes, n, fds_ready;
    char buf[DEFAULT_UDP_BUF_LEN] = { 0 };
    char *tempbuf = NULL;
    fd_set read_fds;
    union sockaddr_u remotess;
    socklen_t sslen = sizeof(remotess.storage);
    struct timeval tv;
    struct timeval *tvp = NULL;
    unsigned int num_sockets;

    for (i = 0; i < NUM_LISTEN_ADDRS; i++) {
        sockfd[i].fd = -1;
        sockfd[i].addr.storage.ss_family = AF_UNSPEC;
    }

    FD_ZERO(&read_fds);

    /* Initialize remotess struct so recvfrom() doesn't hit the fan.. */
    zmem(&remotess.storage, sizeof(remotess.storage));
    remotess.storage.ss_family = o.af;

#ifdef WIN32
    set_pseudo_sigchld_handler(decrease_conn_count);
#else
    /* Reap on SIGCHLD */
    Signal(SIGCHLD, sigchld_handler);
    /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we
       send data to it before noticing. */
    Signal(SIGPIPE, SIG_IGN);
#endif

/* Not sure if this problem exists on Windows, but fcntl and /dev/null don't */
#ifndef WIN32
    /* Check whether stdin is closed. Because we treat this fd specially, we
     * can't risk it being reopened for an incoming connection, so we'll hold
     * it open instead. */
    if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF) {
      logdebug("stdin is closed, attempting to reserve STDIN_FILENO\n");
      i = open("/dev/null", O_RDONLY);
      if (i >= 0 && i != STDIN_FILENO) {
        /* Oh well, we tried */
        logdebug("Couldn't reserve STDIN_FILENO\n");
        close(i);
      }
    }
#endif

    /* set for selecting udp listening sockets */
    fd_set listen_fds;
    fd_list_t listen_fdlist;
    FD_ZERO(&listen_fds);
    init_fdlist(&listen_fdlist, num_listenaddrs);

    num_sockets = 0;
    for (i = 0; i < num_listenaddrs; i++) {
        /* create the UDP listen sockets */
        sockfd[num_sockets].fd = do_listen(SOCK_DGRAM, proto, &listenaddrs[i]);
        if (sockfd[num_sockets].fd == -1) {
            if (o.debug > 0)
                logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno()));
            continue;
        }
        FD_SET(sockfd[num_sockets].fd, &listen_fds);
        add_fd(&listen_fdlist, sockfd[num_sockets].fd);
        sockfd[num_sockets].addr = listenaddrs[i];
        num_sockets++;
    }
    if (num_sockets == 0) {
        if (num_listenaddrs == 1)
            bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno()));
        else
            bye("Unable to open any listening sockets.");
    }

    if (o.idletimeout > 0)
        tvp = &tv;

    while (1) {
        int i, j, conn_count, socket_n;

        if (fdn != -1) {
            /*remove socket descriptor which is burnt */
            FD_CLR(sockfd[fdn].fd, &listen_fds);
            rm_fd(&listen_fdlist, sockfd[fdn].fd);

            /* Rebuild the udp socket which got burnt */
            sockfd[fdn].fd = do_listen(SOCK_DGRAM, proto, &sockfd[fdn].addr);
            if (sockfd[fdn].fd == -1)
                bye("do_listen: %s", socket_strerror(socket_errno()));
            FD_SET(sockfd[fdn].fd, &listen_fds);
            add_fd(&listen_fdlist, sockfd[fdn].fd);

        }
        fdn = -1;
        socket_n = -1;
        fd_set fds;
        FD_ZERO(&fds);
        while (1) {
            /*
             * We just select to get a list of sockets which we can talk to
             */
            if (o.debug > 1)
                logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax);
            fds = listen_fds;

            if (o.idletimeout > 0)
                ms_to_timeval(tvp, o.idletimeout);

            fds_ready = fselect(listen_fdlist.fdmax + 1, &fds, NULL, NULL, tvp);

            if (o.debug > 1)
                logdebug("select returned %d fds ready\n", fds_ready);

            if (fds_ready == 0)
                bye("Idle timeout expired (%d ms).", o.idletimeout);

            /*
             * Figure out which listening socket got a connection. This loop should
             * really call a function for each ready socket instead of breaking on
             * the first one.
             */
            for (i = 0; i <= listen_fdlist.fdmax && fds_ready > 0; i++) {
                /* Loop through descriptors until there is something ready */
                if (!FD_ISSET(i, &fds))
                    continue;

                /* Check each listening socket */
                for (j = 0; j < num_sockets; j++) {
                    if (i == sockfd[j].fd) {
                        if (o.debug > 1)
                            logdebug("Valid descriptor %d \n", i);
                        fdn = j;
                        socket_n = i;
                        break;
                    }
                }

                /* if we found a valid socket break */
                if (fdn != -1) {
                    fds_ready--;
                    break;
                }
            }

            /* Make sure someone connected */
            if (fdn == -1)
                continue;

            /*
             * We just peek so we can get the client connection details without
             * removing anything from the queue. Sigh.
             */
            nbytes = recvfrom(socket_n, buf, sizeof(buf), MSG_PEEK,
                              &remotess.sockaddr, &sslen);
            if (nbytes < 0) {
                loguser("%s.\n", socket_strerror(socket_errno()));
                close(socket_n);
                return 1;
            }

            /* Check conditions that might cause us to deny the connection. */
            conn_count = get_conn_count();
            if (conn_count >= o.conn_limit) {
                if (o.verbose)
                    loguser("New connection denied: connection limit reached (%d)\n", conn_count);
            } else if (!allow_access(&remotess)) {
                if (o.verbose)
                    loguser("New connection denied: not allowed\n");
            } else {
                /* Good to go. */
                break;
            }

            /* Dump the current datagram */
            nbytes = recv(socket_n, buf, sizeof(buf), 0);
            if (nbytes < 0) {
                loguser("%s.\n", socket_strerror(socket_errno()));
                close(socket_n);
                return 1;
            }
            ncat_log_recv(buf, nbytes);
        }

        if (o.debug > 1)
            logdebug("Valid Connection from %d\n", socket_n);

        conn_inc++;

        /*
         * We're using connected udp. This has the down side of only
         * being able to handle one udp client at a time
         */
        Connect(socket_n, &remotess.sockaddr, sslen);

        /* clean slate for buf */
        zmem(buf, sizeof(buf));

        /* are we executing a command? then do it */
        if (o.cmdexec) {
            struct fdinfo info = { 0 };

            info.fd = socket_n;
            if (o.keepopen)
                netrun(&info, o.cmdexec);
            else
                netexec(&info, o.cmdexec);
            continue;
        }

        FD_SET(socket_n, &read_fds);
        FD_SET(STDIN_FILENO, &read_fds);
        fdmax = socket_n;

        /* stdin -> socket and socket -> stdout */
        while (1) {
            fd_set fds;

            fds = read_fds;

            if (o.debug > 1)
                logdebug("udp select'ing\n");

            if (o.idletimeout > 0)
                ms_to_timeval(tvp, o.idletimeout);

            fds_ready = fselect(fdmax + 1, &fds, NULL, NULL, tvp);

            if (fds_ready == 0)
                bye("Idle timeout expired (%d ms).", o.idletimeout);

            if (FD_ISSET(STDIN_FILENO, &fds)) {
                nbytes = Read(STDIN_FILENO, buf, sizeof(buf));
                if (nbytes <= 0) {
                    if (nbytes < 0 && o.verbose) {
                        logdebug("Error reading from stdin: %s\n", strerror(errno));
                    } else if (nbytes == 0 && o.debug) {
                        logdebug("EOF on stdin\n");
                    }
                    FD_CLR(STDIN_FILENO, &read_fds);
                    if (nbytes < 0)
                        return 1;
                    continue;
                }
                if (o.crlf)
                    fix_line_endings((char *) buf, &nbytes, &tempbuf, &crlf_state);
                if (!o.recvonly) {
                    if (tempbuf != NULL)
                        n = send(socket_n, tempbuf, nbytes, 0);
                    else
                        n = send(socket_n, buf, nbytes, 0);
                    if (n < nbytes) {
                        loguser("%s.\n", socket_strerror(socket_errno()));
                        close(socket_n);
                        return 1;
                    }
                    ncat_log_send(buf, nbytes);
                }
                if (tempbuf != NULL) {
                    free(tempbuf);
                    tempbuf = NULL;
                }
            }
            if (FD_ISSET(socket_n, &fds)) {
                nbytes = recv(socket_n, buf, sizeof(buf), 0);
                if (nbytes < 0) {
                    loguser("%s.\n", socket_strerror(socket_errno()));
                    close(socket_n);
                    return 1;
                }
                ncat_log_recv(buf, nbytes);
                if (!o.sendonly)
                    Write(STDOUT_FILENO, buf, nbytes);
            }

            zmem(buf, sizeof(buf));
        }
    }

    return 0;
}
コード例 #18
0
/* Return a listening socket after setting various characteristics on it.
   Returns -1 on error. */
int do_listen(int type, int proto, const union sockaddr_u *srcaddr_u)
{
    int sock = 0, option_on = 1;
    size_t sa_len;

    if (type != SOCK_STREAM && type != SOCK_DGRAM)
        return -1;

    /* We need a socket that can be inherited by child processes in
       ncat_exec_win.c, for --exec and --sh-exec. inheritable_socket is from
       nbase. */
    sock = inheritable_socket(srcaddr_u->storage.ss_family, type, proto);
    if (sock < 0)
        return -1;

    Setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option_on, sizeof(int));

/* IPPROTO_IPV6 is defined in Visual C++ only when _WIN32_WINNT >= 0x501.
   Nbase's nbase_winunix.h defines _WIN32_WINNT to a lower value for
   compatibility with older versions of Windows. This code disables IPv6 sockets
   that also receive IPv4 connections. This is the default on Windows anyway so
   it doesn't make a difference.
   http://support.microsoft.com/kb/950688
   http://msdn.microsoft.com/en-us/library/bb513665
*/
#ifdef IPPROTO_IPV6
#ifdef IPV6_V6ONLY
    if (srcaddr_u->storage.ss_family == AF_INET6) {
        int set = 1;
        /* Tell it to not try and bind to IPV4 */
        if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &set, sizeof(set)) == -1)
            die("Unable to set IPV6 socket to bind only to IPV6");
    }
#endif
#endif

#ifdef HAVE_SYS_UN_H
    if (srcaddr_u->storage.ss_family == AF_UNIX)
        sa_len = SUN_LEN(&srcaddr_u->un);
    else
#endif
#ifdef HAVE_SOCKADDR_SA_LEN
        sa_len = srcaddr_u->sockaddr.sa_len;
#else
        sa_len = sizeof(*srcaddr_u);
#endif

    if (bind(sock, &srcaddr_u->sockaddr, sa_len) < 0) {
#ifdef HAVE_SYS_UN_H
        if (srcaddr_u->storage.ss_family == AF_UNIX)
            bye("bind to %s: %s.", srcaddr_u->un.sun_path,
                socket_strerror(socket_errno()));
        else
#endif
            bye("bind to %s:%hu: %s.", inet_socktop(srcaddr_u),
                inet_port(srcaddr_u), socket_strerror(socket_errno()));
    }

    if (type == SOCK_STREAM)
        Listen(sock, BACKLOG);

    if (o.verbose) {
#ifdef HAVE_SYS_UN_H
        if (srcaddr_u->storage.ss_family == AF_UNIX)
            loguser("Listening on %s\n", srcaddr_u->un.sun_path);
        else
#endif
            loguser("Listening on %s:%hu\n", inet_socktop(srcaddr_u), inet_port(srcaddr_u));
    }
    if (o.test)
        logtest("LISTEN\n");

    return sock;
}
コード例 #19
0
/* This is sufficiently different from the TCP code (wrt SSL, etc) that it
 * resides in its own simpler function
 */
static int ncat_listen_dgram(int proto)
{
    int sockfd[NUM_LISTEN_ADDRS];
    int i, fdn = -1;
    int fdmax, nbytes, fds_ready;
    char buf[DEFAULT_UDP_BUF_LEN] = {0};
    char *tempbuf = NULL;
    fd_set read_fds;
    union sockaddr_u remotess;
    socklen_t sslen = sizeof(remotess.storage);

    for (i = 0; i < NUM_LISTEN_ADDRS; i++) {
        sockfd[i] = -1;
    }

    FD_ZERO(&read_fds);

    /* Initialize remotess struct so recvfrom() doesn't hit the fan.. */
    zmem(&remotess.storage, sizeof(remotess.storage));
    remotess.storage.ss_family = o.af;

#ifdef WIN32
    set_pseudo_sigchld_handler(decrease_conn_count);
#else
    /* Reap on SIGCHLD */
    Signal(SIGCHLD, sigchld_handler);
    /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we
       send data to it before noticing. */
    Signal(SIGPIPE, SIG_IGN);
#endif

    /* set for selecting udp listening sockets */
    fd_set listen_fds;
    fd_list_t listen_fdlist;
    FD_ZERO(&listen_fds);
    init_fdlist(&listen_fdlist, num_listenaddrs);

    for (i = 0; i < num_listenaddrs; i++) {
        /* create the UDP listen sockets */
        sockfd[i] = do_listen(SOCK_DGRAM, proto, &listenaddrs[i]);
        FD_SET(sockfd[i],&listen_fds);
        add_fd(&listen_fdlist, sockfd[i]);
    }

    while (1) {
        int i, j, conn_count, socket_n;

        if (fdn != -1) {
            /*remove socket descriptor which is burnt */
            FD_CLR(sockfd[fdn], &listen_fds);
            rm_fd(&listen_fdlist, sockfd[fdn]);

            /* Rebuild the udp socket which got burnt */
            sockfd[fdn] = do_listen(SOCK_DGRAM, proto, &listenaddrs[fdn]);
            FD_SET(sockfd[fdn],&listen_fds);
            add_fd(&listen_fdlist, sockfd[fdn]);

        }
        fdn = -1;
        socket_n = -1;
            fd_set fds;
            FD_ZERO(&fds);
        while (1) {
            /*
             * We just select to get a list of sockets which we can talk to
             */
            if (o.debug > 1)
                logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax);
            fds = listen_fds;
            fds_ready = fselect(listen_fdlist.fdmax + 1, &fds, NULL, NULL, NULL);

            if (o.debug > 1)
                logdebug("select returned %d fds ready\n", fds_ready);


            /*
             * Figure out which listening socket got a connection. This loop should
             * really call a function for each ready socket instead of breaking on
             * the first one.
             */
            for (i = 0; i <= listen_fdlist.fdmax && fds_ready >0; i++) {
                /* Loop through descriptors until there is something ready */
                if (!FD_ISSET(i, &fds))
                    continue;

                /* Check each listening socket */
                for (j = 0; j < num_listenaddrs; j++) {
                    if (i == sockfd[j]) {
                        if (o.debug >1)
                            logdebug("Valid descriptor %d \n", i);
                        fdn = j;
                        socket_n = i;
                        break;
                    }
                }

                /* if we found a valid socket break */
                if (fdn != -1) {
                    fds_ready--;
                    break;
                }
            }

            /* Make sure someone connected */
            if (fdn == -1)
                continue;

            /*
             * We just peek so we can get the client connection details without
             * removing anything from the queue. Sigh.
             */
            nbytes = Recvfrom(socket_n, buf, sizeof(buf), MSG_PEEK,
                              &remotess.sockaddr, &sslen);

            /* Check conditions that might cause us to deny the connection. */
            conn_count = get_conn_count();
            if (conn_count >= o.conn_limit) {
                if (o.verbose)
                    loguser("New connection denied: connection limit reached (%d)\n", conn_count);
            } else if (!allow_access(&remotess)) {
                if (o.verbose)
                    loguser("New connection denied: not allowed\n");
            } else {
                /* Good to go. */
                break;
            }

            /* Dump the current datagram */
            Recv(socket_n, buf, sizeof(buf), 0);
        }

        if (o.debug > 1)
            logdebug("Valid Connection from %d\n", socket_n);

        conn_inc++;

        /*
         * We're using connected udp. This has the down side of only
         * being able to handle one udp client at a time
         */
        Connect(socket_n, &remotess.sockaddr, sslen);

        /* clean slate for buf */
        zmem(buf, sizeof(buf));

        /* are we executing a command? then do it */
        if (o.cmdexec) {
            struct fdinfo info = { 0 };

            info.fd = socket_n;
            if (o.keepopen)
                netrun(&info, o.cmdexec);
            else
                netexec(&info, o.cmdexec);
            continue;
        }

        FD_SET(socket_n, &read_fds);
        FD_SET(STDIN_FILENO, &read_fds);
        fdmax = socket_n;

        /* stdin -> socket and socket -> stdout */
        while (1) {
            fd_set fds;

            fds = read_fds;

            if (o.debug > 1)
                logdebug("udp select'ing\n");

            fds_ready = fselect(fdmax + 1, &fds, NULL, NULL, NULL);

            if (FD_ISSET(STDIN_FILENO, &fds)) {
                nbytes = Read(STDIN_FILENO, buf, sizeof(buf));
                if (nbytes < 0) {
                    loguser("%s.\n", strerror(errno));
                    return 1;
                } else if (nbytes == 0) {
                    return 0;
                }
                if (o.crlf)
                    fix_line_endings((char *) buf, &nbytes, &tempbuf, &crlf_state);
                if (!o.recvonly) {
                    if (tempbuf != NULL)
                        send(socket_n, tempbuf, nbytes, 0);
                    else
                        send(socket_n, buf, nbytes, 0);
                }
                if (tempbuf != NULL) {
                    free(tempbuf);
                    tempbuf = NULL;
                }
            }
            if (FD_ISSET(socket_n, &fds)) {
                nbytes = recv(socket_n, buf, sizeof(buf), 0);
                if (nbytes < 0) {
                    loguser("%s.\n", socket_strerror(socket_errno()));
                    close(socket_n);
                    return 1;
                }
                if (!o.sendonly)
                    Write(STDOUT_FILENO, buf, nbytes);
            }

            zmem(buf, sizeof(buf));
        }
    }

    return 0;
}