コード例 #1
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
static int socks_proxy(void)
{
    static const struct {
        enum ne_sock_sversion version;
        int addr;
        const char *fqdn;
        unsigned int port;
        const char *username, *password;
    } ts[] = {
        { NE_SOCK_SOCKSV4, 4, NULL, 55555, NULL, NULL },
        { NE_SOCK_SOCKSV4, 4, NULL, 55555, "foobar", NULL },
        { NE_SOCK_SOCKSV4A, 0, "www.example.com", 55555, NULL, NULL },
        { NE_SOCK_SOCKSV5, 0, "www.example.com", 55555, NULL, NULL },
        { NE_SOCK_SOCKSV5, 4, NULL, 55555, NULL, NULL },
#ifdef TEST_IPV6
        { NE_SOCK_SOCKSV5, 6, NULL, 55555, NULL, NULL },
#endif
        { NE_SOCK_SOCKSV5, 0, "www.example.com", 55555, "norman", "foobar" }
    };
    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.expect_port = ts[n].port;
        if (ts[n].addr == 4)
            arg.expect_addr = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
#ifdef TEST_IPV6
        else if (ts[n].addr == 6)
            arg.expect_addr = ne_iaddr_make(ne_iaddr_ipv4, raw6_cafe);
#endif
        else
            arg.expect_fqdn = ts[n].fqdn;
        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, 
                            ts[n].fqdn, ts[n].port,
                            ts[n].username, ts[n].password);
        ONV(ret, ("proxy connect #%u gave %d", n, ret));
        FULLREAD("ok!\n");
        ECHO("hello,\n");
        ECHO("\n");
        ECHO("world\n");
        
        if (ts[n].addr)
            ne_iaddr_free(arg.expect_addr);

        CALL(finish(sock, 0));
    }

    return OK;
}
コード例 #2
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
static int addr_make_v6(void)
{
#ifdef TEST_IPV6   
    struct {
	const unsigned char *addr;
	const char *rep;
    } as[] = {
	{ raw6_cafe, "feed::cafe" },
	{ raw6_babe, "cafe:babe::" },
	{ raw6_nuls, "::" },
	{ NULL, NULL }
    };
    int n;
    
    for (n = 0; as[n].rep != NULL; n++) {
	ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv6, as[n].addr);
	char pr[128];
        unsigned char raw[17];

	ONV(ia == NULL, ("could not make address for '%s'", 
                         as[n].rep));

	ne_iaddr_print(ia, pr, sizeof pr);
	ONV(strcmp(pr, as[n].rep), 
	    ("address %d was '%s' not '%s'", n, pr, as[n].rep));
	
        ONN("bogus ne_iaddr_typeof return", ne_iaddr_typeof(ia) != ne_iaddr_ipv6);

        raw[16] = 'Z';
        ONN("ne_iaddr_raw gave bad retval", ne_iaddr_raw(ia, raw) != raw);
        ONN("raw address mismatch", memcmp(raw, as[n].addr, 4) != 0);
        ONN("ne_iaddr_raw buffer overflow", raw[16] != 'Z');
        
	ne_iaddr_free(ia);
        
        ia = ne_iaddr_parse(as[n].rep, ne_iaddr_ipv6);
        ONV(ia == NULL, ("ne_iaddr_parse failed for %s", as[n].rep));
        ONN("bogus ne_iaddr_typeof return", ne_iaddr_typeof(ia) != ne_iaddr_ipv6);
        ONN("ne_iaddr_raw gave bad retval", ne_iaddr_raw(ia, raw) != raw);
        ONN("raw address mismatch", memcmp(raw, as[n].addr, 4) != 0);
        ONN("ne_iaddr_raw buffer overflow", raw[16] != 'Z');

        ne_iaddr_free(ia);
   }

    return OK;
#else
    /* should fail when lacking IPv6 support. */
    ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv6, raw6_nuls);
    ONN("ne_iaddr_make did not return NULL", ia != NULL);
    ONN("ne_iaddr_parse did not return NULL", ne_iaddr_parse("127.0.0.1", ne_iaddr_ipv6));
