~ubuntu-branches/ubuntu/trusty/curl/trusty

« back to all changes in this revision

Viewing changes to lib/pop3.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2014-01-31 08:42:28 UTC
  • mfrom: (3.4.45 sid)
  • Revision ID: package-import@ubuntu.com-20140131084228-rnste9wj6fqiy9zl
Tags: 7.35.0-1ubuntu1
* Resynchronize on Debian, remaining changes:
  - Drop dependencies not in main:
    + Build-Depends: Drop stunnel4 and libssh2-1-dev.
    + Drop libssh2-1-dev from binary package Depends.
  - Add new libcurl3-udeb package.
  - Add new curl-udeb package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
73
73
 
74
74
#include "strtoofft.h"
75
75
#include "strequal.h"
76
 
#include "sslgen.h"
 
76
#include "vtls/vtls.h"
77
77
#include "connect.h"
78
78
#include "strerror.h"
79
79
#include "select.h"
106
106
static CURLcode pop3_parse_url_options(struct connectdata *conn);
107
107
static CURLcode pop3_parse_url_path(struct connectdata *conn);
108
108
static CURLcode pop3_parse_custom_request(struct connectdata *conn);
 
109
static CURLcode pop3_calc_sasl_details(struct connectdata *conn,
 
110
                                       const char **mech,
 
111
                                       char **initresp, size_t *len,
 
112
                                       pop3state *state1, pop3state *state2);
109
113
 
110
114
/*
111
115
 * POP3 protocol handler.
232
236
                           int *resp)
233
237
{
234
238
  struct pop3_conn *pop3c = &conn->proto.pop3c;
235
 
  size_t wordlen;
236
 
  size_t i;
237
239
 
238
240
  /* Do we have an error response? */
239
241
  if(len >= 4 && !memcmp("-ERR", line, 4)) {
242
244
    return TRUE;
243
245
  }
244
246
 
245
 
  /* Are we processing servergreet responses? */
246
 
  if(pop3c->state == POP3_SERVERGREET) {
247
 
    /* Look for the APOP timestamp */
248
 
    if(len >= 3 && line[len - 3] == '>') {
249
 
      for(i = 0; i < len - 3; ++i) {
250
 
        if(line[i] == '<') {
251
 
          /* Calculate the length of the timestamp */
252
 
          size_t timestamplen = len - 2 - i;
253
 
 
254
 
          /* Allocate some memory for the timestamp */
255
 
          pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1);
256
 
 
257
 
          if(!pop3c->apoptimestamp)
258
 
            break;
259
 
 
260
 
          /* Copy the timestamp */
261
 
          memcpy(pop3c->apoptimestamp, line + i, timestamplen);
262
 
          pop3c->apoptimestamp[timestamplen] = '\0';
263
 
          break;
264
 
        }
265
 
      }
266
 
    }
267
 
  }
268
247
  /* Are we processing CAPA command responses? */
