Exemple #1
0
unsigned int ne_uri_defaultport(const char *scheme)
{
    /* RFC2616/3.2.3 says use case-insensitive comparisons here. */
    if (ne_strcasecmp(scheme, "http") == 0)
	return 80;
    else if (ne_strcasecmp(scheme, "https") == 0)
	return 443;
    else
	return 0;
}
Exemple #2
0
/* Returns non-zero if given content-type is an XML media type,
 * following the RFC 3023 rules. */
static int media_type_is_xml(const ne_content_type *ctype)
{
    size_t stlen;

    return 
        (ne_strcasecmp(ctype->type, "text") == 0
         && ne_strcasecmp(ctype->subtype, "xml") == 0)
        || (ne_strcasecmp(ctype->type, "application") == 0
            && ne_strcasecmp(ctype->subtype, "xml") == 0)
        || ((stlen = strlen(ctype->subtype)) > 4
            && ne_strcasecmp(ctype->subtype + stlen - 4, "+xml") == 0);
}
Exemple #3
0
int ne_get_content_type(ne_request *req, ne_content_type *ct)
{
    const char *value;
    char *sep, *stype;

    value = ne_get_response_header(req, "Content-Type");
    if (value == NULL || strchr(value, '/') == NULL) {
        return -1;
    }

    ct->value = ne_strdup(value);

    stype = strchr(ct->value, '/');

    *stype++ = '\0';
    ct->type = ct->value;
    ct->charset = NULL;

    sep = strchr(stype, ';');

    if (sep) {
	char *tok;
	/* look for the charset parameter. TODO; probably better to
	 * hand-carve a parser than use ne_token/strstr/shave here. */
	*sep++ = '\0';
	do {
	    tok = ne_qtoken(&sep, ';', "\"\'");
	    if (tok) {
		tok = strstr(tok, "charset=");
		if (tok)
		    ct->charset = ne_shave(tok+8, "\"\'");
	    } else {
		break;
	    }
	} while (sep != NULL);
    }

    /* set subtype, losing any trailing whitespace */
    ct->subtype = ne_shave(stype, " \t");

    if (ct->charset == NULL && ne_strcasecmp(ct->type, "text") == 0) {
        /* 3280§3.1: text/xml without charset implies us-ascii. */
        if (ne_strcasecmp(ct->subtype, "xml") == 0)
            ct->charset = "us-ascii";
        /* 2616§3.7.1: subtypes of text/ default to charset ISO-8859-1. */
        else
            ct->charset = "ISO-8859-1";
    }

    return 0;
}
Exemple #4
0
/* This doesn't actually implement complete RFC 2818 logic; omits
 * "f*.example.com" support for simplicity. */
