~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

Viewing changes to src/auth/password-scheme.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/{control,rules}: enable PIE hardening.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2003-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "array.h"
74
74
}
75
75
 
76
76
int password_verify(const char *plaintext, const char *user, const char *scheme,
77
 
                    const unsigned char *raw_password, size_t size)
 
77
                    const unsigned char *raw_password, size_t size,
 
78
                    const char **error_r)
78
79
{
79
80
        const struct password_scheme *s;
80
81
        enum password_encoding encoding;
81
82
        const unsigned char *generated;
82
83
        size_t generated_size;
 
84
        int ret;
83
85
 
84
86
        s = password_scheme_lookup(scheme, &encoding);
85
 
        if (s == NULL)
 
87
        if (s == NULL) {
 
88
                *error_r = "Unknown password scheme";
86
89
                return -1;
87
 
 
88
 
        if (s->password_verify != NULL)
89
 
                return s->password_verify(plaintext, user, raw_password, size);
90
 
 
91
 
        /* generic verification handler: generate the password and compare it
92
 
           to the one in database */
93
 
        s->password_generate(plaintext, user, &generated, &generated_size);
94
 
        return size != generated_size ? 0 :
95
 
                memcmp(generated, raw_password, size) == 0;
 
90
        }
 
91
 
 
92
        if (s->password_verify != NULL) {
 
93
                ret = s->password_verify(plaintext, user, raw_password, size,
 
94
                                         error_r);
 
95
        } else {
 
96
                /* generic verification handler: generate the password and
 
97
                   compare it to the one in database */
 
98
                s->password_generate(plaintext, user,
 
99
                                     &generated, &generated_size);
 
100
                ret = size != generated_size ? 0 :
 
101
                        memcmp(generated, raw_password, size) == 0 ? 1 : 0;
 
102
        }
 
103
 
 
104
        if (ret == 0)
 
105
                *error_r = "Password mismatch";
 
106
        return ret;
96
107
}
97
108
 
98
109
const char *password_get_scheme(const char **password)
300
311
                        continue;
301
312
 
302
313
                if (password_verify(plain_password, user, schemes[i]->name,
303
 
                                    raw_password, raw_password_size) > 0)
 
314
                                    raw_password, raw_password_size,
 
315
                                    &error) > 0)
304
316
                        return schemes[i]->name;
305
317
        }
306
318
        return NULL;
307
319
}
308
320
 
309
 
bool crypt_verify(const char *plaintext, const char *user ATTR_UNUSED,
310
 
                  const unsigned char *raw_password, size_t size)
 
321
int crypt_verify(const char *plaintext, const char *user ATTR_UNUSED,
 
322
                 const unsigned char *raw_password, size_t size,
 
323
                 const char **error_r)
311
324
{
312
325
        const char *password, *crypted;
313
326
 
314
327
        if (size == 0) {
315
328
                /* the default mycrypt() handler would return match */
316
 
                return FALSE;
 
329
                return 0;
317
330
        }
318
331
 
319
332
        password = t_strndup(raw_password, size);
320
333
        crypted = mycrypt(plaintext, password);
321
334
        if (crypted == NULL) {
322
335
                /* really shouldn't happen unless the system is broken */
323
 
                i_error("crypt() failed: %m");
324
 
                return FALSE;
 
336
                *error_r = t_strdup_printf("crypt() failed: %m");
 
337
                return -1;
325
338
        }
326
339
 
327
 
        return strcmp(crypted, password) == 0;
 
340
        return strcmp(crypted, password) == 0 ? 1 : 0;
328
341
}
329
342
 
330
343
static void
340
353
        *size_r = strlen(password);
341
354
}
342
355
 
343
 
static bool
 
356
static int
344
357
md5_verify(const char *plaintext, const char *user,
345
 
           const unsigned char *raw_password, size_t size)
 
358
           const unsigned char *raw_password, size_t size, const char **error_r)