269
 
  else if(pop3c->state == POP3_CAPA) {
 
248
  if(pop3c->state == POP3_CAPA) {
270
249
    /* Do we have the terminating line? */
271
 
    if(len >= 1 && !memcmp(line, ".", 1)) {
 
250
    if(len >= 1 && !memcmp(line, ".", 1))
272
251
      *resp = '+';
273
 
 
274
 
      return TRUE;
275
 
    }
276
 
 
277
 
    /* Does the server support the STLS capability? */
278
 
    if(len >= 4 && !memcmp(line, "STLS", 4))
279
 
      pop3c->tls_supported = TRUE;
280
 
 
281
 
    /* Does the server support clear text authentication? */
282
 
    else if(len >= 4 && !memcmp(line, "USER", 4))
283
 
      pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
284
 
 
285
 
    /* Does the server support APOP authentication? */
286
 
    else if(len >= 4 && !memcmp(line, "APOP", 4))
287
 
      pop3c->authtypes |= POP3_TYPE_APOP;
288
 
 
289
 
    /* Does the server support SASL based authentication? */
290
 
    else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
291
 
      pop3c->authtypes |= POP3_TYPE_SASL;
292
 
 
293
 
      /* Advance past the SASL keyword */
294
 
      line += 5;
295
 
      len -= 5;
296
 
 
297
 
      /* Loop through the data line */
298
 
      for(;;) {
299
 
        while(len &&
300
 
              (*line == ' ' || *line == '\t' ||
301
 
               *line == '\r' || *line == '\n')) {
302
 
 
303
 
          line++;
304
 
          len--;
305
 
        }
306
 
 
307
 
        if(!len)
308
 
          break;
309
 
 
310
 
        /* Extract the word */
311
 
        for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
312
 
              line[wordlen] != '\t' && line[wordlen] != '\r' &&
313
 
              line[wordlen] != '\n';)
314
 
          wordlen++;
315
 
 
316
 
        /* Test the word for a matching authentication mechanism */
317
 
        if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
318
 
          pop3c->authmechs |= SASL_MECH_LOGIN;
319
 
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
320
 
          pop3c->authmechs |= SASL_MECH_PLAIN;
321
 
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
322
 
          pop3c->authmechs |= SASL_MECH_CRAM_MD5;
323
 
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
324
 
          pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
325
 
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
326
 
          pop3c->authmechs |= SASL_MECH_GSSAPI;
327
 
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
328
 
          pop3c->authmechs |= SASL_MECH_EXTERNAL;
329
 
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
330
 
          pop3c->authmechs |= SASL_MECH_NTLM;
331
 
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
332
 
          pop3c->authmechs |= SASL_MECH_XOAUTH2;
333
 
 
334
 
        line += wordlen;
335
 
        len -= wordlen;
336
 
      }
337
 
    }
338
 
 
339
 
    return FALSE;
 
252
    else
 
253
      *resp = '*';
 
254
 
 
255
    return TRUE;
340
256
  }
341
257
 
342
258
  /* Do we have a command or continuation response? */
574
490
 
575
491
/***********************************************************************
576
492
 *
577
 
 * pop3_perform_authenticate()
578
 
 *
579
 
 * Sends an AUTH command allowing the client to login with the appropriate
580
 
 * SASL authentication mechanism.
581
 
 *
582
 
 * Additionally, the function will perform fallback to APOP and USER commands
583
 
 * should a common mechanism not be available between the client and server.
584
 
 */
585
 
static CURLcode pop3_perform_authenticate(struct connectdata *conn)
586
 
{
587
 
  CURLcode result = CURLE_OK;
588
 
  struct SessionHandle *data = conn->data;
 
493
 * pop3_perform_auth()
 
494
 *
 
495
 * Sends an AUTH command allowing the client to login with the given SASL
 
496
 * authentication mechanism.
 
497
 */
 
498
static CURLcode pop3_perform_auth(struct connectdata *conn,
 
499
                                  const char *mech,
 
500
                                  const char *initresp, size_t len,
 
501
                                  pop3state state1, pop3state state2)
 
502
{
 
503
  CURLcode result = CURLE_OK;
 
504
  struct pop3_conn *pop3c = &conn->proto.pop3c;
 
505
 
 
506
  if(initresp && 8 + strlen(mech) + len <= 255) { /* AUTH <mech> ...<crlf> */
 
507
    /* Send the AUTH command with the initial response */
 
508
    result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp);
 
509
 
 
510
    if(!result)
 
511
      state(conn, state2);
 
512
  }
 
513
  else {
 
514
    /* Send the AUTH command */
 
515
    result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
 
516
 
 
517
    if(!result)
 
518
      state(conn, state1);
 
519
  }
 
520
 
 
521
  return result;
 
522
}
 
523
 
 
524
/***********************************************************************
 
525
 *
 
526
 * pop3_perform_authentication()
 
527
 *
 
528
 * Initiates the authentication sequence, with the appropriate SASL
 
529
 * authentication mechanism, falling back to APOP and clear text should a
 
530
 * common mechanism not be available between the client and server.
 
531
 */
 
532
static CURLcode pop3_perform_authentication(struct connectdata *conn)
 
533
{
 
534
  CURLcode result = CURLE_OK;
589
535
  struct pop3_conn *pop3c = &conn->proto.pop3c;
590
536
  const char *mech = NULL;
591
537
  char *initresp = NULL;
601
547
    return result;
602
548
  }
