Example #1
0
void ne_lockstore_remove(ne_lock_store *store, struct ne_lock *lock)
{
    struct lock_list *item;

    /* Find the lock */
    for (item = store->locks; item != NULL; item = item->next)
	if (item->lock == lock)
	    break;
    
  if (item) {	/* XXX coverity #440269 */
    if (item->prev != NULL) {
	item->prev->next = item->next;
    } else {
	store->locks = item->next;
    }
    if (item->next != NULL) {
	item->next->prev = item->prev;
    }
    ne_free(item);
  }
}
Example #2
0
static void parse_dav_header(const char *value, ne_server_capabilities *caps)
{
    char *tokens = ne_strdup(value), *pnt = tokens;
    
    do {
	char *tok = ne_qtoken(&pnt, ',',  "\"'");
	if (!tok) break;
	
	tok = ne_shave(tok, " \r\t\n");

	if (strcmp(tok, "1") == 0) {
	    caps->dav_class1 = 1;
	} else if (strcmp(tok, "2") == 0) {
	    caps->dav_class2 = 1;
	} else if (strcmp(tok, "<http://apache.org/dav/propset/fs/1>") == 0) {
	    caps->dav_executable = 1;
	}
    } while (pnt != NULL);
    
    ne_free(tokens);
}
Example #3
0
ne_ssl_certificate *ne_ssl_cert_read(const char *filename)
{
    int ret;
    gnutls_datum data;
    gnutls_x509_crt x5;

    if (read_to_datum(filename, &data))
        return NULL;

    if (gnutls_x509_crt_init(&x5) != 0)
        return NULL;

    ret = gnutls_x509_crt_import(x5, &data, GNUTLS_X509_FMT_PEM);
    ne_free(data.data);
    if (ret < 0) {
        gnutls_x509_crt_deinit(x5);
        return NULL;
    }
    
    return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);
}
Example #4
0
static int check_redir(struct redir_args *args, const char *expect)
{
    ne_session *sess;
    const ne_uri *loc;
    char *unp;

    CALL(make_session(&sess, serve_redir, args));
    ne_redirect_register(sess);

    CALL(process_redir(sess, args->path, &loc));
    ONN("redirect location was NULL", loc == NULL);

    unp = ne_uri_unparse(loc);
    ONV(strcmp(unp, expect), ("redirected to `%s' not `%s'", unp, expect));
    ne_free(unp);

    ne_session_destroy(sess);
    CALL(await_server());

    return OK;
}
Example #5
0
void ne_session_destroy(ne_session *sess) 
{
    struct hook *hk;

    NE_DEBUG(NE_DBG_HTTP, "sess: Destroying session.\n");

    /* Run the destroy hooks. */
    for (hk = sess->destroy_sess_hooks; hk != NULL; hk = hk->next) {
	ne_destroy_sess_fn fn = (ne_destroy_sess_fn)hk->fn;
	fn(hk->userdata);
    }

    /* Close the connection; note that the notifier callback could
     * still be invoked here. */
    if (sess->connected) {
        ne_close_connection(sess);
    }
    
    destroy_hooks(sess->create_req_hooks);
    destroy_hooks(sess->pre_send_hooks);
    destroy_hooks(sess->post_headers_hooks);
    destroy_hooks(sess->post_send_hooks);
    destroy_hooks(sess->destroy_req_hooks);
    destroy_hooks(sess->destroy_sess_hooks);
    destroy_hooks(sess->close_conn_hooks);
    destroy_hooks(sess->private);

    ne_free(sess->scheme);
    ne_free(sess->server.hostname);
    ne_free(sess->server.hostport);
    if (sess->server.address) ne_addr_destroy(sess->server.address);
    if (sess->proxy.address) ne_addr_destroy(sess->proxy.address);
    if (sess->proxy.hostname) ne_free(sess->proxy.hostname);
    if (sess->user_agent) ne_free(sess->user_agent);

#ifdef NE_HAVE_SSL
    if (sess->ssl_context)
        ne_ssl_context_destroy(sess->ssl_context);

    if (sess->server_cert)
        ne_ssl_cert_free(sess->server_cert);
    
    if (sess->client_cert)
        ne_ssl_clicert_free(sess->client_cert);
#endif

    ne_free(sess);
}
Example #6
0
static int qappend(void)
{
    static const struct {
        const char *in;
        size_t inlen;
        const char *out;
    } ts[] = {
        { "", 0, "" },
        { "a", 1, "a" },
        { "b", 2, "b\\x00" },
        { "alpha\0alpha", 11, "alpha\\x00alpha" },
        { "a\tb", 3, "a\\x09b" },
        { NULL }
    };
    unsigned n;

    for (n = 0; ts[n].in; n++) {
        ne_buffer *buf = ne_buffer_create();
        char *s;
        const unsigned char *in = (const unsigned char *)ts[n].in;

        ne_buffer_qappend(buf, in, ts[n].inlen);

        ONCMP(buf->data, ts[n].out);

        ONV(strlen(buf->data) + 1 != buf->used,
            ("bad buffer length for '%s': %" NE_FMT_SIZE_T, 
             ts[n].out, buf->used));
        
        s = ne_strnqdup(in, ts[n].inlen);
        
        ONCMP(s, ts[n].out);

        ne_free(s);
        ne_buffer_destroy(buf);
    }

    return OK;
}
Example #7
0
char *ne_path_unescape(const char *uri) 
{
    const char *pnt;
    char *ret, *retpos, buf[5] = { "0x00\0" };
    retpos = ret = ne_malloc(strlen(uri) + 1);
    for (pnt = uri; *pnt != '\0'; pnt++) {
	if (*pnt == '%') {
	    if (!isxdigit((unsigned char) pnt[1]) || 
		!isxdigit((unsigned char) pnt[2])) {
		/* Invalid URI */
                ne_free(ret);
		return NULL;
	    }
	    buf[2] = *++pnt; buf[3] = *++pnt; /* bit faster than memcpy */
	    *retpos++ = (char)strtol(buf, NULL, 16);
	} else {
	    *retpos++ = *pnt;
	}
    }
    *retpos = '\0';
    return ret;
}
Example #8
0
/* Custom function of type ne_accept_response. */
static int ra_neon_error_accepter(void *userdata,
                                  ne_request *req,
                                  const ne_status *st)
{
  /* Before, this function was being run for *all* responses including
     the 401 auth challenge.  In neon 0.24.x that was harmless.  But
     in neon 0.25.0, trying to parse a 401 response as XML using
     ne_xml_parse_v aborts the response; so the auth hooks never got a
     chance. */
  ne_content_type ctype;

  /* Only accept non-2xx responses with text/xml content-type */
  if (st->klass != 2 && ne_get_content_type(req, &ctype) == 0)
    {
      int is_xml =
        (strcmp(ctype.type, "text") == 0 && strcmp(ctype.subtype, "xml") == 0);
      ne_free(ctype.value);
      return is_xml;
    }
  else
    return 0;
}
Example #9
0
static int copy_shallow(void)
{
    char *csrc, *cdest, *res;

    csrc = ne_concat(i_path, "ccsrc/", NULL);
    cdest = ne_concat(i_path, "ccdest/", NULL);

    /* Set up the ccsrc collection with one member */
    ONMREQ("MKCOL", csrc, ne_mkcol(i_session, csrc));
    CALL(upload_foo("ccsrc/foo"));

    /* Clean up to make some fresh copies. */
    ne_delete(i_session, cdest);

    /* Now copy with Depth 0 */
    ONV(ne_copy(i_session, 0, NE_DEPTH_ZERO, csrc, cdest),
	("collection COPY `%s' to `%s': %s", csrc, cdest,
	 ne_get_error(i_session)));

    /* Remove the source, to be paranoid. */
    if (ne_delete(i_session, csrc)) {
	t_warning("Could not delete csrc");
    }

    /* Now make sure the child resource hasn't been copied along with
     * the collection. */
    res = ne_concat(i_path, "foo", NULL);
    ne_delete(i_session, res);
    ONV(STATUS(404), 
        ("DELETE on `%s' should fail with 404: got %d", res, GETSTATUS));
    ne_free(res);

    if (ne_delete(i_session, cdest)) {
	t_warning("Could not clean up cdest");
    }

    return OK;
}
Example #10
0
static void parse_dav_header(const char *value, unsigned int *caps)
{
    char *tokens = ne_strdup(value), *pnt = tokens;

    *caps = 0;

    do {
        char *tok = ne_qtoken(&pnt, ',',  "\"'");
        unsigned n;

        if (!tok) break;

        tok = ne_shave(tok, " \r\t\n");

        for (n = 0; n < sizeof(options_map)/sizeof(options_map[0]); n++) {
            if (strcmp(tok, options_map[n].name) == 0) {
                *caps |= options_map[n].cap;
            }
        }
    } while (pnt != NULL);

    ne_free(tokens);
}
Example #11
0
void ne_session_destroy(ne_session *sess) 
{
    struct hook *hk;

    NE_DEBUG(NE_DBG_HTTP, "ne_session_destroy called.\n");

    /* Run the destroy hooks. */
    for (hk = sess->destroy_sess_hooks; hk != NULL; hk = hk->next) {
	ne_destroy_sess_fn fn = (ne_destroy_sess_fn)hk->fn;
	fn(hk->userdata);
    }
    
    destroy_hooks(sess->create_req_hooks);
    destroy_hooks(sess->pre_send_hooks);
    destroy_hooks(sess->post_send_hooks);
    destroy_hooks(sess->destroy_req_hooks);
    destroy_hooks(sess->destroy_sess_hooks);
    destroy_hooks(sess->private);

    ne_free(sess->scheme);
    ne_free(sess->server.hostname);
    ne_free(sess->server.hostport);
    if (sess->server.address) ne_addr_destroy(sess->server.address);
    if (sess->proxy.address) ne_addr_destroy(sess->proxy.address);
    if (sess->proxy.hostname) ne_free(sess->proxy.hostname);
    if (sess->user_agent) ne_free(sess->user_agent);

    if (sess->connected) {
	ne_close_connection(sess);
    }

#ifdef NE_HAVE_SSL
    if (sess->ssl_context)
        ne_ssl_context_destroy(sess->ssl_context);

    if (sess->server_cert)
        ne_ssl_cert_free(sess->server_cert);
    
    if (sess->client_cert)
        ne_ssl_clicert_free(sess->client_cert);
#endif

    ne_free(sess);
}
Example #12
0
static int large_writev(void)
{
    struct string str;
    ne_socket *sock;
    ssize_t n;
    struct ne_iovec vec[4];

    str.data = ne_malloc(LARGE_SIZE);
    str.len = LARGE_SIZE;

    for (n = 0; n < LARGE_SIZE; n++)
	str.data[n] = 41 + n % 130;
    
    for (n = 0; n < 4; n++) {
        vec[n].base = str.data + n * LARGE_SIZE / 4;
        vec[n].len = LARGE_SIZE / 4;
    }

    CALL(begin(&sock, serve_expect, &str));
    CALL(full_writev(sock, vec, 4));
    
    ne_free(str.data);
    return finish(sock, 1);    
}
Example #13
0
/* Duplicate a client certificate, which must be in the decrypted state. */
static ne_ssl_client_cert *dup_client_cert(const ne_ssl_client_cert *cc)
{
    int ret;
    ne_ssl_client_cert *newcc = ne_calloc(sizeof *newcc);

    newcc->decrypted = 1;
    
    if (cc->keyless) {
        newcc->keyless = 1;
#ifdef HAVE_GNUTLS_PRIVKEY_IMPORT_EXT
        newcc->sign_func = cc->sign_func;
        newcc->sign_ud = cc->sign_ud;
#endif
    }
    else {
        ret = gnutls_x509_privkey_init(&newcc->pkey);
        if (ret != 0) goto dup_error;
        
        ret = gnutls_x509_privkey_cpy(newcc->pkey, cc->pkey);
        if (ret != 0) goto dup_error;
    }    

    newcc->cert.subject = x509_crt_copy(cc->cert.subject);
    if (!newcc->cert.subject) goto dup_error;

    if (cc->friendly_name) newcc->friendly_name = ne_strdup(cc->friendly_name);

    populate_cert(&newcc->cert, newcc->cert.subject);
    return newcc;

dup_error:
    if (newcc->pkey) gnutls_x509_privkey_deinit(newcc->pkey);
    if (newcc->cert.subject) gnutls_x509_crt_deinit(newcc->cert.subject);
    ne_free(newcc);
    return NULL;
}    
Example #14
0
/* FIXME: Leaky as a bucket */
void open_connection(const char *url)
{
    char *proxy_host = get_option(opt_proxy), *pnt;
    ne_server_capabilities caps;
    int ret, use_ssl = 0;
    ne_session *sess;

    if (session.connected) {
	close_connection();
    } else {
        ne_uri_free(&session.uri);
        if (session.lastwp) {
            ne_free(session.lastwp);
            session.lastwp = NULL;
        }
    }

    /* Single argument: see whether we have a path or scheme */
    if (strchr(url, '/') == NULL) {
	/* No path, no scheme -> just a hostname */
	pnt = strchr(url, ':');
	if (pnt != NULL) {
	    *pnt++ = '\0';
	    session.uri.port = atoi(pnt);
	} else {
	    session.uri.port = 80;
	}
	session.uri.host = ne_strdup(url);
	session.uri.scheme = ne_strdup("http");
    } else {
	/* Parse the URL */
	if (ne_uri_parse(url, &session.uri) || session.uri.host == NULL) {
	    printf(_("Could not parse URL `%s'\n"), url);
	    return;
	}

	if (session.uri.scheme == NULL)
	    session.uri.scheme = ne_strdup("http");

	if (!session.uri.port)
	    session.uri.port = ne_uri_defaultport(session.uri.scheme);

	if (strcasecmp(session.uri.scheme, "https") == 0) {
	    if (!ne_has_support(NE_FEATURE_SSL)) {
		printf(_("SSL is not enabled.\n"));
		return;
	    }
	    use_ssl = 1;
	}
    }

    session.sess = ne_session_create(session.uri.scheme, session.uri.host,
                                     session.uri.port);
    sess = session.sess;
    
    if (use_ssl && setup_ssl()) {
	return;
    }

    ne_lockstore_register(session.locks, sess);
    ne_redirect_register(sess);
    ne_set_notifier(sess, notifier, NULL);

    if (session.uri.path == NULL) {
	session.uri.path = ne_strdup("/");
    } else {
	if (!ne_path_has_trailing_slash(session.uri.path)) {
	    pnt = ne_concat(session.uri.path, "/", NULL);
	    free(session.uri.path);
	    session.uri.path = pnt;
	}
    }

    /* Get the proxy details */
    if (proxy_host != NULL) {
	if (get_option(opt_proxy_port) != NULL) {
	    proxy_port = atoi(get_option(opt_proxy_port));
	} else {
	    proxy_port = 8080;
	}
	proxy_hostname = proxy_host;
    }

#ifdef ENABLE_NETRC
    {
	netrc_entry *found;
	found = search_netrc(netrc_list, session.uri.host);
	if (found != NULL) {
	    if (found->account && found->password) {
		server_username = found->account;
		server_password = found->password;
	    }
	}
    }
#endif /* ENABLE_NETRC */
#ifdef NE_SESSFLAG_EXPECT100
	ne_set_session_flag(session.sess, NE_SESSFLAG_EXPECT100, get_bool_option(opt_expect100));
#endif /* NE_SESSFLAG_EXPECT100 */
    session.connected = 0;

    ne_set_useragent(session.sess, "cadaver/" PACKAGE_VERSION);
    ne_set_server_auth(session.sess, supply_creds_server, NULL);
    ne_set_proxy_auth(session.sess, supply_creds_proxy, NULL);
    
    if (proxy_host) {
	ne_session_proxy(session.sess, proxy_hostname, proxy_port);
    }

    ret = ne_options(session.sess, session.uri.path, &caps);
    
    switch (ret) {
    case NE_OK:
	session.connected = true;
	if (set_path(session.uri.path)) {
	    close_connection();
	}
	break;
    case NE_CONNECT:
	if (proxy_host) {
	    printf(_("Could not connect to `%s' on port %d:\n%s\n"),
		   proxy_hostname, proxy_port, ne_get_error(session.sess));
	} else {
	    printf(_("Could not connect to `%s' on port %d:\n%s\n"),
		   session.uri.host, session.uri.port, ne_get_error(session.sess));
	}
	break;
    case NE_LOOKUP:
	puts(ne_get_error(session.sess));
	break;
    default:
	printf(_("Could not open collection:\n%s\n"),
	       ne_get_error(session.sess));
	break;
    }

}
Example #15
0
/* This function directly implements the "Remove Dot Segments"
 * algorithm described in RFC 3986 section 5.2.4. */
