diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pop3.c | 99 | ||||
| -rw-r--r-- | lib/pop3.h | 2 | 
2 files changed, 97 insertions, 4 deletions
diff --git a/lib/pop3.c b/lib/pop3.c index 1e399a03b..8ce7f259b 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -84,6 +84,8 @@  #include "url.h"  #include "rawstr.h"  #include "curl_sasl.h" +#include "curl_md5.h" +#include "warnless.h"  #define _MPRINTF_REPLACE /* use our functions only */  #include <curl/mprintf.h> @@ -213,8 +215,9 @@ static const struct Curl_handler Curl_handler_pop3s_proxy = {  #endif  /* Function that checks for an ending pop3 status code at the start of the -   given string, but also detects the supported authentication types as well -   as the allowed SASL authentication mechanisms within the CAPA response. */ +   given string, but also detects the APOP timestamp from the server greeting +   as well as the supported authentication types and allowed SASL mechanisms +   from the CAPA response. */  static int pop3_endofresp(struct pingpong *pp, int *resp)  {    char *line = pp->linestart_resp; @@ -222,6 +225,7 @@ static int pop3_endofresp(struct pingpong *pp, int *resp)    struct connectdata *conn = pp->conn;    struct pop3_conn *pop3c = &conn->proto.pop3c;    size_t wordlen; +  size_t i;    /* Do we have an error response? */    if(len >= 4 && !memcmp("-ERR", line, 4)) { @@ -230,8 +234,31 @@ static int pop3_endofresp(struct pingpong *pp, int *resp)      return FALSE;    } -  /* Are we processing reponses to our CAPA command? */ -  if(pop3c->state == POP3_CAPA) { +  /* Are we processing servergreet responses */ +  if(pop3c->state == POP3_SERVERGREET) { +    /* Look for the APOP timestamp */ +    if(len >= 3 && line[len - 3] == '>') { +      for(i = 0; i < len - 3; ++i) { +        if(line[i] == '<') { +          /* Calculate the length of the timestamp */ +          size_t timestamplen = len - 2 - i; + +          /* Allocate some memory for the timestamp */ +          pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1); + +          if(!pop3c->apoptimestamp) +            break; + +          /* Copy the timestamp */ +          memcpy(pop3c->apoptimestamp, line + i, timestamplen); +          pop3c->apoptimestamp[timestamplen] = '\0'; +          break; +        } +      } +    } +  } +  /* Are we processing CAPA command responses? */ +  else if(pop3c->state == POP3_CAPA) {      /* Do we have the terminating character? */      if(len >= 1 && !memcmp(line, ".", 1)) { @@ -334,6 +361,7 @@ static void state(struct connectdata *conn, pop3state newstate)      "AUTH_NTLM",      "AUTH_NTLM_TYPE2MSG",      "AUTH", +    "APOP",      "USER",      "PASS",      "COMMAND", @@ -393,6 +421,40 @@ static CURLcode pop3_state_user(struct connectdata *conn)    return CURLE_OK;  } +static CURLcode pop3_state_apop(struct connectdata *conn) +{ +  CURLcode result = CURLE_OK; +  struct pop3_conn *pop3c = &conn->proto.pop3c; +  size_t i; +  MD5_context *ctxt; +  unsigned char digest[MD5_DIGEST_LEN]; +  char secret[2 * MD5_DIGEST_LEN + 1]; + +  ctxt = Curl_MD5_init(Curl_DIGEST_MD5); +  if(!ctxt) +    return CURLE_OUT_OF_MEMORY; + +  Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp, +                  curlx_uztoui(strlen(pop3c->apoptimestamp))); + +  Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd, +                  curlx_uztoui(strlen(conn->passwd))); + +  /* Finalise the digest */ +  Curl_MD5_final(ctxt, digest); + +  /* Convert the calculated 16 octet digest into a 32 byte hex string */ +  for(i = 0; i < MD5_DIGEST_LEN; i++) +    snprintf(&secret[2 * i], 3, "%02x", digest[i]); + +  result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret); + +  if(!result) +    state(conn, POP3_APOP); + +  return result; +} +  static CURLcode pop3_authenticate(struct connectdata *conn)  {    CURLcode result = CURLE_OK; @@ -542,6 +604,8 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn,      /* Check supported authentication types by decreasing order of security */      if(conn->proto.pop3c.authtypes & POP3_TYPE_SASL)        result = pop3_authenticate(conn); +    else if(conn->proto.pop3c.authtypes & POP3_TYPE_APOP) +      result = pop3_state_apop(conn);      else if(conn->proto.pop3c.authtypes & POP3_TYPE_CLEARTEXT)        result = pop3_state_user(conn);      else { @@ -883,6 +947,26 @@ static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,    return result;  } +static CURLcode pop3_state_apop_resp(struct connectdata *conn, +                                     int pop3code, +                                     pop3state instate) +{ +  CURLcode result = CURLE_OK; +  struct SessionHandle *data = conn->data; + +  (void)instate; /* no use for this yet */ + +  if(pop3code != '+') { +    failf(data, "Authentication failed: %d", pop3code); +    result = CURLE_LOGIN_DENIED; +  } + +  /* End of connect phase */ +  state(conn, POP3_STOP); + +  return result; +} +  /* For USER responses */  static CURLcode pop3_state_user_resp(struct connectdata *conn,                                       int pop3code, @@ -1100,6 +1184,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)        result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state);        break; +    case POP3_APOP: +      result = pop3_state_apop_resp(conn, pop3code, pop3c->state); +      break; +      case POP3_USER:        result = pop3_state_user_resp(conn, pop3code, pop3c->state);        break; @@ -1408,6 +1496,9 @@ static CURLcode pop3_disconnect(struct connectdata *conn,    Curl_pp_disconnect(&pop3c->pp); +  /* Clear our variables */ +  Curl_safefree(pop3c->apoptimestamp); +    /* Cleanup the SASL module */    Curl_sasl_cleanup(conn, pop3c->authused); diff --git a/lib/pop3.h b/lib/pop3.h index 1ca8bb289..1b6859955 100644 --- a/lib/pop3.h +++ b/lib/pop3.h @@ -40,6 +40,7 @@ typedef enum {    POP3_AUTH_NTLM,    POP3_AUTH_NTLM_TYPE2MSG,    POP3_AUTH, +  POP3_APOP,    POP3_USER,    POP3_PASS,    POP3_COMMAND, @@ -60,6 +61,7 @@ struct pop3_conn {    unsigned int authtypes; /* Supported authentication types */    unsigned int authmechs; /* Accepted SASL authentication mechanisms */    unsigned int authused;  /* SASL auth mechanism used for the connection */ +  char *apoptimestamp;    /* APOP timestamp from the server greeting */    pop3state state;        /* Always use pop3.c:state() to change state! */  };  | 