603
549
 
604
 
  /* Calculate the supported authentication mechanism, by decreasing order of
605
 
     security, as well as the initial response where appropriate */
606
 
  if(pop3c->authtypes & POP3_TYPE_SASL) {
607
 
#ifndef CURL_DISABLE_CRYPTO_AUTH
608
 
    if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
609
 
       (pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
610
 
      mech = SASL_MECH_STRING_DIGEST_MD5;
611
 
      state1 = POP3_AUTH_DIGESTMD5;
612
 
      pop3c->authused = SASL_MECH_DIGEST_MD5;
613
 
    }
614
 
    else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
615
 
            (pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
616
 
      mech = SASL_MECH_STRING_CRAM_MD5;
617
 
      state1 = POP3_AUTH_CRAMMD5;
618
 
      pop3c->authused = SASL_MECH_CRAM_MD5;
619
 
    }
620
 
    else
621
 
#endif
622
 
#ifdef USE_NTLM
623
 
    if((pop3c->authmechs & SASL_MECH_NTLM) &&
624
 
       (pop3c->prefmech & SASL_MECH_NTLM)) {
625
 
      mech = SASL_MECH_STRING_NTLM;
626
 
      state1 = POP3_AUTH_NTLM;
627
 
      state2 = POP3_AUTH_NTLM_TYPE2MSG;
628
 
      pop3c->authused = SASL_MECH_NTLM;
629
 
 
630
 
      if(data->set.sasl_ir)
631
 
        result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
632
 
                                                     &conn->ntlm,
633
 
                                                     &initresp, &len);
634
 
    }
635
 
    else
636
 
#endif
637
 
    if(((pop3c->authmechs & SASL_MECH_XOAUTH2) &&
638
 
        (pop3c->prefmech & SASL_MECH_XOAUTH2) &&
639
 
        (pop3c->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
640
 
      mech = SASL_MECH_STRING_XOAUTH2;
641
 
      state1 = POP3_AUTH_XOAUTH2;
642
 
      state2 = POP3_AUTH_FINAL;
643
 
      pop3c->authused = SASL_MECH_XOAUTH2;
644
 
 
645
 
      if(data->set.sasl_ir)
646
 
        result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
647
 
                                                  conn->xoauth2_bearer,
648
 
                                                  &initresp, &len);
649
 
    }
650
 
    else if((pop3c->authmechs & SASL_MECH_LOGIN) &&
651
 
       (pop3c->prefmech & SASL_MECH_LOGIN)) {
652
 
      mech = SASL_MECH_STRING_LOGIN;
653
 
      state1 = POP3_AUTH_LOGIN;
654
 
      state2 = POP3_AUTH_LOGIN_PASSWD;
655
 
      pop3c->authused = SASL_MECH_LOGIN;
656
 
 
657
 
      if(data->set.sasl_ir)
658
 
        result = Curl_sasl_create_login_message(conn->data, conn->user,
659
 
                                                &initresp, &len);
660
 
    }
661
 
    else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
662
 
            (pop3c->prefmech & SASL_MECH_PLAIN)) {
663
 
      mech = SASL_MECH_STRING_PLAIN;
664
 
      state1 = POP3_AUTH_PLAIN;
665
 
      state2 = POP3_AUTH_FINAL;
666
 
      pop3c->authused = SASL_MECH_PLAIN;
667
 
 
668
 
      if(data->set.sasl_ir)
669
 
        result = Curl_sasl_create_plain_message(conn->data, conn->user,
670
 
                                                conn->passwd, &initresp,
671
 
                                                &len);
672
 
    }
673
 
  }
 
550
  /* Calculate the SASL login details */
 
551
  if(pop3c->authtypes & POP3_TYPE_SASL)
 
552
    result = pop3_calc_sasl_details(conn, &mech, &initresp, &len, &state1,
 
553
                                    &state2);
674
554
 
