Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

pop3: Added support for apop authentication

  • Loading branch information...
commit c09c621af7ad0bb81a5ab96ed0e0ce4e99ae3119 1 parent 4e430a8
Steve Holme authored June 09, 2012
1  RELEASE-NOTES
@@ -16,6 +16,7 @@ This release includes the following changes:
16 16
  o pop3: Added support for sasl ntlm authentication
17 17
  o pop3: Added support for sasl cram-md5 authentication
18 18
  o pop3: Added support for sasl digest-md5 authentication
  19
+ o pop3: Added support for apop authentication
19 20
 
20 21
 This release includes the following bugfixes:
21 22
 
99  lib/pop3.c
@@ -84,6 +84,8 @@
84 84
 #include "url.h"
85 85
 #include "rawstr.h"
86 86
 #include "curl_sasl.h"
  87
+#include "curl_md5.h"
  88
+#include "warnless.h"
87 89
 
88 90
 #define _MPRINTF_REPLACE /* use our functions only */
89 91
 #include <curl/mprintf.h>
@@ -213,8 +215,9 @@ static const struct Curl_handler Curl_handler_pop3s_proxy = {
213 215
 #endif
214 216
 
215 217
 /* Function that checks for an ending pop3 status code at the start of the
216  
-   given string, but also detects the supported authentication types as well
217  
-   as the allowed SASL authentication mechanisms within the CAPA response. */
  218
+   given string, but also detects the APOP timestamp from the server greeting
  219
+   as well as the supported authentication types and allowed SASL mechanisms
  220
+   from the CAPA response. */
218 221
 static int pop3_endofresp(struct pingpong *pp, int *resp)
219 222
 {
220 223
   char *line = pp->linestart_resp;
@@ -222,6 +225,7 @@ static int pop3_endofresp(struct pingpong *pp, int *resp)
222 225
   struct connectdata *conn = pp->conn;
223 226
   struct pop3_conn *pop3c = &conn->proto.pop3c;
224 227
   size_t wordlen;
  228
+  size_t i;
225 229
 
226 230
   /* Do we have an error response? */
227 231
   if(len >= 4 && !memcmp("-ERR", line, 4)) {
@@ -230,8 +234,31 @@ static int pop3_endofresp(struct pingpong *pp, int *resp)
230 234
     return FALSE;
231 235
   }
232 236
 
233  
-  /* Are we processing reponses to our CAPA command? */
234  
-  if(pop3c->state == POP3_CAPA) {
  237
+  /* Are we processing servergreet responses */
  238
+  if(pop3c->state == POP3_SERVERGREET) {
  239
+    /* Look for the APOP timestamp */
  240
+    if(len >= 3 && line[len - 3] == '>') {
  241
+      for(i = 0; i < len - 3; ++i) {
  242
+        if(line[i] == '<') {
  243
+          /* Calculate the length of the timestamp */
  244
+          size_t timestamplen = len - 2 - i;
  245
+
  246
+          /* Allocate some memory for the timestamp */
  247
+          pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1);
  248
+
  249
+          if(!pop3c->apoptimestamp)
  250
+            break;
  251
+
  252
+          /* Copy the timestamp */
  253
+          memcpy(pop3c->apoptimestamp, line + i, timestamplen);
  254
+          pop3c->apoptimestamp[timestamplen] = '\0';
  255
+          break;
  256
+        }
  257
+      }
  258
+    }
  259
+  }
  260
+  /* Are we processing CAPA command responses? */
  261
+  else if(pop3c->state == POP3_CAPA) {
235 262
 
236 263
     /* Do we have the terminating character? */
237 264
     if(len >= 1 && !memcmp(line, ".", 1)) {
@@ -334,6 +361,7 @@ static void state(struct connectdata *conn, pop3state newstate)
334 361
     "AUTH_NTLM",
335 362
     "AUTH_NTLM_TYPE2MSG",
336 363
     "AUTH",
  364
+    "APOP",
337 365
     "USER",
338 366
     "PASS",
339 367
     "COMMAND",
@@ -393,6 +421,40 @@ static CURLcode pop3_state_user(struct connectdata *conn)
393 421
   return CURLE_OK;
394 422
 }
395 423
 
  424
+static CURLcode pop3_state_apop(struct connectdata *conn)
  425
+{
  426
+  CURLcode result = CURLE_OK;
  427
+  struct pop3_conn *pop3c = &conn->proto.pop3c;
  428
+  size_t i;
  429
+  MD5_context *ctxt;
  430
+  unsigned char digest[MD5_DIGEST_LEN];
  431
+  char secret[2 * MD5_DIGEST_LEN + 1];
  432
+
  433
+  ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
  434
+  if(!ctxt)
  435
+    return CURLE_OUT_OF_MEMORY;
  436
+
  437
+  Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp,
  438
+                  curlx_uztoui(strlen(pop3c->apoptimestamp)));
  439
+
  440
+  Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd,
  441
+                  curlx_uztoui(strlen(conn->passwd)));
  442
+
  443
+  /* Finalise the digest */
  444
+  Curl_MD5_final(ctxt, digest);
  445
+
  446
+  /* Convert the calculated 16 octet digest into a 32 byte hex string */
  447
+  for(i = 0; i < MD5_DIGEST_LEN; i++)
  448
+    snprintf(&secret[2 * i], 3, "%02x", digest[i]);
  449
+
  450
+  result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret);
  451
+
  452
+  if(!result)
  453
+    state(conn, POP3_APOP);
  454
+
  455
+  return result;
  456
+}
  457
