diff options
author | AlexSm <alex@ydb.tech> | 2024-01-18 11:28:56 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-18 11:28:56 +0100 |
commit | 9d0a3761b3201e0d9db879a7adf91876ebdb0564 (patch) | |
tree | 541d11ac878c18efd7ebca81e35112aa0fef995b /contrib/libs/curl/lib/imap.c | |
parent | 404ef8886ecc9736bc58ade6da2fbd83b486a408 (diff) | |
download | ydb-9d0a3761b3201e0d9db879a7adf91876ebdb0564.tar.gz |
Library import 8 (#1074)
* Library import 8
* Add contrib/libs/cxxsupp/libcxx/include/__verbose_abort
Diffstat (limited to 'contrib/libs/curl/lib/imap.c')
-rw-r--r-- | contrib/libs/curl/lib/imap.c | 251 |
1 files changed, 117 insertions, 134 deletions
diff --git a/contrib/libs/curl/lib/imap.c b/contrib/libs/curl/lib/imap.c index ffa08bf7a4..47cff4897c 100644 --- a/contrib/libs/curl/lib/imap.c +++ b/contrib/libs/curl/lib/imap.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -45,9 +45,6 @@ #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif -#ifdef HAVE_UTSNAME_H -#include <sys/utsname.h> -#endif #ifdef HAVE_NETDB_H #include <netdb.h> #endif @@ -56,11 +53,6 @@ #include <inet.h> #endif -#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) -#undef in_addr_t -#define in_addr_t unsigned long -#endif - #include <curl/curl.h> #include "urldata.h" #include "sendf.h" @@ -75,11 +67,11 @@ #include "strtoofft.h" #include "strcase.h" #include "vtls/vtls.h" +#include "cfilters.h" #include "connect.h" #include "select.h" #include "multiif.h" #include "url.h" -#include "strcase.h" #include "bufref.h" #include "curl_sasl.h" #include "warnless.h" @@ -390,11 +382,11 @@ static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out) /*********************************************************************** * - * state() + * imap_state() * * This is the ONLY way to change IMAP state! */ -static void state(struct Curl_easy *data, imapstate newstate) +static void imap_state(struct Curl_easy *data, imapstate newstate) { struct imap_conn *imapc = &data->conn->proto.imapc; #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -446,7 +438,7 @@ static CURLcode imap_perform_capability(struct Curl_easy *data, result = imap_sendf(data, "CAPABILITY"); if(!result) - state(data, IMAP_CAPABILITY); + imap_state(data, IMAP_CAPABILITY); return result; } @@ -463,7 +455,7 @@ static CURLcode imap_perform_starttls(struct Curl_easy *data) CURLcode result = imap_sendf(data, "STARTTLS"); if(!result) - state(data, IMAP_STARTTLS); + imap_state(data, IMAP_STARTTLS); return result; } @@ -479,19 +471,27 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data, { /* Start the SSL connection */ struct imap_conn *imapc = &conn->proto.imapc; - CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE, - FIRSTSOCKET, &imapc->ssldone); + CURLcode result; + bool ssldone = FALSE; + if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) { + result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET); + if(result) + goto out; + } + + result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone); if(!result) { + imapc->ssldone = ssldone; if(imapc->state != IMAP_UPGRADETLS) - state(data, IMAP_UPGRADETLS); + imap_state(data, IMAP_UPGRADETLS); if(imapc->ssldone) { imap_to_imaps(conn); result = imap_perform_capability(data, conn); } } - +out: return result; } @@ -511,7 +511,7 @@ static CURLcode imap_perform_login(struct Curl_easy *data, /* Check we have a username and password to authenticate with and end the connect phase if we don't */ if(!data->state.aptr.user) { - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return result; } @@ -528,7 +528,7 @@ static CURLcode imap_perform_login(struct Curl_easy *data, free(passwd); if(!result) - state(data, IMAP_LOGIN); + imap_state(data, IMAP_LOGIN); return result; } @@ -612,7 +612,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data, with and end the connect phase if we don't */ if(imapc->preauth || !Curl_sasl_can_authenticate(&imapc->sasl, data)) { - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return result; } @@ -621,7 +621,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data, if(!result) { if(progress == SASL_INPROGRESS) - state(data, IMAP_AUTHENTICATE); + imap_state(data, IMAP_AUTHENTICATE); else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) /* Perform clear text authentication */ result = imap_perform_login(data, conn); @@ -664,7 +664,7 @@ static CURLcode imap_perform_list(struct Curl_easy *data) } if(!result) - state(data, IMAP_LIST); + imap_state(data, IMAP_LIST); return result; } @@ -704,7 +704,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data) free(mailbox); if(!result) - state(data, IMAP_SELECT); + imap_state(data, IMAP_SELECT); return result; } @@ -746,7 +746,7 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data) return CURLE_URL_MALFORMAT; } if(!result) - state(data, IMAP_FETCH); + imap_state(data, IMAP_FETCH); return result; } @@ -776,7 +776,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data) /* Add external headers and mime version. */ curl_mime_headers(&data->set.mimepost, data->set.headers, 0); - result = Curl_mime_prepare_headers(&data->set.mimepost, NULL, + result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL, NULL, MIMESTRATEGY_MAIL); if(!result) @@ -817,7 +817,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data) free(mailbox); if(!result) - state(data, IMAP_APPEND); + imap_state(data, IMAP_APPEND); return result; } @@ -843,7 +843,7 @@ static CURLcode imap_perform_search(struct Curl_easy *data) result = imap_sendf(data, "SEARCH %s", imap->query); if(!result) - state(data, IMAP_SEARCH); + imap_state(data, IMAP_SEARCH); return result; } @@ -860,7 +860,7 @@ static CURLcode imap_perform_logout(struct Curl_easy *data) CURLcode result = imap_sendf(data, "LOGOUT"); if(!result) - state(data, IMAP_LOGOUT); + imap_state(data, IMAP_LOGOUT); return result; } @@ -951,7 +951,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data, line += wordlen; } } - else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + else if(data->set.use_ssl && !Curl_conn_is_ssl(conn, FIRSTSOCKET)) { /* PREAUTH is not compatible with STARTTLS. */ if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) { /* Switch to TLS connection now */ @@ -1014,7 +1014,7 @@ static CURLcode imap_state_auth_resp(struct Curl_easy *data, if(!result) switch(progress) { case SASL_DONE: - state(data, IMAP_STOP); /* Authenticated */ + imap_state(data, IMAP_STOP); /* Authenticated */ break; case SASL_IDLE: /* No mechanism left after cancellation */ if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT)) @@ -1046,7 +1046,7 @@ static CURLcode imap_state_login_resp(struct Curl_easy *data, } else /* End of connect phase */ - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return result; } @@ -1072,7 +1072,7 @@ static CURLcode imap_state_listsearch_resp(struct Curl_easy *data, result = CURLE_QUOTE_ERROR; else /* End of DO phase */ - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return result; } @@ -1091,10 +1091,19 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode, if(imapcode == '*') { /* See if this is an UIDVALIDITY response */ - char tmp[20]; - if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) { - Curl_safefree(imapc->mailbox_uidvalidity); - imapc->mailbox_uidvalidity = strdup(tmp); + if(checkprefix("OK [UIDVALIDITY ", line + 2)) { + size_t len = 0; + const char *p = &line[2] + strlen("OK [UIDVALIDITY "); + while((len < 20) && p[len] && ISDIGIT(p[len])) + len++; + if(len && (p[len] == ']')) { + struct dynbuf uid; + Curl_dyn_init(&uid, 20); + if(Curl_dyn_addn(&uid, p, len)) + return CURLE_OUT_OF_MEMORY; + Curl_safefree(imapc->mailbox_uidvalidity); + imapc->mailbox_uidvalidity = Curl_dyn_ptr(&uid); + } } } else if(imapcode == IMAP_RESP_OK) { @@ -1106,7 +1115,10 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode, } else { /* Note the currently opened mailbox on this connection */ + DEBUGASSERT(!imapc->mailbox); imapc->mailbox = strdup(imap->mailbox); + if(!imapc->mailbox) + return CURLE_OUT_OF_MEMORY; if(imap->custom) result = imap_perform_list(data); @@ -1140,7 +1152,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data, if(imapcode != '*') { Curl_pgrsSetDownloadSize(data, -1); - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return CURLE_REMOTE_FILE_NOT_FOUND; } @@ -1175,15 +1187,13 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data, if(!chunk) { /* no size, we're done with the data */ - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return CURLE_OK; } result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk); if(result) return result; - data->req.bytecount += chunk; - infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU " bytes are left for transfer", chunk, size - chunk); @@ -1221,7 +1231,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data, } /* End of DO phase */ - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return result; } @@ -1239,7 +1249,7 @@ static CURLcode imap_state_fetch_final_resp(struct Curl_easy *data, result = CURLE_WEIRD_SERVER_REPLY; else /* End of DONE phase */ - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return result; } @@ -1262,7 +1272,7 @@ static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode, Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* End of DO phase */ - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); } return result; @@ -1281,7 +1291,7 @@ static CURLcode imap_state_append_final_resp(struct Curl_easy *data, result = CURLE_UPLOAD_FAILED; else /* End of DONE phase */ - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); return result; } @@ -1369,7 +1379,7 @@ static CURLcode imap_statemachine(struct Curl_easy *data, /* fallthrough, just stop! */ default: /* internal error */ - state(data, IMAP_STOP); + imap_state(data, IMAP_STOP); break; } } while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp)); @@ -1385,9 +1395,10 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done) struct imap_conn *imapc = &conn->proto.imapc; if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) { - result = Curl_ssl_connect_nonblocking(data, conn, FALSE, - FIRSTSOCKET, &imapc->ssldone); - if(result || !imapc->ssldone) + bool ssldone = FALSE; + result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone); + imapc->ssldone = ssldone; + if(result || !ssldone) return result; } @@ -1417,7 +1428,7 @@ static CURLcode imap_init(struct Curl_easy *data) CURLcode result = CURLE_OK; struct IMAP *imap; - imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1); + imap = data->req.p.imap = calloc(1, sizeof(struct IMAP)); if(!imap) result = CURLE_OUT_OF_MEMORY; @@ -1471,7 +1482,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done) return result; /* Start off waiting for the server greeting response */ - state(data, IMAP_SERVERGREET); + imap_state(data, IMAP_SERVERGREET); /* Start off with an response id of '*' */ strcpy(imapc->resptag, "*"); @@ -1507,17 +1518,17 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status, result = status; /* use the already set error code */ } else if(!data->set.connect_only && !imap->custom && - (imap->uid || imap->mindex || data->set.upload || + (imap->uid || imap->mindex || data->state.upload || data->set.mimepost.kind != MIMEKIND_NONE)) { /* Handle responses after FETCH or APPEND transfer has finished */ - if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE) - state(data, IMAP_FETCH_FINAL); + if(!data->state.upload && data->set.mimepost.kind == MIMEKIND_NONE) + imap_state(data, IMAP_FETCH_FINAL); else { /* End the APPEND command first by sending an empty line */ result = Curl_pp_sendf(data, &conn->proto.imapc.pp, "%s", ""); if(!result) - state(data, IMAP_APPEND_FINAL); + imap_state(data, IMAP_APPEND_FINAL); } /* Run the state-machine */ @@ -1561,7 +1572,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, DEBUGF(infof(data, "DO phase starts")); - if(data->set.opt_no_body) { + if(data->req.no_body) { /* Requested no body means no transfer */ imap->transfer = PPTRANSFER_INFO; } @@ -1577,7 +1588,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, selected = TRUE; /* Start the first command in the DO phase */ - if(data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE) + if(data->state.upload || data->set.mimepost.kind != MIMEKIND_NONE) /* APPEND can be executed directly */ result = imap_perform_append(data); else if(imap->custom && (selected || !imap->mailbox)) @@ -1603,7 +1614,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, /* Run the state-machine */ result = imap_multi_statemach(data, dophase_done); - *connected = conn->bits.tcpconnect[FIRSTSOCKET]; + *connected = Curl_conn_is_connected(conn, FIRSTSOCKET); if(*dophase_done) DEBUGF(infof(data, "DO phase is complete")); @@ -1773,8 +1784,8 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...) /* Calculate the tag based on the connection ID and command ID */ msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d", - 'A' + curlx_sltosi(data->conn->connection_id % 26), - (++imapc->cmdid)%1000); + 'A' + curlx_sltosi((long)(data->conn->connection_id % 26)), + ++imapc->cmdid); /* start with a blank buffer */ Curl_dyn_reset(&imapc->dyn); @@ -1802,79 +1813,37 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...) */ static char *imap_atom(const char *str, bool escape_only) { - /* !checksrc! disable PARENBRACE 1 */ - const char atom_specials[] = "(){ %*]"; - const char *p1; - char *p2; - size_t backsp_count = 0; - size_t quote_count = 0; - bool others_exists = FALSE; - size_t newlen = 0; - char *newstr = NULL; + struct dynbuf line; + size_t nclean; + size_t len; if(!str) return NULL; - /* Look for "atom-specials", counting the backslash and quote characters as - these will need escaping */ - p1 = str; - while(*p1) { - if(*p1 == '\\') - backsp_count++; - else if(*p1 == '"') - quote_count++; - else if(!escape_only) { - const char *p3 = atom_specials; - - while(*p3 && !others_exists) { - if(*p1 == *p3) - others_exists = TRUE; - - p3++; - } - } - - p1++; - } - - /* Does the input contain any "atom-special" characters? */ - if(!backsp_count && !quote_count && !others_exists) + len = strlen(str); + nclean = strcspn(str, "() {%*]\\\""); + if(len == nclean) + /* nothing to escape, return a strdup */ return strdup(str); - /* Calculate the new string length */ - newlen = strlen(str) + backsp_count + quote_count + (escape_only ? 0 : 2); + Curl_dyn_init(&line, 2000); - /* Allocate the new string */ - newstr = (char *) malloc((newlen + 1) * sizeof(char)); - if(!newstr) + if(!escape_only && Curl_dyn_addn(&line, "\"", 1)) return NULL; - /* Surround the string in quotes if necessary */ - p2 = newstr; - if(!escape_only) { - newstr[0] = '"'; - newstr[newlen - 1] = '"'; - p2++; + while(*str) { + if((*str == '\\' || *str == '"') && + Curl_dyn_addn(&line, "\\", 1)) + return NULL; + if(Curl_dyn_addn(&line, str, 1)) + return NULL; + str++; } - /* Copy the string, escaping backslash and quote characters along the way */ - p1 = str; - while(*p1) { - if(*p1 == '\\' || *p1 == '"') { - *p2 = '\\'; - p2++; - } - - *p2 = *p1; - - p1++; - p2++; - } - - /* Terminate the string */ - newstr[newlen] = '\0'; + if(!escape_only && Curl_dyn_addn(&line, "\"", 1)) + return NULL; - return newstr; + return Curl_dyn_ptr(&line); } /*********************************************************************** @@ -1921,39 +1890,53 @@ static CURLcode imap_parse_url_options(struct connectdata *conn) CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; const char *ptr = conn->options; + bool prefer_login = false; while(!result && ptr && *ptr) { const char *key = ptr; const char *value; while(*ptr && *ptr != '=') - ptr++; + ptr++; value = ptr + 1; while(*ptr && *ptr != ';') ptr++; - if(strncasecompare(key, "AUTH=", 5)) + if(strncasecompare(key, "AUTH=+LOGIN", 11)) { + /* User prefers plaintext LOGIN over any SASL, including SASL LOGIN */ + prefer_login = true; + imapc->sasl.prefmech = SASL_AUTH_NONE; + } + else if(strncasecompare(key, "AUTH=", 5)) { + prefer_login = false; result = Curl_sasl_parse_url_auth_option(&imapc->sasl, value, ptr - value); - else + } + else { + prefer_login = false; result = CURLE_URL_MALFORMAT; + } if(*ptr == ';') ptr++; } - switch(imapc->sasl.prefmech) { - case SASL_AUTH_NONE: - imapc->preftype = IMAP_TYPE_NONE; - break; - case SASL_AUTH_DEFAULT: - imapc->preftype = IMAP_TYPE_ANY; - break; - default: - imapc->preftype = IMAP_TYPE_SASL; - break; + if(prefer_login) + imapc->preftype = IMAP_TYPE_CLEARTEXT; + else { + switch(imapc->sasl.prefmech) { + case SASL_AUTH_NONE: + imapc->preftype = IMAP_TYPE_NONE; + break; + case SASL_AUTH_DEFAULT: + imapc->preftype = IMAP_TYPE_ANY; + break; + default: + imapc->preftype = IMAP_TYPE_SASL; + break; + } } return result; |