Coverage Report

Created: 2023-05-28 06:42

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