static char *remove_dot_segments(const char *path)
{
    char *in, *inc, *out;

    inc = in = ne_strdup(path);
    out = ne_malloc(strlen(path) + 1);
    out[0] = '\0';

    while (in[0]) {
        /* case 2.A: */
        if (strncmp(in, "./", 2) == 0) {
            in += 2;
        } 
        else if (strncmp(in, "../", 3) == 0) {
            in += 3;
        }

        /* case 2.B: */
        else if (strncmp(in, "/./", 3) == 0) {
            in += 2;
        }
        else if (strcmp(in, "/.") == 0) {
            in[1] = '\0';
        }

        /* case 2.C: */
        else if (strncmp(in, "/../", 4) == 0 || strcmp(in, "/..") == 0) {
            char *p;

            /* Make the next character in the input buffer a "/": */
            if (in[3] == '\0') {
                /* terminating "/.." case */
                in += 2;
                in[0] = '/';
            } else {
                /* "/../" prefix case */
                in += 3;
            }

            /* Trim the last component from the output buffer, or
             * empty it. */
            p = strrchr(out, '/');
            if (p) {
                *p = '\0';
            } else {
                out[0] = '\0';
            }
        }

        /* case 2.D: */
        else if (strcmp(in, ".") == 0 || strcmp(in, "..") == 0) {
            in[0] = '\0';
        }

        /* case 2.E */
        else {
            char *p;

            /* Search for the *second* "/" if the leading character is
             * already "/": */
            p = strchr(in + (in[0] == '/'), '/');
            /* Otherwise, copy the whole string */
            if (p == NULL) p = strchr(in, '\0');

            strncat(out, in, p - in);
            in = p;
        }
    }

    ne_free(inc);

    return out;
}
Example #16
0
void
ne_md5_destroy_ctx(struct ne_md5_ctx *ctx)
{
  ne_free(ctx);
}
Example #17
0
void ne_lock_destroy(struct ne_lock *lock)
{
    ne_lock_free(lock);
    ne_free(lock);
}
Example #18
0
void ne_lockstore_destroy(ne_lock_store *store)
{
    free_list(store->locks, 1);
    ne_free(store);
}
Example #19
0
/* This implemementation does not attempt to support IPv6 using
 * gethostbyname2 et al.  */
