~ubuntu-branches/ubuntu/lucid/mpop/lucid

« back to all changes in this revision

Viewing changes to src/pop3.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Louis
  • Date: 2007-04-22 11:10:07 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070422111007-zxauoipdhkj9lasp
Tags: 1.0.9-1
New upstream release which include a fix for for CVE2007-1558.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *
4
4
 * This file is part of mpop, a POP3 client.
5
5
 *
6
 
 * Copyright (C) 2003, 2004, 2005, 2006
 
6
 * Copyright (C) 2003, 2004, 2005, 2006, 2007
7
7
 * Martin Lambers <marlam@marlam.de>
8
8
 *
9
9
 *   This program is free software; you can redistribute it and/or modify
34
34
#include <strings.h>
35
35
#include <ctype.h>
36
36
#include <errno.h>
37
 
extern int errno;
38
37
#if HAVE_SIGACTION
39
38
# include <signal.h>
40
39
#endif
89
88
 * begin to read its answers, and refill the command pipeline when the number of
90
89
 * unanswered commands drops to PIPELINE_MIN.
91
90
 */
 
91
#ifndef POP3_PIPELINE_MIN
92
92
#define POP3_PIPELINE_MIN       20
 
93
#endif
 
94
#ifndef POP3_PIPELINE_MAX
93
95
#define POP3_PIPELINE_MAX       100
 
96
#endif
94
97
 
95
98
 
96
99
/*
99
102
 * see pop3.h
100
103
 */
101
104
 
102
 
