1 /*
2 Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
3 See COPYRIGHT for license information.
4 */
5
6
7 #include "config.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #ifdef HAVE_UNISTD_H
12 #include <unistd.h>
13 #endif
14 #ifdef HAVE_STDARG_H
15 #include <stdarg.h>
16 #endif
17 #include "netcdf.h"
18 #include "ncbytes.h"
19 #include "ncuri.h"
20 #include "ncauth.h"
21 #include "nclog.h"
22 #include "ncwinpath.h"
23
24 #ifdef _MSC_VER
25 #include <windows.h>
26 #endif
27
28 #undef MEMCHECK
29 #define MEMCHECK(x) if((x)==NULL) {goto nomem;} else {}
30
31 /* Define the curl flag defaults in envv style */
32 static const char* AUTHDEFAULTS[] = {
33 "HTTP.TIMEOUT","1800", /*seconds */ /* Long but not infinite */
34 "HTTP.CONNECTTIMEOUT","50", /*seconds */ /* Long but not infinite */
35 NULL
36 };
37
38 /* Forward */
39 static int setauthfield(NCauth* auth, const char* flag, const char* value);
40 static void setdefaults(NCauth*);
41
42 /**************************************************/
43 /* External Entry Points */
44
45 int
NC_parseproxy(NCauth * auth,const char * surl)46 NC_parseproxy(NCauth* auth, const char* surl)
47 {
48 int ret = NC_NOERR;
49 NCURI* uri = NULL;
50 if(surl == NULL || strlen(surl) == 0)
51 return (NC_NOERR); /* nothing there*/
52 if(ncuriparse(surl,&uri))
53 return (NC_EURL);
54 auth->proxy.user = uri->user;
55 auth->proxy.pwd = uri->password;
56 auth->proxy.host = strdup(uri->host);
57 if(uri->port != NULL)
58 auth->proxy.port = atoi(uri->port);
59 else
60 auth->proxy.port = 80;
61 return (ret);
62 }
63
64 char*
NC_combinehostport(NCURI * uri)65 NC_combinehostport(NCURI* uri)
66 {
67 size_t len;
68 char* host = NULL;
69 char* port = NULL;
70 char* hp = NULL;
71 if(uri == NULL) return NULL;
72 host = uri->host;
73 port = uri->port;
74 if(uri == NULL || host == NULL) return NULL;
75 if(port != NULL && strlen(port) == 0) port = NULL;
76 len = strlen(host);
77 if(port != NULL) len += (1+strlen(port));
78 hp = (char*)malloc(len+1);
79 if(hp == NULL) return NULL;
80 strncpy(hp,host,len);
81 if(port != NULL) {
82 strncat(hp,":",len);
83 strncat(hp,port,len);
84 }
85 return hp;
86 }
87
88 int
NC_authsetup(NCauth * auth,NCURI * uri)89 NC_authsetup(NCauth* auth, NCURI* uri)
90 {
91 int ret = NC_NOERR;
92 char* uri_hostport = NULL;
93
94 if(uri != NULL)
95 uri_hostport = NC_combinehostport(uri);
96 else
97 return NC_EDAP; /* Generic EDAP error. */
98 setdefaults(auth);
99
100 /* Note, we still must do this function even if
101 ncrc_getglobalstate()->rc.ignore is set in order
102 to getinfo e.g. host+port from url
103 */
104
105 setauthfield(auth,"HTTP.DEFLATE",
106 NC_rclookup("HTTP.DEFLATE",uri_hostport));
107 setauthfield(auth,"HTTP.VERBOSE",
108 NC_rclookup("HTTP.VERBOSE",uri_hostport));
109 setauthfield(auth,"HTTP.TIMEOUT",
110 NC_rclookup("HTTP.TIMEOUT",uri_hostport));
111 setauthfield(auth,"HTTP.CONNECTTIMEOUT",
112 NC_rclookup("HTTP.CONNECTTIMEOUT",uri_hostport));
113 setauthfield(auth,"HTTP.USERAGENT",
114 NC_rclookup("HTTP.USERAGENT",uri_hostport));
115 setauthfield(auth,"HTTP.COOKIEFILE",
116 NC_rclookup("HTTP.COOKIEFILE",uri_hostport));
117 setauthfield(auth,"HTTP.COOKIE_FILE",
118 NC_rclookup("HTTP.COOKIE_FILE",uri_hostport));
119 setauthfield(auth,"HTTP.COOKIEJAR",
120 NC_rclookup("HTTP.COOKIEJAR",uri_hostport));
121 setauthfield(auth,"HTTP.COOKIE_JAR",
122 NC_rclookup("HTTP.COOKIE_JAR",uri_hostport));
123 setauthfield(auth,"HTTP.PROXY.SERVER",
124 NC_rclookup("HTTP.PROXY.SERVER",uri_hostport));
125 setauthfield(auth,"HTTP.PROXY_SERVER",
126 NC_rclookup("HTTP.PROXY_SERVER",uri_hostport));
127 setauthfield(auth,"HTTP.SSL.VALIDATE",
128 NC_rclookup("HTTP.SSL.VALIDATE",uri_hostport));
129 setauthfield(auth,"HTTP.SSL.CERTIFICATE",
130 NC_rclookup("HTTP.SSL.CERTIFICATE",uri_hostport));
131 setauthfield(auth,"HTTP.SSL.KEY",
132 NC_rclookup("HTTP.SSL.KEY",uri_hostport));
133 setauthfield(auth,"HTTP.SSL.KEYPASSWORD",
134 NC_rclookup("HTTP.SSL.KEYPASSWORD",uri_hostport));
135 setauthfield(auth,"HTTP.SSL.CAINFO",
136 NC_rclookup("HTTP.SSL.CAINFO",uri_hostport));
137 setauthfield(auth,"HTTP.SSL.CAPATH",
138 NC_rclookup("HTTP.SSL.CAPATH",uri_hostport));
139 setauthfield(auth,"HTTP.SSL.VERIFYPEER",
140 NC_rclookup("HTTP.SSL.VERIFYPEER",uri_hostport));
141 setauthfield(auth,"HTTP.NETRC",
142 NC_rclookup("HTTP.NETRC",uri_hostport));
143
144 { /* Handle various cases for user + password */
145 /* First, see if the user+pwd was in the original url */
146 char* user = NULL;
147 char* pwd = NULL;
148 if(uri->user != NULL && uri->password != NULL) {
149 user = uri->user;
150 pwd = uri->password;
151 } else {
152 user = NC_rclookup("HTTP.CREDENTIALS.USER",uri_hostport);
153 pwd = NC_rclookup("HTTP.CREDENTIALS.PASSWORD",uri_hostport);
154 }
155 if(user != NULL && pwd != NULL) {
156 user = strdup(user); /* so we can consistently reclaim */
157 pwd = strdup(pwd);
158 } else {
159 /* Could not get user and pwd, so try USERPASSWORD */
160 const char* userpwd = NC_rclookup("HTTP.CREDENTIALS.USERPASSWORD",uri_hostport);
161 if(userpwd != NULL) {
162 ret = NC_parsecredentials(userpwd,&user,&pwd);
163 if(ret) {nullfree(uri_hostport); return ret;}
164 }
165 }
166 setauthfield(auth,"HTTP.CREDENTIALS.USERNAME",user);
167 setauthfield(auth,"HTTP.CREDENTIALS.PASSWORD",pwd);
168 nullfree(user);
169 nullfree(pwd);
170 nullfree(uri_hostport);
171 }
172 return (ret);
173 }
174
175 void
NC_authclear(NCauth * auth)176 NC_authclear(NCauth* auth)
177 {
178 if(auth->curlflags.cookiejarcreated) {
179 #ifdef _MSC_VER
180 DeleteFile(auth->curlflags.cookiejar);
181 #else
182 remove(auth->curlflags.cookiejar);
183 #endif
184 }
185 nullfree(auth->curlflags.useragent);
186 nullfree(auth->curlflags.cookiejar);
187 nullfree(auth->curlflags.netrc);
188 nullfree(auth->ssl.certificate);
189 nullfree(auth->ssl.key);
190 nullfree(auth->ssl.keypasswd);
191 nullfree(auth->ssl.cainfo);
192 nullfree(auth->ssl.capath);
193 nullfree(auth->proxy.host);
194 nullfree(auth->proxy.user);
195 nullfree(auth->proxy.pwd);
196 nullfree(auth->creds.user);
197 nullfree(auth->creds.pwd);
198 }
199
200 /**************************************************/
201
202 static int
setauthfield(NCauth * auth,const char * flag,const char * value)203 setauthfield(NCauth* auth, const char* flag, const char* value)
204 {
205 int ret = NC_NOERR;
206 if(value == NULL) goto done;
207 if(strcmp(flag,"HTTP.DEFLATE")==0) {
208 if(atoi(value)) auth->curlflags.compress = 1;
209 #ifdef D4DEBUG
210 nclog(NCLOGNOTE,"HTTP.DEFLATE: %ld", infoflags.compress);
211 #endif
212 }
213 if(strcmp(flag,"HTTP.VERBOSE")==0) {
214 if(atoi(value)) auth->curlflags.verbose = 1;
215 #ifdef D4DEBUG
216 nclog(NCLOGNOTE,"HTTP.VERBOSE: %ld", auth->curlflags.verbose);
217 #endif
218 }
219 if(strcmp(flag,"HTTP.TIMEOUT")==0) {
220 if(atoi(value)) auth->curlflags.timeout = atoi(value);
221 #ifdef D4DEBUG
222 nclog(NCLOGNOTE,"HTTP.TIMEOUT: %ld", auth->curlflags.timeout);
223 #endif
224 }
225 if(strcmp(flag,"HTTP.CONNECTTIMEOUT")==0) {
226 if(atoi(value)) auth->curlflags.connecttimeout = atoi(value);
227 #ifdef D4DEBUG
228 nclog(NCLOGNOTE,"HTTP.CONNECTTIMEOUT: %ld", auth->curlflags.connecttimeout);
229 #endif
230 }
231 if(strcmp(flag,"HTTP.USERAGENT")==0) {
232 if(atoi(value)) auth->curlflags.useragent = strdup(value);
233 MEMCHECK(auth->curlflags.useragent);
234 #ifdef D4DEBUG
235 nclog(NCLOGNOTE,"HTTP.USERAGENT: %s", auth->curlflags.useragent);
236 #endif
237 }
238 if(
239 strcmp(flag,"HTTP.COOKIEFILE")==0
240 || strcmp(flag,"HTTP.COOKIE_FILE")==0
241 || strcmp(flag,"HTTP.COOKIEJAR")==0
242 || strcmp(flag,"HTTP.COOKIE_JAR")==0
243 ) {
244 nullfree(auth->curlflags.cookiejar);
245 auth->curlflags.cookiejar = strdup(value);
246 MEMCHECK(auth->curlflags.cookiejar);
247 #ifdef D4DEBUG
248 nclog(NCLOGNOTE,"HTTP.COOKIEJAR: %s", auth->curlflags.cookiejar);
249 #endif
250 }
251 if(strcmp(flag,"HTTP.PROXY.SERVER")==0 || strcmp(flag,"HTTP.PROXY_SERVER")==0) {
252 ret = NC_parseproxy(auth,value);
253 if(ret != NC_NOERR) goto done;
254 #ifdef D4DEBUG
255 nclog(NCLOGNOTE,"HTTP.PROXY.SERVER: %s", value);
256 #endif
257 }
258 if(strcmp(flag,"HTTP.SSL.VALIDATE")==0) {
259 if(atoi(value)) {
260 auth->ssl.verifypeer = 1;
261 auth->ssl.verifyhost = 1;
262 #ifdef D4DEBUG
263 nclog(NCLOGNOTE,"HTTP.SSL.VALIDATE: %ld", 1);
264 #endif
265 }
266 }
267
268 if(strcmp(flag,"HTTP.SSL.CERTIFICATE")==0) {
269 nullfree(auth->ssl.certificate);
270 auth->ssl.certificate = strdup(value);
271 MEMCHECK(auth->ssl.certificate);
272 #ifdef D4DEBUG
273 nclog(NCLOGNOTE,"HTTP.SSL.CERTIFICATE: %s", auth->ssl.certificate);
274 #endif
275 }
276
277 if(strcmp(flag,"HTTP.SSL.KEY")==0) {
278 nullfree(auth->ssl.key);
279 auth->ssl.key = strdup(value);
280 MEMCHECK(auth->ssl.key);
281 #ifdef D4DEBUG
282 nclog(NCLOGNOTE,"HTTP.SSL.KEY: %s", auth->ssl.key);
283 #endif
284 }
285
286 if(strcmp(flag,"HTTP.SSL.KEYPASSWORD")==0) {
287 nullfree(auth->ssl.keypasswd) ;
288 auth->ssl.keypasswd = strdup(value);
289 MEMCHECK(auth->ssl.keypasswd);
290 #ifdef D4DEBUG
291 nclog(NCLOGNOTE,"HTTP.SSL.KEYPASSWORD: %s", auth->ssl.keypasswd);
292 #endif
293 }
294
295 if(strcmp(flag,"HTTP.SSL.CAINFO")==0) {
296 nullfree(auth->ssl.cainfo) ;
297 auth->ssl.cainfo = strdup(value);
298 MEMCHECK(auth->ssl.cainfo);
299 #ifdef D4DEBUG
300 nclog(NCLOGNOTE,"HTTP.SSL.CAINFO: %s", auth->ssl.cainfo);
301 #endif
302 }
303
304 if(strcmp(flag,"HTTP.SSL.CAPATH")==0) {
305 nullfree(auth->ssl.capath) ;
306 auth->ssl.capath = strdup(value);
307 MEMCHECK(auth->ssl.capath);
308 #ifdef D4DEBUG
309 nclog(NCLOGNOTE,"HTTP.SSL.CAPATH: %s", auth->ssl.capath);
310 #endif
311 }
312
313 if(strcmp(flag,"HTTP.SSL.VERIFYPEER")==0) {
314 const char* s = value;
315 int tf = 0;
316 if(s == NULL || strcmp(s,"0")==0 || strcasecmp(s,"false")==0)
317 tf = 0;
318 else if(strcmp(s,"1")==0 || strcasecmp(s,"true")==0)
319 tf = 1;
320 else
321 tf = 1; /* default if not null */
322 auth->ssl.verifypeer = tf;
323 #ifdef D4DEBUG
324 nclog(NCLOGNOTE,"HTTP.SSL.VERIFYPEER: %d", auth->ssl.verifypeer);
325 #endif
326 }
327
328 if(strcmp(flag,"HTTP.NETRC")==0) {
329 nullfree(auth->curlflags.netrc);
330 auth->curlflags.netrc = strdup(value);
331 MEMCHECK(auth->curlflags.netrc);
332 #ifdef D4DEBUG
333 nclog(NCLOGNOTE,"HTTP.NETRC: %s", auth->curlflags.netrc);
334 #endif
335 }
336
337 if(strcmp(flag,"HTTP.CREDENTIALS.USERNAME")==0) {
338 nullfree(auth->creds.user);
339 auth->creds.user = strdup(value);
340 MEMCHECK(auth->creds.user);
341 }
342 if(strcmp(flag,"HTTP.CREDENTIALS.PASSWORD")==0) {
343 nullfree(auth->creds.pwd);
344 auth->creds.pwd = strdup(value);
345 MEMCHECK(auth->creds.pwd);
346 }
347
348 done:
349 return (ret);
350
351 nomem:
352 return (NC_ENOMEM);
353 }
354
355 /*
356 Given form user:pwd, parse into user and pwd
357 and do %xx unescaping
358 */
359 int
NC_parsecredentials(const char * userpwd,char ** userp,char ** pwdp)360 NC_parsecredentials(const char* userpwd, char** userp, char** pwdp)
361 {
362 char* user = NULL;
363 char* pwd = NULL;
364
365 if(userpwd == NULL)
366 return NC_EINVAL;
367 user = strdup(userpwd);
368 if(user == NULL)
369 return NC_ENOMEM;
370 pwd = strchr(user,':');
371 if(pwd == NULL) {
372 free(user);
373 return NC_EINVAL;
374 }
375 *pwd = '\0';
376 pwd++;
377 if(userp)
378 *userp = ncuridecode(user);
379 if(pwdp)
380 *pwdp = ncuridecode(pwd);
381 free(user);
382 return NC_NOERR;
383 }
384
385 static void
setdefaults(NCauth * auth)386 setdefaults(NCauth* auth)
387 {
388 int ret = NC_NOERR;
389 const char** p;
390 for(p=AUTHDEFAULTS;*p;p+=2) {
391 ret = setauthfield(auth,p[0],p[1]);
392 if(ret) {
393 nclog(NCLOGERR, "RC file defaulting failed for: %s=%s",p[0],p[1]);
394 }
395 }
396 }
397