346
359
{
347
360
        const char *password, *str, *error;
348
361
        const unsigned char *md5_password;
352
365
        if (strncmp(password, "$1$", 3) == 0) {
353
366
                /* MD5-CRYPT */
354
367
                str = password_generate_md5_crypt(plaintext, password);
355
 
                return strcmp(str, password) == 0;
 
368
                return strcmp(str, password) == 0 ? 1 : 0;
356
369
        } else if (password_decode(password, "PLAIN-MD5",
357
370
                                   &md5_password, &md5_size, &error) < 0) {
358
 
                i_error("md5_verify(%s): Not a valid MD5-CRYPT or "
359
 
                        "PLAIN-MD5 password", user);
360
 
                return FALSE;
 
371
                *error_r = "Not a valid MD5-CRYPT or PLAIN-MD5 password";
 
372
                return -1;
361
373
        } else {
362
374
                return password_verify(plaintext, user, "PLAIN-MD5",
363
 
                                       md5_password, md5_size) > 0;
 
375
                                       md5_password, md5_size, error_r);
364
376
        }
365
377
}
366
378
 
367
 
static bool
 
379
static int
368
380
md5_crypt_verify(const char *plaintext, const char *user ATTR_UNUSED,
369
 
                 const unsigned char *raw_password, size_t size)
 
381
                 const unsigned char *raw_password, size_t size,
 
382
                 const char **error_r ATTR_UNUSED)
370
383
{
371
384
        const char *password, *str;
372
385
 
373
386
        password = t_strndup(raw_password, size);
374
387
        str = password_generate_md5_crypt(plaintext, password);
375
 
        return strcmp(str, password) == 0;
 
388
        return strcmp(str, password) == 0 ? 1 : 0;
376
389
}
377
390
 
378
391
static void
453
466
        *size_r = SHA1_RESULTLEN + SSHA_SALT_LEN;
454
467
}
455
468
 
456
 
static bool ssha_verify(const char *plaintext, const char *user,
457
 
                        const unsigned char *raw_password, size_t size)
 
469
static int ssha_verify(const char *plaintext, const char *user ATTR_UNUSED,
 
470
                       const unsigned char *raw_password, size_t size,
 
471
                       const char **error_r)
458
472
{
459
473
        unsigned char sha1_digest[SHA1_RESULTLEN];
460
474
        struct sha1_ctxt ctx;
461
475
 
462
476
        /* format: <SHA1 hash><salt> */
463
477
        if (size <= SHA1_RESULTLEN) {
464
 
                i_error("ssha_verify(%s): SSHA password too short", user);
465
 
                return FALSE;
 
478
                *error_r = "SSHA password is too short";
 
479
                return -1;
466
480
        }
467
481
 
468
482
        sha1_init(&ctx);
469
483
        sha1_loop(&ctx, plaintext, strlen(plaintext));
470
484
        sha1_loop(&ctx, raw_password + SHA1_RESULTLEN, size - SHA1_RESULTLEN);
471
485
        sha1_result(&ctx, sha1_digest);
472
 
        return memcmp(sha1_digest, raw_password, SHA1_RESULTLEN) == 0;
 
486
        return memcmp(sha1_digest, raw_password, SHA1_RESULTLEN) == 0 ? 1 : 0;
473
487
}
474
488
 
475
489
static void
493
507
        *size_r = SHA256_RESULTLEN + SSHA256_SALT_LEN;
494
508
}
495
509
 
496
 
static bool ssha256_verify(const char *plaintext, const char *user,
497
 
                           const unsigned char *raw_password, size_t size)
 
510
static int ssha256_verify(const char *plaintext, const char *user ATTR_UNUSED,
 
511
                          const unsigned char *raw_password, size_t size,
 
512
                          const char **error_r)
