Example #1
0
/* Negotiate an SSL connection. */
int ne__negotiate_ssl(ne_session *sess)
{
    ne_ssl_context *const ctx = sess->ssl_context;
    ne_ssl_certificate *chain;
    gnutls_session sock;

    NE_DEBUG(NE_DBG_SSL, "Negotiating SSL connection.\n");

    /* Pass through the hostname if SNI is enabled. */
    ctx->hostname = 
        sess->flags[NE_SESSFLAG_TLS_SNI] ? sess->server.hostname : NULL;

    if (ne_sock_connect_ssl(sess->socket, ctx, sess)) {
        if (sess->ssl_cc_requested) {
            ne_set_error(sess, _("SSL handshake failed, "
                                 "client certificate was requested: %s"),
                         ne_sock_error(sess->socket));
        }
        else {
            ne_set_error(sess, _("SSL handshake failed: %s"),
                         ne_sock_error(sess->socket));
        }
        return NE_ERROR;
    }

    sock = ne__sock_sslsock(sess->socket);

    chain = make_peers_chain(sock, ctx->cred);
    if (chain == NULL) {
        ne_set_error(sess, _("Server did not send certificate chain"));
        return NE_ERROR;
    }

    if (sess->server_cert && ne_ssl_cert_cmp(sess->server_cert, chain) == 0) {
        /* Same cert as last time; presume OK.  This is not optimal as
         * make_peers_chain() has already gone through and done the
         * expensive DER parsing stuff for the whole chain by now. */
        ne_ssl_cert_free(chain);
        return NE_OK;
    }

    if (check_certificate(sess, sock, chain)) {
        ne_ssl_cert_free(chain);
        return NE_ERROR;
    }

    sess->server_cert = chain;

    return NE_OK;
}
Example #2
0
static int full_writev(ne_socket *sock, struct ne_iovec *vec, int count)
{
    int ret = ne_sock_fullwritev(sock, vec, count);
    NE_DEBUG(NE_DBG_SOCKET, "wrote vector (%d)\n", count);
    ONV(ret, ("writev failed (%d): %s", ret, ne_sock_error(sock)));
    return OK;
}
Example #3
0
int discard_request(ne_socket *sock)
{
    char buffer[1024];
    size_t offset = want_header?strlen(want_header):0;

    clength = 0;

    NE_DEBUG(NE_DBG_HTTP, "Discarding request...\n");
    do {
	ONV(ne_sock_readline(sock, buffer, 1024) < 0,
	    ("error reading line: %s", ne_sock_error(sock)));
	NE_DEBUG(NE_DBG_HTTP, "[req] %s", buffer);
	if (strncasecmp(buffer, "content-length:", 15) == 0) {
	    clength = atoi(buffer + 16);
	}
	if (got_header != NULL && want_header != NULL &&
	    strncasecmp(buffer, want_header, offset) == 0 &&
	    buffer[offset] == ':') {
	    char *value = buffer + offset + 1;
	    if (*value == ' ') value++;
	    got_header(ne_shave(value, "\r\n"));
	}
    } while (strcmp(buffer, "\r\n") != 0);

    return OK;
}
Example #4
0
int full_write(ne_socket *sock, const char *data, size_t len)
{
    int ret = ne_sock_fullwrite(sock, data, len);
    NE_DEBUG(NE_DBG_SOCKET, "wrote: [%.*s]\n", (int)len, data);
    ONV(ret, ("write failed (%d): %s", ret, ne_sock_error(sock)));
    return OK;
}
Example #5
0
/* Exect a read() to return EOF */
static int expect_close(ne_socket *sock)
{
    ssize_t n = ne_sock_read(sock, buffer, 1);
    ONV(n > 0, ("read got %" NE_FMT_SSIZE_T " bytes not closure", n));
    ONV(n < 0 && n != NE_SOCK_CLOSED,
	("read got error not closure: `%s'", ne_sock_error(sock)));
    return OK;
}
Example #6
0
/* do a sock_read() on sock for 'len' bytes, and expect 'str'. */
static int fullread_expect(ne_socket *sock, const char *str, size_t len)
{
    ssize_t ret = ne_sock_fullread(sock, buffer, len);
    ONV(ret, ("fullread failed (%" NE_FMT_SSIZE_T "): %s", 
              ret, ne_sock_error(sock)));
    ONV(memcmp(str, buffer, len),
	("fullread mismatch: `%.*s' not `%.*s'", 
	 (int)len, buffer, (int)len, str));    
    return OK;
}
Example #7
0
static int error(void)
{
    ne_socket *sock = ne_sock_create();

    ne_sock_set_error(sock, "%s:%s", "fish", "42");
    
    ONCMP("fish:42", ne_sock_error(sock), "socket error", "set");

    ne_sock_close(sock);
    return OK;
}
Example #8
0
static int begin(ne_socket **sock, server_fn fn, void *ud)
{
    struct serve_pair pair;
    pair.fn = fn;
    pair.userdata = ud;
    CALL(spawn_server(7777, wrap_serve, &pair));
    CALL(do_connect(sock, localhost, 7777));
    ONV(ne_sock_connect_ssl(*sock, client_ctx, NULL),
	("SSL negotation failed: %s", ne_sock_error(*sock)));
    return OK;
}
Example #9
0
/* when an EOF is received without a clean shutdown (close_notify
   message). */