ne_sock_addr *ne_addr_resolve(const char *hostname, int flags)
{
    ne_sock_addr *addr = ne_calloc(sizeof *addr);
#ifdef USE_GETADDRINFO
    struct addrinfo hints = {0};
    char *pnt;
    hints.ai_socktype = SOCK_STREAM;
    if (hostname[0] == '[' && ((pnt = strchr(hostname, ']')) != NULL)) {
	char *hn = ne_strdup(hostname + 1);
	hn[pnt - hostname - 1] = '\0';
#ifdef AI_NUMERICHOST /* added in the RFC2553 API */
	hints.ai_flags = AI_NUMERICHOST;
#endif
        hints.ai_family = AF_INET6;
	addr->errnum = getaddrinfo(hn, NULL, &hints, &addr->result);
	ne_free(hn);
    } else {
#ifdef USE_GAI_ADDRCONFIG /* added in the RFC3493 API */
        hints.ai_flags = AI_ADDRCONFIG;
        hints.ai_family = AF_UNSPEC;
        addr->errnum = getaddrinfo(hostname, NULL, &hints, &addr->result);
#else
        hints.ai_family = ipv6_disabled ? AF_INET : AF_UNSPEC;
	addr->errnum = getaddrinfo(hostname, NULL, &hints, &addr->result);
#endif
    }
#else /* Use gethostbyname() */
    in_addr_t laddr;
    struct hostent *hp;
    struct hostent h;
    char buf[sizeof(struct in_addr) +
             sizeof(struct in_addr *)*2 +
             sizeof(char *)*8 + 384/*namebuffer*/ + 32/* margin */];
    int errn;
    
    laddr = inet_addr(hostname);
    if (laddr == INADDR_NONE) {
        if (ne_find_cached_host(hostname, &laddr)) {
            addr->addrs = ne_malloc(sizeof *addr->addrs);
            addr->count = 1;
            memcpy(addr->addrs, &laddr, sizeof *addr->addrs);
            return addr;
        }
        
        gethostbyname_r(hostname, &h, buf, sizeof(buf), &hp, &errn);
            //hp = gethostbyname(hostname);
	if (hp == NULL) {
#ifdef WIN32
	    addr->errnum = WSAGetLastError();
#else
            addr->errnum = h_errno;
#endif
	    if (!addr->errnum) {
		addr->errnum = NO_RECOVERY;
	    }
	} else if (hp->h_length != sizeof(struct in_addr)) {
	    /* fail gracefully if somebody set RES_USE_INET6 */
	    addr->errnum = NO_RECOVERY;
	} else {
	    size_t n;
	    /* count addresses */
	    for (n = 0; hp->h_addr_list[n] != NULL; n++)
		/* noop */;

	    addr->count = n;
	    addr->addrs = ne_malloc(n * sizeof *addr->addrs);

            if (n > 0)
                ne_add_cached_host(hostname, hp->h_addr_list[0]);
            
	    for (n = 0; n < addr->count; n++)
		memcpy(&addr->addrs[n], hp->h_addr_list[n], hp->h_length);
	}
    } else {
	addr->addrs = ne_malloc(sizeof *addr->addrs);
	addr->count = 1;
	memcpy(addr->addrs, &laddr, sizeof *addr->addrs);
    }
#endif
    return addr;
}
Example #20
0
/* Pass this the value of the 'Authentication-Info:' header field, if
 * one is received.
 * Returns:
 *    0 if it gives a valid authentication for the server 
 *    non-zero otherwise (don't believe the response in this case!).
 */
