Exemple #1
0
ne_inet_addr *ne_iaddr_make(ne_iaddr_type type, const unsigned char *raw)
{
    ne_inet_addr *ia;
#if !defined(AF_INET6) || !defined(USE_GETADDRINFO)
    /* fail if IPv6 address is given if IPv6 is not supported. */
    if (type == ne_iaddr_ipv6)
	return NULL;
#endif
    ia = ne_calloc(sizeof *ia);
#ifdef USE_GETADDRINFO
    /* ai_protocol and ai_socktype aren't used by connect_socket() so
     * ignore them here. (for now) */
    if (type == ne_iaddr_ipv4) {
	struct sockaddr_in *in4 = ne_calloc(sizeof *in4);
	ia->ai_family = AF_INET;
	ia->ai_addr = (struct sockaddr *)in4;
	ia->ai_addrlen = sizeof *in4;
	in4->sin_family = AF_INET;
	memcpy(&in4->sin_addr.s_addr, raw, sizeof in4->sin_addr.s_addr);
    }
#ifdef AF_INET6
    else {
	struct sockaddr_in6 *in6 = ne_calloc(sizeof *in6);
	ia->ai_family = AF_INET6;
	ia->ai_addr = (struct sockaddr *)in6;
	ia->ai_addrlen = sizeof *in6;
	in6->sin6_family = AF_INET6;
	memcpy(&in6->sin6_addr, raw, sizeof in6->sin6_addr.s6_addr);
    }
#endif
#else /* !USE_GETADDRINFO */
    memcpy(&ia->s_addr, raw, sizeof ia->s_addr);
#endif    
    return ia;
}
Exemple #2
0
ne_session *ne_session_create(const char *scheme,
			      const char *hostname, unsigned int port)
{
    ne_session *sess = ne_calloc(sizeof *sess);

    NE_DEBUG(NE_DBG_HTTP, "HTTP session to %s://%s:%d begins.\n",
	     scheme, hostname, port);

    strcpy(sess->error, "Unknown error.");

    /* use SSL if scheme is https */
    sess->use_ssl = !strcmp(scheme, "https");
    
    /* set the hostname/port */
    set_hostinfo(&sess->server, hostname, port);
    set_hostport(&sess->server, sess->use_ssl?443:80);

#ifdef NE_HAVE_SSL
    if (sess->use_ssl) {
        sess->ssl_context = ne_ssl_context_create(0);
        sess->flags[NE_SESSFLAG_SSLv2] = 1;
    }
#endif

    sess->scheme = ne_strdup(scheme);

    /* Set flags which default to on: */
    sess->flags[NE_SESSFLAG_PERSIST] = 1;

    return sess;
}
Exemple #3
0
/*
 * Create a context to authenticate to specified server, using either
 * ntlm or negotiate.
 */
int ne_sspi_create_context(void **context, char *serverName, int ntlm)
{
    SSPIContext *sspiContext;
    char *canonicalName;

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

    sspiContext = ne_calloc(sizeof(SSPIContext));
    sspiContext->continueNeeded = 0;

    if (ntlm) {
        sspiContext->mechanism = "NTLM";
        sspiContext->serverName = ne_strdup(serverName);
        sspiContext->maxTokenSize = ntlmMaxTokenSize;
    } else {
        sspiContext->mechanism = "Negotiate";
        /* Canonicalize to conform to GSSAPI behavior */
        canonicalName = canonical_hostname(serverName);
        sspiContext->serverName = ne_concat("HTTP/", canonicalName, NULL);
        ne_free(canonicalName);
        NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: Created context with SPN '%s'\n",
                 sspiContext->serverName);
        sspiContext->maxTokenSize = negotiateMaxTokenSize;
    }

    sspiContext->ntlm = ntlm;
    sspiContext->authfinished = 0;
    *context = sspiContext;
    return 0;
}
Exemple #4
0
ne_ssl_certificate *ne_ssl_cert_import(const char *data)
{
    int ret;
    size_t len;
    unsigned char *der;
    gnutls_datum buffer = { NULL, 0 };
    gnutls_x509_crt x5;

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

    /* decode the base64 to get the raw DER representation */
    len = ne_unbase64(data, &der);
    if (len == 0) return NULL;

    buffer.data = der;
    buffer.size = len;

    ret = gnutls_x509_crt_import(x5, &buffer, GNUTLS_X509_FMT_DER);
    ne_free(der);

    if (ret < 0) {
        gnutls_x509_crt_deinit(x5);
        return NULL;
    }

    return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);
}
Exemple #5
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;
    }
    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;
}    
Exemple #6
0
/*
 * Create a context to authenticate to specified server, using either
 * ntlm or negotiate.
 */
