From 710f14edba4491a4ac9222a7e3103b51fd30dbe0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 20 Apr 2014 19:37:54 +0200 Subject: [PATCH] handler: make 'protocol' always specified as a single bit This makes the findprotocol() function work as intended so that libcurl can properly be restricted to not support HTTP while still supporting HTTPS - since the HTTPS handler previously set both the HTTP and HTTPS bits in the protocol field. This fixes --proto and --proto-redir for most SSL protocols. This is done by adding a few new convenience defines that groups HTTP and HTTPS, FTP and FTPS etc that should then be used when the code wants to check for both protocols at once. PROTO_FAMILY_[protocol] style. Bug: https://github.com/bagder/curl/pull/97 Reported-by: drizzt --- lib/ftp.c | 2 +- lib/http.c | 8 ++++---- lib/http2.c | 2 +- lib/imap.c | 2 +- lib/ldap.c | 4 ++-- lib/pop3.c | 2 +- lib/sendf.c | 4 ++-- lib/smtp.c | 2 +- lib/transfer.c | 18 +++++++++--------- lib/url.c | 6 +++--- lib/urldata.h | 11 ++++++++++- 11 files changed, 35 insertions(+), 26 deletions(-) diff --git a/lib/ftp.c b/lib/ftp.c index 8ce57a6de..e8ac363c8 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -208,7 +208,7 @@ const struct Curl_handler Curl_handler_ftps = { ftp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ PORT_FTPS, /* defport */ - CURLPROTO_FTP | CURLPROTO_FTPS, /* protocol */ + CURLPROTO_FTPS, /* protocol */ PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY /* flags */ }; diff --git a/lib/http.c b/lib/http.c index 1a2799f28..5f857ca6b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -144,7 +144,7 @@ const struct Curl_handler Curl_handler_https = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ PORT_HTTPS, /* defport */ - CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */ + CURLPROTO_HTTPS, /* protocol */ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */ }; #endif @@ -1771,7 +1771,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) } http->writebytecount = http->readbytecount = 0; - if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_FTP)) && + if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && data->set.upload) { httpreq = HTTPREQ_PUT; } @@ -1883,7 +1883,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"); } else { - if((conn->handler->protocol&CURLPROTO_HTTP) && + if((conn->handler->protocol&PROTO_FAMILY_HTTP) && data->set.upload && (data->set.infilesize == -1)) { if(conn->bits.authneg) @@ -3190,7 +3190,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, #define HEADER1 k->p /* no conversion needed, just use k->p */ #endif /* CURL_DOES_CONVERSIONS */ - if(conn->handler->protocol & CURLPROTO_HTTP) { + if(conn->handler->protocol & PROTO_FAMILY_HTTP) { nc = sscanf(HEADER1, " HTTP/%d.%d %3d", &httpversion_major, diff --git a/lib/http2.c b/lib/http2.c index aa2db4399..75956a021 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -136,7 +136,7 @@ const struct Curl_handler Curl_handler_http2_ssl = { http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ PORT_HTTP, /* defport */ - CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */ + CURLPROTO_HTTPS, /* protocol */ PROTOPT_SSL /* flags */ }; diff --git a/lib/imap.c b/lib/imap.c index 9808f998a..fc162b6c8 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -155,7 +155,7 @@ const struct Curl_handler Curl_handler_imaps = { imap_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ PORT_IMAPS, /* defport */ - CURLPROTO_IMAP | CURLPROTO_IMAPS, /* protocol */ + CURLPROTO_IMAPS, /* protocol */ PROTOPT_CLOSEACTION | PROTOPT_SSL | PROTOPT_NEEDSPWD /* flags */ }; diff --git a/lib/ldap.c b/lib/ldap.c index c2fa1735f..4c987898b 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -159,7 +159,7 @@ const struct Curl_handler Curl_handler_ldaps = { ZERO_NULL, /* disconnect */ ZERO_NULL, /* readwrite */ PORT_LDAPS, /* defport */ - CURLPROTO_LDAP | CURLPROTO_LDAPS, /* protocol */ + CURLPROTO_LDAPS, /* protocol */ PROTOPT_SSL /* flags */ }; #endif diff --git a/lib/pop3.c b/lib/pop3.c index d33ca0fe5..964804b30 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -156,7 +156,7 @@ const struct Curl_handler Curl_handler_pop3s = { pop3_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ PORT_POP3S, /* defport */ - CURLPROTO_POP3 | CURLPROTO_POP3S, /* protocol */ + CURLPROTO_POP3S, /* protocol */ PROTOPT_CLOSEACTION | PROTOPT_SSL | PROTOPT_NOURLQUERY /* flags */ }; diff --git a/lib/sendf.c b/lib/sendf.c index 1c30c0bc4..4a87c79dd 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -422,7 +422,7 @@ CURLcode Curl_client_write(struct connectdata *conn, } if(type & CLIENTWRITE_BODY) { - if((conn->handler->protocol&CURLPROTO_FTP) && + if((conn->handler->protocol&PROTO_FAMILY_FTP) && conn->proto.ftpc.transfertype == 'A') { /* convert from the network encoding */ CURLcode rc = Curl_convert_from_network(data, ptr, len); diff --git a/lib/smtp.c b/lib/smtp.c index 9512a2a7f..d367d94b8 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -155,7 +155,7 @@ const struct Curl_handler Curl_handler_smtps = { smtp_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ PORT_SMTPS, /* defport */ - CURLPROTO_SMTP | CURLPROTO_SMTPS, /* protocol */ + CURLPROTO_SMTPS, /* protocol */ PROTOPT_CLOSEACTION | PROTOPT_SSL | PROTOPT_NOURLQUERY /* flags */ }; diff --git a/lib/transfer.c b/lib/transfer.c index 3fcc6003e..46e55fbb5 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -99,7 +99,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp) #ifdef CURL_DOES_CONVERSIONS bool sending_http_headers = FALSE; - if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) { + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { const struct HTTP *http = data->req.protop; if(http->sending == HTTPSEND_REQUEST) @@ -319,7 +319,7 @@ static int data_pending(const struct connectdata *conn) TRUE. The thing is if we read everything, then http2_recv won't be called and we cannot signal the HTTP/2 stream has closed. As a workaround, we return nonzero here to call http2_recv. */ - ((conn->handler->protocol&CURLPROTO_HTTP) && conn->httpversion == 20 && + ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20 && conn->proto.httpc.closed); #else Curl_ssl_data_pending(conn, FIRSTSOCKET); @@ -527,7 +527,7 @@ static CURLcode readwrite_data(struct SessionHandle *data, if(0 == k->bodywrites && !is_empty_data) { /* These checks are only made the first time we are about to write a piece of the body */ - if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) { + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { /* HTTP-only checks */ if(data->req.newurl) { @@ -723,7 +723,7 @@ static CURLcode readwrite_data(struct SessionHandle *data, if(!k->ignorebody) { #ifndef CURL_DISABLE_POP3 - if(conn->handler->protocol&CURLPROTO_POP3) + if(conn->handler->protocol&PROTO_FAMILY_POP3) result = Curl_pop3_write(conn, k->str, nread); else #endif /* CURL_DISABLE_POP3 */ @@ -854,7 +854,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data, break; } - if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) { + if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) { if(http->sending == HTTPSEND_REQUEST) /* We're sending the HTTP request headers, not the data. Remember that so we don't change the line endings. */ @@ -892,7 +892,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data, data->req.upload_present = nread; #ifndef CURL_DISABLE_SMTP - if(conn->handler->protocol & CURLPROTO_SMTP) { + if(conn->handler->protocol & PROTO_FAMILY_SMTP) { result = Curl_smtp_escape_eob(conn, nread); if(result) return result; @@ -1873,7 +1873,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, /* if we're talking upload, we can't do the checks below, unless the protocol is HTTP as when uploading over HTTP we will still get a response */ if(data->set.upload && - !(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP))) + !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP))) return CURLE_OK; if(/* workaround for broken TLS servers */ data->state.ssl_connect_retry || @@ -1899,7 +1899,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, transferred! */ - if(conn->handler->protocol&CURLPROTO_HTTP) { + if(conn->handler->protocol&PROTO_FAMILY_HTTP) { struct HTTP *http = data->req.protop; if(http->writebytecount) return Curl_readrewind(conn); @@ -1972,7 +1972,7 @@ Curl_setup_transfer( state info where we wait for the 100-return code */ if((data->state.expect100header) && - (conn->handler->protocol&CURLPROTO_HTTP) && + (conn->handler->protocol&PROTO_FAMILY_HTTP) && (http->sending == HTTPSEND_BODY)) { /* wait with write until we either got 100-continue or a timeout */ k->exp100 = EXP100_AWAITING_CONTINUE; diff --git a/lib/url.c b/lib/url.c index b871bd634..409085f93 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2703,7 +2703,7 @@ static bool SocketIsDead(curl_socket_t sock) static bool IsPipeliningPossible(const struct SessionHandle *handle, const struct connectdata *conn) { - if((conn->handler->protocol & CURLPROTO_HTTP) && + if((conn->handler->protocol & PROTO_FAMILY_HTTP) && Curl_multi_pipeline_enabled(handle->multi) && (handle->set.httpreq == HTTPREQ_GET || handle->set.httpreq == HTTPREQ_HEAD) && @@ -2927,7 +2927,7 @@ ConnectionExists(struct SessionHandle *data, bool canPipeline = IsPipeliningPossible(data, needle); bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) || (data->state.authhost.want & CURLAUTH_NTLM_WB)) && - (needle->handler->protocol & CURLPROTO_HTTP) ? TRUE : FALSE; + (needle->handler->protocol & PROTO_FAMILY_HTTP) ? TRUE : FALSE; struct connectbundle *bundle; *force_reuse = FALSE; @@ -5330,7 +5330,7 @@ static CURLcode create_conn(struct SessionHandle *data, #else /* force this connection's protocol to become HTTP if not already compatible - if it isn't tunneling through */ - if(!(conn->handler->protocol & CURLPROTO_HTTP) && + if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) && !conn->bits.tunnel_proxy) conn->handler = &Curl_handler_http; diff --git a/lib/urldata.h b/lib/urldata.h index ec48f6525..16f08d30e 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -58,6 +58,14 @@ #define CURL_DEFAULT_USER "anonymous" #define CURL_DEFAULT_PASSWORD "ftp@example.com" +/* Convenience defines for checking protocols or their SSL based version. Each + protocol handler should only ever have a single CURLPROTO_ in its protocol + field. */ +#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS) +#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS) +#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S) +#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS) + #define DEFAULT_CONNCACHE_SIZE 5 /* length of longest IPv6 address string including the trailing null */ @@ -778,7 +786,8 @@ struct Curl_handler { ssize_t *nread, bool *readmore); long defport; /* Default port. */ - unsigned int protocol; /* See CURLPROTO_* */ + unsigned int protocol; /* See CURLPROTO_* - this needs to be the single + specific protocol bit */ unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ };