Beispiel #1
0
static CURLcode pop3_authenticate(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  const char *mech = NULL;
  pop3state authstate = POP3_STOP;

  /* Check we have a username and password to authenticate with and end the
     connect phase if we don't */
  if(!conn->bits.user_passwd) {
    state(conn, POP3_STOP);

    return result;
  }

  /* Calculate the supported authentication mechanism by decreasing order of
     security */
  if(pop3c->authtypes & POP3_TYPE_SASL) {
#ifndef CURL_DISABLE_CRYPTO_AUTH
    if(pop3c->authmechs & 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) {
      mech = "CRAM-MD5";
      authstate = POP3_AUTH_CRAMMD5;
      pop3c->authused = SASL_MECH_CRAM_MD5;
    }
    else
#endif
#ifdef USE_NTLM
    if(pop3c->authmechs & SASL_MECH_NTLM) {
      mech = "NTLM";
      authstate = POP3_AUTH_NTLM;
      pop3c->authused = SASL_MECH_NTLM;
    }
    else
#endif
    if(pop3c->authmechs & SASL_MECH_LOGIN) {
      mech = "LOGIN";
      authstate = POP3_AUTH_LOGIN;
      pop3c->authused = SASL_MECH_LOGIN;
    }
    else if(pop3c->authmechs & SASL_MECH_PLAIN) {
      mech = "PLAIN";
      authstate = POP3_AUTH_PLAIN;
      pop3c->authused = SASL_MECH_PLAIN;
    }
  }

  if(mech) {
    /* Perform SASL based authentication */
    result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);

    if(!result)
      state(conn, authstate);
  }
#ifndef CURL_DISABLE_CRYPTO_AUTH
  else if(pop3c->authtypes & POP3_TYPE_APOP)
    /* Perform APOP authentication */
    result = pop3_state_apop(conn);