static int ssl_truncate(void)
{
    ne_socket *sock; int ret;

    CALL(begin(&sock, serve_truncate, NULL));
    ret = ne_sock_read(sock, buffer, 1);
    ONV(ret != NE_SOCK_TRUNC,
	("socket got error %d not truncation: `%s'", ret,
	 ne_sock_error(sock)));
    return finish(sock, 0);
}
Example #10
0
static int line_expect(ne_socket *sock, const char *line)
{
    ssize_t ret = ne_sock_readline(sock, buffer, BUFSIZ);
    size_t len = strlen(line);
    NE_DEBUG(NE_DBG_SOCKET, " -> expected=%s -> actual=%s", line, buffer);
    ONV(ret == NE_SOCK_CLOSED, ("socket closed, expecting `%s'", line));
    ONV(ret < 0, ("socket error `%s', expecting `%s'", 
		  ne_sock_error(sock), line));
    ONV((size_t)ret != len || strcmp(line, buffer),
	("readline mismatch: `%s' not `%s'", buffer, line));
    return OK;
}
Example #11
0
static int wrap_serve(ne_socket *sock, void *ud)
{
    struct serve_pair *pair = ud;
    
    if (ne_sock_accept_ssl(sock, server_ctx)) {
	NE_DEBUG(NE_DBG_SOCKET, "SSL_accept failed: %s\n", ne_sock_error(sock));
	return 1;
    }
    
    NE_DEBUG(NE_DBG_SOCKET, "SSL accept okay.\n");
    return pair->fn(sock, pair->userdata);
}
Example #12
0
/* harder to simulate closure cases for an SSL connection, since it
 * may be doing multiple read()s or write()s per ne_sock_* call. */