498
513
{
499
514
        unsigned char sha256_digest[SHA256_RESULTLEN];
500
515
        struct sha256_ctx ctx;
501
516
 
502
517
        /* format: <SHA256 hash><salt> */
503
518
        if (size <= SHA256_RESULTLEN) {
504
 
                i_error("ssha256_verify(%s): SSHA256 password too short", user);
505
 
                return FALSE;
 
519
                *error_r = "SSHA256 password is too short";
 
520
                return -1;
506
521
        }
507
522
 
508
523
        sha256_init(&ctx);
510
525
        sha256_loop(&ctx, raw_password + SHA256_RESULTLEN,
511
526
                    size - SHA256_RESULTLEN);
512
527
        sha256_result(&ctx, sha256_digest);
513
 
        return memcmp(sha256_digest, raw_password, SHA256_RESULTLEN) == 0;
 
528
        return memcmp(sha256_digest, raw_password,
 
529
                      SHA256_RESULTLEN) == 0 ? 1 : 0;
514
530
}
515
531
 
516
532
static void
534
550
        *size_r = SHA512_RESULTLEN + SSHA512_SALT_LEN;
535
551
}
536
552
 
537
 
static bool ssha512_verify(const char *plaintext, const char *user,
538
 
                           const unsigned char *raw_password, size_t size)
 
553
static int ssha512_verify(const char *plaintext, const char *user ATTR_UNUSED,
 
554
                          const unsigned char *raw_password, size_t size,
 
555
                          const char **error_r)
539
556
{
540
557
        unsigned char sha512_digest[SHA512_RESULTLEN];
541
558
        struct sha512_ctx ctx;
542
559
 
543
560
        /* format: <SHA512 hash><salt> */
544
561
        if (size <= SHA512_RESULTLEN) {
545
 
                i_error("ssha512_verify(%s): SSHA512 password too short", user);
546
 
                return FALSE;
 
562
                *error_r = "SSHA512 password is too short";
 
563
                return -1;
547
564
        }
548
565
 
549
566
        sha512_init(&ctx);
551
568
        sha512_loop(&ctx, raw_password + SHA512_RESULTLEN,
552
569
                    size - SHA512_RESULTLEN);
553
570
        sha512_result(&ctx, sha512_digest);
554
 
        return memcmp(sha512_digest, raw_password, SHA512_RESULTLEN) == 0;
 
571
        return memcmp(sha512_digest, raw_password,
 
572
                      SHA512_RESULTLEN) == 0 ? 1 : 0;
555
573
}
556
574
 
557
575
static void
575
593
        *size_r = MD5_RESULTLEN + SMD5_SALT_LEN;
576
594
}
577
595
 
578
 
static bool smd5_verify(const char *plaintext, const char *user,
579
 
                        const unsigned char *raw_password, size_t size)
 
596
static int smd5_verify(const char *plaintext, const char *user ATTR_UNUSED,
 
597
                       const unsigned char *raw_password, size_t size,
 
598
                       const char **error_r)
580
599
{
581
600
        unsigned char md5_digest[MD5_RESULTLEN];
582
601
        struct md5_context ctx;
583
602
 
584
603
        /* format: <MD5 hash><salt> */
585
604
        if (size <= MD5_RESULTLEN) {
586
 
                i_error("smd5_verify(%s): SMD5 password too short", user);
587
 
                return FALSE;
 
605
                *error_r = "SMD5 password is too short";
 
606
                return -1;
588
607
        }
589
608
 
590
609
        md5_init(&ctx);
591
610
        md5_update(&ctx, plaintext, strlen(plaintext));
592
611
        md5_update(&ctx, raw_password + MD5_RESULTLEN, size - MD5_RESULTLEN);
593
612
        md5_final(&ctx, md5_digest);
594
 
        return memcmp(md5_digest, raw_password, MD5_RESULTLEN) == 0;
 
613
        return memcmp(md5_digest, raw_password, MD5_RESULTLEN) == 0 ? 1 : 0;
595
614
}
596
615
 
597
616
static void
602
621
        *size_r = strlen(plaintext);
603
622
}
604
623
 
 
624
static int
 
625
plain_trunc_verify(const char *plaintext, const char *user ATTR_UNUSED,
 
626
                   const unsigned char *raw_password, size_t size,
 
627
                   const char **error_r)
 