#endif
  else if(pop3c->authtypes & POP3_TYPE_CLEARTEXT)
    /* Perform clear text authentication */
    result = pop3_state_user(conn);
  else {
    /* Other mechanisms not supported */
    infof(conn->data, "No known authentication mechanisms supported!\n");
    result = CURLE_LOGIN_DENIED;
  }

  return result;
}
Beispiel #2
0
/* Start the DO phase */
static CURLcode smtp_mail(struct connectdata *conn)
{
  char *from = NULL;
  char *auth = NULL;
  char *size = NULL;
  CURLcode result = CURLE_OK;
  struct SessionHandle *data = conn->data;

  /* Calculate the FROM parameter */
  if(!data->set.str[STRING_MAIL_FROM])
    /* Null reverse-path, RFC-2821, sect. 3.7 */
    from = strdup("<>");
  else if(data->set.str[STRING_MAIL_FROM][0] == '<')
    from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
  else
    from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);

  if(!from)
    return CURLE_OUT_OF_MEMORY;

  /* Calculate the optional AUTH parameter */
  if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.authused) {
    if(data->set.str[STRING_MAIL_AUTH][0] != '\0')
      auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]);
    else
      /* Empty AUTH, RFC-2554, sect. 5 */
      auth = strdup("<>");

    if(!auth) {
      Curl_safefree(from);

      return CURLE_OUT_OF_MEMORY;
    }
  }

  /* calculate the optional SIZE parameter */
  if(conn->data->set.infilesize > 0) {
    size = aprintf("%" FORMAT_OFF_T, data->set.infilesize);

    if(!size) {
      Curl_safefree(from);
      Curl_safefree(auth);

      return CURLE_OUT_OF_MEMORY;
    }
  }

  /* Send the MAIL command */
  if(!auth && !size)
    result = Curl_pp_sendf(&conn->proto.smtpc.pp,
                           "MAIL FROM:%s", from);
  else if(auth && !size)
    result = Curl_pp_sendf(&conn->proto.smtpc.pp,
                           "MAIL FROM:%s AUTH=%s", from, auth);
  else if(auth && size)
    result = Curl_pp_sendf(&conn->proto.smtpc.pp,
                           "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size);
  else
    result = Curl_pp_sendf(&conn->proto.smtpc.pp,
                           "MAIL FROM:%s SIZE=%s", from, size);

  Curl_safefree(from);
  Curl_safefree(auth);
  Curl_safefree(size);

  if(result)
    return result;

  state(conn, SMTP_MAIL);

  return result;
}
Beispiel #3
0
static CURLcode pop3_statemach_act(struct connectdata *conn)
{
  CURLcode result;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  struct SessionHandle *data=conn->data;
  int pop3code;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  struct pingpong *pp = &pop3c->pp;
  size_t nread = 0;

  if(pp->sendleft)
    return Curl_pp_flushsend(pp);

  /* we read a piece of response */
  result = Curl_pp_readresp(sock, pp, &pop3code, &nread);
  if(result)
    return result;

  if(pop3code) {
    /* we have now received a full POP3 server response */
    switch(pop3c->state) {
    case POP3_SERVERGREET:
      if(pop3code != 'O') {
        failf(data, "Got unexpected pop3-server response");
        return CURLE_FTP_WEIRD_SERVER_REPLY;
      }

      if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
        /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch
           to TLS connection now */
        result = Curl_pp_sendf(&pop3c->pp, "STLS");
        state(conn, POP3_STARTTLS);
      }
      else
        result = pop3_state_user(conn);
      if(result)
        return result;
      break;

    case POP3_USER:
      result = pop3_state_user_resp(conn, pop3code, pop3c->state);
      break;

    case POP3_PASS:
      result = pop3_state_pass_resp(conn, pop3code, pop3c->state);
      break;

    case POP3_STARTTLS:
      result = pop3_state_starttls_resp(conn, pop3code, pop3c->state);
      break;

    case POP3_RETR:
      result = pop3_state_retr_resp(conn, pop3code, pop3c->state);
      break;

    case POP3_LIST:
      result = pop3_state_list_resp(conn, pop3code, pop3c->state);
      break;

    case POP3_LIST_SINGLE:
      result = pop3_state_list_single_resp(conn, pop3code, pop3c->state);
      break;

    case POP3_QUIT:
      /* fallthrough, just stop! */
    default:
      /* internal error */
      state(conn, POP3_STOP);
      break;
    }
  }
  return result;
}
Beispiel #4
0
static CURLcode smtp_authenticate(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  char *initresp = NULL;
  const char *mech = NULL;
  size_t len = 0;
  smtpstate state1 = SMTP_STOP;
  smtpstate state2 = SMTP_STOP;

  /* Check we have a username and password to authenticate with and end the
     connect phase if we don't */
  if(!conn->bits.user_passwd) {
    state(conn, SMTP_STOP);

    return result;
  }

  /* Check supported authentication mechanisms by decreasing order of
     security */
#ifndef CURL_DISABLE_CRYPTO_AUTH
  if(smtpc->authmechs & SASL_MECH_DIGEST_MD5) {
    mech = "DIGEST-MD5";
    state1 = SMTP_AUTH_DIGESTMD5;
    smtpc->authused = SASL_MECH_DIGEST_MD5;
  }
  else if(smtpc->authmechs & SASL_MECH_CRAM_MD5) {
    mech = "CRAM-MD5";
    state1 = SMTP_AUTH_CRAMMD5;
    smtpc->authused = SASL_MECH_CRAM_MD5;
  }
  else
#endif
#ifdef USE_NTLM
  if(smtpc->authmechs & SASL_MECH_NTLM) {
    mech = "NTLM";
    state1 = SMTP_AUTH_NTLM;
    state2 = SMTP_AUTH_NTLM_TYPE2MSG;
    smtpc->authused = SASL_MECH_NTLM;
    result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
                                                 &conn->ntlm,
                                                 &initresp, &len);
  }
  else
