Revert "Update to 7.40.1"
[platform/upstream/curl.git] / lib / pop3.c
index 782458a..314567e 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
@@ -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 */
 };
@@ -561,8 +561,7 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn)
     }
 #ifndef CURL_DISABLE_CRYPTO_AUTH
     else if((pop3c->authtypes & POP3_TYPE_APOP) &&
-            (pop3c->preftype & POP3_TYPE_APOP) &&
-            (pop3c->apoptimestamp))
+            (pop3c->preftype & POP3_TYPE_APOP))
       /* Perform APOP authentication */
       result = pop3_perform_apop(conn);
 #endif
@@ -658,8 +657,9 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
     result = CURLE_FTP_WEIRD_SERVER_REPLY;
   }
   else {
-    /* Look for the APOP timestamp */
+    /* Does the server support APOP authentication? */
     if(len >= 4 && line[len - 2] == '>') {
+      /* Look for the APOP timestamp */
       for(i = 3; i < len - 2; ++i) {
         if(line[i] == '<') {
           /* Calculate the length of the timestamp */
@@ -676,6 +676,9 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
           /* Copy the timestamp */
           memcpy(pop3c->apoptimestamp, line + i, timestamplen);
           pop3c->apoptimestamp[timestamplen] = '\0';
+
+          /* Store the APOP capability */
+          pop3c->authtypes |= POP3_TYPE_APOP;
           break;
         }
       }
@@ -710,10 +713,6 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
     else if(len >= 4 && !memcmp(line, "USER", 4))
       pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
 
-    /* Does the server support APOP authentication? */
-    else if(len >= 4 && !memcmp(line, "APOP", 4))
-      pop3c->authtypes |= POP3_TYPE_APOP;
-
     /* Does the server support SASL based authentication? */
     else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
       pop3c->authtypes |= POP3_TYPE_SASL;
@@ -781,8 +780,12 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
     else
       result = pop3_perform_authentication(conn);
   }
-  else
-    result = pop3_perform_user(conn);
+  else {
+    /* Clear text is supported when CAPA isn't recognised */
+    pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+
+    result = pop3_perform_authentication(conn);
+  }
 
   return result;
 }
@@ -975,10 +978,6 @@ static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn,
   char *rplyb64 = NULL;
   size_t len = 0;
 
-  char nonce[64];
-  char realm[128];
-  char algorithm[64];
-
   (void)instate; /* no use for this yet */
 
   if(pop3code != '+') {
@@ -989,29 +988,25 @@ static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn,
   /* Get the challenge message */
   pop3_get_message(data->state.buffer, &chlg64);
 
-  /* Decode the challange message */
-  result = Curl_sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
-                                               realm, sizeof(realm),
-                                               algorithm, sizeof(algorithm));
-  if(result || strcmp(algorithm, "md5-sess") != 0) {
-    /* Send the cancellation */
-    result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
+  /* Create the response message */
+  result = Curl_sasl_create_digest_md5_message(data, chlg64,
+                                               conn->user, conn->passwd,
+                                               "pop", &rplyb64, &len);
+  if(result) {
+    if(result == CURLE_BAD_CONTENT_ENCODING) {
+      /* Send the cancellation */
+      result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
 
-    if(!result)
-      state(conn, POP3_AUTH_CANCEL);
+      if(!result)
+        state(conn, POP3_AUTH_CANCEL);
+    }
   }
   else {
-    /* Create the response message */
-    result = Curl_sasl_create_digest_md5_message(data, nonce, realm,
-                                                 conn->user, conn->passwd,
-                                                 "pop", &rplyb64, &len);
-    if(!result && rplyb64) {
-      /* Send the response */
-      result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
+    /* Send the response */
+    result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
 
-      if(!result)
-        state(conn, POP3_AUTH_DIGESTMD5_RESP);
-    }
+    if(!result)
+      state(conn, POP3_AUTH_DIGESTMD5_RESP);
   }
 
   Curl_safefree(rplyb64);
@@ -1201,8 +1196,7 @@ static CURLcode pop3_state_auth_cancel_resp(struct connectdata *conn,
     }
 #ifndef CURL_DISABLE_CRYPTO_AUTH
     else if((pop3c->authtypes & POP3_TYPE_APOP) &&
-            (pop3c->preftype & POP3_TYPE_APOP) &&
-            (pop3c->apoptimestamp))
+            (pop3c->preftype & POP3_TYPE_APOP))
       /* Perform APOP authentication */
       result = pop3_perform_apop(conn);
 #endif
@@ -1553,7 +1547,7 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
   *done = FALSE; /* default to not done yet */
 
   /* We always support persistent connections in POP3 */