628
{
 
629
        unsigned int i, plaintext_len, trunc_len = 0;
 
630
 
 
631
        /* format: <length>-<password> */
 
632
        for (i = 0; i < size; i++) {
 
633
                if (raw_password[i] >= '0' && raw_password[i] <= '9')
 
634
                        trunc_len = trunc_len*10 + raw_password[i]-'0';
 
635
                else
 
636
                        break;
 
637
        }
 
638
        if (i == size || raw_password[i] != '-') {
 
639
                *error_r = "PLAIN-TRUNC missing length: prefix";
 
640
                return -1;
 
641
        }
 
642
        i++;
 
643
 
 
644
        plaintext_len = strlen(plaintext);
 
645
        if (size-i == trunc_len && plaintext_len >= trunc_len) {
 
646
                /* possibly truncated password. allow the given password as
 
647
                   long as the prefix matches. */
 
648
                return memcmp(raw_password+i, plaintext, trunc_len) == 0 ? 1 : 0;
 
649
        }
 
650
        return plaintext_len == size-i &&
 
651
                memcmp(raw_password+i, plaintext, plaintext_len) == 0 ? 1 : 0;
 
652
}
 
653
 
605
654
static void
606
655
cram_md5_generate(const char *plaintext, const char *user ATTR_UNUSED,
607
656
                  const unsigned char **raw_password_r, size_t *size_r)
700
749
        *size_r = NTLMSSP_HASH_SIZE;
701
750
}
702
751
 
703
 
static bool otp_verify(const char *plaintext, const char *user ATTR_UNUSED,
704
 
                       const unsigned char *raw_password, size_t size)
 
752
static int otp_verify(const char *plaintext, const char *user ATTR_UNUSED,
 
753
                      const unsigned char *raw_password, size_t size,
 
754
                      const char **error_r)
705
755
{
706
 
        const char *password;
 
756
        const char *password, *generated;
707
757
 
708
758
        password = t_strndup(raw_password, size);
709
 
        return strcasecmp(password,
710
 
                password_generate_otp(plaintext, password, -1)) == 0;
 
759
        if (password_generate_otp(plaintext, password, -1, &generated) < 0) {
 
760
                *error_r = "Invalid OTP data in passdb";
 
761
                return -1;
 
762
        }
 
763
 
 
764
        return strcasecmp(password, generated) == 0 ? 1 : 0;
711
765
}
712
766
 
713
767
static void
716
770
{
717
771
        const char *password;
718
772
 
719
 
        password = password_generate_otp(plaintext, NULL, OTP_HASH_SHA1);
 
773
        if (password_generate_otp(plaintext, NULL, OTP_HASH_SHA1, &password) < 0)
 
774
                i_unreached();
720
775
        *raw_password_r = (const unsigned char *)password;
721
776
        *size_r = strlen(password);
722
777
}
727
782
{
728
783
        const char *password;
729
784
 
730
 
        password = password_generate_otp(plaintext, NULL, OTP_HASH_MD4);
 
785
        if (password_generate_otp(plaintext, NULL, OTP_HASH_MD4, &password) < 0)
 
786
                i_unreached();
731
787
        *raw_password_r = (const unsigned char *)password;
732
788
        *size_r = strlen(password);
733
789
}
762
818
        { "SSHA512", PW_ENCODING_BASE64, 0, ssha512_verify, ssha512_generate },
763
819
        { "PLAIN", PW_ENCODING_NONE, 0, NULL, plain_generate },
764
820
        { "CLEARTEXT", PW_ENCODING_NONE, 0, NULL, plain_generate },
 
821
        { "PLAIN-TRUNC", PW_ENCODING_NONE, 0, plain_trunc_verify, plain_generate },
765
822
        { "CRAM-MD5", PW_ENCODING_HEX, CRAM_MD5_CONTEXTLEN,
766
823
          NULL, cram_md5_generate },
767
824
        { "HMAC-MD5", PW_ENCODING_HEX, CRAM_MD5_CONTEXTLEN,