#endif
  if(smtpc->authmechs & SASL_MECH_LOGIN) {
    mech = "LOGIN";
    state1 = SMTP_AUTH_LOGIN;
    state2 = SMTP_AUTH_PASSWD;
    smtpc->authused = SASL_MECH_LOGIN;
    result = Curl_sasl_create_login_message(conn->data, conn->user,
                                            &initresp, &len);
  }
  else if(smtpc->authmechs & SASL_MECH_PLAIN) {
    mech = "PLAIN";
    state1 = SMTP_AUTH_PLAIN;
    state2 = SMTP_AUTH;
    smtpc->authused = SASL_MECH_PLAIN;
    result = Curl_sasl_create_plain_message(conn->data, conn->user,
                                            conn->passwd, &initresp, &len);
  }
  else {
    infof(conn->data, "No known authentication mechanisms supported!\n");
    result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported */
  }

  if(!result) {
    if(initresp &&
       strlen(mech) + len <= 512 - 8) { /* AUTH <mech> ...<crlf> */
       result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);

      if(!result)
        state(conn, state2);
    }
    else {
      result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);

      if(!result)
        state(conn, state1);
    }
    Curl_safefree(initresp);
  }

  return result;
}
Beispiel #5
0
/* for AUTH CRAM-MD5 responses. */
static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
                                         int smtpcode,
                                         smtpstate instate)
{
  CURLcode result = CURLE_OK;
  struct SessionHandle *data = conn->data;
  char * chlg64 = data->state.buffer;
  unsigned char * chlg;
  size_t chlglen;
  size_t l;
  char * rplyb64;
  HMAC_context * ctxt;
  unsigned char digest[16];
  char reply[MAX_CURL_USER_LENGTH + 32 /* 2 * size of MD5 digest */ + 1];

  (void)instate; /* no use for this yet */

  if(smtpcode != 334) {
    failf(data, "Access denied: %d", smtpcode);
    return CURLE_LOGIN_DENIED;
  }

  /* Get the challenge. */
  for (chlg64 += 4; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
    ;

  chlg = (unsigned char *) NULL;
  chlglen = 0;

  if(*chlg64 != '=') {
    for (l = strlen(chlg64); l--;)
      if(chlg64[l] != '\r' && chlg64[l] != '\n' && chlg64[l] != ' ' &&
       chlg64[l] != '\t')
        break;

    if(++l) {
      chlg64[l] = '\0';

      chlglen = Curl_base64_decode(chlg64, &chlg);
      if(!chlglen)
        return CURLE_OUT_OF_MEMORY;
    }
  }

  /* Compute digest. */
  ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
                        (const unsigned char *) conn->passwd,
                        (unsigned int)(strlen(conn->passwd)));

  if(!ctxt) {
    if(chlg)
      free(chlg);

    return CURLE_OUT_OF_MEMORY;
  }

  if(chlglen > 0)
    Curl_HMAC_update(ctxt, chlg, (unsigned int)(chlglen));

  if(chlg)
    free(chlg);

  Curl_HMAC_final(ctxt, digest);

  /* Prepare the reply. */
  snprintf(reply, sizeof reply,
   "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
   conn->user, digest[0], digest[1], digest[2], digest[3], digest[4], digest[5],
   digest[6], digest[7], digest[8], digest[9], digest[10], digest[11],
   digest[12], digest[13], digest[14], digest[15]);

  /* Encode it to base64 and send it. */
  l = Curl_base64_encode(data, reply, 0, &rplyb64);

  if(!l)
    result = CURLE_OUT_OF_MEMORY;
  else {
    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
    free(rplyb64);

    if(!result)
      state(conn, SMTP_AUTH);
  }

  return result;
}
Beispiel #6
0
static CURLcode smtp_authenticate(struct connectdata *conn)
{
  CURLcode result = CURLE_OK;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  char * initresp;
  const char * mech;
  size_t l;
  smtpstate state1;
  smtpstate state2;

  if(!conn->bits.user_passwd)
    state(conn, SMTP_STOP);             /* End of connect phase. */
  else {
    initresp = (char *) NULL;
    l = 1;

    /* Check supported authentication mechanisms by decreasing order of
       preference. */
    mech = (const char *) NULL;         /* Avoid compiler warnings. */
    state1 = SMTP_STOP;
    state2 = SMTP_STOP;

#ifndef CURL_DISABLE_CRYPTO_AUTH
    if(smtpc->authmechs & SMTP_AUTH_CRAM_MD5) {
      mech = "CRAM-MD5";
      state1 = SMTP_AUTHCRAM;
    }
    else
#endif
    if(smtpc->authmechs & SMTP_AUTH_PLAIN) {
      mech = "PLAIN";
      state1 = SMTP_AUTHPLAIN;
      state2 = SMTP_AUTH;
      l = smtp_auth_plain_data(conn, &initresp);
    }
    else if(smtpc->authmechs & SMTP_AUTH_LOGIN) {
      mech = "LOGIN";
      state1 = SMTP_AUTHLOGIN;
      state2 = SMTP_AUTHPASSWD;
      l = smtp_auth_login_user(conn, &initresp);
    }
    else {
      infof(conn->data, "No known auth mechanisms supported!\n");
      result = CURLE_LOGIN_DENIED;      /* Other mechanisms not supported. */
    }

    if(!result) {
      if(!l)
        result = CURLE_OUT_OF_MEMORY;
      else if(initresp &&
              l + strlen(mech) <= 512 - 8) {   /* AUTH <mech> ...<crlf> */
        result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
        free(initresp);

        if(!result)
          state(conn, state2);
      }
      else {
        Curl_safefree(initresp);

        result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);

        if(!result)
          state(conn, state1);
      }
    }
  }

  return result;
}
Beispiel #7
0
/***********************************************************************
 *
 * smtp_continue_auth()
 *
 * Sends SASL continuation data or cancellation.
 */
