Esempio n. 1
0
int main(int argc, char *argv[])
{
    int n;
    static const char dots[] = "......................";
    
    /* get basename(argv[0]) */
    test_suite = strrchr(argv[0], '/');
    if (test_suite == NULL) {
	test_suite = argv[0];
    } else {
	test_suite++;
    }

#ifdef HAVE_SETLOCALE
    setlocale(LC_MESSAGES, "");
#endif

    ne_i18n_init(NULL);

#if defined(HAVE_ISATTY) && defined(STDOUT_FILENO)
    if (isatty(STDOUT_FILENO)) {
	use_colour = 1;
    }
#endif

    test_argc = argc;
    test_argv = argv;

    debug = fopen("debug.log", "a");
    if (debug == NULL) {
	fprintf(stderr, "%s: Could not open debug.log: %s\n", test_suite,
		strerror(errno));
	return -1;
    }
    child_debug = fopen("child.log", "a");
    if (child_debug == NULL) {
	fprintf(stderr, "%s: Could not open child.log: %s\n", test_suite,
		strerror(errno));
	fclose(debug);
	return -1;
    }

    if (tests[0].fn == NULL) {
	printf("-> no tests found in `%s'\n", test_suite);
	return -1;
    }

    /* install special SEGV handler. */
    signal(SIGSEGV, parent_segv);
    signal(SIGABRT, parent_segv);

    /* test the "no-debugging" mode of ne_debug. */
    ne_debug_init(NULL, 0);
    NE_DEBUG(TEST_DEBUG, "This message should go to /dev/null");

    /* enable debugging for real. */
    ne_debug_init(debug, TEST_DEBUG);
    NE_DEBUG(TEST_DEBUG | NE_DBG_FLUSH, "Version string: %s\n", 
             ne_version_string());
    
    /* another silly test. */
    NE_DEBUG(0, "This message should also go to /dev/null");

    if (ne_sock_init()) {
	COL("43;01"); printf("WARNING:"); NOCOL;
	printf(" Socket library initalization failed.\n");
    }

    printf("-> running `%s':\n", test_suite);
    
    for (n = 0; !aborted && tests[n].fn != NULL; n++) {
	int result, is_xfail = 0;
#ifdef NEON_MEMLEAK
        size_t allocated = ne_alloc_used;
        int is_xleaky = 0;
#endif

	test_name = tests[n].name;
	printf("%2d. %s%.*s ", n, test_name, 
	       (int) (strlen(dots) - strlen(test_name)), dots);
	have_context = 0;
	test_num = n;
	warned = 0;
	fflush(stdout);
	NE_DEBUG(TEST_DEBUG, "******* Running test %d: %s ********\n", 
		 n, test_name);

	/* run the test. */
	result = tests[n].fn();

#ifdef NEON_MEMLEAK
        /* issue warnings for memory leaks, if requested */
        if ((tests[n].flags & T_CHECK_LEAKS) && result == OK &&
            ne_alloc_used > allocated) {
            t_context("memory leak of %" NE_FMT_SIZE_T " bytes",
                      ne_alloc_used - allocated);
            fprintf(debug, "Blocks leaked: ");
            ne_alloc_dump(debug);
            result = FAIL;
        } else if (tests[n].flags & T_EXPECT_LEAKS && result == OK &&
                   ne_alloc_used == allocated) {
            t_context("expected memory leak not detected");
            result = FAIL;
        } else if (tests[n].flags & T_EXPECT_LEAKS && result == OK) {
            fprintf(debug, "Blocks leaked (expected): ");
            ne_alloc_dump(debug);
            is_xleaky = 1;
        } 
#endif

        if (tests[n].flags & T_EXPECT_FAIL) {
            if (result == OK) {
                t_context("test passed but expected failure");
                result = FAIL;
            } else if (result == FAIL) {
                result = OK;
                is_xfail = 1;
            }
        }

	/* align the result column if we've had warnings. */
	if (warned) {
	    printf("    %s ", dots);
	}

	switch (result) {
	case OK:
            if (is_xfail) {
                COL("32;07"); 
                printf("xfail");
            } else {
                COL("32"); 
                printf("pass"); 
            }
            NOCOL;
	    if (warned) {
		printf(" (with %d warning%s)", warned, (warned > 1)?"s":"");
	    }
#ifdef NEON_MEMLEAK
            if (is_xleaky) {
                printf(" (with expected leak, %" NE_FMT_SIZE_T " bytes)",
                       ne_alloc_used - allocated);
            }
#endif
	    putchar('\n');
	    passes++;
	    break;
	case FAILHARD:
	    aborted = 1;
	    /* fall-through */
	case FAIL:
	    COL("41;37;01"); printf("FAIL"); NOCOL;
	    if (have_context) {
		printf(" (%s)", test_context);
	    }
	    putchar('\n');
	    fails++;
	    break;
	case SKIPREST:
	    aborted = 1;
	    /* fall-through */
	case SKIP:
	    COL("44;37;01"); printf("SKIPPED"); NOCOL;
	    if (have_context) {
		printf(" (%s)", test_context);
	    }
	    putchar('\n');
	    skipped++;
	    break;
	default:
	    COL("41;37;01"); printf("OOPS"); NOCOL;
	    printf(" unexpected test result `%d'\n", result);
	    break;
	}

	reap_server();
    }

    /* discount skipped tests */
    if (skipped) {
	printf("-> %d %s.\n", skipped,
	       skipped==1?"test was skipped":"tests were skipped");
	n -= skipped;
	if (passes + fails != n) {
	    printf("-> ARGH! Number of test results does not match "
		   "number of tests.\n"
		   "-> ARGH! Test Results are INRELIABLE.\n");
	}
    }
    /* print the summary. */
    if (skipped && n == 0) {
	printf("<- all tests skipped for `%s'.\n", test_suite);
    } else {
	printf("<- summary for `%s': "
	       "of %d tests run: %d passed, %d failed. %.1f%%\n",
	       test_suite, n, passes, fails, 100*(float)passes/n);
	if (warnings) {
	    printf("-> %d warning%s issued.\n", warnings, 
		   warnings==1?" was":"s were");
	}
    }

    if (fclose(debug)) {
	fprintf(stderr, "Error closing debug.log: %s\n", strerror(errno));
	fails = 1;
    }
       
    if (fclose(child_debug)) {
	fprintf(stderr, "Error closing child.log: %s\n", strerror(errno));
	fails = 1;
    }

    ne_sock_exit();
    
    return fails;
}
Esempio n. 2
0
int serve_file(ne_socket *sock, void *ud)
{
    char buffer[BUFSIZ];
    struct stat st;
    struct serve_file_args *args = ud;
    ssize_t ret;
    int fd;

    CALL(discard_request(sock));

    ne_sock_fullread(sock, buffer, clength);

    fd = open(args->fname, O_RDONLY);
    if (fd < 0) {
	SEND_STRING(sock,
		    "HTTP/1.0 404 File Not Found\r\n"
		    "Content-Length: 0\r\n\r\n");
	return 0;
    }

    ONN("fstat fd", fstat(fd, &st));

    SEND_STRING(sock, "HTTP/1.0 200 OK\r\n");
    if (args->chunks) {
	sprintf(buffer, "Transfer-Encoding: chunked\r\n");
    } else {
	sprintf(buffer, "Content-Length: %" NE_FMT_OFF_T "\r\n",
		st.st_size);
    }

    if (args->headers) {
	strcat(buffer, args->headers);
    }

    strcat(buffer, "\r\n");

    SEND_STRING(sock, buffer);

    NE_DEBUG(NE_DBG_HTTP, "Serving %s (%" NE_FMT_OFF_T " bytes).\n",
	     args->fname, st.st_size);

    if (args->chunks) {
	char buf[1024];

	while ((ret = read(fd, &buf, args->chunks)) > 0) {
	    /* this is a small integer, cast it explicitly to avoid
	     * warnings with printing an ssize_t. */
	    sprintf(buffer, "%x\r\n", (unsigned int)ret);
	    SEND_STRING(sock, buffer);
	    ONN("writing body", ne_sock_fullwrite(sock, buf, ret));
	    SEND_STRING(sock, "\r\n");
	}

	SEND_STRING(sock, "0\r\n\r\n");

    } else {
	while ((ret = read(fd, buffer, BUFSIZ)) > 0) {
	    ONN("writing body", ne_sock_fullwrite(sock, buffer, ret));
	}
    }

    ONN("error reading from file", ret < 0);

    (void) close(fd);

    return OK;
}
Esempio n. 3
0
/* Callback which is passed blocks of the response body. */
static int gz_reader(void *ud, const char *buf, size_t len)
{
    ne_decompress *ctx = ud;
    NE_DEBUG_WINSCP_CONTEXT(ctx->session);
    const char *zbuf;
    size_t count;
    const char *hdr;

    if (len == 0) {
        /* End of response: */
        switch (ctx->state) {
        case NE_Z_BEFORE_DATA:
            hdr = ne_get_response_header(ctx->request, "Content-Encoding");
            if (hdr && ne_strcasecmp(hdr, "gzip") == 0) {
                /* response was truncated: return error. */
                break;
            }
            /* else, fall through */
        case NE_Z_FINISHED: /* complete gzip response */
        case NE_Z_PASSTHROUGH: /* complete uncompressed response */
            return ctx->reader(ctx->userdata, buf, 0);
        default:
            /* invalid state: truncated response. */
            break;
        }
	/* else: truncated response, fail. */
	ne_set_error(ctx->session, "Compressed response was truncated");
	return NE_ERROR;
    }        

    switch (ctx->state) {
    case NE_Z_PASSTHROUGH:
	/* move along there. */
	return ctx->reader(ctx->userdata, buf, len);

    case NE_Z_FINISHED:
	/* Could argue for tolerance, and ignoring trailing content;
	 * but it could mean something more serious. */
	if (len > 0) {
	    ne_set_error(ctx->session,
			 "Unexpected content received after compressed stream");
            return NE_ERROR;
	}
        break;

    case NE_Z_BEFORE_DATA:
	/* work out whether this is a compressed response or not. */
        hdr = ne_get_response_header(ctx->request, "Content-Encoding");
        if (hdr && ne_strcasecmp(hdr, "gzip") == 0) {
            int ret;
	    NE_DEBUG(NE_DBG_HTTP, "compress: got gzipped stream.\n");

            /* inflateInit2() works here where inflateInit() doesn't. */
            ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
            if (ret != Z_OK) {
                set_zlib_error(ctx, _("Could not initialize zlib"), ret);
                return -1;
            }
	    ctx->zstrinit = 1;

	} else {
	    /* No Content-Encoding header: pass it on.  TODO: we could
	     * hack it and register the real callback now. But that
	     * would require add_resp_body_rdr to have defined
	     * ordering semantics etc etc */
	    ctx->state = NE_Z_PASSTHROUGH;
	    return ctx->reader(ctx->userdata, buf, len);
	}

	ctx->state = NE_Z_IN_HEADER;
	/* FALLTHROUGH */

    case NE_Z_IN_HEADER:
	/* copy as many bytes as possible into the buffer. */
	if (len + ctx->hdrcount > 10) {
	    count = 10 - ctx->hdrcount;
	} else {
	    count = len;
	}
	memcpy(ctx->header + ctx->hdrcount, buf, count);
	ctx->hdrcount += count;
	/* have we got the full header yet? */
	if (ctx->hdrcount != 10) {
	    return 0;
	}

	buf += count;
	len -= count;

	switch (parse_header(ctx)) {
	case HDR_EXTENDED:
	    if (len == 0)
		return 0;
	    break;
        case HDR_ERROR:
            return NE_ERROR;
	case HDR_DONE:
	    if (len > 0) {
		return do_inflate(ctx, buf, len);
	    }
            break;
	}

	/* FALLTHROUGH */

    case NE_Z_POST_HEADER:
	/* eating the filename string. */
	zbuf = memchr(buf, '\0', len);
	if (zbuf == NULL) {
	    /* not found it yet. */
	    return 0;
	}

	NE_DEBUG(NE_DBG_HTTP,
		 "compresss: skipped %" NE_FMT_SIZE_T " header bytes.\n", 
		 zbuf - buf);
	/* found end of string. */
	len -= (1 + zbuf - buf);
	buf = zbuf + 1;
	ctx->state = NE_Z_INFLATING;
	if (len == 0) {
	    /* end of string was at end of buffer. */
	    return 0;
	}

	/* FALLTHROUGH */

    case NE_Z_INFLATING:
	return do_inflate(ctx, buf, len);

    case NE_Z_AFTER_DATA:
	return process_footer(ctx, (unsigned char *)buf, len);
    }

    return 0;
}
Esempio n. 4
0
int spawn_server_repeat(int port, server_fn fn, void *userdata, int n)
{
    int fds[2];

#ifdef USE_PIPE
    if (pipe(fds)) {
	perror("spawn_server: pipe");
	return FAIL;
    }
#else
    /* avoid using uninitialized variable. */
    fds[0] = fds[1] = 0;
#endif

    child = fork();

    if (child == 0) {
	/* this is the child. */
	int listener, count = 0;

	in_child();

	listener = do_listen(lh_addr, port);

#ifdef USE_PIPE
	if (write(fds[1], "Z", 1) != 1) abort();
#endif

	close(fds[1]);
	close(fds[0]);

	/* Loop serving requests. */
	while (++count < n) {
	    ne_socket *sock = ne_sock_create();
	    int ret;

	    NE_DEBUG(NE_DBG_HTTP, "child awaiting connection #%d.\n", count);
	    ONN("accept failed", ne_sock_accept(sock, listener));
	    ret = fn(sock, userdata);
	    close_socket(sock);
	    NE_DEBUG(NE_DBG_HTTP, "child served request, %d.\n", ret);
	    if (ret) {
		printf("server child failed: %s\n", test_context);
		exit(-1);
	    }
	    /* don't send back notification to parent more than
	     * once. */
	}

	NE_DEBUG(NE_DBG_HTTP, "child aborted.\n");
	close(listener);

	exit(-1);

    } else {
	char ch;
	/* this is the parent. wait for the child to get ready */
#ifdef USE_PIPE
	if (read(fds[0], &ch, 1) < 0)
	    perror("parent read");

	close(fds[0]);
	close(fds[1]);
#else
	minisleep();
#endif
    }

    return OK;
}
Esempio n. 5
0
ssize_t server_send(ne_socket *sock, const char *str, size_t len)
{
    NE_DEBUG(NE_DBG_HTTP, "Sending: %.*s\n", (int)len, str);
    return ne_sock_fullwrite(sock, str, len);
}
Esempio n. 6
0
/* Return the certificate chain sent by the peer, or NULL on error. */
static ne_ssl_certificate *make_peers_chain(gnutls_session sock,
                                            gnutls_certificate_credentials crd)
{
    ne_ssl_certificate *current = NULL, *top = NULL;
    const gnutls_datum *certs;
    unsigned int n, count;
    ne_ssl_certificate *cert;

    certs = gnutls_certificate_get_peers(sock, &count);
    if (!certs) {
        return NULL;
    }

    NE_DEBUG(NE_DBG_SSL, "ssl: Got %u certs in peer chain.\n", count);
    
    for (n = 0; n < count; n++) {
        gnutls_x509_crt x5;

        if (gnutls_x509_crt_init(&x5) ||
            gnutls_x509_crt_import(x5, &certs[n], GNUTLS_X509_FMT_DER)) {
            if (top) {
                ne_ssl_cert_free(top);
            }
            return NULL;
        }

        cert = populate_cert(ne_calloc(sizeof *cert), x5);
        
        if (top == NULL) {
            current = top = cert;
        } else {
            current->issuer = cert;
            current = cert;
        }
    }

#ifdef HAVE_GNUTLS_CERTIFICATE_GET_X509_CAS
    /* GnuTLS only returns the peers which were *sent* by the server
     * in the Certificate list during the handshake.  Fill in the
     * complete chain manually against the certs we trust: */
    if (current->issuer == NULL) {
        gnutls_x509_crt issuer;
        gnutls_x509_crt *ca_list;
        unsigned int num_cas;
        
        gnutls_certificate_get_x509_cas(crd, &ca_list, &num_cas);

        do { 
            /* Look up the issuer. */
            issuer = find_issuer(ca_list, num_cas, current->subject);
            if (issuer) {
                issuer = x509_crt_copy(issuer);
                cert = populate_cert(ne_calloc(sizeof *cert), issuer);
                /* Check that the issuer does not match the current
                 * cert. */
                if (ne_ssl_cert_cmp(current, cert)) {
                    current = current->issuer = cert;
                }
                else {
                    ne_ssl_cert_free(cert);
                    issuer = NULL;
                }
            }
        } while (issuer);
    }
#endif
    
    return top;
}
Esempio n. 7
0
/* 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;
}
Esempio n. 8
0
/* 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;
}
Esempio n. 9
0
/* Callback invoked when the SSL server requests a client certificate.  */
static int provide_client_cert(gnutls_session session,
                               const gnutls_datum *req_ca_rdn, int nreqs,
                               const gnutls_pk_algorithm *sign_algos,
                               int sign_algos_length, gnutls_retr_st *st)
{
    ne_session *sess = gnutls_session_get_ptr(session);
    
    if (!sess) {
        return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
    }

    NE_DEBUG(NE_DBG_SSL, "ssl: Client cert provider callback; %d CA names.\n",
             nreqs);

    if (!sess->client_cert && sess->ssl_provide_fn) {
#ifdef HAVE_NEW_DN_API
        const ne_ssl_dname **dns;
        ne_ssl_dname *dnarray;
        unsigned dncount = 0;
        int n;

        dns = ne_malloc(nreqs * sizeof(ne_ssl_dname *));
        dnarray = ne_calloc(nreqs * sizeof(ne_ssl_dname));

        for (n = 0; n < nreqs; n++) {
            gnutls_x509_dn_t dn;

            if (gnutls_x509_dn_init(&dn) == 0) {
                dnarray[n].dn = dn;
                if (gnutls_x509_dn_import(dn, &req_ca_rdn[n]) == 0) {
                    dns[dncount++] = &dnarray[n];
                }
                else {
                    gnutls_x509_dn_deinit(dn);
                }            
            }
        }
       
        NE_DEBUG(NE_DBG_SSL, "ssl: Mapped %d CA names to %u DN objects.\n",
                 nreqs, dncount);

        sess->ssl_provide_fn(sess->ssl_provide_ud, sess, dns, dncount);
        
        for (n = 0; n < nreqs; n++) {
            if (dnarray[n].dn) {
                gnutls_x509_dn_deinit(dnarray[n].dn);
            }
        }

        ne_free(dns);
        ne_free(dnarray);
#else /* HAVE_NEW_DN_API */
        /* Nothing to do here other than pretend no CA names were
         * given, and hope the caller can cope. */
        sess->ssl_provide_fn(sess->ssl_provide_ud, sess, NULL, 0);
#endif
    }

    if (sess->client_cert) {
        gnutls_certificate_type type = gnutls_certificate_type_get(session);
        if (type == GNUTLS_CRT_X509) {
            NE_DEBUG(NE_DBG_SSL, "Supplying client certificate.\n");

            st->type = type;
            st->ncerts = 1;
            st->cert.x509 = &sess->client_cert->cert.subject;
            st->key.x509 = sess->client_cert->pkey;
            
            /* tell GNU TLS not to deallocate the certs. */
            st->deinit_all = 0;
        } else {
            return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
        }
    } 
    else {
        NE_DEBUG(NE_DBG_SSL, "No client certificate supplied.\n");
        st->ncerts = 0;
        sess->ssl_cc_requested = 1;
        return 0;
    }

    return 0;
}
Esempio n. 10
0
void select_ctree_cb(GtkCTree * ctree, GtkCTreeNode * node, gpointer data)
{
    GtkCTreeNode *parent;
    struct site *current_site;
    struct site_file *current_file;
    void *data_to_get;
    struct ctree_attachment *actual_data;
   extern GtkWidget *main_area_box, *area_data;
   
    /* Make sure that any changes have been confirmed on the selected site,
     * before selected_site gets changed. This seems to get automatically done
     * by the signal handler.
     */

    if (GTK_CTREE_ROW(node)->parent == NULL) {	/* We're at the top level */
	if ((data_to_get = gtk_ctree_node_get_row_data(GTK_CTREE(ctree), GTK_CTREE_NODE(node))) == NULL) {
	    NE_DEBUG(DEBUG_GNOME, "\"Data get\" returned NULL. Oh dear.\n");
	}
	actual_data = (struct ctree_attachment *) data_to_get;
	if (actual_data->file_or_site != IS_A_SITE)
	    NE_DEBUG(DEBUG_GNOME, "Somehow you've clicked on a site, but ended up with file data!\n");
	current_site = (struct site *) actual_data->info_struct;

	/* Make the data shared */
	selected_site = current_site;
	current_site_node = node;

	NE_DEBUG (DEBUG_GNOME, "Removing widgets from main data area...\n");	
	gtk_container_remove(GTK_CONTAINER(main_area_box), area_data);
	NE_DEBUG (DEBUG_GNOME, "Building site info widgets...\n");
	area_data = make_site_info_area(current_site);
	NE_DEBUG (DEBUG_GNOME, "Adding widgets to main data area...");
	gtk_container_add(GTK_CONTAINER(main_area_box), area_data);
	NE_DEBUG (DEBUG_GNOME, "done.\n");
    } else if (GTK_CTREE_ROW(node)->parent != NULL) {

	parent = GTK_CTREE_ROW(node)->parent;

	/* Grab the file data from that row */
	if ((data_to_get = gtk_ctree_node_get_row_data(GTK_CTREE(ctree), GTK_CTREE_NODE(node))) == NULL) {
	    NE_DEBUG(DEBUG_GNOME, "\"Data get\" for the file returned NULL. Oh dear.\n");
	}
	actual_data = (struct ctree_attachment *) data_to_get;
	if (actual_data->file_or_site != IS_A_FILE)
	    NE_DEBUG(DEBUG_GNOME, "Somehow you've clicked on a file, but ended up with site data!\n");
	current_file = (struct site_file *) actual_data->info_struct;

	/* Grab the site data from the file's parent */
	while (GTK_CTREE_ROW(parent)->parent != NULL) {
	    parent = GTK_CTREE_ROW(parent)->parent;
	    NE_DEBUG(DEBUG_GNOME, "Assigned parent to node->parent.\n");
	}

	if ((data_to_get = gtk_ctree_node_get_row_data(GTK_CTREE(ctree), GTK_CTREE_NODE(parent))) == NULL) {
	    NE_DEBUG(DEBUG_GNOME, "\"Data get\" for the file's parent returned NULL. Oh dear.\n");
	}
	actual_data = (struct ctree_attachment *) data_to_get;
	if (actual_data->file_or_site != IS_A_SITE)
	    NE_DEBUG(DEBUG_GNOME, "Somehow you've clicked on a file, but it's parent was a file too!?\n");
	current_site = (struct site *) actual_data->info_struct;
	selected_site = current_site;
	current_site_node = parent;
	if (current_file == NULL) {
	    gfe_status("Unable to access info about the selected file.");
	} else {
	    /* This line is causing a mutex to deadlock. why....? */
	    NE_DEBUG (DEBUG_GNOME, "Removing widgets from main data area...\n");
	    gtk_container_remove(GTK_CONTAINER(main_area_box), area_data);
	    NE_DEBUG (DEBUG_GNOME, "Making file info area...\n");
	    area_data = make_file_info_area(current_file);
	    NE_DEBUG (DEBUG_GNOME, "Adding file info area to main area...");
	    gtk_container_add(GTK_CONTAINER(main_area_box), area_data);
	    NE_DEBUG (DEBUG_GNOME, "done.\n");
	}
    } else {
	g_warning("If you got to here, something is really buggered, quite frankly.\n");
    }
}
Esempio n. 11
0
/* 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;
}
Esempio n. 12
0
GNode *build_tree_from_site(struct site *a_site)
{

    GNode *tree_root;
    struct site_node_data *tmp;
    struct site_file *current_dir, *current_file;
    
    NE_DEBUG(DEBUG_GNOME, "Called build_tree_from_site for site, %s.\n",
	  a_site->name);

    /* If this site isn't perfect, then don't try and scan the directory.
     */
    /*{
      int ret = rc_verifysite(a_site);
      if ((ret == SITE_NOLOCALDIR) || (ret == SITE_ACCESSLOCALDIR))
	return NULL;
    }*/
    
    tmp = g_malloc0(sizeof(struct site_node_data));
    tmp->name = "ROOT";

    /* Create the root node. */
    tree_root = g_node_new(tmp);

    /* For each dir in site->files, blah... */
    NE_DEBUG(DEBUG_GNOME, "Created root node, about to enter directory loop...\n");

    /* This is not very time efficient, but I'm not the one that dictates the
       * ordering of files/directories, so don't blame me.
       * What we do here is create all the directory nodes first (and the
       * directory nodes _only_), and then add the files once the dirs are known
       * to be in place.
     */
    for (current_dir = a_site->files_tail;
	 (current_dir) && (current_dir->type == file_dir);
	 current_dir = current_dir->prev)
      ;

    /* There! SPLAT! Got you, you little bastard of a bug. */