-  conn->bits.close = FALSE;
+  connkeep(conn, "POP3 default");
 
   /* Set the default response time-out */
   pp->response_time = RESP_TIMEOUT;
@@ -1607,7 +1601,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
     return CURLE_OK;
 
   if(status) {
-    conn->bits.close = TRUE; /* marked for closure */
+    connclose(conn, "POP3 done with bad status");
     result = status;         /* use the already set error code */
   }
 
@@ -1832,56 +1826,68 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
   struct pop3_conn *pop3c = &conn->proto.pop3c;
   const char *options = conn->options;
   const char *ptr = options;
+  bool reset = TRUE;
 
-  if(options) {
+  while(ptr && *ptr) {
     const char *key = ptr;
 
     while(*ptr && *ptr != '=')
         ptr++;
 
     if(strnequal(key, "AUTH", 4)) {
-      const char *value = ptr + 1;
+      size_t len = 0;
+      const char *value = ++ptr;
+
+      if(reset) {
+        reset = FALSE;
+        pop3c->preftype = POP3_TYPE_NONE;
+        pop3c->prefmech = SASL_AUTH_NONE;
+      }
 
-      if(strequal(value, "*")) {
+      while(*ptr && *ptr != ';') {
+        ptr++;
+        len++;
+      }
+
+      if(strnequal(value, "*", len)) {
         pop3c->preftype = POP3_TYPE_ANY;
         pop3c->prefmech = SASL_AUTH_ANY;
       }
-      else if(strequal(value, "+APOP")) {
+      else if(strnequal(value, "+APOP", len)) {
         pop3c->preftype = POP3_TYPE_APOP;
         pop3c->prefmech = SASL_AUTH_NONE;
       }
-      else if(strequal(value, SASL_MECH_STRING_LOGIN)) {
+      else if(strnequal(value, SASL_MECH_STRING_LOGIN, len)) {
         pop3c->preftype = POP3_TYPE_SASL;
-        pop3c->prefmech = SASL_MECH_LOGIN;
+        pop3c->prefmech |= SASL_MECH_LOGIN;
       }
-      else if(strequal(value, SASL_MECH_STRING_PLAIN)) {
+      else if(strnequal(value, SASL_MECH_STRING_PLAIN, len)) {
         pop3c->preftype = POP3_TYPE_SASL;
-        pop3c->prefmech = SASL_MECH_PLAIN;
+        pop3c->prefmech |= SASL_MECH_PLAIN;
       }
-      else if(strequal(value, SASL_MECH_STRING_CRAM_MD5)) {
+      else if(strnequal(value, SASL_MECH_STRING_CRAM_MD5, len)) {
         pop3c->preftype = POP3_TYPE_SASL;
-        pop3c->prefmech = SASL_MECH_CRAM_MD5;
+        pop3c->prefmech |= SASL_MECH_CRAM_MD5;
       }
-      else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5)) {
+      else if(strnequal(value, SASL_MECH_STRING_DIGEST_MD5, len)) {
         pop3c->preftype = POP3_TYPE_SASL;
-        pop3c->prefmech = SASL_MECH_DIGEST_MD5;
+        pop3c->prefmech |= SASL_MECH_DIGEST_MD5;
       }
-      else if(strequal(value, SASL_MECH_STRING_GSSAPI)) {
+      else if(strnequal(value, SASL_MECH_STRING_GSSAPI, len)) {
         pop3c->preftype = POP3_TYPE_SASL;
-        pop3c->prefmech = SASL_MECH_GSSAPI;
+        pop3c->prefmech |= SASL_MECH_GSSAPI;
       }
-      else if(strequal(value, SASL_MECH_STRING_NTLM)) {
+      else if(strnequal(value, SASL_MECH_STRING_NTLM, len)) {
         pop3c->preftype = POP3_TYPE_SASL;
-        pop3c->prefmech = SASL_MECH_NTLM;
+        pop3c->prefmech |= SASL_MECH_NTLM;
       }
-      else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) {
+      else if(strnequal(value, SASL_MECH_STRING_XOAUTH2, len)) {
         pop3c->preftype = POP3_TYPE_SASL;
-        pop3c->prefmech = SASL_MECH_XOAUTH2;
-      }
-      else {
-        pop3c->preftype = POP3_TYPE_NONE;
-        pop3c->prefmech = SASL_AUTH_NONE;
+        pop3c->prefmech |= SASL_MECH_XOAUTH2;
       }
+
+      if(*ptr == ';')
+        ptr++;
     }
     else
       result = CURLE_URL_MALFORMAT;