static int verify_digest_response(struct auth_request *req, auth_session *sess,
                                  const char *value) 
{
    char *hdr, *pnt, *key, *val;
    auth_qop qop = auth_qop_none;
    char *nextnonce = NULL, /* for the nextnonce= value */
	*rspauth = NULL, /* for the rspauth= value */
	*cnonce = NULL, /* for the cnonce= value */
	*nc = NULL, /* for the nc= value */
	*qop_value = NULL;
    unsigned int nonce_count;
    int okay;
    
    if (!req->will_handle) {
	/* Ignore it */
	return 0;
    }
    
    if (sess->scheme != auth_scheme_digest) {
	NE_DEBUG(NE_DBG_HTTPAUTH, "Found Auth-Info header not in response "
		 " to Digest credentials - dodgy.\n");
	return -1;
    }

    pnt = hdr = ne_strdup(value);
    
    NE_DEBUG(NE_DBG_HTTPAUTH, "Auth-Info header: %s\n", value);

    while (tokenize(&pnt, &key, &val, NULL, 0) == 0) {
	val = ne_shave(val, "\"");
	NE_DEBUG(NE_DBG_HTTPAUTH, "Pair: [%s] = [%s]\n", key, val);
	if (strcasecmp(key, "qop") == 0) {
            qop_value = val;
            if (strcasecmp(val, "auth") == 0) {
		qop = auth_qop_auth;
	    } else {
		qop = auth_qop_none;
	    }
	} else if (strcasecmp(key, "nextnonce") == 0) {
	    nextnonce = val;
	} else if (strcasecmp(key, "rspauth") == 0) {
	    rspauth = val;
	} else if (strcasecmp(key, "cnonce") == 0) {
	    cnonce = val;
	} else if (strcasecmp(key, "nc") == 0) { 
	    nc = val;
	    if (sscanf(val, "%x", &nonce_count) != 1) {
		NE_DEBUG(NE_DBG_HTTPAUTH, "Couldn't find nonce count.\n");
	    } else {
		NE_DEBUG(NE_DBG_HTTPAUTH, "Got nonce_count: %u\n", nonce_count);
	    }
	}
    }

    /* Presume the worst */
    okay = -1;

    if ((qop != auth_qop_none) && (qop_value != NULL)) {
	if ((rspauth == NULL) || (cnonce == NULL) || (nc == NULL)) {
	    NE_DEBUG(NE_DBG_HTTPAUTH, "Missing rspauth, cnonce or nc with qop.\n");
	} else { /* Have got rspauth, cnonce and nc */
	    if (strcmp(cnonce, sess->cnonce) != 0) {
		NE_DEBUG(NE_DBG_HTTPAUTH, "Response cnonce doesn't match.\n");
	    } else if (nonce_count != sess->nonce_count) { 
		NE_DEBUG(NE_DBG_HTTPAUTH, "Response nonce count doesn't match.\n");
	    } else {
		/* Calculate and check the response-digest value.
		 * joe: IMO the spec is slightly ambiguous as to whether
		 * we use the qop which WE sent, or the qop which THEY
		 * sent...  */
		struct ne_md5_ctx a2;
		unsigned char a2_md5[16], rdig_md5[16];
		char a2_md5_ascii[33], rdig_md5_ascii[33];

		NE_DEBUG(NE_DBG_HTTPAUTH, "Calculating response-digest.\n");

		/* First off, H(A2) again. */
		ne_md5_init_ctx(&a2);
		ne_md5_process_bytes(":", 1, &a2);
		ne_md5_process_bytes(req->uri, strlen(req->uri), &a2);
		ne_md5_finish_ctx(&a2, a2_md5);
		ne_md5_to_ascii(a2_md5, a2_md5_ascii);
		
		/* We have the stored digest-so-far of 
		 *   H(A1) ":" unq(nonce-value) 
		 *        [ ":" nc-value ":" unq(cnonce-value) ] for qop
		 * in sess->stored_rdig, to save digesting them again.
		 *
		 */
		if (qop != auth_qop_none) {
		    /* Add in qop-value */
		    NE_DEBUG(NE_DBG_HTTPAUTH, "Digesting qop-value [%s:].\n", 
			     qop_value);
		    ne_md5_process_bytes(qop_value, strlen(qop_value), 
					 &sess->stored_rdig);
		    ne_md5_process_bytes(":", 1, &sess->stored_rdig);
		}
		/* Digest ":" H(A2) */
		ne_md5_process_bytes(a2_md5_ascii, 32, &sess->stored_rdig);
		/* All done */
		ne_md5_finish_ctx(&sess->stored_rdig, rdig_md5);
		ne_md5_to_ascii(rdig_md5, rdig_md5_ascii);

		NE_DEBUG(NE_DBG_HTTPAUTH, "Calculated response-digest of: "
			 "[%s]\n", rdig_md5_ascii);
		NE_DEBUG(NE_DBG_HTTPAUTH, "Given response-digest of:      "
			 "[%s]\n", rspauth);

		/* And... do they match? */
		okay = (strcasecmp(rdig_md5_ascii, rspauth) == 0)?0:-1;
		NE_DEBUG(NE_DBG_HTTPAUTH, "Matched: %s\n", okay?"nope":"YES!");
	    }
	}
    } else {
	NE_DEBUG(NE_DBG_HTTPAUTH, "No qop directive, auth okay.\n");
	okay = 0;
    }

    /* Check for a nextnonce */
    if (nextnonce != NULL) {
	NE_DEBUG(NE_DBG_HTTPAUTH, "Found nextnonce of [%s].\n", nextnonce);
	if (sess->nonce != NULL)
	    ne_free(sess->nonce);
	sess->nonce = ne_strdup(nextnonce);
    }

    ne_free(hdr);

    return okay;
}
Example #21
0
void ne_session_system_proxy(ne_session *sess, unsigned int flags)
{
#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
}
Example #22
0
static int execute_command(const char *line)
{
    const struct command *cmd;
    char **tokens;
    int n, argcount, ret = 0;
    tokens = parse_command(line, &argcount);
    if (argcount == 0) {
	free(tokens);
	return 0;
    }
    argcount--;
    cmd = get_command(tokens[0]);
    if (cmd == NULL) {
	printf(_("Unrecognised command. Type 'help' for a list of commands.\n"));
    } else if (argcount < cmd->min_args) {
	printf(_("The `%s' command requires %d argument%s"),
		tokens[0], cmd->min_args, cmd->min_args==1?"":"s");
	if (cmd->short_help) {
	    printf(_(":\n  %s : %s\n"), cmd->call, cmd->short_help);
	} else {
	    printf(".\n");
	}
    } else if (argcount > cmd->max_args) {
	if (cmd->max_args) {
	    printf(_("The `%s' command takes at most %d argument%s"), tokens[0],
		    cmd->max_args, cmd->max_args==1?"":"s");
	} else {
	    printf(_("The `%s' command takes no arguments"), tokens[0]);
	}	    
	if (cmd->short_help) {
	    printf(_(":\n" "  %s : %s\n"), cmd->call, cmd->short_help);
	} else {
	    printf(".\n");
	}
    } else if (!session.connected && cmd->needs_connection) {
	printf(_("The `%s' command can only be used when connected to the server.\n"
		  "Try running `open' first (see `help open' for more details).\n"), 
		  tokens[0]);
    } else if (cmd->id == cmd_quit) {
	ret = -1;
    } else {
	/* Cast away */
	/* with a nod in the general direction of apache */
	switch (cmd->max_args) {
	case 0: cmd->handler.take0(); break;
	case 1: /* tokens[1]==NULL if argcount==0 */
	    cmd->handler.take1(tokens[1]); break; 
	case 2: 
	    if (argcount <=1) {
		cmd->handler.take2(tokens[1], NULL);
	    } else {
		cmd->handler.take2(tokens[1], tokens[2]);
	    }
	    break;
	case 3:
	    cmd->handler.take3(tokens[1], tokens[2], tokens[3]);
	    break;
	case CMD_VARY:
	    cmd->handler.takeV(argcount, (const char **) &tokens[1]);
	default:
	    break;
	}
    }
    for (n = 0; n < argcount; n++) {
        ne_free(tokens[n]);
    }
    ne_free(tokens);
    return ret;
}
Example #23
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;
}
Example #24
0
/* Parses a PKCS#12 structure and loads the certificate, private key
 * and friendly name if possible.  Returns zero on success, non-zero
 * on error. */