/*    if (!current_dir)
      return tree_root;*/

    if (current_dir) 
      {
	  for (current_dir = current_dir->next; 
	       current_dir;
	       current_dir = current_dir->next)
	    {
		core_tree_building_function(current_dir, tree_root);
	    }
      }
    

    for (current_file = a_site->files;
	 (current_file) && (current_file->type != file_dir);
	 current_file = current_file->next) {
	core_tree_building_function(current_file, tree_root);
    }

    /* FIXME: do files here somehow? */
    return tree_root;
}
Esempio n. 13
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;    
}
Esempio n. 14
0
void ne_session_system_proxy(ne_session *sess, unsigned int flags)
{
    NE_DEBUG_WINSCP_CONTEXT(sess);
#ifdef HAVE_LIBPROXY
    pxProxyFactory *pxf = px_proxy_factory_new();
    struct host_info *hi, **lasthi;
    char *url, **proxies;
    ne_uri uri;
    unsigned n;

    free_proxies(sess);

    /* Create URI for session to pass off to libproxy */
    memset(&uri, 0, sizeof uri);
    ne_fill_server_uri(sess, &uri);

    uri.path = "/"; /* make valid URI structure. */
    url = ne_uri_unparse(&uri);
    uri.path = NULL;

    /* Get list of pseudo-URIs from libproxy: */
    proxies = px_proxy_factory_get_proxies(pxf, url);
    
    for (n = 0, lasthi = &sess->proxies; proxies[n]; n++) {
        enum proxy_type ptype;

        ne_uri_free(&uri);

        NE_DEBUG(NE_DBG_HTTP, "sess: libproxy #%u=%s\n", 
                 n, proxies[n]);

        if (ne_uri_parse(proxies[n], &uri))
            continue;
        
        if (!uri.scheme) continue;

        if (ne_strcasecmp(uri.scheme, "http") == 0)
            ptype = PROXY_HTTP;
        else if (ne_strcasecmp(uri.scheme, "socks") == 0)
            ptype = PROXY_SOCKS;
        else if (ne_strcasecmp(uri.scheme, "direct") == 0)
            ptype = PROXY_NONE;
        else
            continue;

        /* Hostname/port required for http/socks schemes. */
        if (ptype != PROXY_NONE && !(uri.host && uri.port))
            continue;
        
        /* Do nothing if libproxy returned only a single "direct://"
         * entry -- a single "direct" (noop) proxy is equivalent to
         * having none. */
        if (n == 0 && proxies[1] == NULL && ptype == PROXY_NONE)
            break;

        NE_DEBUG(NE_DBG_HTTP, "sess: Got proxy %s://%s:%d\n",
                 uri.scheme, uri.host ? uri.host : "(none)",
                 uri.port);
        
        hi = *lasthi = ne_calloc(sizeof *hi);
        
        if (ptype == PROXY_NONE) {
            /* A "direct" URI requires an attempt to connect directly to
             * the origin server, so dup the server details. */
            set_hostinfo(hi, ptype, sess->server.hostname,
                         sess->server.port);
        }
        else {
            /* SOCKS/HTTP proxy. */
            set_hostinfo(hi, ptype, uri.host, uri.port);

            if (ptype == PROXY_HTTP)
                sess->any_proxy_http = 1;
            else if (ptype == PROXY_SOCKS)
                sess->socks_ver = NE_SOCK_SOCKSV5;
        }

        lasthi = &hi->next;
    }

    /* Free up the proxies array: */
    for (n = 0; proxies[n]; n++)
        free(proxies[n]);
    free(proxies[n]);

    ne_free(url);
    ne_uri_free(&uri);
    px_proxy_factory_free(pxf);
#endif
}
Esempio n. 15
0
void *update_thread(void *no_data)
{
    int ret;
    extern sem_t *update_semaphore;
    extern gboolean site_keepgoing;
    
    pthread_detach(pthread_self());
    NE_DEBUG(DEBUG_GNOME, "update_thread: detached.\n");

    for(;;)
      {
	  NE_DEBUG(DEBUG_GNOME, "update_thread: sleeping...\n");
	  /* sleep straight away */
	  sem_wait(update_semaphore);
	  NE_DEBUG(DEBUG_GNOME, "update_thread: Okay, who woke me up!?\n");
	  
	  gdk_threads_enter();
	  gtk_widget_set_sensitive(begin_button, FALSE);
	  gtk_widget_set_sensitive(keep_going_button, FALSE);
	  
	  NE_DEBUG(DEBUG_GNOME, "update_thread: Acquired gtk+ lock\n");
	  
	  if (verifysite_gnome(selected_site)) {
	      close_main_update_window(NULL, NULL);
	      NE_DEBUG(DEBUG_GNOME, "update_thread: The site was wrong, skipping.\n");
	      continue;
	  }
	  
	  NE_DEBUG(DEBUG_GNOME, "update_thread: Verified site okay, updating...");
	  
	  /* Perform the actual update */
	  if (GTK_TOGGLE_BUTTON(keep_going_button)->active) {
	      site_keepgoing = TRUE;
	  } else {
	      site_keepgoing = FALSE;
	  }
	  gdk_threads_leave();	  

	  
	  /* site_update blocks until finished */
	  NE_DEBUG(DEBUG_GNOME, "update_thread: Entering site_update.\n");
	  /* we might want to give this a 3rd argument sometime to allow
	   * updating of single files at a time */
	  /* This calls site_update with a wrapper to facilitate good
	   * abort behaviour */
	  ret = my_abortable_transfer_wrapper(selected_site, site_op_update);
	  NE_DEBUG(DEBUG_GNOME, 
		"update_thread: site_update returned value of %d.\n", ret);
	  
	  gdk_threads_enter();
	  switch (ret) {
	   case SITE_CONNECT:
	      gtk_label_set(GTK_LABEL(status_label), "Unable to establish connection.");
	      gtk_label_set(GTK_LABEL(op_label), " ");
	      gtk_label_set(GTK_LABEL(file_label), " ");
	      gtk_label_set(GTK_LABEL(dir_label), " ");
	      break;
	   case SITE_AUTH:
	      gtk_label_set(GTK_LABEL(status_label), "Authentication with the remote server failed..");
	      gtk_label_set(GTK_LABEL(op_label), " ");
	      gtk_label_set(GTK_LABEL(file_label), " ");
	      gtk_label_set(GTK_LABEL(dir_label), " ");
	      break;
	   case SITE_ERRORS:
	      gtk_label_set(GTK_LABEL(status_label), "There was a problem with the file/directory transfer.");
	      gtk_label_set(GTK_LABEL(op_label), " ");
	      gtk_label_set(GTK_LABEL(file_label), " ");
	      gtk_label_set(GTK_LABEL(dir_label), " ");
	      site_write_stored_state(selected_site);
	      rescan_selected(1);
	      gtk_widget_set_sensitive(error_button, TRUE);
	      break;
	   case SITE_LOOKUP:
	      gtk_label_set(GTK_LABEL(status_label), "Unable to connect: Host name look-up failed.");
	      gtk_label_set(GTK_LABEL(op_label), " ");
	      gtk_label_set(GTK_LABEL(file_label), " ");
	      gtk_label_set(GTK_LABEL(dir_label), " ");
	      break;
	   case SITE_OK:
	      gtk_label_set(GTK_LABEL(status_label), "Update complete. (No errors)");
	      gtk_label_set(GTK_LABEL(op_label), " ");
	      gtk_label_set(GTK_LABEL(file_label), " ");
	      gtk_label_set(GTK_LABEL(dir_label), " ");
	      site_write_stored_state(selected_site);
	      rescan_selected(1);
	      break;
	   case SITE_FAILED:
	      gtk_label_set(GTK_LABEL(status_label), "Update failed. (Authentication problems)");
	      gtk_label_set(GTK_LABEL(op_label), " ");
	      gtk_label_set(GTK_LABEL(file_label), " ");
	      gtk_label_set(GTK_LABEL(dir_label), " ");
	      break;
	   case SITE_ABORTED:
	      gtk_label_set(GTK_LABEL(status_label), "Update was aborted.");
	      gtk_label_set(GTK_LABEL(op_label), " ");
	      gtk_label_set(GTK_LABEL(file_label), " ");
	      gtk_label_set(GTK_LABEL(dir_label), " ");
	      site_write_stored_state(selected_site);
	      /*rescan_selected(1);*/
	      break;
	   default:
	      gtk_label_set(GTK_LABEL(status_label), "Unexpected Update Return Value! Contact Maintainer.");
	      NE_DEBUG(DEBUG_GNOME, "ARG! site_update returned %d.\n", ret);
	      break;
	  }
	  NE_DEBUG(DEBUG_GNOME, "Dealt with site_update's return code. Changing sensitivities.\n");
	  gtk_widget_hide (kill_button);
	  gtk_widget_show (close_button); 
	  gtk_widget_set_sensitive(close_button, TRUE);
	  gtk_window_set_modal(GTK_WINDOW(upload_window), FALSE);
	  gdk_threads_leave();
	  NE_DEBUG(DEBUG_GNOME, "update_thread: Reported update status okay, looping...\n");
      }
}
Esempio n. 16
0
/*
 * Processes received authentication tokens as well as supplies the
 * response token.
 */