pop3_session_t *pop3_session_new(int force_pipelining,
 
105
pop3_session_t *pop3_session_new(int pipelining,
103
106
        const char *local_hostname, const char *local_user,
104
107
        FILE *debug)
105
108
{
131
134
    tls_clear(&session->tls);
132
135
#endif /* HAVE_TLS */
133
136
    session->cap.flags = 0;
134
 
    session->pipelining = force_pipelining;
 
137
    session->pipelining = pipelining;
135
138
    /* every POP3 server supports this: */
136
139
    session->cap.flags |= POP3_CAP_AUTH_USER;
137
140
    session->cap.apop_timestamp = NULL;
402
405
 
403
406
 
404
407
/*
 
408
 * pop3_get_addr()
 
409
 *
 
410
 * Reads the next mail address from the given string and returns it in an
 
411
 * allocated buffer. If no mail address is found, NULL will be returned.
 
412
 * If a buffer is returned, the string in it will only contain the following
 
413
 * characters: letters a-z and A-Z, digits 0-9, and any of ".@_-+/".
 
414
 * Note that this is only a subset of what the RFCs 2821 and 2822 allow!
 
415
 */
 
416
char *pop3_get_addr(const char *s)
 
417
{
 
418
    enum states { STATE_DEFAULT, STATE_DQUOTE, 
 
419
        STATE_BRACKETS_START, STATE_IN_BRACKETS, 
 
420
        STATE_PARENTH_START, STATE_IN_PARENTH,
 
421
        STATE_IN_ADDRESS, STATE_BACKQUOTE,
 
422
        STATE_END };
 
423
    int state = STATE_DEFAULT;
 
424
    int oldstate = STATE_DEFAULT;
 
425
    int backquote_savestate = STATE_DEFAULT;
 
426
    int parentheses_depth = 0;
 
427
    int parentheses_savestate = STATE_DEFAULT;
 
428
    char *addr = NULL;
 
429
    size_t addr_len = 0;
 
430
    int forget_addr = 0;
 
431
    int finish_addr = 0;
 
432
    size_t bufsize = 0;
 
433
    /* The buffer that is filled with the mail address grows by
 
434
     * 'bufsize_step' if the remaining space becomes too small. This value must
 
435
     * be at least 2. Wasted characters are at most (bufsize_step - 1). A value
 
436
     * of 10 means low wasted space and a low number of realloc()s per
 
437
     * recipient. */
 
438
    const size_t bufsize_step = 10;
 
439
    const char *p = s;
 
440
 
 
441
    for (;;)
 
442
    {
 
443
        oldstate = state;
 
444
        if (!*p)
 
445
        {
 
446
            if (addr)
 
447
                finish_addr = 1;
 
448
            state = STATE_END;
 
449
        }
 
450
        else
 
451
        {
 
452
            switch (state)
 
453
            {
 
454
                case STATE_DEFAULT:
 
455
                    if (*p == '\\')
 
456
                    {
 
457
                        backquote_savestate = state;
 
458
                        state = STATE_BACKQUOTE;
 
459
                    }
 
460
                    else if (*p == '(')
 
461
                    {
 
462
                        parentheses_savestate = state;
 
463
                        state = STATE_PARENTH_START;
 
464
                    }
 
465
                    else if (*p == '"')
 
466
                    {
 
467
                        if (addr)
 
468
                            forget_addr = 1;
 
469
                        state = STATE_DQUOTE;
 
470
                    }
 
471
                    else if (*p == '<')
 
472
                    {
 
473
                        if (addr)
 
474
                            forget_addr = 1;
 
475
                        state = STATE_BRACKETS_START;
 
476
                    }
 
477
                    else if (*p == ' ' || *p == '\t')
 
478
                        ; /* keep state */
 
479
                    else if (*p == ':')
 
480
                    {
 
481
                        if (addr)
 
482
                            forget_addr = 1;
 
483
                    }
 
484
                    else if (*p == ';' || *p == ',')
 
485
                    {
 
486
                        if (addr)
 
487
                        {
 
488
                            finish_addr = 1;
 
489
                            state = STATE_END;
 
490
                        }
 
491
                    }
 
492
                    else
 
493
                    {
 
494
                        if (addr)
 
495
                            forget_addr = 1;
 
496
                        state = STATE_IN_ADDRESS;
 
497
                    }
 
498
                    break;
 
499
 
 
500
                case STATE_DQUOTE:
 
501
                    if (*p == '\\')
 
502
                    {
 
503
                        backquote_savestate = state;
 
504
                        state = STATE_BACKQUOTE;
 
505
                    }
 
506
                    else if (*p == '"')
 
507
                        state = STATE_DEFAULT;
 
508
                    break;
 
509
 
 
510
                case STATE_BRACKETS_START:
 
511
                    if (*p == '(')
 
512
                    {
 
513
                        parentheses_savestate = state;
 
514
                        state = STATE_PARENTH_START;
 
515
                    }
 
516
                    else if (*p == '>')
 
517
                        state = STATE_DEFAULT;
 
518
                    else
 
519
                        state = STATE_IN_BRACKETS;
 
520
                    break;
 
521
 
 
522
                case STATE_IN_BRACKETS:
 
523
                    if (*p == '\\')
 
524
                    {
 
525
                        backquote_savestate = state;
 
526
                        state = STATE_BACKQUOTE;
 
527
                    }
 
528
                    else if (*p == '(')
 
529
                    {
 
530
                        parentheses_savestate = state;
 
531
                        state = STATE_PARENTH_START;
 
532
                    }
 
533
                    else if (*p == '>')
 
534
                    {
 
535
                        finish_addr = 1;
 
536
                        state = STATE_END;
 
537
                    }
 
538
                    break;
 
539
 
 
540
                case STATE_PARENTH_START:
 
541
                    if (*p == ')')
 
542
                        state = parentheses_savestate;
 
543
                    else
 
544
                    {
 
545
                        parentheses_depth++;
 
546
                        state = STATE_IN_PARENTH;
 
547
                    }
 
548
                    break;
 
549
 
 
550
                case STATE_IN_PARENTH:
 
551
                    if (*p == '\\')
 
552
                    {
 
553
                        backquote_savestate = state;
 
554
                        state = STATE_BACKQUOTE;
 
555
                    }
 
556
                    else if (*p == '(')
 
557
                        state = STATE_PARENTH_START;
 
558
                    else if (*p == ')')
 
559
                    {
 
560
                        parentheses_depth--;
 
561
                        if (parentheses_depth == 0)
 
562
                            state = parentheses_savestate;
 
563
                    }
 
564
                    break;
 
565
 
 
566
                case STATE_IN_ADDRESS:
 
567
                    if (*p == '\\')
 
568
                    {
 
569
                        backquote_savestate = state;
 
570
                        state = STATE_BACKQUOTE;
 
571
                    }
 
572
                    else if (*p == '"')
 
573
                    {
 
574
                        forget_addr = 1;
 
575
                        state = STATE_DQUOTE;
 
576
                    }
 
577
                    else if (*p == '(')
 
578
                    {
 
579
                        parentheses_savestate = state;
 
580
                        state = STATE_PARENTH_START;
 
581
                    }
 
582
                    else if (*p == '<')
 
583
                    {
 
584
                        forget_addr = 1;
 
585
                        state = STATE_BRACKETS_START;
 
586
                    }
 
587
                    else if (*p == ' ' || *p == '\t')
 
588
                        state = STATE_DEFAULT;
 
589
                    else if (*p == ':')
 
590
                    {
 
591
                        forget_addr = 1;
 
592
                        state = STATE_DEFAULT;
 
593
                    }
 
594
                    else if (*p == ',' || *p == ';')
 
595
                    {
 
596
                        finish_addr = 1;
 
597
                        state = STATE_END;
 
598
                    }
 
599
                    break;
 
600
 
 
601
                case STATE_BACKQUOTE:
 
602
                    state = backquote_savestate;
 
603
                    break;
 
604
            }
 
605
        }
 
606
 
 
607
        if (forget_addr)
 
608
        {
 
609
            /* this was just junk */
 
610
            free(addr);
 
611
            addr = NULL;
 
612
            addr_len = 0;
 
613
            bufsize = 0;
 
614
            forget_addr = 0;
 
615
        }
 
616
        if (finish_addr)
 
617
        {
 
618
            addr[addr_len] = '\0';
 
619
        }
 
620
        if (state == STATE_END)
 
621
        {
 
622
            break;
 
623
        }
 
624
        if ((state == STATE_IN_ADDRESS || state == STATE_IN_BRACKETS)
 
625
                && oldstate != STATE_PARENTH_START
 
626
                && oldstate != STATE_IN_PARENTH)
 
627
        {
 
628
            /* Add this character to the current recipient */
 
629
            addr_len++;
 
630
            if (bufsize < addr_len + 1)
 
631
            {
 
632
                bufsize += bufsize_step;
 
633
                addr = xrealloc(addr, bufsize * sizeof(char));
 
634
            }
 
635
            /* sanitize characters */
 
636
            if (c_isalpha((unsigned char)*p) || c_isdigit((unsigned char)*p)
 
637
                    || *p == '.' || *p == '@' || *p == '_' || *p == '-' 
 
638
                    || *p == '+' || *p == '/')
 
639
            {
 
640
                addr[addr_len - 1] = *p;
 
641
            }
 
642
            else if (c_isspace((unsigned char)*p))
 
643
            {
 
644
                addr[addr_len - 1] = '-';
 
645
            }
 
646
            else
 
647
            {
 
648
                addr[addr_len - 1] = '_';
 
649
            }
 
650
        }
 
651
        p++;
 
652
    }
 
653
 
 
654
    return addr;
 
655
}
 
656
 
 
657
 
 
658
/*
405
659
 * pop3_get_greeting()
406
660
 *
407
661
 * see pop3.h
411
665
        char **errmsg, char **errstr)
412
666
{
413
667
    int e;
414
 
    char *p, *q;
 
668
    char *p, *q, *a;
415
669
    
416
670
    if ((e = pop3_get_msg(session, 0, errstr)) != POP3_EOK)
417
671
    {
429
683
        /* 'greeting' is large enough */
430
684
        strcpy(greeting, session->buffer + 4);
431
685
    }
432
 
    /* search APOP timestamp */
433
 
    if ((p = strchr(session->buffer, '<')) != NULL)
 
686
    /* Search APOP timestamp. Make sure that it is a valid RFC822 message id as
 
687
     * required by RFC 1939 and that it is reasonably long. This should make
 
688
     * man-in-the-middle attacks as described in CVE-2007-1558 a little bit
 
689
     * harder. Nevertheless, APOP is considered broken, and is never used
 
690
     * automatically unless TLS is active. */
 
691
    a = NULL;
 
692
    if ((p = strchr(session->buffer, '<')) != NULL      /* start of timestamp */
 
693
            && (q = strchr(p + 1, '>')) != NULL         /* end of timestamp */
 
694
            && (q - p + 1) >= 12                        /* minimum length */
 
695
            && (a = pop3_get_addr(p))                   /* valid address */
 
696
            && strlen(a) + 2 == (size_t)(q - p + 1)     /* no specials */
 
697
            && strncmp(p + 1, a, q - p - 1) == 0)       /* no invalid chars */
434
698
    {
435
 
        if ((q = strchr(p, '>')) != NULL)
436
 
        {
437
 
            session->cap.flags |= POP3_CAP_AUTH_APOP;
438
 
            session->cap.apop_timestamp = xmalloc((q - p + 2) * sizeof(char));
439
 
            strncpy(session->cap.apop_timestamp, p, q - p + 1);
440
 
            session->cap.apop_timestamp[q - p + 1] = '\0';
441
 
        }
 
699
        session->cap.flags |= POP3_CAP_AUTH_APOP;
 
700
        session->cap.apop_timestamp = xmalloc((q - p + 2) * sizeof(char));
 
701
        strncpy(session->cap.apop_timestamp, p, q - p + 1);
 
702
        session->cap.apop_timestamp[q - p + 1] = '\0';
442
703
    }
 
704
    free(a);
443
705
 
444
706
    return POP3_EOK;
445
707
}
617
879
        return POP3_EPROTO;
