1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 #include "tool_setup.h" 23 24 #include "strcase.h" 25 26 #define ENABLE_CURLX_PRINTF 27 /* use our own printf() functions */ 28 #include "curlx.h" 29 30 #include "tool_cfgable.h" 31 #include "tool_getparam.h" 32 #include "tool_getpass.h" 33 #include "tool_homedir.h" 34 #include "tool_msgs.h" 35 #include "tool_paramhlp.h" 36 #include "tool_version.h" 37 38 #include "memdebug.h" /* keep this as LAST include */ 39 40 struct getout *new_getout(struct OperationConfig *config) 41 { 42 struct getout *node = calloc(1, sizeof(struct getout)); 43 struct getout *last = config->url_last; 44 if(node) { 45 /* append this new node last in the list */ 46 if(last) 47 last->next = node; 48 else 49 config->url_list = node; /* first node */ 50 51 /* move the last pointer */ 52 config->url_last = node; 53 54 node->flags = config->default_node_flags; 55 } 56 return node; 57 } 58 59 ParameterError file2string(char **bufp, FILE *file) 60 { 61 char buffer[256]; 62 char *ptr; 63 char *string = NULL; 64 size_t stringlen = 0; 65 size_t buflen; 66 67 if(file) { 68 while(fgets(buffer, sizeof(buffer), file)) { 69 ptr = strchr(buffer, '\r'); 70 if(ptr) 71 *ptr = '\0'; 72 ptr = strchr(buffer, '\n'); 73 if(ptr) 74 *ptr = '\0'; 75 buflen = strlen(buffer); 76 ptr = realloc(string, stringlen + buflen + 1); 77 if(!ptr) { 78 Curl_safefree(string); 79 return PARAM_NO_MEM; 80 } 81 string = ptr; 82 strcpy(string + stringlen, buffer); 83 stringlen += buflen; 84 } 85 } 86 *bufp = string; 87 return PARAM_OK; 88 } 89 90 ParameterError file2memory(char **bufp, size_t *size, FILE *file) 91 { 92 char *newbuf; 93 char *buffer = NULL; 94 size_t alloc = 512; 95 size_t nused = 0; 96 size_t nread; 97 98 if(file) { 99 do { 100 if(!buffer || (alloc == nused)) { 101 /* size_t overflow detection for huge files */ 102 if(alloc + 1 > ((size_t)-1)/2) { 103 Curl_safefree(buffer); 104 return PARAM_NO_MEM; 105 } 106 alloc *= 2; 107 /* allocate an extra char, reserved space, for null termination */ 108 newbuf = realloc(buffer, alloc + 1); 109 if(!newbuf) { 110 Curl_safefree(buffer); 111 return PARAM_NO_MEM; 112 } 113 buffer = newbuf; 114 } 115 nread = fread(buffer + nused, 1, alloc-nused, file); 116 nused += nread; 117 } while(nread); 118 /* null terminate the buffer in case it's used as a string later */ 119 buffer[nused] = '\0'; 120 /* free trailing slack space, if possible */ 121 if(alloc != nused) { 122 newbuf = realloc(buffer, nused + 1); 123 if(!newbuf) { 124 Curl_safefree(buffer); 125 return PARAM_NO_MEM; 126 } 127 buffer = newbuf; 128 } 129 /* discard buffer if nothing was read */ 130 if(!nused) { 131 Curl_safefree(buffer); /* no string */ 132 } 133 } 134 *size = nused; 135 *bufp = buffer; 136 return PARAM_OK; 137 } 138 139 void cleanarg(char *str) 140 { 141 #ifdef HAVE_WRITABLE_ARGV 142 /* now that GetStr has copied the contents of nextarg, wipe the next 143 * argument out so that the username:password isn't displayed in the 144 * system process list */ 145 if(str) { 146 size_t len = strlen(str); 147 memset(str, ' ', len); 148 } 149 #else 150 (void)str; 151 #endif 152 } 153 154 /* 155 * Parse the string and write the long in the given address. Return PARAM_OK 156 * on success, otherwise a parameter specific error enum. 157 * 158 * Since this function gets called with the 'nextarg' pointer from within the 159 * getparameter a lot, we must check it for NULL before accessing the str 160 * data. 161 */ 162 163 ParameterError str2num(long *val, const char *str) 164 { 165 if(str) { 166 char *endptr; 167 long num; 168 errno = 0; 169 num = strtol(str, &endptr, 10); 170 if(errno == ERANGE) 171 return PARAM_NUMBER_TOO_LARGE; 172 if((endptr != str) && (endptr == str + strlen(str))) { 173 *val = num; 174 return PARAM_OK; /* Ok */ 175 } 176 } 177 return PARAM_BAD_NUMERIC; /* badness */ 178 } 179 180 /* 181 * Parse the string and write the long in the given address. Return PARAM_OK 182 * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS! 183 * 184 * Since this function gets called with the 'nextarg' pointer from within the 185 * getparameter a lot, we must check it for NULL before accessing the str 186 * data. 187 */ 188 189 ParameterError str2unum(long *val, const char *str) 190 { 191 ParameterError result = str2num(val, str); 192 if(result != PARAM_OK) 193 return result; 194 if(*val < 0) 195 return PARAM_NEGATIVE_NUMERIC; 196 197 return PARAM_OK; 198 } 199 200 /* 201 * Parse the string and write the double in the given address. Return PARAM_OK 202 * on success, otherwise a parameter specific error enum. 203 * 204 * The 'max' argument is the maximum value allowed, as the numbers are often 205 * multiplied when later used. 206 * 207 * Since this function gets called with the 'nextarg' pointer from within the 208 * getparameter a lot, we must check it for NULL before accessing the str 209 * data. 210 */ 211 212 static ParameterError str2double(double *val, const char *str, long max) 213 { 214 if(str) { 215 char *endptr; 216 double num; 217 errno = 0; 218 num = strtod(str, &endptr); 219 if(errno == ERANGE) 220 return PARAM_NUMBER_TOO_LARGE; 221 if(num > max) { 222 /* too large */ 223 return PARAM_NUMBER_TOO_LARGE; 224 } 225 if((endptr != str) && (endptr == str + strlen(str))) { 226 *val = num; 227 return PARAM_OK; /* Ok */ 228 } 229 } 230 return PARAM_BAD_NUMERIC; /* badness */ 231 } 232 233 /* 234 * Parse the string and write the double in the given address. Return PARAM_OK 235 * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS! 236 * 237 * The 'max' argument is the maximum value allowed, as the numbers are often 238 * multiplied when later used. 239 * 240 * Since this function gets called with the 'nextarg' pointer from within the 241 * getparameter a lot, we must check it for NULL before accessing the str 242 * data. 243 */ 244 245 ParameterError str2udouble(double *valp, const char *str, long max) 246 { 247 double value; 248 ParameterError result = str2double(&value, str, max); 249 if(result != PARAM_OK) 250 return result; 251 if(value < 0) 252 return PARAM_NEGATIVE_NUMERIC; 253 254 *valp = value; 255 return PARAM_OK; 256 } 257 258 /* 259 * Parse the string and modify the long in the given address. Return 260 * non-zero on failure, zero on success. 261 * 262 * The string is a list of protocols 263 * 264 * Since this function gets called with the 'nextarg' pointer from within the 265 * getparameter a lot, we must check it for NULL before accessing the str 266 * data. 267 */ 268 269 long proto2num(struct OperationConfig *config, long *val, const char *str) 270 { 271 char *buffer; 272 const char *sep = ","; 273 char *token; 274 275 static struct sprotos { 276 const char *name; 277 long bit; 278 } const protos[] = { 279 { "all", CURLPROTO_ALL }, 280 { "http", CURLPROTO_HTTP }, 281 { "https", CURLPROTO_HTTPS }, 282 { "ftp", CURLPROTO_FTP }, 283 { "ftps", CURLPROTO_FTPS }, 284 { "scp", CURLPROTO_SCP }, 285 { "sftp", CURLPROTO_SFTP }, 286 { "telnet", CURLPROTO_TELNET }, 287 { "ldap", CURLPROTO_LDAP }, 288 { "ldaps", CURLPROTO_LDAPS }, 289 { "dict", CURLPROTO_DICT }, 290 { "file", CURLPROTO_FILE }, 291 { "tftp", CURLPROTO_TFTP }, 292 { "imap", CURLPROTO_IMAP }, 293 { "imaps", CURLPROTO_IMAPS }, 294 { "pop3", CURLPROTO_POP3 }, 295 { "pop3s", CURLPROTO_POP3S }, 296 { "smtp", CURLPROTO_SMTP }, 297 { "smtps", CURLPROTO_SMTPS }, 298 { "rtsp", CURLPROTO_RTSP }, 299 { "gopher", CURLPROTO_GOPHER }, 300 { "smb", CURLPROTO_SMB }, 301 { "smbs", CURLPROTO_SMBS }, 302 { NULL, 0 } 303 }; 304 305 if(!str) 306 return 1; 307 308 buffer = strdup(str); /* because strtok corrupts it */ 309 if(!buffer) 310 return 1; 311 312 /* Allow strtok() here since this isn't used threaded */ 313 /* !checksrc! disable BANNEDFUNC 2 */ 314 for(token = strtok(buffer, sep); 315 token; 316 token = strtok(NULL, sep)) { 317 enum e_action { allow, deny, set } action = allow; 318 319 struct sprotos const *pp; 320 321 /* Process token modifiers */ 322 while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */ 323 switch (*token++) { 324 case '=': 325 action = set; 326 break; 327 case '-': 328 action = deny; 329 break; 330 case '+': 331 action = allow; 332 break; 333 default: /* Includes case of terminating NULL */ 334 Curl_safefree(buffer); 335 return 1; 336 } 337 } 338 339 for(pp = protos; pp->name; pp++) { 340 if(curl_strequal(token, pp->name)) { 341 switch(action) { 342 case deny: 343 *val &= ~(pp->bit); 344 break; 345 case allow: 346 *val |= pp->bit; 347 break; 348 case set: 349 *val = pp->bit; 350 break; 351 } 352 break; 353 } 354 } 355 356 if(!(pp->name)) { /* unknown protocol */ 357 /* If they have specified only this protocol, we say treat it as 358 if no protocols are allowed */ 359 if(action == set) 360 *val = 0; 361 warnf(config->global, "unrecognized protocol '%s'\n", token); 362 } 363 } 364 Curl_safefree(buffer); 365 return 0; 366 } 367 368 /** 369 * Check if the given string is a protocol supported by libcurl 370 * 371 * @param str the protocol name 372 * @return PARAM_OK protocol supported 373 * @return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL protocol not supported 374 * @return PARAM_REQUIRES_PARAMETER missing parameter 375 */ 376 int check_protocol(const char *str) 377 { 378 const char * const *pp; 379 const curl_version_info_data *curlinfo = curl_version_info(CURLVERSION_NOW); 380 if(!str) 381 return PARAM_REQUIRES_PARAMETER; 382 for(pp = curlinfo->protocols; *pp; pp++) { 383 if(curl_strequal(*pp, str)) 384 return PARAM_OK; 385 } 386 return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL; 387 } 388 389 /** 390 * Parses the given string looking for an offset (which may be a 391 * larger-than-integer value). The offset CANNOT be negative! 392 * 393 * @param val the offset to populate 394 * @param str the buffer containing the offset 395 * @return PARAM_OK if successful, a parameter specific error enum if failure. 396 */ 397 ParameterError str2offset(curl_off_t *val, const char *str) 398 { 399 char *endptr; 400 if(str[0] == '-') 401 /* offsets aren't negative, this indicates weird input */ 402 return PARAM_NEGATIVE_NUMERIC; 403 404 #if(SIZEOF_CURL_OFF_T > SIZEOF_LONG) 405 { 406 CURLofft offt = curlx_strtoofft(str, &endptr, 0, val); 407 if(CURL_OFFT_FLOW == offt) 408 return PARAM_NUMBER_TOO_LARGE; 409 else if(CURL_OFFT_INVAL == offt) 410 return PARAM_BAD_NUMERIC; 411 } 412 #else 413 errno = 0; 414 *val = strtol(str, &endptr, 0); 415 if((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE) 416 return PARAM_NUMBER_TOO_LARGE; 417 #endif 418 if((endptr != str) && (endptr == str + strlen(str))) 419 return PARAM_OK; 420 421 return PARAM_BAD_NUMERIC; 422 } 423 424 static CURLcode checkpasswd(const char *kind, /* for what purpose */ 425 const size_t i, /* operation index */ 426 const bool last, /* TRUE if last operation */ 427 char **userpwd) /* pointer to allocated string */ 428 { 429 char *psep; 430 char *osep; 431 432 if(!*userpwd) 433 return CURLE_OK; 434 435 /* Attempt to find the password separator */ 436 psep = strchr(*userpwd, ':'); 437 438 /* Attempt to find the options separator */ 439 osep = strchr(*userpwd, ';'); 440 441 if(!psep && **userpwd != ';') { 442 /* no password present, prompt for one */ 443 char passwd[256] = ""; 444 char prompt[256]; 445 size_t passwdlen; 446 size_t userlen = strlen(*userpwd); 447 char *passptr; 448 449 if(osep) 450 *osep = '\0'; 451 452 /* build a nice-looking prompt */ 453 if(!i && last) 454 curlx_msnprintf(prompt, sizeof(prompt), 455 "Enter %s password for user '%s':", 456 kind, *userpwd); 457 else 458 curlx_msnprintf(prompt, sizeof(prompt), 459 "Enter %s password for user '%s' on URL #%" 460 CURL_FORMAT_CURL_OFF_TU ":", 461 kind, *userpwd, (curl_off_t) (i + 1)); 462 463 /* get password */ 464 getpass_r(prompt, passwd, sizeof(passwd)); 465 passwdlen = strlen(passwd); 466 467 if(osep) 468 *osep = ';'; 469 470 /* extend the allocated memory area to fit the password too */ 471 passptr = realloc(*userpwd, 472 passwdlen + 1 + /* an extra for the colon */ 473 userlen + 1); /* an extra for the zero */ 474 if(!passptr) 475 return CURLE_OUT_OF_MEMORY; 476 477 /* append the password separated with a colon */ 478 passptr[userlen] = ':'; 479 memcpy(&passptr[userlen + 1], passwd, passwdlen + 1); 480 *userpwd = passptr; 481 } 482 483 return CURLE_OK; 484 } 485 486 ParameterError add2list(struct curl_slist **list, const char *ptr) 487 { 488 struct curl_slist *newlist = curl_slist_append(*list, ptr); 489 if(newlist) 490 *list = newlist; 491 else 492 return PARAM_NO_MEM; 493 494 return PARAM_OK; 495 } 496 497 int ftpfilemethod(struct OperationConfig *config, const char *str) 498 { 499 if(curl_strequal("singlecwd", str)) 500 return CURLFTPMETHOD_SINGLECWD; 501 if(curl_strequal("nocwd", str)) 502 return CURLFTPMETHOD_NOCWD; 503 if(curl_strequal("multicwd", str)) 504 return CURLFTPMETHOD_MULTICWD; 505 506 warnf(config->global, "unrecognized ftp file method '%s', using default\n", 507 str); 508 509 return CURLFTPMETHOD_MULTICWD; 510 } 511 512 int ftpcccmethod(struct OperationConfig *config, const char *str) 513 { 514 if(curl_strequal("passive", str)) 515 return CURLFTPSSL_CCC_PASSIVE; 516 if(curl_strequal("active", str)) 517 return CURLFTPSSL_CCC_ACTIVE; 518 519 warnf(config->global, "unrecognized ftp CCC method '%s', using default\n", 520 str); 521 522 return CURLFTPSSL_CCC_PASSIVE; 523 } 524 525 long delegation(struct OperationConfig *config, char *str) 526 { 527 if(curl_strequal("none", str)) 528 return CURLGSSAPI_DELEGATION_NONE; 529 if(curl_strequal("policy", str)) 530 return CURLGSSAPI_DELEGATION_POLICY_FLAG; 531 if(curl_strequal("always", str)) 532 return CURLGSSAPI_DELEGATION_FLAG; 533 534 warnf(config->global, "unrecognized delegation method '%s', using none\n", 535 str); 536 537 return CURLGSSAPI_DELEGATION_NONE; 538 } 539 540 /* 541 * my_useragent: returns allocated string with default user agent 542 */ 543 static char *my_useragent(void) 544 { 545 return strdup(CURL_NAME "/" CURL_VERSION); 546 } 547 548 CURLcode get_args(struct OperationConfig *config, const size_t i) 549 { 550 CURLcode result = CURLE_OK; 551 bool last = (config->next ? FALSE : TRUE); 552 553 /* Check we have a password for the given host user */ 554 if(config->userpwd && !config->oauth_bearer) { 555 result = checkpasswd("host", i, last, &config->userpwd); 556 if(result) 557 return result; 558 } 559 560 /* Check we have a password for the given proxy user */ 561 if(config->proxyuserpwd) { 562 result = checkpasswd("proxy", i, last, &config->proxyuserpwd); 563 if(result) 564 return result; 565 } 566 567 /* Check we have a user agent */ 568 if(!config->useragent) { 569 config->useragent = my_useragent(); 570 if(!config->useragent) { 571 helpf(config->global->errors, "out of memory\n"); 572 result = CURLE_OUT_OF_MEMORY; 573 } 574 } 575 576 return result; 577 } 578 579 /* 580 * Parse the string and modify ssl_version in the val argument. Return PARAM_OK 581 * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS! 582 * 583 * Since this function gets called with the 'nextarg' pointer from within the 584 * getparameter a lot, we must check it for NULL before accessing the str 585 * data. 586 */ 587 588 ParameterError str2tls_max(long *val, const char *str) 589 { 590 static struct s_tls_max { 591 const char *tls_max_str; 592 long tls_max; 593 } const tls_max_array[] = { 594 { "default", CURL_SSLVERSION_MAX_DEFAULT }, 595 { "1.0", CURL_SSLVERSION_MAX_TLSv1_0 }, 596 { "1.1", CURL_SSLVERSION_MAX_TLSv1_1 }, 597 { "1.2", CURL_SSLVERSION_MAX_TLSv1_2 }, 598 { "1.3", CURL_SSLVERSION_MAX_TLSv1_3 } 599 }; 600 size_t i = 0; 601 if(!str) 602 return PARAM_REQUIRES_PARAMETER; 603 for(i = 0; i < sizeof(tls_max_array)/sizeof(tls_max_array[0]); i++) { 604 if(!strcmp(str, tls_max_array[i].tls_max_str)) { 605 *val = tls_max_array[i].tls_max; 606 return PARAM_OK; 607 } 608 } 609 return PARAM_BAD_USE; 610 } 611