int ne_sspi_authenticate(void *context, const char *base64Token, char **responseToken)
{
    SecBufferDesc outBufferDesc;
    SecBuffer outBuffer;
    int status;
    SECURITY_STATUS securityStatus;
    ULONG contextFlags;

    SSPIContext *sspiContext;
    if (initialized <= 0) {
        return -1;
    }

    status = getContext(context, &sspiContext);
    if (status) {
        return status;
    }

    /* TODO: Not sure what flags should be set. joe: this needs to be
     * driven by the ne_auth interface; the GSSAPI code needs similar
     * flags. */
    contextFlags = ISC_REQ_CONFIDENTIALITY | ISC_REQ_MUTUAL_AUTH;

    initSingleEmptyBuffer(&outBufferDesc, &outBuffer);
    status = makeBuffer(&outBufferDesc, sspiContext->maxTokenSize);
    if (status) {
        return status;
    }

    if (base64Token) {
        SecBufferDesc inBufferDesc;
        SecBuffer inBuffer;

        if (!sspiContext->continueNeeded) {
            freeBuffer(&outBufferDesc);
            NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: Got an unexpected token.\n");
            return -1;
        }

        initSingleEmptyBuffer(&inBufferDesc, &inBuffer);

        status = base64ToBuffer(base64Token, &inBufferDesc);
        if (status) {
            freeBuffer(&outBufferDesc);
            return status;
        }

        securityStatus =
            initializeSecurityContext(&sspiContext->credentials,
                                      &(sspiContext->context),
                                      sspiContext->serverName, contextFlags,
                                      &inBufferDesc, &(sspiContext->context),
                                      &outBufferDesc);
        if (securityStatus == SEC_E_OK)
        {
            sspiContext->authfinished = 1;
        }
        freeBuffer(&inBufferDesc);
    } else {
        if (sspiContext->continueNeeded) {
            freeBuffer(&outBufferDesc);
            NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: Expected a token from server.\n");
            return -1;
        }
        if (sspiContext->authfinished && (sspiContext->credentials.dwLower || sspiContext->credentials.dwUpper)) {
            if (sspiContext->authfinished)
            {
                freeBuffer(&outBufferDesc);
                sspiContext->authfinished = 0;
                NE_DEBUG(NE_DBG_HTTPAUTH,"sspi: failing because starting over from failed try.\n");
                return -1;
            }
            sspiContext->authfinished = 0;
        }

        /* Reset any existing context since we are starting over */
        resetContext(sspiContext);

        if (acquireCredentialsHandle
            (&sspiContext->credentials, sspiContext->mechanism) != SEC_E_OK) {
                freeBuffer(&outBufferDesc);
                NE_DEBUG(NE_DBG_HTTPAUTH,
                    "sspi: acquireCredentialsHandle failed.\n");
                return -1;
        }

        securityStatus =
            initializeSecurityContext(&sspiContext->credentials, NULL,
                                      sspiContext->serverName, contextFlags,
                                      NULL, &(sspiContext->context),
                                      &outBufferDesc);
    }

    if (securityStatus == SEC_I_COMPLETE_AND_CONTINUE
        || securityStatus == SEC_I_COMPLETE_NEEDED) {
        SECURITY_STATUS compleStatus =
            pSFT->CompleteAuthToken(&(sspiContext->context), &outBufferDesc);

        if (compleStatus != SEC_E_OK) {
            freeBuffer(&outBufferDesc);
            NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: CompleteAuthToken failed.\n");
            return -1;
        }
    }

    if (securityStatus == SEC_I_COMPLETE_AND_CONTINUE
        || securityStatus == SEC_I_CONTINUE_NEEDED) {
        sspiContext->continueNeeded = 1;
    } else {
        sspiContext->continueNeeded = 0;
    }

    if (!(securityStatus == SEC_I_COMPLETE_AND_CONTINUE
          || securityStatus == SEC_I_COMPLETE_NEEDED
          || securityStatus == SEC_I_CONTINUE_NEEDED
          || securityStatus == SEC_E_OK)) {
        NE_DEBUG(NE_DBG_HTTPAUTH,
                 "sspi: initializeSecurityContext [failed] [%x].\n",
                 securityStatus);
        freeBuffer(&outBufferDesc);
        return -1;
    }

    *responseToken = ne_base64(outBufferDesc.pBuffers->pvBuffer,
                               outBufferDesc.pBuffers->cbBuffer);
    freeBuffer(&outBufferDesc);

    return 0;
}