static int pkcs12_parse(gnutls_pkcs12 p12, gnutls_x509_privkey *pkey,
                        gnutls_x509_crt *x5, char **friendly_name,
                        const char *password)
{
    gnutls_pkcs12_bag bag = NULL;
    int i, j, ret = 0;

    for (i = 0; ret == 0; ++i) {
        if (bag) gnutls_pkcs12_bag_deinit(bag);

        ret = gnutls_pkcs12_bag_init(&bag);
        if (ret < 0) continue;

        ret = gnutls_pkcs12_get_bag(p12, i, bag);
        if (ret < 0) continue;

        gnutls_pkcs12_bag_decrypt(bag, password);

        for (j = 0; ret == 0 && j < gnutls_pkcs12_bag_get_count(bag); ++j) {
            gnutls_pkcs12_bag_type type;
            gnutls_datum data;

            if (friendly_name && *friendly_name == NULL) {
                char *name = NULL;
                gnutls_pkcs12_bag_get_friendly_name(bag, j, &name);
                if (name) {
                    if (name[0] == '.') name++; /* weird GnuTLS bug? */
                    *friendly_name = ne_strdup(name);
                }
            }

            type = gnutls_pkcs12_bag_get_type(bag, j);
            switch (type) {
            case GNUTLS_BAG_PKCS8_KEY:
            case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
                /* Ignore any but the first key encountered; really
                 * need to match up keyids. */
                if (*pkey) break;

                gnutls_x509_privkey_init(pkey);

                ret = gnutls_pkcs12_bag_get_data(bag, j, &data);
                if (ret < 0) continue;

                ret = gnutls_x509_privkey_import_pkcs8(*pkey, &data,
                                                       GNUTLS_X509_FMT_DER,
                                                       password,
                                                       0);
                if (ret < 0) continue;
                break;
            case GNUTLS_BAG_CERTIFICATE:
                /* Ignore any but the first cert encountered; again,
                 * really need to match up keyids. */
                if (*x5) break;

                ret = gnutls_x509_crt_init(x5);
                if (ret < 0) continue;

                ret = gnutls_pkcs12_bag_get_data(bag, j, &data);
                if (ret < 0) continue;

                ret = gnutls_x509_crt_import(*x5, &data, GNUTLS_X509_FMT_DER);
                if (ret < 0) continue;

                break;
            default:
                break;
            }
        }
    }

    /* Make sure last bag is freed */
    if (bag) gnutls_pkcs12_bag_deinit(bag);

    /* Free in case of error */
    if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
        if (*x5) gnutls_x509_crt_deinit(*x5);
        if (*pkey) gnutls_x509_privkey_deinit(*pkey);
        if (friendly_name && *friendly_name) ne_free(*friendly_name);
    }

    if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) ret = 0;
    return ret;
}
Example #25
0
static int ah_post_send(ne_request *req, void *cookie, const ne_status *status)
{
    auth_session *sess = cookie;
    struct auth_request *areq = ne_get_request_private(req, sess->spec->id);
    const char *auth_hdr, *auth_info_hdr;
    int ret = NE_OK;

    if (!areq) return NE_OK;

    auth_hdr = ne_get_response_header(req, sess->spec->resp_hdr);
    auth_info_hdr = ne_get_response_header(req, sess->spec->resp_info_hdr);

    if (sess->context == AUTH_CONNECT && status->code == 401 && !auth_hdr) {
        /* Some broken proxies issue a 401 as a proxy auth challenge
         * to a CONNECT request; handle this here. */
        auth_hdr = ne_get_response_header(req, "WWW-Authenticate");
        auth_info_hdr = NULL;
    }

#ifdef HAVE_GSSAPI
    /* whatever happens: forget the GSSAPI token cached thus far */
    if (sess->gssapi_token) {
        ne_free(sess->gssapi_token);
        sess->gssapi_token = NULL;
    }
#endif

    NE_DEBUG(NE_DBG_HTTPAUTH, 
	     "ah_post_send (#%d), code is %d (want %d), %s is %s\n",
	     sess->attempt, status->code, sess->spec->status_code, 
	     sess->spec->resp_hdr, auth_hdr ? auth_hdr : "(none)");
    if (auth_info_hdr && sess->scheme == auth_scheme_digest) {
        if (verify_digest_response(areq, sess, auth_info_hdr)) {
            NE_DEBUG(NE_DBG_HTTPAUTH, "Response authentication invalid.\n");
            ne_set_error(sess->sess, "%s", _(sess->spec->fail_msg));
            ret = NE_ERROR;
        }
    }
#ifdef HAVE_GSSAPI
    /* one must wonder... has Mr Brezak actually read RFC2617? */
    else if (sess->scheme == auth_scheme_gssapi 
             && (status->klass == 2 || status->klass == 3)
             && auth_hdr) {
        char *hdr = ne_strdup(auth_hdr);
        if (verify_negotiate_response(sess, hdr)) { 
            NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Mutual auth failed.\n");
            ret = NE_ERROR;
        }
        ne_free(hdr);
    }
#endif /* HAVE_GSSAPI */
    else if ((status->code == sess->spec->status_code ||
              (status->code == 401 && sess->context == AUTH_CONNECT)) &&
	       auth_hdr) {
        /* note above: allow a 401 in response to a CONNECT request
         * from a proxy since some buggy proxies send that. */
	NE_DEBUG(NE_DBG_HTTPAUTH, "Got challenge (code %d).\n", status->code);
	if (!auth_challenge(sess, auth_hdr)) {
	    ret = NE_RETRY;
	} else {
	    clean_session(sess);
	    ret = sess->spec->fail_code;
	}
    }
#ifdef HAVE_SSPI
    else if (sess->sspi_context) {
        ne_sspi_clear_context(sess->sspi_context);
    }
#endif

    return ret;
}
Example #26
0
static void free_hostinfo(struct host_info *hi)
{
    if (hi->hostname) ne_free(hi->hostname);
    if (hi->hostport) ne_free(hi->hostport);
    if (hi->address) ne_addr_destroy(hi->address);
}
Example #27
0
/* Continue a GSS-API Negotiate exchange, using input TOKEN if
 * non-NULL.  Returns non-zero on error. */