675
555
  if(!result) {
676
556
    if(mech && (pop3c->preftype & POP3_TYPE_SASL)) {
677
557
      /* Perform SASL based authentication */
678
 
      if(initresp &&
679
 
         8 + strlen(mech) + len <= 255) { /* AUTH <mech> ...<crlf> */
680
 
        result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp);
681
 
 
682
 
        if(!result)
683
 
          state(conn, state2);
684
 
      }
685
 
      else {
686
 
        result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
687
 
 
688
 
        if(!result)
689
 
          state(conn, state1);
690
 
      }
 
558
      result = pop3_perform_auth(conn, mech, initresp, len, state1, state2);
691
559
 
692
560
      Curl_safefree(initresp);
693
561
    }
777
645
{
778
646
  CURLcode result = CURLE_OK;
779
647
  struct SessionHandle *data = conn->data;
 
648
  struct pop3_conn *pop3c = &conn->proto.pop3c;
 
649
  const char *line = data->state.buffer;
 
650
  size_t len = strlen(line);
 
651
  size_t i;
780
652
 
781
653
  (void)instate; /* no use for this yet */
782
654
 
784
656
    failf(data, "Got unexpected pop3-server response");
785
657
    result = CURLE_FTP_WEIRD_SERVER_REPLY;
786
658
  }
787
 
  else
 
659
  else {
 
660
    /* Does the server support APOP authentication? */
 
661
    if(len >= 4 && line[len - 2] == '>') {
 
662
      /* Look for the APOP timestamp */
 
663
      for(i = 3; i < len - 2; ++i) {
 
664
        if(line[i] == '<') {
 
665
          /* Calculate the length of the timestamp */
 
666
          size_t timestamplen = len - 1 - i;
 
667
          if(!timestamplen)
 
668
            break;
 
669
 
 
670
          /* Allocate some memory for the timestamp */
 
671
          pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1);
 
672
 
 
673
          if(!pop3c->apoptimestamp)
 
674
            break;
 
675
 
 
676
          /* Copy the timestamp */
 
677
          memcpy(pop3c->apoptimestamp, line + i, timestamplen);
 
678
          pop3c->apoptimestamp[timestamplen] = '\0';
 
679
 
 
680
          /* Store the APOP capability */
 
681
          pop3c->authtypes |= POP3_TYPE_APOP;
 
682
          break;
 
683
        }
 
684
      }
 
685
    }
 
686
 
788
687
    result = pop3_perform_capa(conn);
 
688
  }
789
689
 
790
690
  return result;
791
691
}
797
697
  CURLcode result = CURLE_OK;
798
698
  struct SessionHandle *data = conn->data;
799
699
  struct pop3_conn *pop3c = &conn->proto.pop3c;
 
700
  const char *line = data->state.buffer;
 
701
  size_t len = strlen(line);
 
702
  size_t wordlen;
800
703
 
801
704
  (void)instate; /* no use for this yet */
802
705
 
803
 
  if(pop3code != '+')
804
 
    result = pop3_perform_user(conn);
805
 
  else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
806
 
    /* We don't have a SSL/TLS connection yet, but SSL is requested */
807
 
    if(pop3c->tls_supported)
808
 
      /* Switch to TLS connection now */
809
 
      result = pop3_perform_starttls(conn);
810
 
    else if(data->set.use_ssl == CURLUSESSL_TRY)
811
 
      /* Fallback and carry on with authentication */
812
 
      result = pop3_perform_authenticate(conn);
813
 
    else {
814
 
      failf(data, "STLS not supported.");
815
 
      result = CURLE_USE_SSL_FAILED;
816
 
    }
817
 
  }
818
 
  else
819
 
    result = pop3_perform_authenticate(conn);
 
706
  /* Do we have a untagged response? */
 