#endif
    return OK;
}
コード例 #3
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
static int addr_peer(void)
{
    ne_socket *sock = ne_sock_create();
    ne_inet_addr *ia, *ia2;
    unsigned int port = 9999, realport;
    int ret;

    ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
    ONN("ne_iaddr_make returned NULL", ia == NULL);
    
    CALL(new_spawn_server(1, serve_close, NULL, &realport));
    ONN("could not connect", ne_sock_connect(sock, ia, realport));

    ia2 = ne_sock_peer(sock, &port);
    ret = ne_iaddr_cmp(ia, ia2);
    ONV(ret != 0,
        ("comparison of peer with server address was %d", ret));

    ONV(port != realport, ("got peer port %u, expected %u", port, realport));
 
    ne_sock_close(sock);
    CALL(await_server());

    ne_iaddr_free(ia);
    ne_iaddr_free(ia2);
    return OK;
}
コード例 #4
0
ファイル: socket.c プロジェクト: cern-it-sdc-id/davix
static int addr_reverse(void)
{
    ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
    char buf[128], *syshost = NULL;

#ifdef HAVE_GETHOSTNAME
    char host[128];

    if (gethostname(host, sizeof host) == 0) {
        syshost = host;
    }
#endif

    ONN("ne_iaddr_make returned NULL", ia == NULL);

    ONN("reverse lookup for 127.0.0.1 failed",
        ne_iaddr_reverse(ia, buf, sizeof buf) != 0);

    ONV(!(strcmp(buf, "localhost.localdomain") == 0
          || strcmp(buf, "localhost") == 0
          || (syshost && strcmp(buf, syshost) == 0)),
        ("reverse lookup for 127.0.0.1 got %s", buf));

    ne_iaddr_free(ia);

    return OK;
}
コード例 #5
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
/* No obvious way to reliably test a connect() timeout.  But
 * www.example.com seems to drop packets on ports other than 80 so
 * that actually works pretty well.  Disabled by default. */
static int connect_timeout(void)
{
    static const unsigned char example_dot_com[] = "\xC0\x00\x22\xA6";
    ne_socket *sock = ne_sock_create();
    ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv4, example_dot_com);

    ne_sock_connect_timeout(sock, 1);

    TO_OP(ne_sock_connect(sock, ia, 8080));

    ne_iaddr_free(ia);
    ne_sock_close(sock);

    return OK;
}
コード例 #6
0
ファイル: socket.c プロジェクト: cern-it-sdc-id/davix
/* Connect to an address crafted using ne_iaddr_make rather than from
 * the resolver. */
