]> granicus.if.org Git - curl/commitdiff
pop3: Added support for ;auth=<mech> in the URL
authorSteve Holme <steve_holme@hotmail.com>
Sat, 13 Apr 2013 15:09:28 +0000 (16:09 +0100)
committerSteve Holme <steve_holme@hotmail.com>
Sat, 13 Apr 2013 15:16:21 +0000 (16:16 +0100)
Added support for specifying the preferred authentication type and SASL
mechanism in the URL as per RFC-2384.

lib/pop3.c
lib/pop3.h

index 1dbe31816555eb17c283502d318d436822f2d093..ee4a713a8f49c05733048ec99f22f84b9934431f 100644 (file)
@@ -101,6 +101,7 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
                         int numsocks);
 static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
 static CURLcode pop3_setup_connection(struct connectdata *conn);
+static CURLcode pop3_parse_url_options(struct connectdata *conn);
 static CURLcode pop3_parse_url_path(struct connectdata *conn);
 static CURLcode pop3_parse_custom_request(struct connectdata *conn);
 
@@ -514,12 +515,14 @@ static CURLcode pop3_authenticate(struct connectdata *conn)
      security */
   if(pop3c->authtypes & POP3_TYPE_SASL) {
 #ifndef CURL_DISABLE_CRYPTO_AUTH
-    if(pop3c->authmechs & SASL_MECH_DIGEST_MD5) {
+    if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
+       (pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
       mech = "DIGEST-MD5";
       authstate = POP3_AUTH_DIGESTMD5;
       pop3c->authused = SASL_MECH_DIGEST_MD5;
     }
-    else if(pop3c->authmechs & SASL_MECH_CRAM_MD5) {
+    else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
+            (pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
       mech = "CRAM-MD5";
       authstate = POP3_AUTH_CRAMMD5;
       pop3c->authused = SASL_MECH_CRAM_MD5;
@@ -527,26 +530,29 @@ static CURLcode pop3_authenticate(struct connectdata *conn)
     else
 #endif
 #ifdef USE_NTLM
-    if(pop3c->authmechs & SASL_MECH_NTLM) {
+    if((pop3c->authmechs & SASL_MECH_NTLM) &&
+       (pop3c->prefmech & SASL_MECH_NTLM)) {
       mech = "NTLM";
       authstate = POP3_AUTH_NTLM;
       pop3c->authused = SASL_MECH_NTLM;
     }
     else
 #endif
-    if(pop3c->authmechs & SASL_MECH_LOGIN) {
+    if((pop3c->authmechs & SASL_MECH_LOGIN) &&
+       (pop3c->prefmech & SASL_MECH_LOGIN)) {
       mech = "LOGIN";
       authstate = POP3_AUTH_LOGIN;
       pop3c->authused = SASL_MECH_LOGIN;
     }
-    else if(pop3c->authmechs & SASL_MECH_PLAIN) {
+    else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
+            (pop3c->prefmech & SASL_MECH_PLAIN)) {
       mech = "PLAIN";
       authstate = POP3_AUTH_PLAIN;
       pop3c->authused = SASL_MECH_PLAIN;
     }
   }
 
-  if(mech) {
+  if(mech && (pop3c->preftype & POP3_TYPE_SASL)) {
     /* Perform SASL based authentication */
     result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
 
@@ -554,11 +560,13 @@ static CURLcode pop3_authenticate(struct connectdata *conn)
       state(conn, authstate);
   }
 #ifndef CURL_DISABLE_CRYPTO_AUTH
-  else if(pop3c->authtypes & POP3_TYPE_APOP)
+  else if((pop3c->authtypes & POP3_TYPE_APOP) &&
+          (pop3c->preftype & POP3_TYPE_APOP))
     /* Perform APOP authentication */
     result = pop3_state_apop(conn);
 #endif
-  else if(pop3c->authtypes & POP3_TYPE_CLEARTEXT)
+  else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) &&
+          (pop3c->preftype & POP3_TYPE_CLEARTEXT))
     /* Perform clear text authentication */
     result = pop3_state_user(conn);
   else {
@@ -1332,9 +1340,18 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
   pp->endofresp = pop3_endofresp;
   pp->conn = conn;
 
+  /* Set the default preferred authentication type and mechanism */
+  pop3c->preftype = POP3_TYPE_ANY;
+  pop3c->prefmech = SASL_AUTH_ANY;
+
   /* Initialise the pingpong layer */
   Curl_pp_init(pp);
 
+  /* Parse the URL options */
+  result = pop3_parse_url_options(conn);
+  if(result)
+    return result;
+
   /* Start off waiting for the server greeting response */
   state(conn, POP3_SERVERGREET);
 
@@ -1608,6 +1625,72 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
   return CURLE_OK;
 }
 
+/***********************************************************************
+ *
+ * pop3_parse_url_options()
+ *
+ * Parse the URL login options.
+ */
+static CURLcode pop3_parse_url_options(struct connectdata *conn)
+{
+  CURLcode result = CURLE_OK;
+  struct pop3_conn *pop3c = &conn->proto.pop3c;
+  const char *options = conn->options;
+  const char *ptr = options;
+
+  if(options) {
+    const char *key = ptr;
+
+    while(*ptr && *ptr != '=')
+        ptr++;
+
+    if(strnequal(key, "AUTH", 4)) {
+      const char *value = ptr + 1;
+
+      if(strequal(value, "*")) {
+        pop3c->preftype = POP3_TYPE_ANY;
+        pop3c->prefmech = SASL_AUTH_ANY;
+      }
+      else if(strequal(value, "+APOP")) {
+        pop3c->preftype = POP3_TYPE_APOP;
+        pop3c->prefmech = SASL_AUTH_NONE;
+      }
+      else if(strequal(value, "LOGIN")) {
+        pop3c->preftype = POP3_TYPE_SASL;
+        pop3c->prefmech = SASL_MECH_LOGIN;
+      }
+      else if(strequal(value, "PLAIN")) {
+        pop3c->preftype = POP3_TYPE_SASL;
+        pop3c->prefmech = SASL_MECH_PLAIN;
+      }
+      else if(strequal(value, "CRAM-MD5")) {
+        pop3c->preftype = POP3_TYPE_SASL;
+        pop3c->prefmech = SASL_MECH_CRAM_MD5;
+      }
+      else if(strequal(value, "DIGEST-MD5")) {
+        pop3c->preftype = POP3_TYPE_SASL;
+        pop3c->prefmech = SASL_MECH_DIGEST_MD5;
+      }
+      else if(strequal(value, "GSSAPI")) {
+        pop3c->preftype = POP3_TYPE_SASL;
+        pop3c->prefmech = SASL_MECH_GSSAPI;
+      }
+      else if(strequal(value, "NTLM")) {
+        pop3c->preftype = POP3_TYPE_SASL;
+        pop3c->prefmech = SASL_MECH_NTLM;
+      }
+      else {
+        pop3c->preftype = POP3_TYPE_NONE;
+        pop3c->prefmech = SASL_AUTH_NONE;
+      }
+    }
+    else
+      result = CURLE_URL_MALFORMAT;
+  }
+
+  return result;
+}
+
 /***********************************************************************
  *
  * pop3_parse_url_path()
index 129dffc71fabcd34f4419f699aff461916ec7ee7..5fd4b244e672df569f98afeeb6405356279ea3d3 100644 (file)
@@ -74,6 +74,8 @@ struct pop3_conn {
                              non-body */
   unsigned int authtypes; /* Supported authentication types */
   unsigned int authmechs; /* Accepted SASL authentication mechanisms */
+  unsigned int preftype;  /* Preferred authentication type */
+  unsigned int prefmech;  /* Preferred SASL authentication mechanism */
   unsigned int authused;  /* SASL auth mechanism used for the connection */
   char *apoptimestamp;    /* APOP timestamp from the server greeting */
   bool tls_supported;     /* StartTLS capability supported by server */
@@ -87,6 +89,10 @@ extern const struct Curl_handler Curl_handler_pop3s;
 #define POP3_TYPE_APOP      0x0002
 #define POP3_TYPE_SASL      0x0004
 
+/* Authentication type values */
+#define POP3_TYPE_NONE      0
+#define POP3_TYPE_ANY       ~0
+
 /* This is the 5-bytes End-Of-Body marker for POP3 */
 #define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
 #define POP3_EOB_LEN 5