static int continue_negotiate(auth_session *sess, const char *token)
{
    unsigned int major, minor;
    gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
    unsigned char *bintoken = NULL;
    int ret;

    if (token) {
        input.length = ne_unbase64(token, &bintoken);
        if (input.length == 0) {
            NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Invalid input [%s].\n",
                     token);
            return -1;
        }
        input.value = bintoken;
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Continuation token [%s]\n", token);
    }
    else if (sess->gssctx != GSS_C_NO_CONTEXT) {
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Reset incomplete context.\n");
        gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER);
    }

    major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &sess->gssctx,
                                 sess->gssname, sess->gssmech, 
                                 GSS_C_MUTUAL_FLAG, GSS_C_INDEFINITE, 
                                 GSS_C_NO_CHANNEL_BINDINGS,
                                 &input, &sess->gssmech, &output, NULL, NULL);

    /* done with the input token. */
    if (bintoken) ne_free(bintoken);

    if (GSS_ERROR(major)) {
        ne_buffer *err = ne_buffer_create();
        int flag = 0;

        make_gss_error(err, &flag, major, GSS_C_GSS_CODE);
        make_gss_error(err, &flag, minor, GSS_C_MECH_CODE);
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Error: %s\n", err->data);
        ne_set_error(sess->sess, _("GSSAPI authentication error (%s)"), 
                     err->data);
        ne_buffer_destroy(err);
        return -1;
    }

    if (major == GSS_S_CONTINUE_NEEDED || major == GSS_S_COMPLETE) {
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: init_sec_context OK. (major=%d)\n",
                 major);
        ret = 0;
    } 
    else {
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Init failure %d.\n", major);
        ret = -1;
    }

    if (major != GSS_S_CONTINUE_NEEDED) {
        /* context no longer needed: destroy it */
        gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER);
    }

    if (output.length) {
        sess->gssapi_token = ne_base64(output.value, output.length);
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Output token: [%s]\n", 
                 sess->gssapi_token);
        gss_release_buffer(&minor, &output);
    } else {
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: No output token.\n");
    }

    return ret;
}
Example #28
0
static void lk_destroy(ne_request *req, void *userdata)
{
    struct lh_req_cookie *lrc = ne_get_request_private(req, HOOK_ID);
    free_list(lrc->submit, 0);
    ne_free(lrc);
}
Example #29
0
/* Passed the value of a "(Proxy,WWW)-Authenticate: " header field.
 * Returns 0 if valid challenge was accepted; non-zero if no valid
 * challenge was found. */