static int addr_connect(void)
{
    ne_socket *sock = ne_sock_create();
    ne_inet_addr *ia;

    ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
    ONN("ne_iaddr_make returned NULL", ia == NULL);

    CALL(spawn_server(7777, serve_close, NULL));
    ONN("could not connect", ne_sock_connect(sock, ia, 7777));
    ne_sock_close(sock);
    CALL(await_server());

    ne_iaddr_free(ia);
    return OK;
}
コード例 #7
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
static int addr_make_v4(void)
{
    ne_inet_addr *ia;
    char pr[50];
    
    ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
    ONN("ne_iaddr_make returned NULL", ia == NULL);

    ne_iaddr_print(ia, pr, sizeof pr);
    ONV(strcmp(pr, "127.0.0.1"), ("address was %s not 127.0.0.1", pr));

    CALL(check_is_raw127(ia));
    
    ne_iaddr_free(ia);

    return OK;
}
コード例 #8
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
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;
}
コード例 #9
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
static int addr_reverse(void)
{
    ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
    char buf[128], *syshost = NULL;
    int match;

#ifdef HAVE_GETHOSTNAME
    char host[128];

    if (gethostname(host, sizeof host) == 0) {
        syshost = host;
    }
#endif

    ONN("ne_iaddr_make returned NULL", ia == NULL);

    ONN("reverse lookup for 127.0.0.1 failed",
        ne_iaddr_reverse(ia, buf, sizeof buf) != 0);

    NE_DEBUG(NE_DBG_SOCKET, "Reverse lookup for 127.0.0.1 => %s\n", buf);

    match = strcmp(buf, "localhost.localdomain") == 0
        || strcmp(buf, "localhost") == 0;

    if (!match && syshost)
        /* If the returned name has the system hostname as a prefix, that's
         * good enough. */
        match = strncmp(buf, syshost, strlen(syshost)) == 0;

    if (!match)
        t_warning("reverse lookup for 127.0.0.1 got '%s'", buf);
    
    ONN("reverse lookup for 127.0.0.1 got empty string", strlen(buf) == 0);

    ne_iaddr_free(ia);

    return OK;
}
コード例 #10
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
static int addr_compare(void)
{
    ne_inet_addr *ia1, *ia2;
    int ret;

    ia1 = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
    ia2 = ne_iaddr_make(ne_iaddr_ipv4, raw_127);
    ONN("addr_make returned NULL", !ia1 || !ia2);

    ret = ne_iaddr_cmp(ia1, ia2);
    ONV(ret != 0, ("comparison of equal IPv4 addresses was %d", ret));
    ne_iaddr_free(ia2);

    ia2 = ne_iaddr_make(ne_iaddr_ipv4, raw_1234);
    ret = ne_iaddr_cmp(ia1, ia2);
    ONN("comparison of unequal IPv4 addresses was zero", ret == 0);
    
#ifdef TEST_IPV6
    ne_iaddr_free(ia2);
    ia2 = ne_iaddr_make(ne_iaddr_ipv6, raw6_cafe);
    ONN("could not make IPv6 address", !ia2);
    ret = ne_iaddr_cmp(ia1, ia2);
    ONN("comparison of IPv4 and IPv6 addresses was zero", ret == 0);

    ne_iaddr_free(ia1);
    ia1 = ne_iaddr_make(ne_iaddr_ipv6, raw6_cafe);
    ret = ne_iaddr_cmp(ia1, ia2);
    ONN("comparison of equal IPv6 addresses was not zero", ret != 0);

    ne_iaddr_free(ia1);
    ia1 = ne_iaddr_make(ne_iaddr_ipv6, raw6_babe);
    ret = ne_iaddr_cmp(ia1, ia2);
    ONN("comparison of unequal IPv6 address was zero", ret == 0);
#endif    

    ne_iaddr_free(ia1);
    ne_iaddr_free(ia2);
    return OK;
}
コード例 #11
0
ファイル: ne_openssl.c プロジェクト: Rupan/winscp
/* Check certificate identity.  Returns zero if identity matches; 1 if
 * identity does not match, or <0 if the certificate had no identity.
 * If 'identity' is non-NULL, store the malloc-allocated identity in
 * *identity.  Logic specified by RFC 2818 and RFC 3280. */
