Coverage Report

Created: 2025-10-28 07:06

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