static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp)
{
  struct smtp_conn *smtpc = &conn->proto.smtpc;

  return Curl_pp_sendf(&smtpc->pp, "%s", resp);
}
Beispiel #8
0
static CURLcode smtp_statemach_act(struct connectdata *conn)
{
  CURLcode result;
  curl_socket_t sock = conn->sock[FIRSTSOCKET];
  struct SessionHandle *data=conn->data;
  int smtpcode;
  struct smtp_conn *smtpc = &conn->proto.smtpc;
  struct pingpong *pp = &smtpc->pp;
  size_t nread = 0;

  if(pp->sendleft)
    /* we have a piece of a command still left to send */
    return Curl_pp_flushsend(pp);

  /* we read a piece of response */
  result = Curl_pp_readresp(sock, pp, &smtpcode, &nread);
  if(result)
    return result;

  if(smtpcode) {
    /* we have now received a full SMTP server response */
    switch(smtpc->state) {
    case SMTP_SERVERGREET:
      if(smtpcode/100 != 2) {
        failf(data, "Got unexpected smtp-server response: %d", smtpcode);
        return CURLE_FTP_WEIRD_SERVER_REPLY;
      }

      if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) {
        /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch
           to TLS connection now */
        result = Curl_pp_sendf(&smtpc->pp, "STARTTLS", NULL);
        state(conn, SMTP_STARTTLS);
      }
      else
        result = smtp_state_ehlo(conn);
      if(result)
        return result;
      break;

    case SMTP_EHLO:
      result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state);
      break;

    case SMTP_MAIL:
      result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
      break;

    case SMTP_RCPT:
      result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state);
      break;

    case SMTP_STARTTLS:
      result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
      break;

    case SMTP_DATA:
      result = smtp_state_data_resp(conn, smtpcode, smtpc->state);
      break;

    case SMTP_QUIT:
      /* fallthrough, just stop! */
    default:
      /* internal error */
      state(conn, SMTP_STOP);
      break;
    }
  }
  return result;
}