static int check_identity(const ne_uri *server, X509 *cert, char **identity)
{
    STACK_OF(GENERAL_NAME) *names;
    int match = 0, found = 0;
    const char *hostname;
    
    hostname = server ? server->host : "";

    names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
    if (names) {
	int n;

        /* subjectAltName contains a sequence of GeneralNames */
	for (n = 0; n < sk_GENERAL_NAME_num(names) && !match; n++) {
	    GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, n);
	    
            /* handle dNSName and iPAddress name extensions only. */
	    if (nm->type == GEN_DNS) {
		char *name = dup_ia5string(nm->d.ia5);
                if (identity && !found) *identity = ne_strdup(name);
		match = ne__ssl_match_hostname(name, strlen(name), hostname);
		free(name);
		found = 1;
            } 
            else if (nm->type == GEN_IPADD) {
                /* compare IP address with server IP address. */
                ne_inet_addr *ia;
                if (nm->d.ip->length == 4)
                    ia = ne_iaddr_make(ne_iaddr_ipv4, nm->d.ip->data);
                else if (nm->d.ip->length == 16)
                    ia = ne_iaddr_make(ne_iaddr_ipv6, nm->d.ip->data);
                else
                    ia = NULL;
                /* ne_iaddr_make returns NULL if address type is unsupported */
                if (ia != NULL) { /* address type was supported. */
                    char buf[128];

                    match = strcmp(hostname, 
                                   ne_iaddr_print(ia, buf, sizeof buf)) == 0;
                    found = 1;
                    ne_iaddr_free(ia);
                } else {
                    NE_DEBUG(NE_DBG_SSL, "iPAddress name with unsupported "
                             "address type (length %d), skipped.\n",
                             nm->d.ip->length);
                }
            } 
            else if (nm->type == GEN_URI) {
                char *name = dup_ia5string(nm->d.ia5);
                ne_uri uri;

                if (ne_uri_parse(name, &uri) == 0 && uri.host && uri.scheme) {
                    ne_uri tmp;

                    if (identity && !found) *identity = ne_strdup(name);
                    found = 1;

                    if (server) {
                        /* For comparison purposes, all that matters is
                         * host, scheme and port; ignore the rest. */
                        memset(&tmp, 0, sizeof tmp);
                        tmp.host = uri.host;
                        tmp.scheme = uri.scheme;
                        tmp.port = uri.port;
                        
                        match = ne_uri_cmp(server, &tmp) == 0;
                    }
                }

                ne_uri_free(&uri);
                free(name);
            }
	}
        /* free the whole stack. */
        sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
    }
    
    /* Check against the commonName if no DNS alt. names were found,
     * as per RFC3280. */
    if (!found) {
	X509_NAME *subj = X509_get_subject_name(cert);
	X509_NAME_ENTRY *entry;
	ne_buffer *cname = ne_buffer_ncreate(30);
	int idx = -1, lastidx;

	/* find the most specific commonName attribute. */
	do {
	    lastidx = idx;
	    idx = X509_NAME_get_index_by_NID(subj, NID_commonName, lastidx);
	} while (idx >= 0);
	
	if (lastidx < 0) {
            /* no commonName attributes at all. */
            ne_buffer_destroy(cname);
	    return -1;
        }

	/* extract the string from the entry */
        entry = X509_NAME_get_entry(subj, lastidx);
        if (append_dirstring(cname, X509_NAME_ENTRY_get_data(entry))) {
            ne_buffer_destroy(cname);
            return -1;
        }
        if (identity) *identity = ne_strdup(cname->data);
        match = ne__ssl_match_hostname(cname->data, cname->used - 1, hostname);
        ne_buffer_destroy(cname);
    }

    NE_DEBUG(NE_DBG_SSL, "Identity match for '%s': %s\n", hostname, 
             match ? "good" : "bad");
    return match ? 0 : 1;
}
コード例 #12
0
ファイル: ne_gnutls.c プロジェクト: Nymphetaminer/dsl-n55u
/* Check certificate identity.  Returns zero if identity matches; 1 if
 * identity does not match, or <0 if the certificate had no identity.
 * If 'identity' is non-NULL, store the malloc-allocated identity in
 * *identity.  If 'server' is non-NULL, it must be the network address
 * of the server in use, and identity must be NULL. */
