예제 #1
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;
}
예제 #2
0
int discard_request(ne_socket *sock)
{
    char buffer[1024];
    size_t offset = want_header?strlen(want_header):0;

    clength = 0;

    NE_DEBUG(NE_DBG_HTTP, "Discarding request...\n");
    do {
	ONV(ne_sock_readline(sock, buffer, 1024) < 0,
	    ("error reading line: %s", ne_sock_error(sock)));
	NE_DEBUG(NE_DBG_HTTP, "[req] %s", buffer);
	if (strncasecmp(buffer, "content-length:", 15) == 0) {
	    clength = atoi(buffer + 16);
	}
	if (got_header != NULL && want_header != NULL &&
	    strncasecmp(buffer, want_header, offset) == 0 &&
	    buffer[offset] == ':') {
	    char *value = buffer + offset + 1;
	    if (*value == ' ') value++;
	    got_header(ne_shave(value, "\r\n"));
	}
    } while (strcmp(buffer, "\r\n") != 0);

    return OK;
}
예제 #3
0
파일: cadaver.c 프로젝트: grimneko/cadaver
char *readline(const char *prompt)
{
    static char buf[256];
    char *ret;
    if (prompt) {
	printf("%s", prompt);
    }
    ret = fgets(buf, 256, stdin);
    if (ret) {
	return ne_strdup(ne_shave(buf, "\r\n"));
    } else {
	return NULL;
    }
}
예제 #4
0
파일: ne_locks.c 프로젝트: elazzi/winscp
static int lk_startelm(void *userdata, int parent,
                       const char *nspace, const char *name,
		       const char **atts)
{
    struct lock_ctx *ctx = userdata;
    int id;
    NE_DEBUG_WINSCP_CONTEXT(ne_get_session(ctx->req));

    id = ne_xml_mapid(element_map, NE_XML_MAPLEN(element_map), nspace, name);

    NE_DEBUG(NE_DBG_LOCKS, "lk_startelm: %s => %d\n", name, id);
    
    if (id == 0)
        return NE_XML_DECLINE;    

    if (parent == 0 && ctx->token == NULL) {
        const char *token = ne_get_response_header(ctx->req, "Lock-Token");
        /* at the root element; retrieve the Lock-Token header,
         * and bail if it wasn't given. */
        if (token == NULL) {
            ne_xml_set_error(ctx->parser, 
                             _("LOCK response missing Lock-Token header"));
            return NE_XML_ABORT;
        }

        if (token[0] == '<') token++;
        ctx->token = ne_strdup(token);
        ne_shave(ctx->token, ">");
        NE_DEBUG(NE_DBG_LOCKS, "lk_startelm: Finding token %s\n",
                 ctx->token);
    }

    /* TODO: only accept 'prop' as root for LOCK response */
    if (!can_accept(parent, id))
        return NE_XML_DECLINE;

    if (id == ELM_activelock && !ctx->found) {
	/* a new activelock */
	ne_lock_free(&ctx->active);
	memset(&ctx->active, 0, sizeof ctx->active);
        ctx->active.timeout = NE_TIMEOUT_INVALID;
    }

    ne_buffer_clear(ctx->cdata);

    return id;
}
예제 #5
0
파일: ne_basic.c 프로젝트: tolsen/limeberry
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);
}
예제 #6
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);
}
예제 #7
0
파일: cadaver.c 프로젝트: grimneko/cadaver
static int init_rcfile(void)
{
    int ret = 0;
    char buf[BUFSIZ];
    struct stat st;
    FILE *f;

    if (rcfile == NULL) {
	rcfile = ne_concat(getenv("HOME"), "/.cadaverrc", NULL);

	if (stat(rcfile, &st) != 0) {
	    NE_DEBUG(DEBUG_FILES, "No rcfile\n");
	    free(rcfile);
	    return 0;
	}
    }

    f = fopen(rcfile, "r");
    if (f == NULL) {
        printf(_("Could not read rcfile %s: %s\n"), rcfile, 
	   strerror(errno));
    } else {
	for (;;) {
	    if (fgets(buf, BUFSIZ, f) != NULL) {
		ret = execute_command(ne_shave(buf, "\r\n"));
		if (ret != 0)
		    break;
	    } else {
		break;
	    }
	}
	fclose(f);
    }
    free(rcfile);
    return ret;
}
예제 #8
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;
}
예제 #9
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;
}