int ne_sspi_create_context(void **context, char *serverName, int ntlm)
{
    SSPIContext *sspiContext;

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

    sspiContext = ne_calloc(sizeof(SSPIContext));
    sspiContext->continueNeeded = 0;

    if (ntlm) {
        sspiContext->mechanism = "NTLM";
        sspiContext->serverName = ne_strdup(serverName);
        sspiContext->maxTokenSize = ntlmMaxTokenSize;
    } else {
        sspiContext->mechanism = "Negotiate";
        sspiContext->serverName = ne_concat("HTTP/", serverName, NULL);
        sspiContext->maxTokenSize = negotiateMaxTokenSize;
    }

    sspiContext->ntlm = ntlm;
    sspiContext->authfinished = 0;
    *context = sspiContext;
    return 0;
}
Exemple #7
0
static void auth_register(ne_session *sess, int isproxy,
			  const struct auth_class *ahc, const char *id, 
			  ne_auth_creds creds, void *userdata) 
{
    auth_session *ahs = ne_calloc(sizeof *ahs);

    ahs->creds = creds;
    ahs->userdata = userdata;
    ahs->sess = sess;
    ahs->spec = ahc;

    if (strcmp(ne_get_scheme(sess), "https") == 0) {
        ahs->context = isproxy ? AUTH_CONNECT : AUTH_NOTCONNECT;
#ifdef HAVE_GSSAPI
        {
            get_gss_name(&ahs->gssname, (isproxy ? sess->proxy.hostname 
                                         : sess->server.hostname));
            ahs->gssctx = GSS_C_NO_CONTEXT;
            ahs->gssmech = GSS_C_NO_OID;
        }
#endif
    } else {
        ahs->context = AUTH_ANY;
    }
    
    /* Register hooks */
    ne_hook_create_request(sess, ah_create, ahs);
    ne_hook_pre_send(sess, ah_pre_send, ahs);
    ne_hook_post_send(sess, ah_post_send, ahs);
    ne_hook_destroy_request(sess, ah_destroy, ahs);
    ne_hook_destroy_session(sess, free_auth, ahs);

    ne_set_session_private(sess, id, ahs);
}
Exemple #8
0
ne_ssl_client_cert *ne_ssl_clicert_read(const char *filename)
{
    int ret;
    gnutls_datum data;
    gnutls_pkcs12 p12;
    ne_ssl_client_cert *cc;
    char *friendly_name = NULL;
    gnutls_x509_crt cert = NULL;
    gnutls_x509_privkey pkey = NULL;

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

    if (gnutls_pkcs12_init(&p12) != 0) {
        return NULL;
    }

    ret = gnutls_pkcs12_import(p12, &data, GNUTLS_X509_FMT_DER, 0);
    ne_free(data.data);
    if (ret < 0) {
        gnutls_pkcs12_deinit(p12);
        return NULL;
    }

    if (gnutls_pkcs12_verify_mac(p12, "") == 0) {
        if (pkcs12_parse(p12, &pkey, &cert, &friendly_name, "") != 0
            || !cert || !pkey) {
            gnutls_pkcs12_deinit(p12);
            return NULL;
        }

        cc = ne_calloc(sizeof *cc);
        cc->pkey = pkey;
        cc->decrypted = 1;
        cc->friendly_name = friendly_name;
        populate_cert(&cc->cert, cert);
        gnutls_pkcs12_deinit(p12);
        cc->p12 = NULL;
        return cc;
    } else {
        /* TODO: calling pkcs12_parse() here to find the friendly_name
         * seems to break horribly.  */
        cc = ne_calloc(sizeof *cc);
        cc->p12 = p12;
        return cc;
    }
}
Exemple #9
0
nssl_context *sock_create_ssl_context(void)
{
    nssl_context *ctx = ne_calloc(sizeof *ctx);
#ifdef ENABLE_SSL
    ctx->ctx = SSL_CTX_new(SSLv23_client_method());
#endif
    return ctx;
}
Exemple #10
0
struct ne_lock *ne_lock_create(void)
{
    struct ne_lock *lock = ne_calloc(sizeof *lock);
    lock->depth = NE_DEPTH_ZERO;
    lock->type = ne_locktype_write;
    lock->scope = ne_lockscope_exclusive;
    lock->timeout = NE_TIMEOUT_INVALID;
    return lock;
}
Exemple #11
0
static ne_socket *create_sock(int fd)
{
    ne_socket *sock = ne_calloc(sizeof *sock);
    sock->fd = fd;
    sock->rdtimeout = SOCKET_READ_TIMEOUT;
    sock->bufpos = sock->buffer;
    sock->ops = &iofns_raw;
    return sock;
}
Exemple #12
0
static nsocket *create_sock(int fd)
{
    nsocket *sock = ne_calloc(sizeof *sock);
#ifdef ENABLE_SSL
    sock->default_ctx = SSL_CTX_new(SSLv23_client_method());
#endif
    sock->fd = fd;
    return sock;
}
Exemple #13
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 /* this was missing from the RFC2133 API */
	hints.ai_flags = AI_NUMERICHOST;
