curl_path.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <[email protected]>, 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.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. * SPDX-License-Identifier: curl AND ISC
  22. *
  23. ***************************************************************************/
  24. #include "../curl_setup.h"
  25. #ifdef USE_SSH
  26. #include "curl_path.h"
  27. #include <curl/curl.h>
  28. #include "../curlx/strparse.h"
  29. #include "../curl_memory.h"
  30. #include "../escape.h"
  31. #include "../memdebug.h"
  32. #define MAX_SSHPATH_LEN 100000 /* arbitrary */
  33. /* figure out the path to work with in this particular request */
  34. CURLcode Curl_getworkingpath(struct Curl_easy *data,
  35. char *homedir, /* when SFTP is used */
  36. char **path) /* returns the allocated
  37. real path to work with */
  38. {
  39. char *working_path;
  40. size_t working_path_len;
  41. struct dynbuf npath;
  42. CURLcode result =
  43. Curl_urldecode(data->state.up.path, 0, &working_path,
  44. &working_path_len, REJECT_ZERO);
  45. if(result)
  46. return result;
  47. /* new path to switch to in case we need to */
  48. curlx_dyn_init(&npath, MAX_SSHPATH_LEN);
  49. /* Check for /~/, indicating relative to the user's home directory */
  50. if((data->conn->handler->protocol & CURLPROTO_SCP) &&
  51. (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) {
  52. /* It is referenced to the home directory, so strip the leading '/~/' */
  53. if(curlx_dyn_addn(&npath, &working_path[3], working_path_len - 3)) {
  54. free(working_path);
  55. return CURLE_OUT_OF_MEMORY;
  56. }
  57. }
  58. else if((data->conn->handler->protocol & CURLPROTO_SFTP) &&
  59. (!strcmp("/~", working_path) ||
  60. ((working_path_len > 2) && !memcmp(working_path, "/~/", 3)))) {
  61. if(curlx_dyn_add(&npath, homedir)) {
  62. free(working_path);
  63. return CURLE_OUT_OF_MEMORY;
  64. }
  65. if(working_path_len > 2) {
  66. size_t len;
  67. const char *p;
  68. int copyfrom = 3;
  69. /* Copy a separating '/' if homedir does not end with one */
  70. len = curlx_dyn_len(&npath);
  71. p = curlx_dyn_ptr(&npath);
  72. if(len && (p[len-1] != '/'))
  73. copyfrom = 2;
  74. if(curlx_dyn_addn(&npath, &working_path[copyfrom],
  75. working_path_len - copyfrom)) {
  76. free(working_path);
  77. return CURLE_OUT_OF_MEMORY;
  78. }
  79. }
  80. else {
  81. if(curlx_dyn_add(&npath, "/")) {
  82. free(working_path);
  83. return CURLE_OUT_OF_MEMORY;
  84. }
  85. }
  86. }
  87. if(curlx_dyn_len(&npath)) {
  88. free(working_path);
  89. /* store the pointer for the caller to receive */
  90. *path = curlx_dyn_ptr(&npath);
  91. }
  92. else
  93. *path = working_path;
  94. DEBUGASSERT(*path && (*path)[0]);
  95. return CURLE_OK;
  96. }
  97. #define MAX_PATHLENGTH 65535 /* arbitrary long */
  98. CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir)
  99. {
  100. const char *cp = *cpp;
  101. struct dynbuf out;
  102. CURLcode result;
  103. DEBUGASSERT(homedir);
  104. *path = NULL;
  105. *cpp = NULL;
  106. if(!*cp || !homedir)
  107. return CURLE_QUOTE_ERROR;
  108. curlx_dyn_init(&out, MAX_PATHLENGTH);
  109. /* Ignore leading whitespace */
  110. curlx_str_passblanks(&cp);
  111. /* Check for quoted filenames */
  112. if(*cp == '\"' || *cp == '\'') {
  113. char quot = *cp++;
  114. /* Search for terminating quote, unescape some chars */
  115. while(*cp != quot) {
  116. if(!*cp) /* End of string */
  117. goto fail;
  118. if(*cp == '\\') { /* Escaped characters */
  119. cp++;
  120. if(*cp != '\'' && *cp != '\"' && *cp != '\\')
  121. goto fail;
  122. }
  123. result = curlx_dyn_addn(&out, cp, 1);
  124. if(result)
  125. return result;
  126. cp++;
  127. }
  128. cp++; /* pass the end quote */
  129. if(!curlx_dyn_len(&out))
  130. goto fail;
  131. }
  132. else {
  133. struct Curl_str word;
  134. bool content = FALSE;
  135. int rc;
  136. /* Handling for relative path - prepend home directory */
  137. if(cp[0] == '/' && cp[1] == '~' && cp[2] == '/') {
  138. result = curlx_dyn_add(&out, homedir);
  139. if(!result)
  140. result = curlx_dyn_addn(&out, "/", 1);
  141. if(result)
  142. return result;
  143. cp += 3;
  144. content = TRUE;
  145. }
  146. /* Read to end of filename - either to whitespace or terminator */
  147. rc = curlx_str_word(&cp, &word, MAX_PATHLENGTH);
  148. if(rc) {
  149. if(rc == STRE_BIG) {
  150. curlx_dyn_free(&out);
  151. return CURLE_TOO_LARGE;
  152. }
  153. else if(!content)
  154. /* no path, no word, this is incorrect */
  155. goto fail;
  156. }
  157. else {
  158. /* append the word */
  159. result = curlx_dyn_addn(&out, curlx_str(&word), curlx_strlen(&word));
  160. if(result)
  161. return result;
  162. }
  163. }
  164. /* skip whitespace */
  165. curlx_str_passblanks(&cp);
  166. /* return pointer to second parameter if it exists */
  167. *cpp = cp;
  168. *path = curlx_dyn_ptr(&out);
  169. return CURLE_OK;
  170. fail:
  171. curlx_dyn_free(&out);
  172. return CURLE_QUOTE_ERROR;
  173. }
  174. #endif /* if SSH is used */