1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
22 #include "tool_setup.h"
26 #define ENABLE_CURLX_PRINTF
27 /* use our own printf() functions */
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"
38 #include "memdebug.h" /* keep this as LAST include */
40 struct getout *new_getout(struct OperationConfig *config)
42 struct getout *node = calloc(1, sizeof(struct getout));
43 struct getout *last = config->url_last;
45 /* append this new node last in the list */
49 config->url_list = node; /* first node */
51 /* move the last pointer */
52 config->url_last = node;
54 node->flags = config->default_node_flags;
59 ParameterError file2string(char **bufp, FILE *file)
68 while(fgets(buffer, sizeof(buffer), file)) {
69 ptr = strchr(buffer, '\r');
72 ptr = strchr(buffer, '\n');
75 buflen = strlen(buffer);
76 ptr = realloc(string, stringlen + buflen + 1);
78 Curl_safefree(string);
82 strcpy(string + stringlen, buffer);
90 ParameterError file2memory(char **bufp, size_t *size, FILE *file)
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);
107 /* allocate an extra char, reserved space, for null termination */
108 newbuf = realloc(buffer, alloc + 1);
110 Curl_safefree(buffer);
115 nread = fread(buffer + nused, 1, alloc-nused, file);
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 */
122 newbuf = realloc(buffer, nused + 1);
124 Curl_safefree(buffer);
129 /* discard buffer if nothing was read */
131 Curl_safefree(buffer); /* no string */
139 void cleanarg(char *str)
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 */
146 size_t len = strlen(str);
147 memset(str, ' ', len);
155 * Parse the string and write the long in the given address. Return PARAM_OK
156 * on success, otherwise a parameter specific error enum.
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
163 ParameterError str2num(long *val, const char *str)
169 num = strtol(str, &endptr, 10);
171 return PARAM_NUMBER_TOO_LARGE;
172 if((endptr != str) && (endptr == str + strlen(str))) {
174 return PARAM_OK; /* Ok */
177 return PARAM_BAD_NUMERIC; /* badness */
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!
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
189 ParameterError str2unum(long *val, const char *str)
191 ParameterError result = str2num(val, str);
192 if(result != PARAM_OK)
195 return PARAM_NEGATIVE_NUMERIC;
201 * Parse the string and write the double in the given address. Return PARAM_OK
202 * on success, otherwise a parameter specific error enum.
204 * The 'max' argument is the maximum value allowed, as the numbers are often
205 * multiplied when later used.
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
212 static ParameterError str2double(double *val, const char *str, long max)
218 num = strtod(str, &endptr);
220 return PARAM_NUMBER_TOO_LARGE;
223 return PARAM_NUMBER_TOO_LARGE;
225 if((endptr != str) && (endptr == str + strlen(str))) {
227 return PARAM_OK; /* Ok */
230 return PARAM_BAD_NUMERIC; /* badness */
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!
237 * The 'max' argument is the maximum value allowed, as the numbers are often
238 * multiplied when later used.
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
245 ParameterError str2udouble(double *valp, const char *str, long max)
248 ParameterError result = str2double(&value, str, max);
249 if(result != PARAM_OK)
252 return PARAM_NEGATIVE_NUMERIC;
259 * Parse the string and modify the long in the given address. Return
260 * non-zero on failure, zero on success.
262 * The string is a list of protocols
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
269 long proto2num(struct OperationConfig *config, long *val, const char *str)
272 const char *sep = ",";
275 static struct sprotos {
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 },
308 buffer = strdup(str); /* because strtok corrupts it */
312 /* Allow strtok() here since this isn't used threaded */
313 /* !checksrc! disable BANNEDFUNC 2 */
314 for(token = strtok(buffer, sep);
316 token = strtok(NULL, sep)) {
317 enum e_action { allow, deny, set } action = allow;
319 struct sprotos const *pp;
321 /* Process token modifiers */
322 while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
333 default: /* Includes case of terminating NULL */
334 Curl_safefree(buffer);
339 for(pp = protos; pp->name; pp++) {
340 if(curl_strequal(token, pp->name)) {
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 */
361 warnf(config->global, "unrecognized protocol '%s'\n", token);
364 Curl_safefree(buffer);
369 * Check if the given string is a protocol supported by libcurl
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
376 int check_protocol(const char *str)
378 const char * const *pp;
379 const curl_version_info_data *curlinfo = curl_version_info(CURLVERSION_NOW);
381 return PARAM_REQUIRES_PARAMETER;
382 for(pp = curlinfo->protocols; *pp; pp++) {
383 if(curl_strequal(*pp, str))
386 return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL;
390 * Parses the given string looking for an offset (which may be a
391 * larger-than-integer value). The offset CANNOT be negative!
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.
397 ParameterError str2offset(curl_off_t *val, const char *str)
401 /* offsets aren't negative, this indicates weird input */
402 return PARAM_NEGATIVE_NUMERIC;
404 #if(SIZEOF_CURL_OFF_T > SIZEOF_LONG)
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;
414 *val = strtol(str, &endptr, 0);
415 if((*val == LONG_MIN || *val == LONG_MAX) && errno == ERANGE)
416 return PARAM_NUMBER_TOO_LARGE;
418 if((endptr != str) && (endptr == str + strlen(str)))
421 return PARAM_BAD_NUMERIC;
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 */
435 /* Attempt to find the password separator */
436 psep = strchr(*userpwd, ':');
438 /* Attempt to find the options separator */
439 osep = strchr(*userpwd, ';');
441 if(!psep && **userpwd != ';') {
442 /* no password present, prompt for one */
443 char passwd[256] = "";
446 size_t userlen = strlen(*userpwd);
452 /* build a nice-looking prompt */
454 curlx_msnprintf(prompt, sizeof(prompt),
455 "Enter %s password for user '%s':",
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));
464 getpass_r(prompt, passwd, sizeof(passwd));
465 passwdlen = strlen(passwd);
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 */
475 return CURLE_OUT_OF_MEMORY;
477 /* append the password separated with a colon */
478 passptr[userlen] = ':';
479 memcpy(&passptr[userlen + 1], passwd, passwdlen + 1);
486 ParameterError add2list(struct curl_slist **list, const char *ptr)
488 struct curl_slist *newlist = curl_slist_append(*list, ptr);
497 int ftpfilemethod(struct OperationConfig *config, const char *str)
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;
506 warnf(config->global, "unrecognized ftp file method '%s', using default\n",
509 return CURLFTPMETHOD_MULTICWD;
512 int ftpcccmethod(struct OperationConfig *config, const char *str)
514 if(curl_strequal("passive", str))
515 return CURLFTPSSL_CCC_PASSIVE;
516 if(curl_strequal("active", str))
517 return CURLFTPSSL_CCC_ACTIVE;
519 warnf(config->global, "unrecognized ftp CCC method '%s', using default\n",
522 return CURLFTPSSL_CCC_PASSIVE;
525 long delegation(struct OperationConfig *config, char *str)
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;
534 warnf(config->global, "unrecognized delegation method '%s', using none\n",
537 return CURLGSSAPI_DELEGATION_NONE;
541 * my_useragent: returns allocated string with default user agent
543 static char *my_useragent(void)
545 return strdup(CURL_NAME "/" CURL_VERSION);
548 CURLcode get_args(struct OperationConfig *config, const size_t i)
550 CURLcode result = CURLE_OK;
551 bool last = (config->next ? FALSE : TRUE);
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);
560 /* Check we have a password for the given proxy user */
561 if(config->proxyuserpwd) {
562 result = checkpasswd("proxy", i, last, &config->proxyuserpwd);
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;
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!
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
588 ParameterError str2tls_max(long *val, const char *str)
590 static struct s_tls_max {
591 const char *tls_max_str;
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 }
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;
609 return PARAM_BAD_USE;