mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-27 07:30:33 +08:00
a2e0f069ec
Primary change is to cleanup code and remove duplicated code. 1. Unify the rc file reading into libdispatch/drc.c. Eventually extend if we need rc file for netcdf itself as opposed to the dap code. 2. Unify the extraction from the rc file of DAP authorization info. 3. Misc. other small unifications: make temp file, read file. 4. Avoid use of libcurl when reading file:// because there is some kind of problem with the Visual Studio version. Might be related to the winpath problem. In any case, do direct read instead. 5. Add new error code NC_ERCFILE for errors in reading RC file. 6. Complete documentation cleanup as indicated in this comment https://github.com/Unidata/netcdf-c/pull/472#issuecomment-325926426 7. Convert some occurrences of #ifdef _WIN32 to #ifdef _MSC_VER
383 lines
10 KiB
C
383 lines
10 KiB
C
/*
|
|
Copyright (c) 1998-2017 University Corporation for Atmospheric Research/Unidata
|
|
See LICENSE.txt for license information.
|
|
*/
|
|
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
#ifdef HAVE_STDARG_H
|
|
#include <stdarg.h>
|
|
#endif
|
|
#include "netcdf.h"
|
|
#include "ncbytes.h"
|
|
#include "ncuri.h"
|
|
#include "ncauth.h"
|
|
#include "nclog.h"
|
|
#include "ncwinpath.h"
|
|
|
|
#ifdef _MSC_VER
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#undef MEMCHECK
|
|
#define MEMCHECK(x) if((x)==NULL) {goto nomem;} else {}
|
|
|
|
/* Define the curl flag defaults in envv style */
|
|
static const char* AUTHDEFAULTS[] = {
|
|
"HTTP.TIMEOUT","10", /*seconds */
|
|
NULL
|
|
};
|
|
|
|
/* Forward */
|
|
static int setauthfield(NCauth* auth, const char* flag, const char* value);
|
|
static void setdefaults(NCauth*);
|
|
|
|
/**************************************************/
|
|
/* External Entry Points */
|
|
|
|
int
|
|
NC_parseproxy(NCauth* auth, const char* surl)
|
|
{
|
|
int ret = NC_NOERR;
|
|
NCURI* uri = NULL;
|
|
if(surl == NULL || strlen(surl) == 0)
|
|
return (NC_NOERR); /* nothing there*/
|
|
if(ncuriparse(surl,&uri) != NCU_OK)
|
|
return (NC_EURL);
|
|
auth->proxy.user = uri->user;
|
|
auth->proxy.pwd = uri->password;
|
|
auth->proxy.host = strdup(uri->host);
|
|
if(uri->port != NULL)
|
|
auth->proxy.port = atoi(uri->port);
|
|
else
|
|
auth->proxy.port = 80;
|
|
return (ret);
|
|
}
|
|
|
|
char*
|
|
NC_combinehostport(NCURI* uri)
|
|
{
|
|
size_t len;
|
|
char* host = NULL;
|
|
char* port = NULL;
|
|
if(uri == NULL) return NULL;
|
|
host = uri->host;
|
|
port = uri->port;
|
|
if(uri == NULL || host == NULL) return NULL;
|
|
if(port != NULL && strlen(port) == 0) port = NULL;
|
|
len = strlen(host);
|
|
if(port != NULL) len += (1+strlen(port));
|
|
char* hp = (char*)malloc(len+1);
|
|
if(hp == NULL) return NULL;
|
|
strncpy(hp,host,len);
|
|
if(port != NULL) {
|
|
strncat(hp,":",len);
|
|
strncat(hp,port,len);
|
|
}
|
|
return hp;
|
|
}
|
|
|
|
int
|
|
NC_authsetup(NCauth* auth, NCURI* uri)
|
|
{
|
|
int ret = NC_NOERR;
|
|
char* uri_hostport = NULL;
|
|
|
|
if(uri != NULL)
|
|
uri_hostport = NC_combinehostport(uri);
|
|
|
|
setdefaults(auth);
|
|
|
|
/* Note, we still must do this function even if
|
|
ncrc_globalstate.rc.ignore is set in order
|
|
to getinfo e.g. host+port from url
|
|
*/
|
|
|
|
setauthfield(auth,"HTTP.DEFLATE",
|
|
NC_rclookup("HTTP.DEFLATE",uri_hostport));
|
|
setauthfield(auth,"HTTP.VERBOSE",
|
|
NC_rclookup("HTTP.VERBOSE",uri_hostport));
|
|
setauthfield(auth,"HTTP.TIMEOUT",
|
|
NC_rclookup("HTTP.TIMEOUT",uri_hostport));
|
|
setauthfield(auth,"HTTP.USERAGENT",
|
|
NC_rclookup("HTTP.USERAGENT",uri_hostport));
|
|
setauthfield(auth,"HTTP.COOKIEFILE",
|
|
NC_rclookup("HTTP.COOKIEFILE",uri_hostport));
|
|
setauthfield(auth,"HTTP.COOKIE_FILE",
|
|
NC_rclookup("HTTP.COOKIE_FILE",uri_hostport));
|
|
setauthfield(auth,"HTTP.COOKIEJAR",
|
|
NC_rclookup("HTTP.COOKIEJAR",uri_hostport));
|
|
setauthfield(auth,"HTTP.COOKIE_JAR",
|
|
NC_rclookup("HTTP.COOKIE_JAR",uri_hostport));
|
|
setauthfield(auth,"HTTP.PROXY.SERVER",
|
|
NC_rclookup("HTTP.PROXY.SERVER",uri_hostport));
|
|
setauthfield(auth,"HTTP.PROXY_SERVER",
|
|
NC_rclookup("HTTP.PROXY_SERVER",uri_hostport));
|
|
setauthfield(auth,"HTTP.SSL.VALIDATE",
|
|
NC_rclookup("HTTP.SSL.VALIDATE",uri_hostport));
|
|
setauthfield(auth,"HTTP.SSL.CERTIFICATE",
|
|
NC_rclookup("HTTP.SSL.CERTIFICATE",uri_hostport));
|
|
setauthfield(auth,"HTTP.SSL.KEY",
|
|
NC_rclookup("HTTP.SSL.KEY",uri_hostport));
|
|
setauthfield(auth,"HTTP.SSL.KEYPASSWORD",
|
|
NC_rclookup("HTTP.SSL.KEYPASSWORD",uri_hostport));
|
|
setauthfield(auth,"HTTP.SSL.CAINFO",
|
|
NC_rclookup("HTTP.SSL.CAINFO",uri_hostport));
|
|
setauthfield(auth,"HTTP.SSL.CAPATH",
|
|
NC_rclookup("HTTP.SSL.CAPATH",uri_hostport));
|
|
setauthfield(auth,"HTTP.SSL.VERIFYPEER",
|
|
NC_rclookup("HTTP.SSL.VERIFYPEER",uri_hostport));
|
|
setauthfield(auth,"HTTP.NETRC",
|
|
NC_rclookup("HTTP.NETRC",uri_hostport));
|
|
{ /* Handle various cases for user + password */
|
|
/* First, see if the user+pwd was in the original url */
|
|
char* user = NULL;
|
|
char* pwd = NULL;
|
|
if(uri->user != NULL && uri->password != NULL) {
|
|
user = uri->user;
|
|
pwd = uri->password;
|
|
} else {
|
|
user = NC_rclookup("HTTP.CREDENTIALS.USER",uri_hostport);
|
|
pwd = NC_rclookup("HTTP.CREDENTIALS.PASSWORD",uri_hostport);
|
|
}
|
|
if(user != NULL && pwd != NULL) {
|
|
user = strdup(user); /* so we can consistently reclaim */
|
|
pwd = strdup(pwd);
|
|
} else {
|
|
/* Could not get user and pwd, so try USERPASSWORD */
|
|
const char* userpwd = NC_rclookup("HTTP.CREDENTIALS.USERPASSWORD",uri_hostport);
|
|
if(userpwd != NULL) {
|
|
ret = NC_parsecredentials(userpwd,&user,&pwd);
|
|
if(ret) return ret;
|
|
}
|
|
}
|
|
setauthfield(auth,"HTTP.USERNAME",user);
|
|
setauthfield(auth,"HTTP.PASSWORD",pwd);
|
|
nullfree(user);
|
|
nullfree(pwd);
|
|
}
|
|
return (ret);
|
|
}
|
|
|
|
void
|
|
NC_authclear(NCauth* auth)
|
|
{
|
|
if(auth->curlflags.cookiejarcreated) {
|
|
#ifdef _MSC_VER
|
|
DeleteFile(auth->curlflags.cookiejar);
|
|
#else
|
|
remove(auth->curlflags.cookiejar);
|
|
#endif
|
|
}
|
|
nullfree(auth->curlflags.useragent);
|
|
nullfree(auth->curlflags.cookiejar);
|
|
nullfree(auth->curlflags.netrc);
|
|
nullfree(auth->ssl.certificate);
|
|
nullfree(auth->ssl.key);
|
|
nullfree(auth->ssl.keypasswd);
|
|
nullfree(auth->ssl.cainfo);
|
|
nullfree(auth->ssl.capath);
|
|
nullfree(auth->proxy.host);
|
|
nullfree(auth->proxy.user);
|
|
nullfree(auth->proxy.pwd);
|
|
nullfree(auth->creds.user);
|
|
nullfree(auth->creds.pwd);
|
|
}
|
|
|
|
/**************************************************/
|
|
|
|
static int
|
|
setauthfield(NCauth* auth, const char* flag, const char* value)
|
|
{
|
|
int ret = NC_NOERR;
|
|
if(value == NULL) goto done;
|
|
if(strcmp(flag,"HTTP.DEFLATE")==0) {
|
|
if(atoi(value)) auth->curlflags.compress = 1;
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.DEFLATE: %ld", infoflags.compress);
|
|
#endif
|
|
}
|
|
if(strcmp(flag,"HTTP.VERBOSE")==0) {
|
|
if(atoi(value)) auth->curlflags.verbose = 1;
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.VERBOSE: %ld", auth->curlflags.verbose);
|
|
#endif
|
|
}
|
|
if(strcmp(flag,"HTTP.TIMEOUT")==0) {
|
|
if(atoi(value)) auth->curlflags.timeout = atoi(value);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.TIMEOUT: %ld", auth->curlflags.timeout);
|
|
#endif
|
|
}
|
|
if(strcmp(flag,"HTTP.USERAGENT")==0) {
|
|
if(atoi(value)) auth->curlflags.useragent = strdup(value);
|
|
MEMCHECK(auth->curlflags.useragent);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.USERAGENT: %s", auth->curlflags.useragent);
|
|
#endif
|
|
}
|
|
if(
|
|
strcmp(flag,"HTTP.COOKIEFILE")==0
|
|
|| strcmp(flag,"HTTP.COOKIE_FILE")==0
|
|
|| strcmp(flag,"HTTP.COOKIEJAR")==0
|
|
|| strcmp(flag,"HTTP.COOKIE_JAR")==0
|
|
) {
|
|
nullfree(auth->curlflags.cookiejar);
|
|
auth->curlflags.cookiejar = strdup(value);
|
|
MEMCHECK(auth->curlflags.cookiejar);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.COOKIEJAR: %s", auth->curlflags.cookiejar);
|
|
#endif
|
|
}
|
|
if(strcmp(flag,"HTTP.PROXY.SERVER")==0 || strcmp(flag,"HTTP.PROXY_SERVER")==0) {
|
|
ret = NC_parseproxy(auth,value);
|
|
if(ret != NC_NOERR) goto done;
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.PROXY.SERVER: %s", value);
|
|
#endif
|
|
}
|
|
if(strcmp(flag,"HTTP.SSL.VALIDATE")==0) {
|
|
if(atoi(value)) {
|
|
auth->ssl.verifypeer = 1;
|
|
auth->ssl.verifyhost = 1;
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.SSL.VALIDATE: %ld", 1);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if(strcmp(flag,"HTTP.SSL.CERTIFICATE")==0) {
|
|
nullfree(auth->ssl.certificate);
|
|
auth->ssl.certificate = strdup(value);
|
|
MEMCHECK(auth->ssl.certificate);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.SSL.CERTIFICATE: %s", auth->ssl.certificate);
|
|
#endif
|
|
}
|
|
|
|
if(strcmp(flag,"HTTP.SSL.KEY")==0) {
|
|
nullfree(auth->ssl.key);
|
|
auth->ssl.key = strdup(value);
|
|
MEMCHECK(auth->ssl.key);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.SSL.KEY: %s", auth->ssl.key);
|
|
#endif
|
|
}
|
|
|
|
if(strcmp(flag,"HTTP.SSL.KEYPASSWORD")==0) {
|
|
nullfree(auth->ssl.keypasswd) ;
|
|
auth->ssl.keypasswd = strdup(value);
|
|
MEMCHECK(auth->ssl.keypasswd);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.SSL.KEYPASSWORD: %s", auth->ssl.keypasswd);
|
|
#endif
|
|
}
|
|
|
|
if(strcmp(flag,"HTTP.SSL.CAINFO")==0) {
|
|
nullfree(auth->ssl.cainfo) ;
|
|
auth->ssl.cainfo = strdup(value);
|
|
MEMCHECK(auth->ssl.cainfo);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.SSL.CAINFO: %s", auth->ssl.cainfo);
|
|
#endif
|
|
}
|
|
|
|
if(strcmp(flag,"HTTP.SSL.CAPATH")==0) {
|
|
nullfree(auth->ssl.capath) ;
|
|
auth->ssl.capath = strdup(value);
|
|
MEMCHECK(auth->ssl.capath);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.SSL.CAPATH: %s", auth->ssl.capath);
|
|
#endif
|
|
}
|
|
|
|
if(strcmp(flag,"HTTP.SSL.VERIFYPEER")==0) {
|
|
const char* s = value;
|
|
int tf = 0;
|
|
if(s == NULL || strcmp(s,"0")==0 || strcasecmp(s,"false")==0)
|
|
tf = 0;
|
|
else if(strcmp(s,"1")==0 || strcasecmp(s,"true")==0)
|
|
tf = 1;
|
|
else
|
|
tf = 1; /* default if not null */
|
|
auth->ssl.verifypeer = tf;
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.SSL.VERIFYPEER: %d", auth->ssl.verifypeer);
|
|
#endif
|
|
}
|
|
|
|
if(strcmp(flag,"HTTP.NETRC")==0) {
|
|
nullfree(auth->curlflags.netrc);
|
|
auth->curlflags.netrc = strdup(value);
|
|
MEMCHECK(auth->curlflags.netrc);
|
|
#ifdef D4DEBUG
|
|
nclog(NCLOGNOTE,"HTTP.NETRC: %s", auth->curlflags.netrc);
|
|
#endif
|
|
}
|
|
|
|
if(strcmp(flag,"HTTP.CREDENTIALS.USERNAME")==0) {
|
|
nullfree(auth->creds.user);
|
|
auth->creds.user = strdup(value);
|
|
MEMCHECK(auth->creds.user);
|
|
}
|
|
if(strcmp(flag,"HTTP.CREDENTIALS.PASSWORD")==0) {
|
|
nullfree(auth->creds.pwd);
|
|
auth->creds.pwd = strdup(value);
|
|
MEMCHECK(auth->creds.pwd);
|
|
}
|
|
|
|
done:
|
|
return (ret);
|
|
|
|
nomem:
|
|
return (NC_ENOMEM);
|
|
}
|
|
|
|
/*
|
|
Given form user:pwd, parse into user and pwd
|
|
and do %xx unescaping
|
|
*/
|
|
int
|
|
NC_parsecredentials(const char* userpwd, char** userp, char** pwdp)
|
|
{
|
|
char* user = NULL;
|
|
char* pwd = NULL;
|
|
|
|
if(userpwd == NULL)
|
|
return NC_EINVAL;
|
|
user = strdup(userpwd);
|
|
if(user == NULL)
|
|
return NC_ENOMEM;
|
|
pwd = strchr(user,':');
|
|
if(pwd == NULL)
|
|
return NC_EINVAL;
|
|
*pwd = '\0';
|
|
pwd++;
|
|
if(userp)
|
|
*userp = ncuridecode(user);
|
|
if(pwdp)
|
|
*pwdp = ncuridecode(pwd);
|
|
free(user);
|
|
return NC_NOERR;
|
|
}
|
|
|
|
static void
|
|
setdefaults(NCauth* auth)
|
|
{
|
|
int ret = NC_NOERR;
|
|
const char** p;
|
|
for(p=AUTHDEFAULTS;*p;p+=2) {
|
|
ret = setauthfield(auth,p[0],p[1]);
|
|
if(ret) {
|
|
nclog(NCLOGERR, "RC file defaulting failed for: %s=%s",p[0],p[1]);
|
|
}
|
|
}
|
|
}
|
|
|