618
880
    }
619
881
    
620
 
    /* Set the pipelining flag if we know whether pipelining is supported or
621
 
     * not. Otherwise don't change it. */
622
 
    if (session->cap.flags & POP3_CAP_CAPA) 
 
882
    /* Automatically set the pipelining flag to off (0) or on (1) if it is not
 
883
     * already set. */
 
884
    if (session->pipelining == 2)
623
885
    {
624
 
        if (session->cap.flags & POP3_CAP_PIPELINING)
 
886
        if (session->cap.flags & POP3_CAP_CAPA 
 
887
                && session->cap.flags & POP3_CAP_PIPELINING)
625
888
        {
626
889
            session->pipelining = 1;
627
890
        }
806
1069
    const char *p = uid;
807
1070
    
808
1071
    /* According to RFC 1939, a valid UID must consist of one to 70 characters
809
 
     * in the range 0x21 to 0x7e. We allow longer UIDs, spaces inside UIDs (but
810
 
     * no space at the beginning of an UID), and non-ASCII characters in UIDs
811
 
     * as long as they are not control characters.
 
1072
     * in the range 0x21 to 0x7e. We allow longer UIDs, spaces inside UIDs, and
 
1073
     * non-ASCII characters in UIDs as long as they are not control characters.
812
1074
     * I know of one case where the POP3 server uses non-ASCII characters in 
813
1075
     * UIDs. I don't know if any server needs the other extensions, though. */
814
 
    if (*p == ' ')
815
 
    {
816
 
        return 0;
817
 
    }
818
1076
    while (*p != '\0')
819
1077
    {
820
1078
        if (c_iscntrl((unsigned char)*p))
890
1148
            if (p == session->buffer || *p != ' ' 
891
1149
                    || (n == LONG_MAX && errno == ERANGE)
892
1150
                    || n < 1 || n > session->total_number
893
 
                    || session->msg_uid[n - 1]
894
 
                    || !pop3_uidl_check_uid(p + 1))
 
1151
                    || session->msg_uid[n - 1])
 
1152
            {
 
1153
                goto invalid_reply;
 
1154
            }
 
1155
            /* Allow more than one space between the number and the UID, even
 
1156
             * though RFC 1939 says it must be exactly one. Needed for the
 
1157
             * "Maillennium V05.00c++" POP3 server used by Comcast.net as of
 
1158
             * 2007-01-29. */
 
1159
            while (*p == ' ')
 
1160
            {
 
1161
                p++;
 
1162
            }
 
1163
            if (!pop3_uidl_check_uid(p))
895
1164
            {
896
1165
                goto invalid_reply;
897
1166
            }
1226
1495
}
1227
1496
 