int ne__ssl_match_hostname(const char *cn, size_t cnlen, const char *hostname)
{
    const char *dot;

    NE_DEBUG(NE_DBG_SSL, "ssl: Match common name '%s' against '%s'\n",
             cn, hostname);

    if (strncmp(cn, "*.", 2) == 0 && cnlen > 2
        && (dot = strchr(hostname, '.')) != NULL) {
        ne_inet_addr *ia;

        /* Prevent wildcard CN matches against anything which can be
         * parsed as an IP address (i.e. a CN of "*.1.1.1" should not
         * be match 8.1.1.1).  draft-saintandre-tls-server-id-check
         * will require some more significant changes to cert ID
         * verification which will probably obviate this check, but
         * this is a desirable policy tightening in the mean time. */
        ia = ne_iaddr_parse(hostname, ne_iaddr_ipv4);
        if (ia == NULL)
            ia = ne_iaddr_parse(hostname, ne_iaddr_ipv6);
        
        if (ia) {
            NE_DEBUG(NE_DBG_SSL, "ssl: Denying wildcard match for numeric "
                     "IP address.\n");
            ne_iaddr_free(ia);
            return 0;
        }

	hostname = dot + 1;
	cn += 2;
        cnlen -= 2;
    }

    return cnlen == strlen(hostname) && !ne_strcasecmp(cn, hostname);
}
Exemple #5
0
static int parse_depth(const char *depth)
{
    if (ne_strcasecmp(depth, "infinity") == 0) {
	return NE_DEPTH_INFINITE;
    } else if (isdigit(depth[0])) {
	return atoi(depth);
    } else {
	return -1;
    }
}
Exemple #6
0
/* Submit the given lock for the given URI */
static void submit_lock(struct lh_req_cookie *lrc, struct ne_lock *lock)
{
    struct lock_list *item;

    /* Check for dups */
    for (item = lrc->submit; item != NULL; item = item->next) {
	if (ne_strcasecmp(item->lock->token, lock->token) == 0)
	    return;
    }

    insert_lock(&lrc->submit, lock);
}
static int casecmp(void)
{
    static const struct {
        const char *left, *right;
        int expect;
    } ts[] = {
        { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0 },
        { "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", 0 },
        { "foo", "bar", 1 },
        { "!#:[@\377", "!#:[@\377", 0 },
        { "bar", "foo", -1 },
        { "foop", "foo", 1 },
        { "foo", "foop", -1 },
        { NULL, NULL, 0 }
    };
    size_t n;
    
    for (n = 0; ts[n].left; n++) {
        int actual;

        actual = ne_strcasecmp(ts[n].left, ts[n].right);
        
        ONV(ts[n].expect == 0 && actual != 0,
            ("strcasecmp(%s, %s) gave %d, expected 0",
             ts[n].left, ts[n].right, actual));

        ONV(ts[n].expect > 0 && actual <= 0,
            ("strcasecmp(%s, %s) gave %d, expected > 0",
             ts[n].left, ts[n].right, actual));

        ONV(ts[n].expect < 0 && actual >= 0,
            ("strcasecmp(%s, %s) gave %d, expected < 0",
             ts[n].left, ts[n].right, actual));
    }

    ONN("comparison of identical pointers did not give zero",
        ne_strcasecmp(ts[0].left, ts[0].left) != 0);

    return OK;
}
Exemple #8
0
static long parse_timeout(const char *timeout)
{
    if (ne_strcasecmp(timeout, "infinite") == 0) {
	return NE_TIMEOUT_INFINITE;
    } else if (strncasecmp(timeout, "Second-", 7) == 0) {
	long to = strtol(timeout+7, NULL, 10);
	if (to == LONG_MIN || to == LONG_MAX)
	    return NE_TIMEOUT_INVALID;
	return to;
    } else {
	return NE_TIMEOUT_INVALID;
    }
}
Exemple #9
0
/* Return non-zero if hostname from certificate (cn) matches hostname
 * used for session (hostname).  (Wildcard matching is no longer
 * mandated by RFC3280, but certs are deployed which use wildcards) */
static int match_hostname(char *cn, const char *hostname)
{
    const char *dot;
    NE_DEBUG(NE_DBG_SSL, "Match %s on %s...\n", cn, hostname);
    dot = strchr(hostname, '.');
    if (dot == NULL) {
	char *pnt = strchr(cn, '.');
	/* hostname is not fully-qualified; unqualify the cn. */
	if (pnt != NULL) {
	    *pnt = '\0';
	}
    }
    else if (strncmp(cn, "*.", 2) == 0) {
	hostname = dot + 1;
	cn += 2;
    }
    return !ne_strcasecmp(cn, hostname);
}
Exemple #10
0
/* This doesn't actually implement complete RFC 2818 logic; omits
 * "f*.example.com" support for simplicity. */
int ne__ssl_match_hostname(char *cn, const char *hostname)
{
    const char *dot;

    dot = strchr(hostname, '.');
    if (dot == NULL) {
	char *pnt = strchr(cn, '.');
	/* hostname is not fully-qualified; unqualify the cn. */
	if (pnt != NULL) {
	    *pnt = '\0';
	}
    }
    else if (strncmp(cn, "*.", 2) == 0) {
	hostname = dot + 1;
	cn += 2;
    }

    return !ne_strcasecmp(cn, hostname);
}
Exemple #11
0
/* TODO: implement properly */
int ne_path_compare(const char *a, const char *b) 
{
    int ret = ne_strcasecmp(a, b);
    if (ret) {
	/* This logic says: "If the lengths of the two URIs differ by
	 * exactly one, and the LONGER of the two URIs has a trailing
	 * slash and the SHORTER one DOESN'T, then..." */
	int traila = ne_path_has_trailing_slash(a),
	    trailb = ne_path_has_trailing_slash(b),
	    lena = strlen(a), lenb = strlen(b);
	if (traila != trailb && abs(lena - lenb) == 1 &&
	    ((traila && lena > lenb) || (trailb && lenb > lena))) {
	    /* Compare them, ignoring the trailing slash on the longer
	     * URI */
	    if (strncasecmp(a, b, lena < lenb ? lena : lenb) == 0)
		ret = 0;
	}
    }
    return ret;
}
Exemple #12
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
}
/* 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;
}