+
396 458
 static CURLcode pop3_authenticate(struct connectdata *conn)
397 459
 {
398 460
   CURLcode result = CURLE_OK;
@@ -542,6 +604,8 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn,
542 604
     /* Check supported authentication types by decreasing order of security */
543 605
     if(conn->proto.pop3c.authtypes & POP3_TYPE_SASL)
544 606
       result = pop3_authenticate(conn);
  607
+    else if(conn->proto.pop3c.authtypes & POP3_TYPE_APOP)
  608
+      result = pop3_state_apop(conn);
545 609
     else if(conn->proto.pop3c.authtypes & POP3_TYPE_CLEARTEXT)
546 610
       result = pop3_state_user(conn);
547 611
     else {
@@ -883,6 +947,26 @@ static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,
883 947
   return result;
884 948
 }
885 949
 
  950
+static CURLcode pop3_state_apop_resp(struct connectdata *conn,
  951
+                                     int pop3code,
  952
+                                     pop3state instate)
  953
+{
  954
+  CURLcode result = CURLE_OK;
  955
+  struct SessionHandle *data = conn->data;
  956
+
  957
+  (void)instate; /* no use for this yet */
  958
+
  959
+  if(pop3code != '+') {
  960
+    failf(data, "Authentication failed: %d", pop3code);
  961
+    result = CURLE_LOGIN_DENIED;
  962
+  }
  963
+
  964
+  /* End of connect phase */
  965
+  state(conn, POP3_STOP);
  966
+
  967
+  return result;
  968
+}
  969
+
886 970
 /* For USER responses */
887 971
 static CURLcode pop3_state_user_resp(struct connectdata *conn,
888 972
                                      int pop3code,
@@ -1100,6 +1184,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
1100 1184
       result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state);
1101 1185
       break;
1102 1186
 
  1187
+    case POP3_APOP:
  1188
+      result = pop3_state_apop_resp(conn, pop3code, pop3c->state);
  1189
+      break;
  1190
+
1103 1191
     case POP3_USER:
1104 1192
       result = pop3_state_user_resp(conn, pop3code, pop3c->state);
1105 1193
       break;
@@ -1408,6 +1496,9 @@ static CURLcode pop3_disconnect(struct connectdata *conn,
1408 1496
 
1409 1497
   Curl_pp_disconnect(&pop3c->pp);
1410 1498
 
  1499
+  /* Clear our variables */
  1500
+  Curl_safefree(pop3c->apoptimestamp);
  1501
+
1411 1502
   /* Cleanup the SASL module */
1412 1503
   Curl_sasl_cleanup(conn, pop3c->authused);
1413 1504
 
2  lib/pop3.h
@@ -40,6 +40,7 @@ typedef enum {
40 40
   POP3_AUTH_NTLM,
41 41
   POP3_AUTH_NTLM_TYPE2MSG,
42 42
   POP3_AUTH,
  43
+  POP3_APOP,
43 44
   POP3_USER,
44 45
   POP3_PASS,
45 46
   POP3_COMMAND,
@@ -60,6 +61,7 @@ struct pop3_conn {
60 61
   unsigned int authtypes; /* Supported authentication types */
61 62
   unsigned int authmechs; /* Accepted SASL authentication mechanisms */
62 63
   unsigned int authused;  /* SASL auth mechanism used for the connection */
  64
+  char *apoptimestamp;    /* APOP timestamp from the server greeting */
63 65
   pop3state state;        /* Always use pop3.c:state() to change state! */
64 66
 };
65 67
 

0 notes on commit c09c621

Please sign in to comment.
Something went wrong with that request. Please try again.