static int check_identity(const ne_uri *server, gnutls_x509_crt cert,
                          char **identity)
{
    char name[255];
    unsigned int critical;
    int ret, seq = 0;
    int match = 0, found = 0;
    size_t len;
    const char *hostname;
    
    hostname = server ? server->host : "";

    do {
        len = sizeof name - 1;
        ret = gnutls_x509_crt_get_subject_alt_name(cert, seq, name, &len,
                                                   &critical);
        switch (ret) {
        case GNUTLS_SAN_DNSNAME:
            name[len] = '\0';
            if (identity && !found) *identity = ne_strdup(name);
            match = ne__ssl_match_hostname(name, len, hostname);
            found = 1;
            break;
        case GNUTLS_SAN_IPADDRESS: {
            ne_inet_addr *ia;
            if (len == 4)
                ia = ne_iaddr_make(ne_iaddr_ipv4, (unsigned char *)name);
            else if (len == 16)
                ia = ne_iaddr_make(ne_iaddr_ipv6, (unsigned char *)name);
            else 
                ia = NULL;
            if (ia) {
                char buf[128];
                
                match = strcmp(hostname, 
                               ne_iaddr_print(ia, buf, sizeof buf)) == 0;
                if (identity) *identity = ne_strdup(buf);
                found = 1;
                ne_iaddr_free(ia);
            } else {
                NE_DEBUG(NE_DBG_SSL, "iPAddress name with unsupported "
                         "address type (length %" NE_FMT_SIZE_T "), skipped.\n",
                         len);
            }
        } break;
        case GNUTLS_SAN_URI: {
            ne_uri uri;
            
            name[len] = '\0';
            
            if (ne_uri_parse(name, &uri) == 0 && uri.host && uri.scheme) {
                ne_uri tmp;
                
                if (identity && !found) *identity = ne_strdup(name);
                found = 1;
                
                if (server) {
                    /* For comparison purposes, all that matters is
                     * host, scheme and port; ignore the rest. */
                    memset(&tmp, 0, sizeof tmp);
                    tmp.host = uri.host;
                    tmp.scheme = uri.scheme;
                    tmp.port = uri.port;
                    
                    match = ne_uri_cmp(server, &tmp) == 0;
                }
            }
            
            ne_uri_free(&uri);
        } break;

        default:
            break;
        }
        seq++;
    } while (!match && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

    /* Check against the commonName if no DNS alt. names were found,
     * as per RFC3280. */
    if (!found) {
        seq = oid_find_highest_index(cert, 1, GNUTLS_OID_X520_COMMON_NAME);

        if (seq >= 0) {
            len = sizeof name;
            name[0] = '\0';
            ret = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME,
                                                seq, 0, name, &len);
            if (ret == 0) {
                if (identity) *identity = ne_strdup(name);
                match = ne__ssl_match_hostname(name, len, hostname);
            }
        } else {
            return -1;
        }
    }

    if (*hostname)
        NE_DEBUG(NE_DBG_SSL, "ssl: Identity match for '%s': %s\n", hostname, 
                 match ? "good" : "bad");

    return match ? 0 : 1;
}
コード例 #13
0
ファイル: ne_gnutls.c プロジェクト: GCrean/sitecopy
/* Check certificate identity.  Returns zero if identity matches; 1 if
 * identity does not match, or <0 if the certificate had no identity.
 * If 'identity' is non-NULL, store the malloc-allocated identity in
 * *identity.  If 'server' is non-NULL, it must be the network address
 * of the server in use, and identity must be NULL. */
static int check_identity(const char *hostname, gnutls_x509_crt cert,
                          char **identity)
{
    char name[255];
    unsigned int critical;
    int ret, seq = 0;
    int match = 0, found = 0;
    size_t len;

    do {
        len = sizeof name;
        ret = gnutls_x509_crt_get_subject_alt_name(cert, seq, name, &len,
                                                   &critical);
        switch (ret) {
        case GNUTLS_SAN_DNSNAME:
            if (identity && !found) *identity = ne_strdup(name);
            match = match_hostname(name, hostname);
            found = 1;
            break;
        case GNUTLS_SAN_IPADDRESS: {
            ne_inet_addr *ia;
            if (len == 4)
                ia = ne_iaddr_make(ne_iaddr_ipv4, (unsigned char *)name);
            else if (len == 16)
                ia = ne_iaddr_make(ne_iaddr_ipv6, (unsigned char *)name);
            else 
                ia = NULL;
            if (ia) {
                char buf[128];
                
                match = strcmp(hostname, 
                               ne_iaddr_print(ia, buf, sizeof buf)) == 0;
                if (identity) *identity = ne_strdup(buf);
                found = 1;
                ne_iaddr_free(ia);
            } else {
                NE_DEBUG(NE_DBG_SSL, "iPAddress name with unsupported "
                         "address type (length %" NE_FMT_SIZE_T "), skipped.\n",
                         len);
            }
        } break;
        default:
            break;
        }
        seq++;
    } while (!match && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

    /* Check against the commonName if no DNS alt. names were found,
     * as per RFC3280. */
    if (!found) {
        seq = oid_find_highest_index(cert, 1, GNUTLS_OID_X520_COMMON_NAME);

        if (seq >= 0) {
            len = sizeof name;
            name[0] = '\0';
            ret = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME,
                                                seq, 0, name, &len);
            if (ret == 0) {
                if (identity) *identity = ne_strdup(name);
                match = match_hostname(name, hostname);
            }
        } else {
            return -1;
        }
    }

    NE_DEBUG(NE_DBG_SSL, "Identity match: %s\n", match ? "good" : "bad");
    return match ? 0 : 1;
}
コード例 #14
0
ファイル: socket.c プロジェクト: Ugnis/Far-NetBox
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;
}