1228
1497
 
1229
 
/*
1230
 
 * pop3_get_addr()
1231
 
 *
1232
 
 * Reads the next mail address from the given string and returns it in an
1233
 
 * allocated buffer. If no mail address is found, NULL will be returned.
1234
 
 * If a buffer is returned, the string in it will only contain the following
1235
 
 * characters: letters a-z and A-Z, digits 0-9, and any of ".@_-+/".
1236
 
 * Note that this is only a subset of what the RFCs 2821 and 2822 allow!
1237
 
 */
1238
 
char *pop3_get_addr(const char *s)
1239
 
{
1240
 
    enum states { STATE_DEFAULT, STATE_DQUOTE, 
1241
 
        STATE_BRACKETS_START, STATE_IN_BRACKETS, 
1242
 
        STATE_PARENTH_START, STATE_IN_PARENTH,
1243
 
        STATE_IN_ADDRESS, STATE_BACKQUOTE,
1244
 
        STATE_END };
1245
 
    int state = STATE_DEFAULT;
1246
 
    int oldstate = STATE_DEFAULT;
1247
 
    int backquote_savestate = STATE_DEFAULT;
1248
 
    int parentheses_depth = 0;
1249
 
    int parentheses_savestate = STATE_DEFAULT;
1250
 
    char *addr = NULL;
1251
 
    size_t addr_len = 0;
1252
 
    int forget_addr = 0;
1253
 
    int finish_addr = 0;
1254
 
    size_t bufsize = 0;
1255
 
    /* The buffer that is filled with the mail address grows by
1256
 
     * 'bufsize_step' if the remaining space becomes too small. This value must
1257
 
     * be at least 2. Wasted characters are at most (bufsize_step - 1). A value
1258
 
     * of 10 means low wasted space and a low number of realloc()s per
1259
 
     * recipient. */
1260
 
    const size_t bufsize_step = 10;
1261
 
    const char *p = s;
1262
 
 
1263
 
    for (;;)
1264
 
    {
1265
 
        oldstate = state;
1266
 
        if (!*p)
1267
 
        {
1268
 
            if (addr)
1269
 
                finish_addr = 1;
1270
 
            state = STATE_END;
1271
 
        }
1272
 
        else
1273
 
        {
1274
 
            switch (state)
1275
 
            {
1276
 
                case STATE_DEFAULT:
1277
 
                    if (*p == '\\')
1278
 
                    {
1279
 
                        backquote_savestate = state;
1280
 
                        state = STATE_BACKQUOTE;
1281
 
                    }
1282
 
                    else if (*p == '(')
1283
 
                    {
1284
 
                        parentheses_savestate = state;
1285
 
                        state = STATE_PARENTH_START;
1286
 
                    }
1287
 
                    else if (*p == '"')
1288
 
                    {
1289
 
                        if (addr)
1290
 
                            forget_addr = 1;
1291
 
                        state = STATE_DQUOTE;
1292
 
                    }
1293
 
                    else if (*p == '<')
1294
 
                    {
1295
 
                        if (addr)
1296
 
                            forget_addr = 1;
1297
 
                        state = STATE_BRACKETS_START;
1298
 
                    }
1299
 
                    else if (*p == ' ' || *p == '\t')
1300
 
                        ; /* keep state */
1301
 
                    else if (*p == ':')
1302
 
                    {
1303
 
                        if (addr)
1304
 
                            forget_addr = 1;
1305
 
                    }
1306
 
                    else if (*p == ';' || *p == ',')
1307
 
                    {
1308
 
                        if (addr)
1309
 
                        {
1310
 
                            finish_addr = 1;
1311
 
                            state = STATE_END;
1312
 
                        }
1313
 
                    }
1314
 
                    else
1315
 
                    {
1316
 
                        if (addr)
1317
 
                            forget_addr = 1;
1318
 
                        state = STATE_IN_ADDRESS;
1319
 
                    }
1320
 
                    break;
1321
 
 
1322
 
                case STATE_DQUOTE:
1323
 
                    if (*p == '\\')
1324
 
                    {
1325
 
                        backquote_savestate = state;
1326
 
                        state = STATE_BACKQUOTE;
1327
 
                    }
1328
 
                    else if (*p == '"')
1329
 
                        state = STATE_DEFAULT;
1330
 
                    break;
1331
 
 
1332
 
                case STATE_BRACKETS_START:
1333
 
                    if (*p == '(')
1334
 
                    {
1335
 
                        parentheses_savestate = state;
1336
 
                        state = STATE_PARENTH_START;
1337
 
                    }
1338
 
                    else if (*p == '>')
1339
 
                        state = STATE_DEFAULT;
1340
 
                    else
1341
 
                        state = STATE_IN_BRACKETS;
1342
 
                    break;
1343
 
 
1344
 
                case STATE_IN_BRACKETS:
1345
 
                    if (*p == '\\')
1346
 
                    {
1347
 
                        backquote_savestate = state;
1348
 
                        state = STATE_BACKQUOTE;
1349
 
                    }
1350
 
                    else if (*p == '(')
1351
 
                    {
1352
 
                        parentheses_savestate = state;
1353
 
                        state = STATE_PARENTH_START;
1354
 
                    }
1355
 
                    else if (*p == '>')
1356
 
                    {
1357
 
                        finish_addr = 1;
1358
 
                        state = STATE_END;
1359
 
                    }
1360
 
                    break;
1361
 
 
1362
 
                case STATE_PARENTH_START:
1363
 
                    if (*p == ')')
1364
 
                        state = parentheses_savestate;
1365
 
                    else
1366
 
                    {
1367
 
                        parentheses_depth++;
1368
 
                        state = STATE_IN_PARENTH;
1369
 
                    }
1370
 
                    break;
1371
 
 
1372
 
                case STATE_IN_PARENTH:
1373
 
                    if (*p == '\\')
1374
 
                    {
1375
 
                        backquote_savestate = state;
1376
 
                        state = STATE_BACKQUOTE;
1377
 
                    }
1378
 
                    else if (*p == '(')
1379
 
                        state = STATE_PARENTH_START;
1380
 
                    else if (*p == ')')
1381
 
                    {
1382
 
                        parentheses_depth--;
1383
 
                        if (parentheses_depth == 0)
1384
 
                            state = parentheses_savestate;
1385
 
                    }
1386
 
                    break;
1387
 
 
1388
 
                case STATE_IN_ADDRESS:
1389
 
                    if (*p == '\\')
1390
 
                    {
1391
 
                        backquote_savestate = state;
1392
 
                        state = STATE_BACKQUOTE;
1393
 
                    }
1394
 
                    else if (*p == '"')
1395
 
                    {
1396
 
                        forget_addr = 1;
1397
 
                        state = STATE_DQUOTE;
1398
 
                    }
1399
 
                    else if (*p == '(')
1400
 
                    {
1401
 
                        parentheses_savestate = state;
1402
 
                        state = STATE_PARENTH_START;
1403
 
                    }
1404
 
                    else if (*p == '<')
1405
 
                    {
1406
 
                        forget_addr = 1;
1407
 
                        state = STATE_BRACKETS_START;
1408
 
                    }
1409
 
                    else if (*p == ' ' || *p == '\t')
1410
 
                        state = STATE_DEFAULT;
1411
 
                    else if (*p == ':')
1412
 
                    {
1413
 
                        forget_addr = 1;
1414
 
                        state = STATE_DEFAULT;
1415
 
                    }
1416
 
                    else if (*p == ',' || *p == ';')
1417
 
                    {
1418
 
                        finish_addr = 1;
1419
 
                        state = STATE_END;
1420
 
                    }
1421
 
                    break;
1422
 
 
1423
 
                case STATE_BACKQUOTE:
1424
 
                    state = backquote_savestate;
1425
 
                    break;
1426
 
            }
1427
 
        }
1428
 
 
1429
 
        if (forget_addr)
1430
 
        {
1431
 
            /* this was just junk */
1432
 
            free(addr);
1433
 
            addr = NULL;
1434
 
            addr_len = 0;
1435
 
            bufsize = 0;
1436
 
            forget_addr = 0;
1437
 
        }
1438
 
        if (finish_addr)
1439
 
        {
1440
 
            addr[addr_len] = '\0';
1441
 
        }
1442
 
        if (state == STATE_END)
1443
 
        {
1444
 
            break;
1445
 
        }
1446
 
        if ((state == STATE_IN_ADDRESS || state == STATE_IN_BRACKETS)
1447
 
                && oldstate != STATE_PARENTH_START
1448
 
                && oldstate != STATE_IN_PARENTH)
1449
 
        {
1450
 
            /* Add this character to the current recipient */
1451
 
            addr_len++;
1452
 
            if (bufsize < addr_len + 1)
1453
 
            {
1454
 
                bufsize += bufsize_step;
1455
 
                addr = xrealloc(addr, bufsize * sizeof(char));
1456
 
            }
1457
 
            /* sanitize characters */
1458
 
            if (c_isalpha((unsigned char)*p) || c_isdigit((unsigned char)*p)
1459
 
                    || *p == '.' || *p == '@' || *p == '_' || *p == '-' 
1460
 
                    || *p == '+' || *p == '/')
1461
 
            {
1462
 
                addr[addr_len - 1] = *p;
1463
 
            }
1464
 
            else if (c_isspace((unsigned char)*p))
1465
 
            {
1466
 
                addr[addr_len - 1] = '-';
1467
 
            }
1468
 
            else
1469
 
            {
1470
 
                addr[addr_len - 1] = '_';
1471
 
            }
1472
 
        }
1473
 
        p++;
1474
 
    }
1475
 
 
1476
 
    return addr;
1477
 
}
1478
 
 
1479
 
 
1480
1498
/* 
1481
1499
 * pop3_retr_get_from_addr()
1482
1500
 *
2667
2685
        {
2668
2686
            auth_mech = "CRAM-MD5";
2669
2687
        }
2670
 
        else if (session->cap.flags & POP3_CAP_AUTH_APOP)
2671
 
        {
2672
 
            auth_mech = "APOP";
2673
 
        }
2674
 
        else if (gsasl_client_support_p(ctx, "NTLM") 
2675
 
                && (session->cap.flags & POP3_CAP_AUTH_NTLM))
2676
 
        {
2677
 
            auth_mech = "NTLM";
2678
 
        }
2679
2688
#ifdef HAVE_TLS
2680
2689
        else if (tls_is_active(&session->tls))
2681
2690
        {
2682
 
            if (gsasl_client_support_p(ctx, "PLAIN") 
 
2691
            if (session->cap.flags & POP3_CAP_AUTH_APOP)
 
2692
            {
 
2693
                auth_mech = "APOP";
 
2694
            }
 
2695
            else if (gsasl_client_support_p(ctx, "PLAIN") 
2683
2696
                    && (session->cap.flags & POP3_CAP_AUTH_PLAIN))
2684
2697
            {
2685
2698
                auth_mech = "PLAIN";
2693
2706
            {
2694
2707
                auth_mech = "LOGIN";
2695
2708
            }
 
2709
            else if (gsasl_client_support_p(ctx, "NTLM") 
 
2710
                    && (session->cap.flags & POP3_CAP_AUTH_NTLM))
 
2711
            {
 
2712
                auth_mech = "NTLM";
 
2713
            }
2696
2714
        }
2697
2715
#endif /* HAVE_TLS */
2698
2716
    }