Coverage Report

Created: 2022-11-18 06:58

/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
NULL
42
};
43
44
/* Forward */
45
static int setauthfield(NCauth* auth, const char* flag, const char* value);
46
static void setdefaults(NCauth*);
47
48
/**************************************************/
49
/* External Entry Points */
50
51
int
52
NC_parseproxy(NCauth* auth, const char* surl)
53
0
{
54
0
    int ret = NC_NOERR;
55
0
    NCURI* uri = NULL;
56
0
    if(surl == NULL || strlen(surl) == 0)
57
0
  return (NC_NOERR); /* nothing there*/
58
0
    if(ncuriparse(surl,&uri))
59
0
  return (NC_EURL);
60
0
    auth->proxy.user = uri->user;
61
0
    auth->proxy.pwd = uri->password;
62
0
    auth->proxy.host = strdup(uri->host);
63
0
    if(uri->port != NULL)
64
0
        auth->proxy.port = atoi(uri->port);
65
0
    else
66
0
        auth->proxy.port = 80;
67
0
    return (ret);
68
0
}
69
70
char*
71
NC_combinehostport(NCURI* uri)
72
0
{
73
0
    size_t len;
74
0
    char* host = NULL;
75
0
    char* port = NULL;
76
0
    char* hp = NULL;
77
0
    if(uri == NULL) return NULL;
78
0
    host = uri->host;
79
0
    port = uri->port;
80
0
    if(uri == NULL || host == NULL) return NULL;
81
0
    if(port != NULL && strlen(port) == 0) port = NULL;
82
0
    len = strlen(host);
83
0
    if(port != NULL) len += (1+strlen(port));
84
0
    hp = (char*)malloc(len+1);
85
0
    if(hp == NULL) return NULL;
86
0
    snprintf(hp, len+1, "%s%s%s", host, port ? ":" : "", port ? port : "");
87
0
    return hp;
88
0
}
89
90
int
91
NC_authsetup(NCauth** authp, NCURI* uri)
92
0
{
93
0
    int ret = NC_NOERR;
94
0
    char* uri_hostport = NULL;
95
0
    NCauth* auth = NULL;
96
97
0
    if(uri != NULL)
98
0
      uri_hostport = NC_combinehostport(uri);
99
0
    else
100
0
      {ret = NC_EDAP; goto done;}  /* Generic EDAP error. */
101
0
    if((auth=calloc(1,sizeof(NCauth)))==NULL)
102
0
        {ret = NC_ENOMEM; goto done;}
103
104
0
    setdefaults(auth);
105
106
    /* Note, we still must do this function even if
107
       ncrc_getglobalstate()->rc.ignore is set in order
108
       to getinfo e.g. host+port  from url
109
    */
110
111
0
    setauthfield(auth,"HTTP.DEFLATE",
112
0
          NC_rclookup("HTTP.DEFLATE",uri_hostport,uri->path));
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
    /* Get the Default profile */
180
0
    auth->s3profile = strdup("default");
181
182
0
    if(authp) {*authp = auth; auth = NULL;}
183
0
done:
184
0
    nullfree(uri_hostport);
185
0
    return (ret);
186
0
}
187
188
void
189
NC_authfree(NCauth* auth)
190
0
{
191
0
    if(auth == NULL) return;
192
0
    if(auth->curlflags.cookiejarcreated) {
193
#ifdef _MSC_VER
194
        DeleteFile(auth->curlflags.cookiejar);
195
#else
196
0
        remove(auth->curlflags.cookiejar);
197
0
#endif
198
0
    }
199
0
    nullfree(auth->curlflags.useragent);
200
0
    nullfree(auth->curlflags.cookiejar);
201
0
    nullfree(auth->curlflags.netrc);
202
0
    nullfree(auth->ssl.certificate);
203
0
    nullfree(auth->ssl.key);
204
0
    nullfree(auth->ssl.keypasswd);
205
0
    nullfree(auth->ssl.cainfo);
206
0
    nullfree(auth->ssl.capath);
207
0
    nullfree(auth->proxy.host);
208
0
    nullfree(auth->proxy.user);
209
0
    nullfree(auth->proxy.pwd);
210
0
    nullfree(auth->creds.user);
211
0
    nullfree(auth->creds.pwd);
212
0
    nullfree(auth->s3profile);
213
0
    nullfree(auth);
214
0
}
215
216
/**************************************************/
217
218
static int
219
setauthfield(NCauth* auth, const char* flag, const char* value)
220
0
{
221
0
    int ret = NC_NOERR;
222
0
    if(value == NULL) goto done;
223
0
    if(strcmp(flag,"HTTP.DEFLATE")==0) {
224
0
        if(atoi(value)) auth->curlflags.compress = 1;
225
#ifdef DEBUG
226
        nclog(NCLOGNOTE,"HTTP.DEFLATE: %ld", (long)auth->curlflags.compress);
227
#endif
228
0
    }
229
0
    if(strcmp(flag,"HTTP.VERBOSE")==0) {
230
0
        if(atoi(value)) auth->curlflags.verbose = 1;
231
#ifdef DEBUG
232
            nclog(NCLOGNOTE,"HTTP.VERBOSE: %ld", (long)auth->curlflags.verbose);
233
#endif
234
0
    }
235
0
    if(strcmp(flag,"HTTP.TIMEOUT")==0) {
236
0
        if(atoi(value)) auth->curlflags.timeout = atoi(value);
237
#ifdef DEBUG
238
            nclog(NCLOGNOTE,"HTTP.TIMEOUT: %ld", (long)auth->curlflags.timeout);
239
#endif
240
0
    }
241
0
    if(strcmp(flag,"HTTP.CONNECTTIMEOUT")==0) {
242
0
        if(atoi(value)) auth->curlflags.connecttimeout = atoi(value);
243
#ifdef DEBUG
244
            nclog(NCLOGNOTE,"HTTP.CONNECTTIMEOUT: %ld", (long)auth->curlflags.connecttimeout);
245
#endif
246
0
    }
247
0
    if(strcmp(flag,"HTTP.USERAGENT")==0) {
248
0
        if(atoi(value)) auth->curlflags.useragent = strdup(value);
249
0
        MEMCHECK(auth->curlflags.useragent);
250
#ifdef DEBUG
251
            nclog(NCLOGNOTE,"HTTP.USERAGENT: %s", auth->curlflags.useragent);
252
#endif
253
0
    }
254
0
    if(
255
0
  strcmp(flag,"HTTP.COOKIEFILE")==0
256
0
        || strcmp(flag,"HTTP.COOKIE_FILE")==0
257
0
        || strcmp(flag,"HTTP.COOKIEJAR")==0
258
0
        || strcmp(flag,"HTTP.COOKIE_JAR")==0
259
0
      ) {
260
0
  nullfree(auth->curlflags.cookiejar);
261
0
        auth->curlflags.cookiejar = strdup(value);
262
0
        MEMCHECK(auth->curlflags.cookiejar);
263
#ifdef DEBUG
264
            nclog(NCLOGNOTE,"HTTP.COOKIEJAR: %s", auth->curlflags.cookiejar);
265
#endif
266
0
    }
267
0
    if(strcmp(flag,"HTTP.PROXY.SERVER")==0 || strcmp(flag,"HTTP.PROXY_SERVER")==0) {
268
0
        ret = NC_parseproxy(auth,value);
269
0
        if(ret != NC_NOERR) goto done;
270
#ifdef DEBUG
271
            nclog(NCLOGNOTE,"HTTP.PROXY.SERVER: %s", value);
272
#endif
273
0
    }
274
0
    if(strcmp(flag,"HTTP.SSL.VERIFYPEER")==0) {
275
0
  int v;
276
0
        if((v = atol(value))) {
277
0
      auth->ssl.verifypeer = v;
278
#ifdef DEBUG
279
                nclog(NCLOGNOTE,"HTTP.SSL.VERIFYPEER: %d", v);
280
#endif
281
0
  }
282
0
    }
283
0
    if(strcmp(flag,"HTTP.SSL.VERIFYHOST")==0) {
284
0
  int v;
285
0
        if((v = atol(value))) {
286
0
      auth->ssl.verifyhost = v;
287
#ifdef DEBUG
288
                nclog(NCLOGNOTE,"HTTP.SSL.VERIFYHOST: %d", v);
289
#endif
290
0
  }
291
0
    }
292
0
    if(strcmp(flag,"HTTP.SSL.VALIDATE")==0) {
293
0
        if(atoi(value)) {
294
0
      auth->ssl.verifypeer = 1;
295
0
      auth->ssl.verifyhost = 2;
296
0
  }
297
0
    }
298
299
0
    if(strcmp(flag,"HTTP.SSL.CERTIFICATE")==0) {
300
0
  nullfree(auth->ssl.certificate);
301
0
        auth->ssl.certificate = strdup(value);
302
0
        MEMCHECK(auth->ssl.certificate);
303
#ifdef DEBUG
304
            nclog(NCLOGNOTE,"HTTP.SSL.CERTIFICATE: %s", auth->ssl.certificate);
305
#endif
306
0
    }
307
308
0
    if(strcmp(flag,"HTTP.SSL.KEY")==0) {
309
0
  nullfree(auth->ssl.key);
310
0
        auth->ssl.key = strdup(value);
311
0
        MEMCHECK(auth->ssl.key);
312
#ifdef DEBUG
313
            nclog(NCLOGNOTE,"HTTP.SSL.KEY: %s", auth->ssl.key);
314
#endif
315
0
    }
316
317
0
    if(strcmp(flag,"HTTP.SSL.KEYPASSWORD")==0) {
318
0
  nullfree(auth->ssl.keypasswd) ;
319
0
        auth->ssl.keypasswd = strdup(value);
320
0
        MEMCHECK(auth->ssl.keypasswd);
321
#ifdef DEBUG
322
            nclog(NCLOGNOTE,"HTTP.SSL.KEYPASSWORD: %s", auth->ssl.keypasswd);
323
#endif
324
0
    }
325
326
0
    if(strcmp(flag,"HTTP.SSL.CAINFO")==0) {
327
0
  nullfree(auth->ssl.cainfo) ;
328
0
        auth->ssl.cainfo = strdup(value);
329
0
        MEMCHECK(auth->ssl.cainfo);
330
#ifdef DEBUG
331
            nclog(NCLOGNOTE,"HTTP.SSL.CAINFO: %s", auth->ssl.cainfo);
332
#endif
333
0
    }
334
335
0
    if(strcmp(flag,"HTTP.SSL.CAPATH")==0) {
336
0
  nullfree(auth->ssl.capath) ;
337
0
        auth->ssl.capath = strdup(value);
338
0
        MEMCHECK(auth->ssl.capath);
339
#ifdef DEBUG
340
            nclog(NCLOGNOTE,"HTTP.SSL.CAPATH: %s", auth->ssl.capath);
341
#endif
342
0
    }
343
0
    if(strcmp(flag,"HTTP.NETRC")==0) {
344
0
        nullfree(auth->curlflags.netrc);
345
0
        auth->curlflags.netrc = strdup(value);
346
0
        MEMCHECK(auth->curlflags.netrc);
347
#ifdef DEBUG
348
            nclog(NCLOGNOTE,"HTTP.NETRC: %s", auth->curlflags.netrc);
349
#endif
350
0
    }
351
352
0
    if(strcmp(flag,"HTTP.CREDENTIALS.USERNAME")==0) {
353
0
        nullfree(auth->creds.user);
354
0
        auth->creds.user = strdup(value);
355
0
        MEMCHECK(auth->creds.user);
356
0
    }
357
0
    if(strcmp(flag,"HTTP.CREDENTIALS.PASSWORD")==0) {
358
0
        nullfree(auth->creds.pwd);
359
0
        auth->creds.pwd = strdup(value);
360
0
        MEMCHECK(auth->creds.pwd);
361
0
    }
362
363
0
done:
364
0
    return (ret);
365
366
0
nomem:
367
0
    return (NC_ENOMEM);
368
0
}
369
370
/*
371
Given form user:pwd, parse into user and pwd
372
and do %xx unescaping
373
*/
374
int
375
NC_parsecredentials(const char* userpwd, char** userp, char** pwdp)
376
0
{
377
0
  char* user = NULL;
378
0
  char* pwd = NULL;
379
380
0
  if(userpwd == NULL)
381
0
  return NC_EINVAL;
382
0
  user = strdup(userpwd);
383
0
  if(user == NULL)
384
0
  return NC_ENOMEM;
385
0
  pwd = strchr(user,':');
386
0
  if(pwd == NULL) {
387
0
    free(user);
388
0
  return NC_EINVAL;
389
0
  }
390
0
  *pwd = '\0';
391
0
  pwd++;
392
0
  if(userp)
393
0
  *userp = ncuridecode(user);
394
0
  if(pwdp)
395
0
  *pwdp = ncuridecode(pwd);
396
0
  free(user);
397
0
  return NC_NOERR;
398
0
}
399
400
static void
401
setdefaults(NCauth* auth)
402
0
{
403
0
    int ret = NC_NOERR;
404
0
    const char** p;
405
0
    for(p=AUTHDEFAULTS;*p;p+=2) {
406
0
  ret = setauthfield(auth,p[0],p[1]);
407
0
  if(ret) {
408
0
            nclog(NCLOGERR, "RC file defaulting failed for: %s=%s",p[0],p[1]);
409
0
  }
410
0
    }
411
0
}