2012-08-01 04:34:13 +08:00
|
|
|
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
|
|
|
See the COPYRIGHT file for more information. */
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "ocinternal.h"
|
|
|
|
#include "ocdebug.h"
|
|
|
|
#include "ocrc.h"
|
|
|
|
|
2014-03-15 04:07:35 +08:00
|
|
|
#define OC_MAX_REDIRECTS 10L
|
|
|
|
|
|
|
|
|
2012-08-01 04:34:13 +08:00
|
|
|
/* Condition on libcurl version */
|
|
|
|
/* Set up an alias as needed */
|
|
|
|
#ifndef HAVE_CURLOPT_KEYPASSWD
|
|
|
|
#define CURLOPT_KEYPASSWD CURLOPT_SSLKEYPASSWD
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static char* combinecredentials(const char* user, const char* pwd);
|
|
|
|
|
|
|
|
void
|
|
|
|
oc_curl_debug(OCstate* state)
|
|
|
|
{
|
|
|
|
curl_easy_setopt(state->curl,CURLOPT_VERBOSE,1);
|
|
|
|
curl_easy_setopt(state->curl,CURLOPT_ERRORBUFFER,(void*)state->curlerror);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
oc_curl_printerror(OCstate* state)
|
|
|
|
{
|
|
|
|
fprintf(stderr,"curl error details: %s\n",state->curlerror);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determine if this version of curl supports
|
|
|
|
"file://..." &/or "https://..." urls.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
oc_curl_protocols(struct OCGLOBALSTATE* state)
|
|
|
|
{
|
|
|
|
const char* const* proto; /*weird*/
|
|
|
|
curl_version_info_data* curldata;
|
|
|
|
curldata = curl_version_info(CURLVERSION_NOW);
|
|
|
|
for(proto=curldata->protocols;*proto;proto++) {
|
|
|
|
if(strcmp("file",*proto)==0) {state->curl.proto_file=1;break;}
|
|
|
|
if(strcmp("http",*proto)==0) {state->curl.proto_https=1;break;}
|
|
|
|
}
|
|
|
|
if(ocdebug > 0) {
|
2012-08-09 07:15:18 +08:00
|
|
|
oclog(OCLOGNOTE,"Curl file:// support = %d",state->curl.proto_file);
|
|
|
|
oclog(OCLOGNOTE,"Curl https:// support = %d",state->curl.proto_https);
|
2012-08-01 04:34:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Set various general curl flags */
|
2014-06-27 06:40:08 +08:00
|
|
|
CURLcode
|
2012-08-01 04:34:13 +08:00
|
|
|
ocset_curl_flags(OCstate* state)
|
|
|
|
{
|
|
|
|
CURLcode cstat = CURLE_OK;
|
|
|
|
CURL* curl = state->curl;
|
|
|
|
struct OCcurlflags* flags = &state->curlflags;
|
|
|
|
|
2013-11-15 06:13:20 +08:00
|
|
|
#if 0
|
|
|
|
cstat = curl_easy_reset(curl);
|
|
|
|
#endif
|
|
|
|
|
2012-08-01 04:34:13 +08:00
|
|
|
#ifdef CURLOPT_ENCODING
|
|
|
|
if (flags->compress) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_ENCODING,"deflate, gzip");
|
|
|
|
if(cstat != CURLE_OK) goto done;
|
|
|
|
OCDBG(1,"CURLOPT_ENCODING=deflate, gzip");
|
|
|
|
}
|
|
|
|
#endif
|
2013-11-15 06:13:20 +08:00
|
|
|
#if 0
|
|
|
|
Do not think this is correct
|
|
|
|
if (flags->cookiejar) {
|
2012-08-01 04:34:13 +08:00
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_COOKIESESSION, 1);
|
|
|
|
if (cstat != CURLE_OK) goto done;
|
|
|
|
OCDBG(1,"CURLOPT_COOKIESESSION=1");
|
|
|
|
}
|
2013-11-15 06:13:20 +08:00
|
|
|
#endif
|
2012-08-01 04:34:13 +08:00
|
|
|
if (flags->cookiejar) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_COOKIEJAR, flags->cookiejar);
|
|
|
|
if (cstat != CURLE_OK) goto done;
|
|
|
|
OCDBG1(1,"CURLOPT_COOKIEJAR=%s",flags->cookiejar);
|
2013-11-15 06:13:20 +08:00
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_COOKIEFILE, flags->cookiejar);
|
2012-08-01 04:34:13 +08:00
|
|
|
if (cstat != CURLE_OK) goto done;
|
|
|
|
}
|
|
|
|
if (flags->verbose) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
|
|
if (cstat != CURLE_OK) goto done;
|
|
|
|
OCDBG1(1,"CURLOPT_VERBOSE=%ld",1L);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags->timeout) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)flags->timeout);
|
|
|
|
if (cstat != CURLE_OK) goto done;
|
|
|
|
OCDBG1(1,"CURLOPT_TIMEOUT=%ld",1L);
|
|
|
|
}
|
|
|
|
|
2012-12-04 11:32:41 +08:00
|
|
|
if (flags->useragent) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_USERAGENT, flags->useragent);
|
|
|
|
if (cstat != CURLE_OK) goto done;
|
|
|
|
OCDBG1(1,"CURLOPT_USERAGENT=%s",flags->useragent);
|
|
|
|
}
|
|
|
|
|
2012-08-01 04:34:13 +08:00
|
|
|
/* Following are always set */
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
|
|
|
OCDBG1(1,"CURLOPT_FOLLOWLOCATION=%ld",1L);
|
2014-03-15 04:07:35 +08:00
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L);
|
|
|
|
OCDBG1(1,"CURLOPT_UNRESTRICTED_AUTH=%ld",1L);
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_MAXREDIRS, OC_MAX_REDIRECTS);
|
|
|
|
OCDBG1(1,"CURLOPT_MAXREDIRS=%ld",OC_MAX_REDIRECTS);
|
2013-11-15 06:13:20 +08:00
|
|
|
#if 0
|
|
|
|
cstat = curl_setopt(curl,CURLOPT_RETURNTRANSFER, 1L);
|
|
|
|
OCDBG1(1,"CURLOPT_RETURNTRANSFER=%ld",1L);
|
|
|
|
#endif
|
2012-08-01 04:34:13 +08:00
|
|
|
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, state->error.curlerrorbuf);
|
|
|
|
OCDBG1(1,"CURLOPT_ERRORBUFFER",0);
|
|
|
|
|
|
|
|
done:
|
|
|
|
return cstat;
|
|
|
|
}
|
|
|
|
|
2014-05-09 04:13:51 +08:00
|
|
|
OCerror
|
2012-08-01 04:34:13 +08:00
|
|
|
ocset_proxy(OCstate* state)
|
|
|
|
{
|
|
|
|
CURLcode cstat;
|
|
|
|
CURL* curl = state->curl;
|
|
|
|
struct OCproxy *proxy = &state->proxy;
|
|
|
|
struct OCcredentials *creds = &state->creds;
|
|
|
|
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_PROXY, proxy->host);
|
|
|
|
if (cstat != CURLE_OK) return OC_ECURL;
|
|
|
|
OCDBG1(1,"CURLOPT_PROXY=%s",proxy->host);
|
|
|
|
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxy->port);
|
|
|
|
if (cstat != CURLE_OK) return OC_ECURL;
|
|
|
|
OCDBG1(1,"CURLOPT_PROXYPORT=%d",proxy->port);
|
|
|
|
|
|
|
|
if (creds->username) {
|
|
|
|
char *combined = combinecredentials(creds->username,creds->password);
|
|
|
|
if (!combined) return OC_ENOMEM;
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, combined);
|
|
|
|
if (cstat != CURLE_OK) return OC_ECURL;
|
|
|
|
OCDBG1(1,"CURLOPT_PROXYUSERPWD=%s",combined);
|
|
|
|
#ifdef CURLOPT_PROXYAUTH
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
|
|
|
|
if(cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_PROXYAUTH=%ld",(long)CURLAUTH_ANY);
|
|
|
|
#endif
|
|
|
|
free(combined);
|
|
|
|
}
|
|
|
|
return OC_NOERR;
|
|
|
|
}
|
|
|
|
|
2014-05-09 04:13:51 +08:00
|
|
|
OCerror
|
2012-08-01 04:34:13 +08:00
|
|
|
ocset_ssl(OCstate* state)
|
|
|
|
{
|
|
|
|
CURLcode cstat = CURLE_OK;
|
|
|
|
CURL* curl = state->curl;
|
|
|
|
struct OCSSL* ssl = &state->ssl;
|
|
|
|
long verify = (ssl->validate?1L:0L);
|
|
|
|
cstat=curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, verify);
|
|
|
|
if (cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_SSL_VERIFYPEER=%ld",verify);
|
|
|
|
cstat=curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, (verify?2L:0L));
|
|
|
|
if (cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_SSL_VERIFYHOST=%ld",(verify?2L:0L));
|
|
|
|
#ifdef OCIGNORE
|
|
|
|
if(verify)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if(ssl->certificate) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_SSLCERT, ssl->certificate);
|
|
|
|
if(cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_SSLCERT=%s",ssl->certificate);
|
|
|
|
}
|
|
|
|
if(ssl->key) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_SSLKEY, ssl->key);
|
|
|
|
if(cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_SSLKEY=%s",ssl->key);
|
|
|
|
}
|
|
|
|
if(ssl->keypasswd) {
|
|
|
|
/* libcurl prior to 7.16.4 used 'CURLOPT_SSLKEYPASSWD' */
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_KEYPASSWD, ssl->keypasswd);
|
|
|
|
if(cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_SSLKEY=%s",ssl->key);
|
|
|
|
}
|
|
|
|
if(ssl->cainfo) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_CAINFO, ssl->cainfo);
|
|
|
|
if(cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_CAINFO=%s",ssl->cainfo);
|
|
|
|
}
|
|
|
|
if(ssl->capath) {
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_CAPATH, ssl->capath);
|
|
|
|
if(cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_CAPATH=%s",ssl->capath);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, ssl->verifypeer);
|
|
|
|
if(cstat != CURLE_OK) goto fail;
|
|
|
|
OCDBG1(1,"CURLOPT_SSL_VERIFYPEER=%d",ssl->verifypeer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OC_NOERR;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
return OC_ECURL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is called with arguments while the other functions in this file are
|
|
|
|
* used with global values read from the.dodsrc file. The reason is that
|
|
|
|
* we may have multiple password sources.
|
|
|
|
*/
|
2014-05-09 04:13:51 +08:00
|
|
|
OCerror
|
2012-08-01 04:34:13 +08:00
|
|
|
ocset_user_password(OCstate* state)
|
|
|
|
{
|
|
|
|
CURLcode cstat;
|
|
|
|
CURL* curl = state->curl;
|
|
|
|
char* combined = NULL;
|
|
|
|
const char* userC = state->creds.username;
|
|
|
|
const char* passwordC = state->creds.password;
|
|
|
|
|
|
|
|
if(userC == NULL || passwordC == NULL) return OC_NOERR;
|
|
|
|
|
|
|
|
combined = combinecredentials(userC,passwordC);
|
|
|
|
if (!combined) return OC_ENOMEM;
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_USERPWD, combined);
|
|
|
|
if (cstat != CURLE_OK) goto done;
|
|
|
|
OCDBG1(1,"CURLOPT_USERPWD=%s",combined);
|
|
|
|
cstat = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long) CURLAUTH_ANY);
|
|
|
|
if (cstat != CURLE_OK) goto done;
|
|
|
|
OCDBG1(1,"CURLOPT_HTTPAUTH=%ld",(long)CURLAUTH_ANY);
|
|
|
|
|
|
|
|
done:
|
|
|
|
if(combined != NULL) free(combined);
|
|
|
|
return (cstat == CURLE_OK?OC_NOERR:OC_ECURL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char*
|
|
|
|
combinecredentials(const char* user, const char* pwd)
|
|
|
|
{
|
|
|
|
int userPassSize = strlen(user) + strlen(pwd) + 2;
|
|
|
|
char *userPassword = malloc(sizeof(char) * userPassSize);
|
|
|
|
if (!userPassword) {
|
2012-08-09 07:15:18 +08:00
|
|
|
oclog(OCLOGERR,"Out of Memory\n");
|
2012-08-01 04:34:13 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
strcpy(userPassword, user);
|
|
|
|
strcat(userPassword, ":");
|
|
|
|
strcat(userPassword, pwd);
|
|
|
|
return userPassword;
|
|
|
|
}
|