diff options
author | Brad King <brad.king@kitware.com> | 2023-03-20 16:40:49 -0400 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2023-03-20 16:40:49 -0400 |
commit | e3dc4df9b95272037d27be25ae5ef030ffd83fa4 (patch) | |
tree | 6132bc02d5204bd988b32ee8ab06053ec7c0e4c4 /Utilities/cmcurl/lib/ftp.c | |
parent | 4e6c3cd93bc870f44442e6d7e59896bc6d86ce25 (diff) | |
parent | e8bff971d9d835a65bcb1711e7214afe37b238e0 (diff) | |
download | cmake-e3dc4df9b95272037d27be25ae5ef030ffd83fa4.tar.gz |
Merge branch 'upstream-curl' into update-curl
* upstream-curl:
curl 2023-03-20 (b16d1fa8)
Diffstat (limited to 'Utilities/cmcurl/lib/ftp.c')
-rw-r--r-- | Utilities/cmcurl/lib/ftp.c | 154 |
1 files changed, 109 insertions, 45 deletions
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c index 8c728745d9..ef9ec1e41f 100644 --- a/Utilities/cmcurl/lib/ftp.c +++ b/Utilities/cmcurl/lib/ftp.c @@ -436,6 +436,12 @@ static CURLcode InitiateTransfer(struct Curl_easy *data) bool connected; DEBUGF(infof(data, "ftp InitiateTransfer()")); + if(conn->bits.ftp_use_data_ssl && data->set.ftp_use_port && + !Curl_conn_is_ssl(conn, SECONDARYSOCKET)) { + result = Curl_ssl_cfilter_add(data, conn, SECONDARYSOCKET); + if(result) + return result; + } result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &connected); if(result || !connected) return result; @@ -1795,6 +1801,29 @@ static char *control_address(struct connectdata *conn) return conn->primary_ip; } +static bool match_pasv_6nums(const char *p, + unsigned int *array) /* 6 numbers */ +{ + int i; + for(i = 0; i < 6; i++) { + unsigned long num; + char *endp; + if(i) { + if(*p != ',') + return FALSE; + p++; + } + if(!ISDIGIT(*p)) + return FALSE; + num = strtoul(p, &endp, 10); + if(num > 255) + return FALSE; + array[i] = (unsigned int)num; + p = endp; + } + return TRUE; +} + static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, int ftpcode) { @@ -1814,27 +1843,18 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, /* positive EPSV response */ char *ptr = strchr(str, '('); if(ptr) { - unsigned int num; - char separator[4]; + char sep; ptr++; - if(5 == sscanf(ptr, "%c%c%c%u%c", - &separator[0], - &separator[1], - &separator[2], - &num, - &separator[3])) { - const char sep1 = separator[0]; - int i; - - /* The four separators should be identical, or else this is an oddly - formatted reply and we bail out immediately. */ - for(i = 1; i<4; i++) { - if(separator[i] != sep1) { - ptr = NULL; /* set to NULL to signal error */ - break; - } - } - if(num > 0xffff) { + /* |||12345| */ + sep = ptr[0]; + /* the ISDIGIT() check here is because strtoul() accepts leading minus + etc */ + if((ptr[1] == sep) && (ptr[2] == sep) && ISDIGIT(ptr[3])) { + char *endp; + unsigned long num = strtoul(&ptr[3], &endp, 10); + if(*endp != sep) + ptr = NULL; + else if(num > 0xffff) { failf(data, "Illegal port number in EPSV reply"); return CURLE_FTP_WEIRD_PASV_REPLY; } @@ -1856,8 +1876,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, else if((ftpc->count1 == 1) && (ftpcode == 227)) { /* positive PASV response */ - unsigned int ip[4] = {0, 0, 0, 0}; - unsigned int port[2] = {0, 0}; + unsigned int ip[6]; /* * Scan for a sequence of six comma-separated numbers and use them as @@ -1869,15 +1888,12 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, * "227 Entering passive mode. 127,0,0,1,4,51" */ while(*str) { - if(6 == sscanf(str, "%u,%u,%u,%u,%u,%u", - &ip[0], &ip[1], &ip[2], &ip[3], - &port[0], &port[1])) + if(match_pasv_6nums(str, ip)) break; str++; } - if(!*str || (ip[0] > 255) || (ip[1] > 255) || (ip[2] > 255) || - (ip[3] > 255) || (port[0] > 255) || (port[1] > 255) ) { + if(!*str) { failf(data, "Couldn't interpret the 227-response"); return CURLE_FTP_WEIRD_227_FORMAT; } @@ -1897,7 +1913,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, if(!ftpc->newhost) return CURLE_OUT_OF_MEMORY; - ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); + ftpc->newport = (unsigned short)(((ip[4]<<8) + ip[5]) & 0xffff); } else if(ftpc->count1 == 0) { /* EPSV failed, move on to PASV */ @@ -2032,6 +2048,30 @@ static CURLcode ftp_state_port_resp(struct Curl_easy *data, return result; } +static int twodigit(const char *p) +{ + return (p[0]-'0') * 10 + (p[1]-'0'); +} + +static bool ftp_213_date(const char *p, int *year, int *month, int *day, + int *hour, int *minute, int *second) +{ + size_t len = strlen(p); + if(len < 14) + return FALSE; + *year = twodigit(&p[0]) * 100 + twodigit(&p[2]); + *month = twodigit(&p[4]); + *day = twodigit(&p[6]); + *hour = twodigit(&p[8]); + *minute = twodigit(&p[10]); + *second = twodigit(&p[12]); + + if((*month > 12) || (*day > 31) || (*hour > 23) || (*minute > 59) || + (*second > 60)) + return FALSE; + return TRUE; +} + static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, int ftpcode) { @@ -2046,8 +2086,8 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the last .sss part is optional and means fractions of a second */ int year, month, day, hour, minute, second; - if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d", - &year, &month, &day, &hour, &minute, &second)) { + if(ftp_213_date(&data->state.buffer[4], + &year, &month, &day, &hour, &minute, &second)) { /* we have a time, reformat it */ char timebuf[24]; msnprintf(timebuf, sizeof(timebuf), @@ -2635,7 +2675,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data, int ftpcode; struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; - static const char ftpauth[][4] = { "SSL", "TLS" }; + static const char * const ftpauth[] = { "SSL", "TLS" }; size_t nread = 0; if(pp->sendleft) @@ -3221,7 +3261,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, if(data->state.wildcardmatch) { if(data->set.chunk_end && ftpc->file) { Curl_set_in_callback(data, true); - data->set.chunk_end(data->wildcard.customptr); + data->set.chunk_end(data->set.wildcardptr); Curl_set_in_callback(data, false); } ftpc->known_filesize = -1; @@ -3728,7 +3768,7 @@ static CURLcode init_wc_data(struct Curl_easy *data) char *last_slash; struct FTP *ftp = data->req.p.ftp; char *path = ftp->path; - struct WildcardData *wildcard = &(data->wildcard); + struct WildcardData *wildcard = data->wildcard; CURLcode result = CURLE_OK; struct ftp_wc *ftpwc = NULL; @@ -3776,7 +3816,7 @@ static CURLcode init_wc_data(struct Curl_easy *data) goto fail; } - wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */ + wildcard->ftpwc = ftpwc; /* put it to the WildcardData tmp pointer */ wildcard->dtor = wc_data_dtor; /* wildcard does not support NOCWD option (assert it?) */ @@ -3814,13 +3854,13 @@ static CURLcode init_wc_data(struct Curl_easy *data) } Curl_safefree(wildcard->pattern); wildcard->dtor = ZERO_NULL; - wildcard->protdata = NULL; + wildcard->ftpwc = NULL; return result; } static CURLcode wc_statemach(struct Curl_easy *data) { - struct WildcardData * const wildcard = &(data->wildcard); + struct WildcardData * const wildcard = data->wildcard; struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; @@ -3837,7 +3877,7 @@ static CURLcode wc_statemach(struct Curl_easy *data) case CURLWC_MATCHING: { /* In this state is LIST response successfully parsed, so lets restore previous WRITEFUNCTION callback and WRITEDATA pointer */ - struct ftp_wc *ftpwc = wildcard->protdata; + struct ftp_wc *ftpwc = wildcard->ftpwc; data->set.fwrite_func = ftpwc->backup.write_function; data->set.out = ftpwc->backup.file_descriptor; ftpwc->backup.write_function = ZERO_NULL; @@ -3876,7 +3916,7 @@ static CURLcode wc_statemach(struct Curl_easy *data) long userresponse; Curl_set_in_callback(data, true); userresponse = data->set.chunk_bgn( - finfo, wildcard->customptr, (int)wildcard->filelist.size); + finfo, data->set.wildcardptr, (int)wildcard->filelist.size); Curl_set_in_callback(data, false); switch(userresponse) { case CURL_CHUNK_BGN_FUNC_SKIP: @@ -3916,7 +3956,7 @@ static CURLcode wc_statemach(struct Curl_easy *data) case CURLWC_SKIP: { if(data->set.chunk_end) { Curl_set_in_callback(data, true); - data->set.chunk_end(data->wildcard.customptr); + data->set.chunk_end(data->set.wildcardptr); Curl_set_in_callback(data, false); } Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); @@ -3926,7 +3966,7 @@ static CURLcode wc_statemach(struct Curl_easy *data) } case CURLWC_CLEAN: { - struct ftp_wc *ftpwc = wildcard->protdata; + struct ftp_wc *ftpwc = wildcard->ftpwc; result = CURLE_OK; if(ftpwc) result = Curl_ftp_parselist_geterror(ftpwc->parser); @@ -3939,7 +3979,7 @@ static CURLcode wc_statemach(struct Curl_easy *data) case CURLWC_ERROR: case CURLWC_CLEAR: if(wildcard->dtor) - wildcard->dtor(wildcard->protdata); + wildcard->dtor(wildcard->ftpwc); return result; } } @@ -3966,8 +4006,8 @@ static CURLcode ftp_do(struct Curl_easy *data, bool *done) if(data->state.wildcardmatch) { result = wc_statemach(data); - if(data->wildcard.state == CURLWC_SKIP || - data->wildcard.state == CURLWC_DONE) { + if(data->wildcard->state == CURLWC_SKIP || + data->wildcard->state == CURLWC_DONE) { /* do not call ftp_regular_transfer */ return CURLE_OK; } @@ -4053,6 +4093,8 @@ static CURLcode ftp_disconnect(struct Curl_easy *data, } freedirs(ftpc); + Curl_safefree(ftpc->account); + Curl_safefree(ftpc->alternative_to_user); Curl_safefree(ftpc->prevpath); Curl_safefree(ftpc->server_os); Curl_pp_disconnect(pp); @@ -4322,11 +4364,31 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, char *type; struct FTP *ftp; CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; - data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1); + ftp = calloc(sizeof(struct FTP), 1); if(!ftp) return CURLE_OUT_OF_MEMORY; + /* clone connection related data that is FTP specific */ + if(data->set.str[STRING_FTP_ACCOUNT]) { + ftpc->account = strdup(data->set.str[STRING_FTP_ACCOUNT]); + if(!ftpc->account) { + free(ftp); + return CURLE_OUT_OF_MEMORY; + } + } + if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) { + ftpc->alternative_to_user = + strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); + if(!ftpc->alternative_to_user) { + Curl_safefree(ftpc->account); + free(ftp); + return CURLE_OUT_OF_MEMORY; + } + } + data->req.p.ftp = ftp; + ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ /* FTP URLs support an extension like ";type=<typecode>" that @@ -4361,7 +4423,9 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, /* get some initial data into the ftp struct */ ftp->transfer = PPTRANSFER_BODY; ftp->downloadsize = 0; - conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ + ftpc->known_filesize = -1; /* unknown size for now */ + ftpc->use_ssl = data->set.use_ssl; + ftpc->ccc = data->set.ftp_ccc; return result; } |