static int auth_challenge(auth_session *sess, const char *value) 
{
    char *pnt, *key, *val, *hdr, sep;
    struct auth_challenge *chall = NULL, *challenges = NULL;
    int success;

    pnt = hdr = ne_strdup(value); 

    NE_DEBUG(NE_DBG_HTTPAUTH, "Got new auth challenge: %s\n", value);

    /* The header value may be made up of one or more challenges.  We
     * split it down into attribute-value pairs, then search for
     * schemes in the pair keys. */

    while (!tokenize(&pnt, &key, &val, &sep, 1)) {

	if (val == NULL) {
            auth_scheme scheme;

	    if (strcasecmp(key, "basic") == 0) {
		scheme = auth_scheme_basic;
	    } else if (strcasecmp(key, "digest") == 0) {
		scheme = auth_scheme_digest;
            }
#ifdef HAVE_GSSAPI
            else if (strcasecmp(key, "negotiate") == 0) {
                scheme = auth_scheme_gssapi;
            }
#else
#ifdef HAVE_SSPI
            else if (strcasecmp(key, "negotiate") == 0) {
                scheme = auth_scheme_sspi_negotiate;
            } else if (strcasecmp(key, "ntlm") == 0) {
                scheme = auth_scheme_sspi_ntlm;
            }
#endif
#endif
            else {
		NE_DEBUG(NE_DBG_HTTPAUTH, "Ignoring challenge '%s'.\n", key);
                chall = NULL;
                continue;
	    }
            
            NE_DEBUG(NE_DBG_HTTPAUTH, "New '%s' challenge.\n", key);
            chall = ne_calloc(sizeof *chall);
            chall->scheme = scheme;
            chall->next = challenges;
            challenges = chall;

            if (sep == ' ' && 
                (scheme == auth_scheme_gssapi 
                 || scheme == auth_scheme_sspi_negotiate 
                 || scheme == auth_scheme_sspi_ntlm) ) {
                /* Cope with the fact that the unquoted base64
                 * paramater token doesn't match the 2617 auth-param
                 * grammar: */
                chall->opaque = ne_shave(ne_token(&pnt, ','), " \t");
                NE_DEBUG(NE_DBG_HTTPAUTH, "auth: Negotiate parameter '%s'\n",
                         chall->opaque);
                if (!pnt) break; /* stop parsing at end-of-string. */
            }
	    continue;
	} else if (chall == NULL) {
	    /* Ignore pairs for an unknown challenge. */
            NE_DEBUG(NE_DBG_HTTPAUTH, "Ignored pair: %s = %s\n", key, val);
	    continue;
	}

	/* Strip quotes off value. */
	val = ne_shave(val, "\"'");

	NE_DEBUG(NE_DBG_HTTPAUTH, "Got pair: [%s] = [%s]\n", key, val);

	if (strcasecmp(key, "realm") == 0) {
	    chall->realm = val;
	} else if (strcasecmp(key, "nonce") == 0) {
	    chall->nonce = val;
	} else if (strcasecmp(key, "opaque") == 0) {
	    chall->opaque = val;
	} else if (strcasecmp(key, "stale") == 0) {
	    /* Truth value */
	    chall->stale = (strcasecmp(val, "true") == 0);
	} else if (strcasecmp(key, "algorithm") == 0) {
	    if (strcasecmp(val, "md5") == 0) {
		chall->alg = auth_alg_md5;
	    } else if (strcasecmp(val, "md5-sess") == 0) {
		chall->alg = auth_alg_md5_sess;
	    } else {
		chall->alg = auth_alg_unknown;
	    }
	} else if (strcasecmp(key, "qop") == 0) {
            /* iterate over each token in the value */
            do {
                const char *tok = ne_shave(ne_token(&val, ','), " \t");
                
                if (strcasecmp(tok, "auth") == 0) {
                    chall->qop_auth = 1;
                }
            } while (val);
            
            chall->got_qop = chall->qop_auth;
	}
    }

    NE_DEBUG(NE_DBG_HTTPAUTH, "Finished parsing parameters.\n");

    /* Did we find any challenges */
    if (challenges == NULL) {
	ne_free(hdr);
	return -1;
    }
    
    success = 0;

#ifdef HAVE_GSSAPI
    /* Ignore Negotiate challenges from origin servers which don't
     * come over SSL. */
    if (sess->spec == &ah_proxy_class || sess->context != AUTH_ANY) {
        NE_DEBUG(NE_DBG_HTTPAUTH, "Looking for GSSAPI.\n");
        /* Try a GSSAPI challenge */
        for (chall = challenges; chall != NULL; chall = chall->next) {
            if (chall->scheme == auth_scheme_gssapi) {
                if (!gssapi_challenge(sess, chall)) {
                    success = 1;
                    break;
                }
            }
        }
    }
#endif

#ifdef HAVE_SSPI
    if (!success) {
        NE_DEBUG(NE_DBG_HTTPAUTH, "Looking for SSPI/Negotiate.\n");
        for (chall = challenges; chall != NULL; chall = chall->next)  {
            if (chall->scheme == auth_scheme_sspi_negotiate) {
                if (!sspi_challenge(sess, chall, 0)) {
                    success = 1;
                    break;
                }
            }
        }
    }
    
    if (!success) {
        NE_DEBUG(NE_DBG_HTTPAUTH, "Looking for SSPI/NTLM.\n");
        for (chall = challenges; chall != NULL; chall = chall->next) {
            if (chall->scheme == auth_scheme_sspi_ntlm) {
                if (!sspi_challenge(sess, chall, 1)) {
                    success = 1;
                    break;
                }
            }
        }
    }
#endif

    /* Try a digest challenge */
    if (!success) {
        NE_DEBUG(NE_DBG_HTTPAUTH, "Looking for Digest challenges.\n");
        for (chall = challenges; chall != NULL; chall = chall->next) {
        	if (chall->scheme == auth_scheme_digest) {
        	    if (!digest_challenge(sess, chall)) {
        		success = 1;
        		break;
        	    }
        	}
        }
    }

    if (!success) {
	NE_DEBUG(NE_DBG_HTTPAUTH, 
		 "No good Digest challenges, looking for Basic.\n");
	for (chall = challenges; chall != NULL; chall = chall->next) {
	    if (chall->scheme == auth_scheme_basic) {
		if (!basic_challenge(sess, chall)) {
		    success = 1;
		    break;
		}
	    }
	}

	if (!success) {
	    /* No good challenges - record this in the session state */
	    NE_DEBUG(NE_DBG_HTTPAUTH, "Did not understand any challenges.\n");
	}

    }
    
    /* Remember whether we can now supply the auth details */
    sess->can_handle = success;

    while (challenges != NULL) {
	chall = challenges->next;
	ne_free(challenges);
	challenges = chall;
    }

    ne_free(hdr);

    return !success;
}
Example #30
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. */
static int check_identity(const char *hostname, X509 *cert, char **identity)
{
    STACK_OF(GENERAL_NAME) *names;
    int match = 0, found = 0;
    
    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 = match_hostname(name, hostname);
		ne_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);
                }
            } /* TODO: handle uniformResourceIdentifier too */

	}
        /* 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 commonNmae 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 = match_hostname(cname->data, hostname);
        ne_buffer_destroy(cname);
    }

    NE_DEBUG(NE_DBG_SSL, "Identity match for '%s': %s\n", hostname, 
             match ? "good" : "bad");
    return match ? 0 : 1;
}