707
  if(pop3code == '*') {
 
708
    /* Does the server support the STLS capability? */
 
709
    if(len >= 4 && !memcmp(line, "STLS", 4))
 
710
      pop3c->tls_supported = TRUE;
 
711
 
 
712
    /* Does the server support clear text authentication? */
 
713
    else if(len >= 4 && !memcmp(line, "USER", 4))
 
714
      pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
 
715
 
 
716
    /* Does the server support SASL based authentication? */
 
717
    else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
 
718
      pop3c->authtypes |= POP3_TYPE_SASL;
 
719
 
 
720
      /* Advance past the SASL keyword */
 
721
      line += 5;
 
722
      len -= 5;
 
723
 
 
724
      /* Loop through the data line */
 
725
      for(;;) {
 
726
        while(len &&
 
727
              (*line == ' ' || *line == '\t' ||
 
728
               *line == '\r' || *line == '\n')) {
 
729
 
 
730
          line++;
 
731
          len--;
 
732
        }
 
733
 
 
734
        if(!len)
 
735
          break;
 
736
 
 
737
        /* Extract the word */
 
738
        for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
 
739
              line[wordlen] != '\t' && line[wordlen] != '\r' &&
 
740
              line[wordlen] != '\n';)
 
741
          wordlen++;
 
742
 
 
743
        /* Test the word for a matching authentication mechanism */
 
744
        if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
 
745
          pop3c->authmechs |= SASL_MECH_LOGIN;
 
746
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
 
747
          pop3c->authmechs |= SASL_MECH_PLAIN;
 
748
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
 
749
          pop3c->authmechs |= SASL_MECH_CRAM_MD5;
 
750
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
 
751
          pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
 
752
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
 
753
          pop3c->authmechs |= SASL_MECH_GSSAPI;
 
754
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
 
755
          pop3c->authmechs |= SASL_MECH_EXTERNAL;
 
756
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
 
757
          pop3c->authmechs |= SASL_MECH_NTLM;
 
758
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
 
759
          pop3c->authmechs |= SASL_MECH_XOAUTH2;
 
760
 
 
761
        line += wordlen;
 
762
        len -= wordlen;
 
763
      }
 
764
    }
 
765
  }
 
766
  else if(pop3code == '+') {
 
767
    if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
 
768
      /* We don't have a SSL/TLS connection yet, but SSL is requested */
 
769
      if(pop3c->tls_supported)
 
770
        /* Switch to TLS connection now */
 
771
        result = pop3_perform_starttls(conn);
 
772
      else if(data->set.use_ssl == CURLUSESSL_TRY)
 
773
        /* Fallback and carry on with authentication */
 
774
        result = pop3_perform_authentication(conn);
 
775
      else {
 
776
        failf(data, "STLS not supported.");
 
777
        result = CURLE_USE_SSL_FAILED;
 
778
      }
 
779
    }
 
780
    else
 
781
      result = pop3_perform_authentication(conn);
 
782
  }
 
783
  else {
 
784
    /* Clear text is supported when CAPA isn't recognised */
 
785
    pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
 
786
 
 
787
    result = pop3_perform_authentication(conn);
 
788
  }
820
789
 
821
790
  return result;
822
791
}
837
806
      result = CURLE_USE_SSL_FAILED;
838
807
    }
839
808
    else
840
 
      result = pop3_perform_authenticate(conn);
 
809
      result = pop3_perform_authentication(conn);
841
810
  }
842
811
  else
843
812
    result = pop3_perform_upgrade_tls(conn);
1205
1174
                                            int pop3code,
1206
1175
                                            pop3state instate)
1207
1176
{
 
1177
  CURLcode result = CURLE_OK;
1208
1178
  struct SessionHandle *data = conn->data;
 
1179
  struct pop3_conn *pop3c = &conn->proto.pop3c;
 
1180
  const char *mech = NULL;
 
1181
  char *initresp = NULL;
 
1182
  size_t len = 0;
 
1183
  pop3state state1 = POP3_STOP;
 
1184
  pop3state state2 = POP3_STOP;
1209
1185
 
1210
1186
  (void)pop3code;
1211
1187
  (void)instate; /* no use for this yet */
1212
1188
 
1213
 
  failf(data, "Authentication cancelled");
1214
 
 
1215
 
  return CURLE_LOGIN_DENIED;
 
1189
  /* Remove the offending mechanism from the supported list */
 
1190
  pop3c->authmechs ^= pop3c->authused;
 
1191
 
 
1192
  /* Calculate alternative SASL login details */
 
1193
  result = pop3_calc_sasl_details(conn, &mech, &initresp, &len, &state1,
 
1194
                                  &state2);
 
1195
 
 
1196
  if(!result) {
 
1197
    /* Do we have any mechanisms left or can we fallback to another
 
1198
       authentication type? */
 
1199
    if(mech) {
 
1200
      /* Retry SASL based authentication */
 
1201
      result = pop3_perform_auth(conn, mech, initresp, len, state1, state2);
 
1202
 
 
1203
      Curl_safefree(initresp);
 
1204
    }
 
1205
#ifndef CURL_DISABLE_CRYPTO_AUTH
 
1206
    else if((pop3c->authtypes & POP3_TYPE_APOP) &&
 
1207
            (pop3c->preftype & POP3_TYPE_APOP))
 
1208
      /* Perform APOP authentication */
 
1209
      result = pop3_perform_apop(conn);
 
1210
#endif
 
1211
    else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) &&
 
1212
            (pop3c->preftype & POP3_TYPE_CLEARTEXT))
 