#endif
        hints.ai_family = AF_INET6;
	addr->errnum = getaddrinfo(hn, NULL, &hints, &addr->result);
	ne_free(hn);
    } else {
        hints.ai_family = ipv6_disabled ? AF_INET : AF_UNSPEC;
	addr->errnum = getaddrinfo(hostname, NULL, &hints, &addr->result);
    }
#else /* Use gethostbyname() */
    unsigned long laddr;
    struct hostent *hp;
    
    laddr = inet_addr(hostname);
    if (laddr == INADDR_NONE) {
	hp = gethostbyname(hostname);
	if (hp == NULL) {
#ifdef WIN32
	    addr->errnum = WSAGetLastError();
#else
            addr->errnum = h_errno;
#endif
	} 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);

	    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;
}
Exemple #14
0
ne_socket *ne_sock_create(void)
{
    ne_socket *sock = ne_calloc(sizeof *sock);
    sock->rdtimeout = SOCKET_READ_TIMEOUT;
    sock->cotimeout = 0;
    sock->bufpos = sock->buffer;
    sock->ops = &iofns_raw;
    sock->fd = -1;
    return sock;
}
Exemple #15
0
ne_ssl_context *ne_ssl_context_create(int flags)
{
    ne_ssl_context *ctx = ne_calloc(sizeof *ctx);
    gnutls_certificate_allocate_credentials(&ctx->cred);
    if (flags == NE_SSL_CTX_CLIENT) {
        gnutls_certificate_client_set_retrieve_function(ctx->cred,
                                                        provide_client_cert);
    }
    return ctx;
}
Exemple #16
0
void ne_session_proxy(ne_session *sess, const char *hostname,
		      unsigned int port)
{
    free_proxies(sess);

    sess->proxies = ne_calloc(sizeof *sess->proxies);

    sess->any_proxy_http = 1;
    
    set_hostinfo(sess->proxies, PROXY_HTTP, hostname, port);
}
Exemple #17
0
ne_ssl_context *ne_ssl_context_create(int flags)
{
    ne_ssl_context *ctx = ne_calloc(sizeof *ctx);
    gnutls_certificate_allocate_credentials(&ctx->cred);
    if (flags == NE_SSL_CTX_CLIENT) {
        gnutls_certificate_client_set_retrieve_function(ctx->cred,
                                                        provide_client_cert);
    }
    gnutls_certificate_set_verify_flags(ctx->cred, 
                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
    return ctx;
}
Exemple #18
0
/*
 * Creates a SecBuffer of a specified size.
 */
static int makeBuffer(SecBufferDesc * secBufferDesc, ULONG size)
{
    SecBuffer *buffer;
    if (getSingleBufferDescriptor(secBufferDesc, &buffer)) {
        return -1;
    }

    buffer->BufferType = SECBUFFER_TOKEN;
    buffer->cbBuffer = size;
    buffer->pvBuffer = ne_calloc(size);

    return 0;
}
Exemple #19
0
struct ne_lock *ne_lock_copy(const struct ne_lock *lock)
{
    struct ne_lock *ret = ne_calloc(sizeof *ret);

    ne_uri_copy(&ret->uri, &lock->uri);
    ret->token = ne_strdup(lock->token);
    ret->depth = lock->depth;
    ret->type = lock->type;
    ret->scope = lock->scope;
    if (lock->owner) ret->owner = ne_strdup(lock->owner);
    ret->timeout = lock->timeout;

    return ret;
}
Exemple #20
0
ne_session *ne_session_create(const char *scheme,
			      const char *hostname, unsigned int port)
{
    ne_session *sess = ne_calloc(sizeof *sess);

    NE_DEBUG(NE_DBG_HTTP, "HTTP session to %s://%s:%d begins.\n",
	     scheme, hostname, port);

    strcpy(sess->error, "Unknown error.");

    /* use SSL if scheme is https */
    sess->use_ssl = !strcmp(scheme, "https");
    
    /* set the hostname/port */
    set_hostinfo(&sess->server, PROXY_NONE, hostname, port);
    set_hostport(&sess->server, sess->use_ssl?443:80);

#ifdef NE_HAVE_SSL
    if (sess->use_ssl) {
        ne_inet_addr *ia;

        sess->ssl_context = ne_ssl_context_create(0);
        sess->flags[NE_SESSFLAG_SSLv2] = 1;
        
        /* If the hostname parses as an IP address, don't
         * enable SNI by default. */
        ia = ne_iaddr_parse(hostname, ne_iaddr_ipv4);
        if (ia == NULL)
            ia = ne_iaddr_parse(hostname, ne_iaddr_ipv6);

        if (ia) {
            ne_iaddr_free(ia);
        } 
        else {
            sess->flags[NE_SESSFLAG_TLS_SNI] = 1;
        }
        NE_DEBUG(NE_DBG_SSL, "ssl: SNI %s by default.\n",
                 sess->flags[NE_SESSFLAG_TLS_SNI] ?
                 "enabled" : "disabled");
    }
#endif

    sess->scheme = ne_strdup(scheme);

    /* Set flags which default to on: */
    sess->flags[NE_SESSFLAG_PERSIST] = 1;

    return sess;
}
Exemple #21
0
void ne_session_socks_proxy(ne_session *sess, enum ne_sock_sversion vers, 
                            const char *hostname, unsigned int port,
                            const char *username, const char *password)
{
    free_proxies(sess);

    sess->proxies = ne_calloc(sizeof *sess->proxies);

    set_hostinfo(sess->proxies, PROXY_SOCKS, hostname, port);

    sess->socks_ver = vers;

    if (username) sess->socks_user = ne_strdup(username);
    if (password) sess->socks_password = ne_strdup(password);
}
Exemple #22
0
struct ne_lock *ne_lock_copy(const struct ne_lock *lock)
{
    struct ne_lock *ret = ne_calloc(sizeof *ret);

    ret->uri.path = ne_strdup(lock->uri.path);
    ret->uri.host = ne_strdup(lock->uri.host);
    ret->uri.scheme = ne_strdup(lock->uri.scheme);
    ret->uri.port = lock->uri.port;
    ret->token = ne_strdup(lock->token);
    ret->depth = lock->depth;
    ret->type = lock->type;
    ret->scope = lock->scope;
    if (lock->owner) ret->owner = ne_strdup(lock->owner);
    ret->timeout = lock->timeout;

    return ret;
}
Exemple #23
0
ne_inet_addr *ne_sock_peer(ne_socket *sock, unsigned int *port)
{
    union saun {
        struct sockaddr sa;
        struct sockaddr_in sin;
#if defined(USE_GETADDRINFO) && defined(AF_INET6)
        struct sockaddr_in6 sin6;
#endif
    } saun;
    socklen_t len = sizeof saun;
    ne_inet_addr *ia;
    struct sockaddr *sad = (struct sockaddr *)&saun;

    if (getpeername(sock->fd, sad, &len) != 0) {
        set_strerror(sock, errno);
        return NULL;
    }

#if !defined(USE_GETADDRINFO) || !defined(AF_INET6)
    if (sad->sa_family != AF_INET) {
        set_error(sock, _("Socket family not supported"));
        return NULL;
    }
#endif                  

    ia = ne_calloc(sizeof *ia);
#ifdef USE_GETADDRINFO
    ia->ai_addr = ne_malloc(sizeof *ia);
    ia->ai_addrlen = len;
    memcpy(ia->ai_addr, sad, len);
    ia->ai_family = saun.sa.sa_family;
#else
    memcpy(ia, &saun.sin.sin_addr.s_addr, sizeof *ia);
#endif    

#if defined(USE_GETADDRINFO) && defined(AF_INET6)
    *port = ntohs(saun.sa.sa_family == AF_INET ? 
                  saun.sin.sin_port : saun.sin6.sin6_port);
#else
    *port = ntohs(saun.sin.sin_port);
#endif

    return ia;
}
Exemple #24
0
ne_decompress *ne_decompress_reader(ne_request *req, ne_accept_response acpt,
				    ne_block_reader rdr, void *userdata)
{
    ne_decompress *ctx = ne_calloc(sizeof *ctx);

    ne_add_request_header(req, "Accept-Encoding", "gzip");

    ne_add_response_body_reader(req, gz_acceptor, gz_reader, ctx);

    ctx->reader = rdr;
    ctx->userdata = userdata;
    ctx->session = ne_get_session(req);
    ctx->request = req;
    ctx->acceptor = acpt;

    ne__reqhook_pre_send(req, gz_pre_send, ctx);

    return ctx;    
}
Exemple #25
0
void ne_set_addrlist2(ne_session *sess, unsigned int port,
                      const ne_inet_addr **addrs, size_t n)
{
    struct host_info *hi, **lasthi;
    size_t i;

    free_proxies(sess);

    lasthi = &sess->proxies;

    for (i = 0; i < n; i++) {
        *lasthi = hi = ne_calloc(sizeof *hi);
        
        hi->proxy = PROXY_NONE;
        hi->network = addrs[i];
        hi->port = port;

        lasthi = &hi->next;
    }
}
Exemple #26
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);
}
Exemple #27
0
static void ah_create(ne_request *req, void *session, const char *method,
		      const char *uri)
{
    auth_session *sess = session;
    int is_connect = strcmp(method, "CONNECT") == 0;

    if (sess->context == AUTH_ANY ||
        (is_connect && sess->context == AUTH_CONNECT) ||
        (!is_connect && sess->context == AUTH_NOTCONNECT)) {
        struct auth_request *areq = ne_calloc(sizeof *areq);
        
        NE_DEBUG(NE_DBG_HTTPAUTH, "ah_create, for %s\n", sess->spec->resp_hdr);
        
        areq->method = method;
        areq->uri = uri;
        areq->request = req;
        
        sess->attempt = 0;
        
        ne_set_request_private(req, sess->spec->id, areq);
    }
}
Exemple #28
0
ne_ssl_client_cert *ne__ssl_clicert_exkey_import(const unsigned char *der,
                                                 size_t der_len)
{
    ne_ssl_client_cert *cc;
    gnutls_x509_crt x5;
    gnutls_datum datum;

    datum.data = (unsigned char *)der;
    datum.size = der_len;    

    if (gnutls_x509_crt_init(&x5) 
        || gnutls_x509_crt_import(x5, &datum, GNUTLS_X509_FMT_DER)) {
        NE_DEBUG(NE_DBG_SSL, "ssl: crt_import failed.\n");
        return NULL;
    }
    
    cc = ne_calloc(sizeof *cc);
    cc->keyless = 1;
    cc->decrypted = 1;
    populate_cert(&cc->cert, x5);

    return cc;    
}
Exemple #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;
}
Exemple #30
0
ne_lock_store *ne_lockstore_create(void)
{
    return ne_calloc(sizeof(ne_lock_store));
}