handler: make 'protocol' always specified as a single bit
authorDaniel Stenberg <daniel@haxx.se>
Sun, 20 Apr 2014 17:37:54 +0000 (19:37 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 23 Apr 2014 20:36:01 +0000 (22:36 +0200)
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
lib/http.c
lib/http2.c
lib/imap.c
lib/ldap.c
lib/pop3.c
lib/sendf.c
lib/smtp.c
lib/transfer.c
lib/url.c
lib/urldata.h

index 8ce57a6de800f7da80836faa4d8f90dbbbecd5fe..e8ac363c862b387d2920f8820b52ccf683a13af4 100644 (file)
--- 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 */
 };
index 1a2799f28658bcbe1989e64ef0c6c78bbaef9f84..5f857ca6b7522760dd1f77e0606c00800238b573 100644 (file)
@@ -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,
index aa2db439957cf658c120a8bf1b0208a661f23b90..75956a02121d3fa4e70c4c800de807aa092204cc 100644 (file)
@@ -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 */
 };
 
index 9808f998a9b80f3c792b7062f1fb9b7690207cb1..fc162b6c8fe630d68385ad7677a45524b240a08a 100644 (file)
@@ -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 */
 };
index c2fa1735faf9f40487077962bdd7af3b81a541f6..4c987898bbf5c9eb317c4f91c7563cb83fc94d24 100644 (file)
@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 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
@@ -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
index d33ca0fe56b0e509f3a77ffba5b12adb31bdead8..964804b306c5f98c6927bac0e266b49d3abcbd1a 100644 (file)
@@ -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 */
 };
index 1c30c0bc410bb959ab7c43177af62d1fa4d519fb..4a87c79dd9ccb43916bb4facbbb2603343e4fdf6 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 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
@@ -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);
index 9512a2a7fcb46bb5fac2cc37011ce8a3a0464180..d367d94b8c583f2f4b32fbf3c2c71040d798085c 100644 (file)
@@ -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 */
 };
index 3fcc6003ebaeabc5c73645649fbb1c4e150ed75c..46e55fbb5e8f4da3e71d4d259114a5ee35f5cd77 100644 (file)
@@ -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;
index b871bd634080eaa68f993f70b8dc7328fba8bb46..409085f93199c201c37eccf2ee91bb2de9d68787 100644 (file)
--- 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;
 
index ec48f6525d3e4049ffbb40d7afed1cf6b86c8340..16f08d30e6e172bb7c8602ad6bc86484f90c660c 100644 (file)
 #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_* */
 };