static int ssl_closure(void)
{
    ne_socket *sock;
    ssize_t ret;
    CALL(begin(&sock, serve_close, NULL));
    CALL(full_write(sock, "a", 1));
    CALL(await_server());
    do {
        ret = ne_sock_fullwrite(sock, "a", 1);
    } while (ret == 0);
    ONV(ret != NE_SOCK_RESET && ret != NE_SOCK_CLOSED,
	("write got %" NE_FMT_SSIZE_T " not reset or closure: %s", ret,
         ne_sock_error(sock)));
    return good_close(sock);
}
Example #13
0
/* Create and connect *sock to address addr on given port. */
static int do_connect(ne_socket **sock, ne_sock_addr *addr, unsigned int port)
{
    const ne_inet_addr *ia;

    *sock = ne_sock_create();
    ONN("could not create socket", *sock == NULL);

    for (ia = ne_addr_first(addr); ia; ia = ne_addr_next(addr)) {
	if (ne_sock_connect(*sock, ia, port) == 0)
            return OK;
    }
    
    t_context("could not connect to server: %s", ne_sock_error(*sock));
    ne_sock_close(*sock);
    return FAIL;
}
Example #14
0
static int line_closure(void)
{
    ne_socket *sock;
    ssize_t ret;
    DECL(oneline, STR "\n" "foobar");
    
    CALL(begin(&sock, serve_sstring, &oneline));
    LINE(STR "\n");
    
    ret = ne_sock_readline(sock, buffer, BUFSIZ);
    ONV(ret != NE_SOCK_CLOSED, 
	("readline got %" NE_FMT_SSIZE_T " not EOF: %s", ret,
         ne_sock_error(sock)));
    
    return finish(sock, 0);
}   
Example #15
0
static int read_reset(void)
{
    ne_socket *sock;
    ssize_t ret;
    CALL(begin(&sock, serve_reset, NULL));
    CALL(full_write(sock, "a", 1));
    CALL(await_server());
    ret = ne_sock_read(sock, buffer, 1);
    if (ret == NE_SOCK_CLOSED) {
        ne_sock_close(sock);
        return SKIP;
    }
    ONV(ret != NE_SOCK_RESET, 
        ("read got %" NE_FMT_SSIZE_T " not reset: %s", ret,
         ne_sock_error(sock)));
    return good_close(sock);
}    
Example #16
0
int discard_body(ne_socket *sock)
{
    while (clength > 0) {
	char buf[BUFSIZ];
	size_t bytes = clength;
	ssize_t ret;
	if (bytes > sizeof(buf)) bytes = sizeof(buf);
	NE_DEBUG(NE_DBG_HTTP, "Discarding %" NE_FMT_SIZE_T " bytes.\n",
		 bytes);
	ret = ne_sock_read(sock, buf, bytes);
	ONV(ret < 0, ("socket read failed (%" NE_FMT_SSIZE_T "): %s",
		      ret, ne_sock_error(sock)));
	clength -= ret;
	NE_DEBUG(NE_DBG_HTTP, "Got %" NE_FMT_SSIZE_T " bytes.\n", ret);
    }
    NE_DEBUG(NE_DBG_HTTP, "Discard successful.\n");
    return OK;
}
Example #17
0
static int serve_ppeer(ne_socket *sock, void *ud)
{
    unsigned int port = 99999;
    ne_inet_addr *ia = ne_sock_peer(sock, &port);
    char buf[128], line[256];

    if (ia == NULL)
        ne_snprintf(line, sizeof line, "error: %s", ne_sock_error(sock));
    else
        ne_snprintf(line, sizeof line,
                    "%s@%u\n", ne_iaddr_print(ia, buf, sizeof buf),
                    port);

    CALL(full_write(sock, line, strlen(line)));
         
    ne_iaddr_free(ia);
    
    return OK;
}
Example #18
0
static int write_reset(void)
{
    ne_socket *sock;
    int ret;
    CALL(begin(&sock, serve_reset, NULL));
    CALL(full_write(sock, "a", 1));
    CALL(await_server());
    ret = ne_sock_fullwrite(sock, "a", 1);
    if (ret == 0) {
        ne_sock_close(sock);
        return SKIP;
    }
    if (ret == NE_SOCK_CLOSED) {
        t_warning("got EOF, failed to elicit TCP RST");
    } else {
        ONV(ret != NE_SOCK_RESET, 
            ("write got %d not reset: %s", ret, ne_sock_error(sock)));
    }
    return good_close(sock);
}
Example #19
0
static int try_prebind(int addr, int port)
{
    ne_socket *sock = ne_sock_create();
    ne_inet_addr *ia;
    char buf[128], line[256];
    unsigned int srvport;

    ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
    ONN("ne_iaddr_make returned NULL", ia == NULL);
    
    CALL(new_spawn_server(1, serve_ppeer, NULL, &srvport));

    ne_sock_prebind(sock, addr ? ia : NULL, port ? 7778 : 0);

    ONN("could not connect", ne_sock_connect(sock, ia, srvport));

    ne_snprintf(line, sizeof line,
                "%s@%d\n", ne_iaddr_print(ia, buf, sizeof buf),
                7778);
    
    if (!port) {
        /* Don't know what port will be chosen, so... */
        ssize_t ret = ne_sock_readline(sock, buffer, BUFSIZ);
        
        ONV(ret < 0, ("socket error `%s'", ne_sock_error(sock)));

        ONV(strncmp(line, buffer, strchr(line, '@') - line) != 0,
            ("bad address: '%s', expecting '%s'",
             buffer, line));
    }
    else {
        LINE(line);
    }

    ne_sock_close(sock);
    CALL(await_server());

    ne_iaddr_free(ia);
    return OK;
}
Example #20
0
/* Negotiate an SSL connection. */
int ne__negotiate_ssl(ne_session *sess)
{
    ne_ssl_context *const ctx = sess->ssl_context;
    ne_ssl_certificate *chain;
    gnutls_session sock;

    NE_DEBUG(NE_DBG_SSL, "Negotiating SSL connection.\n");

    if (ne_sock_connect_ssl(sess->socket, ctx, sess)) {
	ne_set_error(sess, _("SSL negotiation failed: %s"),
		     ne_sock_error(sess->socket));
	return NE_ERROR;
    }

    sock = ne__sock_sslsock(sess->socket);

    chain = make_peers_chain(sock);
    if (chain == NULL) {
        ne_set_error(sess, _("Server did not send certificate chain"));
        return NE_ERROR;
    }

    if (sess->server_cert && ne_ssl_cert_cmp(sess->server_cert, chain) == 0) {
        /* Same cert as last time; presume OK.  This is not optimal as
         * make_peers_chain() has already gone through and done the
         * expensive DER parsing stuff for the whole chain by now. */
        ne_ssl_cert_free(chain);
        return NE_OK;
    }

    if (check_certificate(sess, sock, chain)) {
        ne_ssl_cert_free(chain);
        return NE_ERROR;
    }

    sess->server_cert = chain;

    return NE_OK;
}
Example #21
0
static int fail_socks(void)
{
    static const struct {
        enum ne_sock_sversion version;
        enum socks_failure failure;
        const char *expect;
        const char *username, *password;
    } ts[] = {
        { NE_SOCK_SOCKSV5, fail_init_vers, 
          "Invalid version in proxy response", NULL, NULL },
        { NE_SOCK_SOCKSV5, fail_init_trunc,
          "Could not read initial response from proxy: Connection closed",
          NULL, NULL },
        { NE_SOCK_SOCKSV5, fail_init_close, 
          "Could not read initial response from proxy: Connection closed", 
          NULL, NULL },
        { NE_SOCK_SOCKSV5, fail_no_auth, 
          "No acceptable authentication method",
          NULL, NULL },
        { NE_SOCK_SOCKSV5, fail_bogus_auth, 
          "Unexpected authentication method chosen",
          NULL, NULL },
        { NE_SOCK_SOCKSV5, fail_auth_close, 
          "Could not read login reply: Connection closed",
          "foo", "bar" },
        { NE_SOCK_SOCKSV5, fail_auth_denied, 
          "Authentication failed", "foo", "bar" }
    };
    unsigned n;

    for (n = 0; n < sizeof(ts)/sizeof(ts[n]); n++) {
        ne_socket *sock;
        struct socks_server arg = {0};
        int ret;

        arg.version = ts[n].version;
        arg.failure = ts[n].failure;
        arg.expect_port = 5555;
        arg.expect_addr = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
        arg.username = ts[n].username;
        arg.password = ts[n].password;
        
        CALL(begin_socks(&sock, &arg, echo_server, NULL));

        ret = ne_sock_proxy(sock, ts[n].version, arg.expect_addr, 
                            NULL, arg.expect_port,
                            ts[n].username, ts[n].password);
        ONV(ret == 0, 
            ("proxy connect #%u succeeded, expected failure '%s'", n, 
             ts[n].expect));
        
        if (ret != 0 && strstr(ne_sock_error(sock), ts[n].expect) == NULL) {
            t_warning("proxy connect #%u got unexpected failure '%s', wanted '%s'",
                      n, ne_sock_error(sock), ts[n].expect);
        }    

        ne_iaddr_free(arg.expect_addr);

        CALL(finish(sock, 0));
    }

    return OK;
}
Example #22
0
static int netxml_alarm_subscribe(const char *page)
{
	int	ret, port = -1, secret = -1;
	char	buf[LARGEBUF], *s;
	ne_request	*request;
	ne_sock_addr	*addr;
	const ne_inet_addr	*ai;
	char	resp_buf[LARGEBUF];

	/* Clear response buffer */
	memset(resp_buf, 0, sizeof(resp_buf));

	upsdebugx(2, "%s: %s", __func__, page);

	sock = ne_sock_create();

	if (gethostname(buf, sizeof(buf)) == 0) {
		dstate_setinfo("driver.hostname", "%s", buf);
	} else {
		dstate_setinfo("driver.hostname", "<unknown>");
	}

#ifdef HAVE_NE_SOCK_CONNECT_TIMEOUT
	ne_sock_connect_timeout(sock, timeout);
#endif
	ne_sock_read_timeout(sock, 1);

	netxml_get_page(subdriver->configure);

	snprintf(buf, sizeof(buf),	"<?xml version=\"1.0\"?>\n");
	snprintfcat(buf, sizeof(buf),	"<Subscribe>\n");
	snprintfcat(buf, sizeof(buf),		"<Class>%s v%s</Class>\n", progname, DRIVER_VERSION);
	snprintfcat(buf, sizeof(buf),		"<Type>connected socket</Type>\n");
	snprintfcat(buf, sizeof(buf),		"<HostName>%s</HostName>\n", dstate_getinfo("driver.hostname"));
	snprintfcat(buf, sizeof(buf),		"<XMLClientParameters>\n");
	snprintfcat(buf, sizeof(buf),		"<ShutdownDuration>%d</ShutdownDuration>\n", shutdown_duration);
	if( shutdown_timer > 0 ) {
		snprintfcat(buf, sizeof(buf),	"<ShutdownTimer>%d</ShutdownTimer>\r\n", shutdown_timer);
	}
	else {
		snprintfcat(buf, sizeof(buf),	"<ShutdownTimer>NONE</ShutdownTimer>\n");
	}
	snprintfcat(buf, sizeof(buf),			"<AutoConfig>LOCAL</AutoConfig>\n");
	snprintfcat(buf, sizeof(buf),			"<OutletGroup>1</OutletGroup>\n");
	snprintfcat(buf, sizeof(buf),		"</XMLClientParameters>\n");
	snprintfcat(buf, sizeof(buf),		"<Warning></Warning>\n");
	snprintfcat(buf, sizeof(buf),	"</Subscribe>\n");

	/* now send subscription message setting all the proper flags */
	request = ne_request_create(session, "POST", page);
	ne_set_request_body_buffer(request, buf, strlen(buf));

	/* as the NMC reply is not xml standard compliant let's parse it this way */
	do {
#ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT
		alarm(timeout+1);
#endif
		ret = ne_begin_request(request);

#ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT
		alarm(0);
#endif
		if (ret != NE_OK) {
			break;
		}

		ret = ne_read_response_block(request, resp_buf, sizeof(resp_buf));

		if (ret == NE_OK) {
			ret = ne_end_request(request);
		}

	} while (ret == NE_RETRY);

	ne_request_destroy(request);

	/* due to different formats used by the various NMCs, we need to\
	   break up the reply in lines and parse each one separately */
	for (s = strtok(resp_buf, "\r\n"); s != NULL; s = strtok(NULL, "\r\n")) {
		upsdebugx(2, "%s: parsing %s", __func__, s);

		if (!strncasecmp(s, "<Port>", 6) && (sscanf(s+6, "%u", &port) != 1)) {
			return NE_RETRY;
		}

		if (!strncasecmp(s, "<Secret>", 8) && (sscanf(s+8, "%u", &secret) != 1)) {
			return NE_RETRY;
		}
	}

	if ((port == -1) || (secret == -1)) {
		upsdebugx(2, "%s: parsing initial subcription failed", __func__);
		return NE_RETRY;
	}

	/* Resolve the given hostname.  'flags' must be zero.  Hex
	* string IPv6 addresses (e.g. `::1') may be enclosed in brackets
	* (e.g. `[::1]'). */
	addr = ne_addr_resolve(uri.host, 0);

	/* Returns zero if name resolution was successful, non-zero on
	* error. */
	if (ne_addr_result(addr) != 0) {
		upsdebugx(2, "%s: name resolution failure on %s: %s", __func__, uri.host, ne_addr_error(addr, buf, sizeof(buf)));
		ne_addr_destroy(addr);
		return NE_RETRY;
	}

	for (ai = ne_addr_first(addr); ai != NULL; ai = ne_addr_next(addr)) {

		upsdebugx(2, "%s: connecting to host %s port %d", __func__, ne_iaddr_print(ai, buf, sizeof(buf)), port);

#ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT
		alarm(timeout+1);
#endif
		ret = ne_sock_connect(sock, ai, port);

#ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT
		alarm(0);
#endif
		if (ret == NE_OK) {
			upsdebugx(2, "%s: connection to %s open on fd %d", __func__, uri.host, ne_sock_fd(sock));
			break;
		}
	}

	ne_addr_destroy(addr);

	if (ai == NULL) {
		upsdebugx(2, "%s: failed to create listening socket", __func__);
		return NE_RETRY;
	}

	snprintf(buf, sizeof(buf), "<Subscription Identification=\"%u\"></Subscription>", secret);
	ret = ne_sock_fullwrite(sock, buf, strlen(buf) + 1);

	if (ret != NE_OK) {
		upsdebugx(2, "%s: send failed: %s", __func__, ne_sock_error(sock));
		return NE_RETRY;
	}

	ret = ne_sock_read(sock, buf, sizeof(buf));

	if (ret < 1) {
		upsdebugx(2, "%s: read failed: %s", __func__, ne_sock_error(sock));
		return NE_RETRY;
	}

	if (strcasecmp(buf, "<Subscription Answer=\"ok\"></Subscription>")) {
		upsdebugx(2, "%s: subscription rejected", __func__);
		return NE_RETRY;
	}

	upslogx(LOG_INFO, "NSM connection to '%s' established", uri.host);
	return NE_OK;
}
Example #23
0
void upsdrv_updateinfo(void)
{
	int	ret, errors = 0;

	/* We really should be dealing with alarms through a separate callback, so that we can keep the
	 * processing of alarms and polling for data separated. Currently, this isn't supported by the
	 * driver main body, so we'll have to revert to polling each time we're called, unless the
	 * socket indicates we're no longer connected.
	 */
	if (testvar("subscribe")) {
		char	buf[LARGEBUF];

		ret = ne_sock_read(sock, buf, sizeof(buf));

		if (ret > 0) {
			/* alarm message received */

			ne_xml_parser	*parser = ne_xml_create();
			upsdebugx(2, "%s: ne_sock_read(%d bytes) => %s", __func__, ret, buf);
			ne_xml_push_handler(parser, subdriver->startelm_cb, subdriver->cdata_cb, subdriver->endelm_cb, NULL);
			ne_xml_parse(parser, buf, strlen(buf));
			ne_xml_destroy(parser);
			time(&lastheard);

		} else if ((ret == NE_SOCK_TIMEOUT) && (difftime(time(NULL), lastheard) < 180)) {
			/* timed out */

			upsdebugx(2, "%s: ne_sock_read(timeout)", __func__);

		} else {
			/* connection closed or unknown error */

			upslogx(LOG_ERR, "NSM connection with '%s' lost", uri.host);

			upsdebugx(2, "%s: ne_sock_read(%d) => %s", __func__, ret, ne_sock_error(sock));
			ne_sock_close(sock);

			if (netxml_alarm_subscribe(subdriver->subscribe) == NE_OK) {
				extrafd = ne_sock_fd(sock);
				time(&lastheard);
				return;
			}

			dstate_datastale();
			extrafd = -1;
			return;
		}
	}

	/* get additional data */
	ret = netxml_get_page(subdriver->getobject);
	if (ret != NE_OK) {
		errors++;
	}

	ret = netxml_get_page(subdriver->summary);
	if (ret != NE_OK) {
		errors++;
	}

	if (errors > 1) {
		dstate_datastale();
		return;
	}

	status_init();

	alarm_init();
	netxml_alarm_set();
	alarm_commit();

	netxml_status_set();
	status_commit();

	dstate_dataok();
}
Example #24
0
static int good_close(ne_socket *sock)
{
    NE_DEBUG(NE_DBG_SOCKET, "Socket error was %s\n", ne_sock_error(sock));
    ONN("close failed", ne_sock_close(sock));
    return OK;    
}