1213
      /* Perform clear text authentication */
 
1214
      result = pop3_perform_user(conn);
 
1215
    else {
 
1216
      failf(data, "Authentication cancelled");
 
1217
 
 
1218
      result = CURLE_LOGIN_DENIED;
 
1219
    }
 
1220
  }
 
1221
 
 
1222
  return result;
1216
1223
}
1217
1224
 
1218
1225
/* For final responses in the AUTH sequence */
1375
1382
  if(pp->sendleft)
1376
1383
    return Curl_pp_flushsend(pp);
1377
1384
 
1378
 
  /* Read the response from the server */
1379
 
  result = Curl_pp_readresp(sock, pp, &pop3code, &nread);
1380
 
  if(result)
1381
 
    return result;
1382
 
 
1383
 
  if(pop3code) {
 
1385
 do {
 
1386
    /* Read the response from the server */
 
1387
    result = Curl_pp_readresp(sock, pp, &pop3code, &nread);
 
1388
    if(result)
 
1389
      return result;
 
1390
 
 
1391
    if(!pop3code)
 
1392
      break;
 
1393
 
1384
1394
    /* We have now received a full POP3 server response */
1385
1395
    switch(pop3c->state) {
1386
1396
    case POP3_SERVERGREET:
1470
1480
      state(conn, POP3_STOP);
1471
1481
      break;
1472
1482
    }
1473
 
  }
 
1483
  } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp));
1474
1484
 
1475
1485
  return result;
1476
1486
}
1824
1834
  struct pop3_conn *pop3c = &conn->proto.pop3c;
1825
1835
  const char *options = conn->options;
1826
1836
  const char *ptr = options;
 
1837
  bool reset = TRUE;
1827
1838
 
1828
 
  if(options) {
 
1839
  while(ptr && *ptr) {
1829
1840
    const char *key = ptr;
1830
1841
 
1831
1842
    while(*ptr && *ptr != '=')
1832
1843
        ptr++;
1833
1844
 
1834
1845
    if(strnequal(key, "AUTH", 4)) {
1835
 
      const char *value = ptr + 1;
1836
 
 
1837
 
      if(strequal(value, "*")) {
 
1846
      size_t len = 0;
 
1847
      const char *value = ++ptr;
 
1848
 
 
1849
      if(reset) {
 
1850
        reset = FALSE;
 
1851
        pop3c->preftype = POP3_TYPE_NONE;
 
1852
        pop3c->prefmech = SASL_AUTH_NONE;
 
1853
      }
 
1854
 
 
1855
      while(*ptr && *ptr != ';') {
 
1856
        ptr++;
 
1857
        len++;
 
1858
      }
 
1859
 
 
1860
      if(strnequal(value, "*", len)) {
1838
1861
        pop3c->preftype = POP3_TYPE_ANY;
1839
1862
        pop3c->prefmech = SASL_AUTH_ANY;
1840
1863
      }
1841
 
      else if(strequal(value, "+APOP")) {
 
1864
      else if(strnequal(value, "+APOP", len)) {
1842
1865
        pop3c->preftype = POP3_TYPE_APOP;
1843
1866
        pop3c->prefmech = SASL_AUTH_NONE;
1844
1867
      }
1845
 
      else if(strequal(value, SASL_MECH_STRING_LOGIN)) {
1846
 
        pop3c->preftype = POP3_TYPE_SASL;
1847
 
        pop3c->prefmech = SASL_MECH_LOGIN;
1848
 
      }
1849
 
      else if(strequal(value, SASL_MECH_STRING_PLAIN)) {
1850
 
        pop3c->preftype = POP3_TYPE_SASL;
1851
 
        pop3c->prefmech = SASL_MECH_PLAIN;
1852
 
      }
1853
 
      else if(strequal(value, SASL_MECH_STRING_CRAM_MD5)) {
1854
 
        pop3c->preftype = POP3_TYPE_SASL;
1855
 
        pop3c->prefmech = SASL_MECH_CRAM_MD5;
1856
 
      }
1857
 
      else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5)) {
1858
 
        pop3c->preftype = POP3_TYPE_SASL;
1859
 
        pop3c->prefmech = SASL_MECH_DIGEST_MD5;
1860
 
      }
1861
 
      else if(strequal(value, SASL_MECH_STRING_GSSAPI)) {
1862
 
        pop3c->preftype = POP3_TYPE_SASL;
1863
 
        pop3c->prefmech = SASL_MECH_GSSAPI;
1864
 
      }
1865
 
      else if(strequal(value, SASL_MECH_STRING_NTLM)) {
1866
 
        pop3c->preftype = POP3_TYPE_SASL;
1867
 
        pop3c->prefmech = SASL_MECH_NTLM;
1868
 
      }
1869
 
      else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) {
1870
 
        pop3c->preftype = POP3_TYPE_SASL;
1871
 
        pop3c->prefmech = SASL_MECH_XOAUTH2;
1872
 
      }
1873
 
      else {
1874
 
        pop3c->preftype = POP3_TYPE_NONE;
1875
 
        pop3c->prefmech = SASL_AUTH_NONE;
1876
 
      }
 
1868
      else if(strnequal(value, SASL_MECH_STRING_LOGIN, len)) {
 
1869
        pop3c->preftype = POP3_TYPE_SASL;
 
1870
        pop3c->prefmech |= SASL_MECH_LOGIN;
 
1871
      }
 
1872
      else if(strnequal(value, SASL_MECH_STRING_PLAIN, len)) {
 
1873
        pop3c->preftype = POP3_TYPE_SASL;
 
1874
        pop3c->prefmech |= SASL_MECH_PLAIN;
 
1875
      }
 
1876
      else if(strnequal(value, SASL_MECH_STRING_CRAM_MD5, len)) {
 
1877
        pop3c->preftype = POP3_TYPE_SASL;
 
1878
        pop3c->prefmech |= SASL_MECH_CRAM_MD5;
 
1879
      }
 
1880
      else if(strnequal(value, SASL_MECH_STRING_DIGEST_MD5, len)) {
 
1881
        pop3c->preftype = POP3_TYPE_SASL;
 
1882
        pop3c->prefmech |= SASL_MECH_DIGEST_MD5;
 
1883
      }
 
1884
      else if(strnequal(value, SASL_MECH_STRING_GSSAPI, len)) {
 
1885
        pop3c->preftype = POP3_TYPE_SASL;
 
1886
        pop3c->prefmech |= SASL_MECH_GSSAPI;
 
1887
      }
 
1888
      else if(strnequal(value, SASL_MECH_STRING_NTLM, len)) {
 
1889
        pop3c->preftype = POP3_TYPE_SASL;
 
1890
        pop3c->prefmech |= SASL_MECH_NTLM;
 
1891
      }
 
1892
      else if(strnequal(value, SASL_MECH_STRING_XOAUTH2, len)) {
 
1893
        pop3c->preftype = POP3_TYPE_SASL;
 
1894
        pop3c->prefmech |= SASL_MECH_XOAUTH2;
 
1895
      }
 
1896
 
 
1897
      if(*ptr == ';')
 
1898
        ptr++;
1877
1899
    }
1878
1900
    else
1879
1901
      result = CURLE_URL_MALFORMAT;
1921
1943
 
1922
1944
/***********************************************************************
1923
1945
 *
 
1946
 * pop3_calc_sasl_details()
 
1947
 *
 
1948
 * Calculate the required login details for SASL authentication.
 
1949
 */
 
1950
static CURLcode pop3_calc_sasl_details(struct connectdata *conn,
 
1951
                                       const char **mech,
 
1952
                                       char **initresp, size_t *len,
 
1953
                                       pop3state *state1, pop3state *state2)
 
1954
{
 
1955
  CURLcode result = CURLE_OK;
 
1956
  struct SessionHandle *data = conn->data;
 
1957
  struct pop3_conn *pop3c = &conn->proto.pop3c;
 
1958
 
 
1959
  /* Calculate the supported authentication mechanism, by decreasing order of
 
1960
     security, as well as the initial response where appropriate */
 
1961
#ifndef CURL_DISABLE_CRYPTO_AUTH
 
1962
  if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
 
1963
      (pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
 
1964
    *mech = SASL_MECH_STRING_DIGEST_MD5;
 
1965
    *state1 = POP3_AUTH_DIGESTMD5;
 
1966
    pop3c->authused = SASL_MECH_DIGEST_MD5;
 
1967
  }
 
1968
  else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
 
1969
          (pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
 
1970
    *mech = SASL_MECH_STRING_CRAM_MD5;
 
1971
    *state1 = POP3_AUTH_CRAMMD5;
 
1972
    pop3c->authused = SASL_MECH_CRAM_MD5;
 
1973
  }
 
1974
  else
 
1975
#endif
 
1976
#ifdef USE_NTLM
 
1977
  if((pop3c->authmechs & SASL_MECH_NTLM) &&
 
1978
      (pop3c->prefmech & SASL_MECH_NTLM)) {
 
1979
    *mech = SASL_MECH_STRING_NTLM;
 
1980
    *state1 = POP3_AUTH_NTLM;
 
1981
    *state2 = POP3_AUTH_NTLM_TYPE2MSG;
 
1982
    pop3c->authused = SASL_MECH_NTLM;
 
1983
 
 
1984
    if(data->set.sasl_ir)
 
1985
      result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
 
1986
                                                    &conn->ntlm,
 
1987
                                                    initresp, len);
 
1988
  }
 
1989
  else
 
1990
#endif
 
1991
  if(((pop3c->authmechs & SASL_MECH_XOAUTH2) &&
 
1992
      (pop3c->prefmech & SASL_MECH_XOAUTH2) &&
 
1993
      (pop3c->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
 
1994
    *mech = SASL_MECH_STRING_XOAUTH2;
 
1995
    *state1 = POP3_AUTH_XOAUTH2;
 
1996
    *state2 = POP3_AUTH_FINAL;
 
1997
    pop3c->authused = SASL_MECH_XOAUTH2;
 
1998
 
 
1999
    if(data->set.sasl_ir)
 
2000
      result = Curl_sasl_create_xoauth2_message(data, conn->user,
 
2001
                                                conn->xoauth2_bearer,
 
2002
                                                initresp, len);
 
2003
  }
 
2004
  else if((pop3c->authmechs & SASL_MECH_LOGIN) &&
 
2005
          (pop3c->prefmech & SASL_MECH_LOGIN)) {
 
2006
    *mech = SASL_MECH_STRING_LOGIN;
 
2007
    *state1 = POP3_AUTH_LOGIN;
 
2008
    *state2 = POP3_AUTH_LOGIN_PASSWD;
 
2009
    pop3c->authused = SASL_MECH_LOGIN;
 
2010
 
 
2011
    if(data->set.sasl_ir)
 
2012
      result = Curl_sasl_create_login_message(data, conn->user, initresp, len);
 
2013
  }
 
2014
  else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
 
2015
          (pop3c->prefmech & SASL_MECH_PLAIN)) {
 
2016
    *mech = SASL_MECH_STRING_PLAIN;
 
2017
    *state1 = POP3_AUTH_PLAIN;
 
2018
    *state2 = POP3_AUTH_FINAL;
 
2019
    pop3c->authused = SASL_MECH_PLAIN;
 
2020
 
 
2021
    if(data->set.sasl_ir)
 
2022
      result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
 
2023
                                              initresp, len);
 
2024
  }
 
2025
 
 
2026
  return result;
 
2027
}
 
2028
 
 
2029
/***********************************************************************
 
2030
 *
1924
2031
 * Curl_pop3_write()
1925
2032
 *
1926
2033
 * This function scans the body after the end-of-body and writes everything