]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add support for PBKDF2
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 26 Jul 2017 23:09:03 +0000 (19:09 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 26 Jul 2017 23:09:12 +0000 (19:09 -0400)
45 files changed:
scripts/Pbkdf2Passwd [new file with mode: 0755]
share/dictionary.freeradius.internal
src/modules/rlm_pap/rlm_pap.c
src/tests/modules/pap/all.mk [new file with mode: 0644]
src/tests/modules/pap/module.conf [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_dig_big.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_dig_big.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_dig_small.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_dig_small.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter0.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter0.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter1.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter1.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter1000.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter1000.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter100000.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter100000.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter_big.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter_big.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter_miss.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter_miss.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter_small.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_iter_small.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt0.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt0.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt1.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt1.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt1024.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt1024.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt64.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt64.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt_big.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt_big.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt_small.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_salt_small.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha1.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha1.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha2_224.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha2_224.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha2_256.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha2_256.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha2_384.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha2_384.unlang [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha2_512.attrs [new file with mode: 0644]
src/tests/modules/pap/pbkfd2_sha2_512.unlang [new file with mode: 0644]

diff --git a/scripts/Pbkdf2Passwd b/scripts/Pbkdf2Passwd
new file mode 100755 (executable)
index 0000000..2176320
--- /dev/null
@@ -0,0 +1,168 @@
+#!/usr/bin/perl -w
+use strict;
+use Getopt::Long qw(:config no_ignore_case);
+use Pod::Usage;
+use Crypt::PBKDF2;
+use Time::HiRes;
+use Math::Random::Secure qw(irand);
+
+my %opts;
+GetOptions(\%opts,
+       qw[ help|?! man! a|algorithm=s i|iterations=i l|len=i s|salt=s S|Salt=s t|time! z|saltlen=i ]
+) or pod2usage(2);
+pod2usage(1) if $opts{help};
+pod2usage(-verbose => 2) if $opts{man};
+
+my $algo = 'HMACSHA2';
+if (exists $opts{a}) {
+       my %algorithm = ('1' => 'HMACSHA1', 'sha1' => 'HMACSHA1', 
+               '2' => 'HMACSHA2', 'sha2' => 'HMACSHA2',
+               '3' => 'HMACSHA3', 'sha3' => 'HMACSHA3');
+       $algo = $algorithm{$opts{a}};
+       if (!defined $algo) {
+               print "Bad algorithm\n";
+               exit(1);
+       }
+}
+
+my $iter;
+my %hargs;
+my $ssiz;
+if ($algo eq 'HMACSHA1') {
+       $iter = 1000;
+       %hargs = ( output_len => 20 );
+       $ssiz = 8;
+} elsif ($algo eq 'HMACSHA2' or $algo eq 'HMACSHA3') {
+       $iter = 10000;
+       my $len = 256;
+       if (exists $opts{l}) {
+               my @length = (224, 256, 384, 512);
+               if (grep {$_ eq $opts{l}} @length) {
+                       $len = $opts{l};
+               } else {
+                       print "Bad length\n";
+                       exit(1);
+               }
+       }
+       %hargs = ( hash_args => {
+               sha_size => $len,
+       } );
+       $ssiz = 16;
+}
+
+if (exists $opts{i}) {
+       $iter = $opts{i};
+       if ($iter < 1 || $iter > 0xffffffff) {
+               print "Bad iterations\n";
+               exit(1);
+       }
+}
+
+my $password = $ARGV[0];
+if (!defined $password) {
+       print "Missing password\n";
+       exit(1);
+}
+
+my $salt = $opts{s};
+if (exists $opts{S}) {
+       if (defined $salt) {
+               print "Redundant salt\n";
+               exit(1);
+       }
+       $salt = pack('H*', $opts{S});
+}
+if (!defined $salt) {
+       $ssiz = $opts{z} if (exists $opts{z});
+       if ($ssiz < 0) {
+               print "Bad salt length\n";
+               exit(1);
+       }
+       while ($ssiz >= 4) {
+               $salt .= pack('N', irand());
+               $ssiz -= 4;
+       }
+       $salt .= substr(pack('N', irand()), 1, $ssiz) if ($ssiz > 0);
+}
+
+my $pbkdf2;
+$pbkdf2 = Crypt::PBKDF2->new(
+       hash_class => $algo,
+       %hargs,
+       iterations => $iter,
+       salt_len => $ssiz, # Seems to use non-cryptographic rand
+);
+
+my $t0 = [Time::HiRes::gettimeofday];
+my $hash = $pbkdf2->generate($password, $salt);
+my $t1 = Time::HiRes::tv_interval($t0);
+print substr($hash, 10)."\n";
+print "Time:".$t1."\n" if (exists $opts{t});
+
+__END__
+
+=head1 NAME
+
+Pbkdf2Passwd - Generate a PBKDF2 hashed password
+
+=head1 DESCRIPTION
+
+Generate a Password Based Key Derivation Functiong version 2 using given
+password, a hashing algorithm, the number of iterations, and optional salt.
+
+=head1 SYNOPSIS
+
+   Pbkdf2Passwd [options] <password>
+
+=head1 OPTIONS
+
+=over
+
+=item B<-a> or B<-algorithm> <algorithm>
+
+Format options:
+
+=over 
+
+=item B<1> or B<sha1> : SHA-1
+
+=item B<2> or B<sha2> : SHA-2 (default)
+
+=item B<3> or B<sha3> : SHA-3
+
+=back
+
+=item B<-i> or B<-iterations> <count>
+
+Count of algorithm iterations (1 to 4294967295 | SHA-1 default: 1000,
+SHA-2 / SHA-3 default: 10000).
+
+=item B<-l> or B<-length> <length>
+
+For SHA-2 / SHA-3 algorithm bit length (224, 256, 384, or 512 | default: 256).
+
+=item B<-s> or B<-salt> <string>
+
+=item B<-S> or B<-Salt> <hexadecimal string>
+
+Salt string appended to password and hashed.
+
+=item B<-z> or B<-saltlen> <length>
+
+Byte length of random salt appended to password and hashed, if no salt string
+is explicitly given (SHA-1 default:8, SHA-2 / SHA-3 default: 16).
+
+=item B<-t> or B<-time>
+
+Approximate time to generate password (in seconds).
+
+=item B<-?> or B<-help>
+
+Print a brief help message.
+
+=item B<-man>
+
+Print the manual page.
+
+=back
+=cut
index 195e57eb8e27ffa87eab96cddeb4bd5fb4957bbd..e6d43b8d2a669a5c5c2f64dc17957adcda5e7e0d 100644 (file)
@@ -290,6 +290,7 @@ ATTRIBUTE   SSHA2-224-Password                      1180    octets
 ATTRIBUTE      SSHA2-256-Password                      1181    octets
 ATTRIBUTE      SSHA2-384-Password                      1182    octets
 ATTRIBUTE      SSHA2-512-Password                      1183    octets
+ATTRIBUTE      PBKDF2-Password                         1184    octets
 
 ATTRIBUTE      Exec-Export                             1190    string
 
index 26b37746017cb9ce3c0b60a29d9ef8295228975a..a21d7f1401b105fbafbafecc204049832e70f6a5 100644 (file)
@@ -85,6 +85,7 @@ static const FR_NAME_NUMBER header_names[] = {
        { "{ssha256}",          FR_SSHA2_256_PASSWORD },
        { "{ssha384}",          FR_SSHA2_384_PASSWORD },
        { "{ssha512}",          FR_SSHA2_512_PASSWORD },
+       { "{x-pbkdf2}",         FR_PBKDF2_PASSWORD },
 #endif
        { "{sha}",              FR_SHA_PASSWORD },
        { "{ssha}",             FR_SSHA_PASSWORD },
@@ -98,6 +99,17 @@ static const FR_NAME_NUMBER header_names[] = {
        { NULL, 0 }
 };
 
+#ifdef HAVE_OPENSSL_EVP_H
+static const FR_NAME_NUMBER pbkdf2_names[] = {
+       { "HMACSHA1",           FR_SSHA_PASSWORD },
+       { "HMACSHA2+224",       FR_SSHA2_224_PASSWORD },
+       { "HMACSHA2+256",       FR_SSHA2_256_PASSWORD },
+       { "HMACSHA2+384",       FR_SSHA2_384_PASSWORD },
+       { "HMACSHA2+512",       FR_SSHA2_512_PASSWORD },
+       { NULL, 0 }
+};
+#endif
+
 static int mod_instantiate(void *instance, CONF_SECTION *conf)
 {
        rlm_pap_t               *inst = instance;
@@ -417,6 +429,10 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, UNUSED void *t
                        }
                        found_pw = true;
                        break;
+
+               case FR_PBKDF2_PASSWORD:
+                       found_pw = true; /* Already base64 standardized */
+                       break;
 #endif
 
                case FR_SHA_PASSWORD:
@@ -792,6 +808,190 @@ static rlm_rcode_t CC_HINT(nonnull) pap_auth_ssha2(rlm_pap_t const *inst, REQUES
 
        return RLM_MODULE_OK;
 }
+
+#define B64_DIM(siz) FR_BASE64_DEC_LENGTH(FR_BASE64_ENC_LENGTH(siz))
+
+static inline rlm_rcode_t CC_HINT(nonnull) pap_auth_pbkdf2_ldap(REQUEST *request, const uint8_t *str, size_t len)
+{
+       rlm_rcode_t             rcode = RLM_MODULE_INVALID;
+
+       uint8_t const           *p, *q, *end;
+       ssize_t                 slen;
+
+       EVP_MD const            *evp_md;
+       int                     digest_type;
+       size_t                  digest_len;
+
+       uint32_t                iterations;
+
+       uint8_t                 *salt = NULL;
+       size_t                  salt_len;
+       uint8_t                 hash[EVP_MAX_MD_SIZE];
+       uint8_t                 digest[EVP_MAX_MD_SIZE];
+
+       RDEBUG("Comparing with \"known-good\" PBKDF2-Password (ldap format)");
+
+       /*
+        *      Parse PBKDF string = {hash_algorithm}:base64(interations):base64(salt):base64(hash)
+        */
+       p = str;
+       end = p + len;
+
+       q = memchr(p, ':', end - p);
+       if (!q) {
+               REDEBUG("PBKDF2-Password has no component separators");
+               goto finish;
+       }
+
+       digest_type = fr_substr2int(pbkdf2_names, (char const *)p, -1, q - p);
+       switch (digest_type) {
+       case FR_SSHA_PASSWORD:
+               evp_md = EVP_sha1();
+               digest_len = 20;
+               break;
+
+       case FR_SSHA2_224_PASSWORD:
+               evp_md = EVP_sha224();
+               digest_len = 28;
+               break;
+
+       case FR_SSHA2_256_PASSWORD:
+               evp_md = EVP_sha256();
+               digest_len = 32;
+               break;
+
+       case FR_SSHA2_384_PASSWORD:
+               evp_md = EVP_sha384();
+               digest_len = 48;
+               break;
+
+       case FR_SSHA2_512_PASSWORD:
+               evp_md = EVP_sha512();
+               digest_len = 64;
+               break;
+
+       default:
+               REDEBUG("Unknown PBKDF2 hash method \"%.*s\"", (int)(q - p), p);
+               goto finish;
+       }
+
+       p = q + 1;
+
+       if (((end - p) < 1) || !(q = memchr(p, ':', end - p))) {
+               REDEBUG("PBKDF2-Password missing iterations component");
+               goto finish;
+       }
+
+       if ((q - p) == 0) {
+               REDEBUG("PBKDF2-Password iterations component too short");
+               goto finish;
+       }
+
+       (void)fr_strerror();
+       slen = fr_base64_decode((uint8_t *)&iterations, sizeof(iterations), (char const *)p, q - p);
+       if (slen < 0) {
+               REDEBUG("Failed decoding PBKDF2-Password iterations component (%.*s): %s", (int)(q - p), p,
+                       fr_strerror());
+               goto finish;
+       }
+       if (slen != sizeof(iterations)) {
+               REDEBUG("Decoded PBKDF2-Password iterations component is wrong size");
+       }
+
+       iterations = ntohl(iterations);
+
+       p = q + 1;
+
+       if (((end - p) < 1) || !(q = memchr(p, ':', end - p))) {
+               REDEBUG("PBKDF2-Password missing salt component");
+               goto finish;
+       }
+
+       if ((q - p) == 0) {
+               REDEBUG("PBKDF2-Password salt component too short");
+               goto finish;
+       }
+
+       MEM(salt = talloc_array(request, uint8_t, FR_BASE64_DEC_LENGTH(q - p)));
+       slen = fr_base64_decode(salt, talloc_array_length(salt), (char const *) p, q - p);
+       if (slen < 0) {
+               REDEBUG("Failed decoding PBKDF2-Password salt component: %s", fr_strerror());
+               goto finish;
+       }
+       salt_len = (size_t)slen;
+
+       p = q + 1;
+
+       if ((q - p) == 0) {
+               REDEBUG("PBKDF2-Password hash component too short");
+               goto finish;
+       }
+
+       slen = fr_base64_decode(hash, sizeof(hash), (char const *)p, end - p);
+       if (slen < 0) {
+               REDEBUG("Failed decoding PBKDF2-Password hash component: %s", fr_strerror());
+               goto finish;
+       }
+
+       if ((size_t)slen != digest_len) {
+               REDEBUG("PBKDF2-Password hash component length is incorrect for hash type, expected %zu, got %zd",
+                       digest_len, slen);
+
+               RHEXDUMP(L_DBG_LVL_2, hash, slen, "hash component");
+
+               goto finish;
+       }
+
+       RDEBUG2("PBKDF2 %s: Iterations %u, salt length %zu, hash length %zd",
+               fr_int2str(pbkdf2_names, digest_type, "<UNKNOWN>"),
+               iterations, salt_len, slen);
+
+       /*
+        *      Hash and compare
+        */
+       if (PKCS5_PBKDF2_HMAC((char const *)request->password->vp_octets, (int)request->password->vp_length,
+                             (unsigned char const *)salt, (int)salt_len,
+                             (int)iterations,
+                             evp_md,
+                             (int)digest_len, (unsigned char *)digest) == 0) {
+               REDEBUG("PBKDF2 digest failure");
+               goto finish;
+       }
+
+       if (fr_digest_cmp(digest, hash, (size_t)digest_len) != 0) {
+               REDEBUG("PBKDF2 digest does not match \"known good\" digest");
+               rcode = RLM_MODULE_REJECT;
+               RHEXDUMP(L_DBG_LVL_3, salt, salt_len, "salt");
+               RHEXDUMP(L_DBG_LVL_3, hash, slen, "\"known good\" digest");
+               RHEXDUMP(L_DBG_LVL_3, digest, digest_len, "computed digest");
+       } else {
+               rcode = RLM_MODULE_OK;
+       }
+
+finish:
+       talloc_free(salt);
+
+       return rcode;
+}
+
+static inline rlm_rcode_t CC_HINT(nonnull) pap_auth_pbkdf2(UNUSED rlm_pap_t const *inst,
+                                                          REQUEST *request, VALUE_PAIR *vp)
+{
+       if (vp->vp_length < 2) {
+               REDEBUG("PBKDF2-Password too short");
+               return RLM_MODULE_INVALID;
+       }
+
+       if (vp->vp_octets[0] == '$') {
+               ERROR("Crypt PBKDF2 is currently unsupported");
+               return RLM_MODULE_FAIL;
+       } else {
+               return pap_auth_pbkdf2_ldap(request, vp->vp_octets, vp->vp_length);
+       }
+
+       REDEBUG("Can't determine format of PBKDF2-Password");
+       return RLM_MODULE_INVALID;
+}
 #endif
 
 static rlm_rcode_t CC_HINT(nonnull) pap_auth_nt(rlm_pap_t const *inst, REQUEST *request, VALUE_PAIR *vp)
@@ -992,6 +1192,10 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, UNUSED void
                case FR_SSHA2_512_PASSWORD:
                        auth_func = &pap_auth_ssha2;
                        break;
+
+               case FR_PBKDF2_PASSWORD:
+                       auth_func = &pap_auth_pbkdf2;
+                       break;
 #endif
 
                case FR_SHA_PASSWORD:
diff --git a/src/tests/modules/pap/all.mk b/src/tests/modules/pap/all.mk
new file mode 100644 (file)
index 0000000..5c1de6f
--- /dev/null
@@ -0,0 +1,3 @@
+#
+#  Test the "pap" module
+#
diff --git a/src/tests/modules/pap/module.conf b/src/tests/modules/pap/module.conf
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/src/tests/modules/pap/pbkfd2_dig_big.attrs b/src/tests/modules/pap/pbkfd2_dig_big.attrs
new file mode 100644 (file)
index 0000000..90fc451
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_dig_big'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/pap/pbkfd2_dig_big.unlang b/src/tests/modules/pap/pbkfd2_dig_big.unlang
new file mode 100644 (file)
index 0000000..ad08b75
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_dig_big') {
+       update control {
+               &PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_dig_small.attrs b/src/tests/modules/pap/pbkfd2_dig_small.attrs
new file mode 100644 (file)
index 0000000..dbc5bdd
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_dig_small'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/pap/pbkfd2_dig_small.unlang b/src/tests/modules/pap/pbkfd2_dig_small.unlang
new file mode 100644 (file)
index 0000000..c2a8804
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_dig_small') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI'
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_iter0.attrs b/src/tests/modules/pap/pbkfd2_iter0.attrs
new file mode 100644 (file)
index 0000000..871017e
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_iter0'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/pap/pbkfd2_iter0.unlang b/src/tests/modules/pap/pbkfd2_iter0.unlang
new file mode 100644 (file)
index 0000000..8fe972d
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_iter0') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAAAP:CuNDJ9NimZoP5ljnPNCBUA==:f09zV7dReGg5SIv/EXY9tCL4XQRr5guhL0Q6UXSKI3c='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_iter1.attrs b/src/tests/modules/pap/pbkfd2_iter1.attrs
new file mode 100644 (file)
index 0000000..e3d62cb
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_iter1'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/pap/pbkfd2_iter1.unlang b/src/tests/modules/pap/pbkfd2_iter1.unlang
new file mode 100644 (file)
index 0000000..6182fba
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_iter1') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:OErtptMl2hOxhQqvNw7sNw==:4KkrgL+3Q9j8KlHPivtApBKRZAjyWjtDWmZEz2UjNko='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_iter1000.attrs b/src/tests/modules/pap/pbkfd2_iter1000.attrs
new file mode 100644 (file)
index 0000000..10a19c3
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_iter1000'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/pap/pbkfd2_iter1000.unlang b/src/tests/modules/pap/pbkfd2_iter1000.unlang
new file mode 100644 (file)
index 0000000..49f59c0
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_iter1000') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAD6A:yhmqoKrtPLY2KYK6cNjnfw==:Y6gkSZEo4TRtlsryHqnGYZhoe2qn5tJ4IUyyVHb/3WU='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_iter100000.attrs b/src/tests/modules/pap/pbkfd2_iter100000.attrs
new file mode 100644 (file)
index 0000000..8da916c
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_iter100000'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_iter100000.unlang b/src/tests/modules/pap/pbkfd2_iter100000.unlang
new file mode 100644 (file)
index 0000000..619dc11
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_iter100000') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AA9CQA:fCfnJGMVC1QLtTOPiaSICA==:KCmjMpQ+lokMvyFTl4f4pPJNc0xJq4iHZPdtHa0OEXM='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_iter_big.attrs b/src/tests/modules/pap/pbkfd2_iter_big.attrs
new file mode 100644 (file)
index 0000000..9f8dddb
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_iter_big'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/pap/pbkfd2_iter_big.unlang b/src/tests/modules/pap/pbkfd2_iter_big.unlang
new file mode 100644 (file)
index 0000000..ab45ece
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_iter_big') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAAAQ==:E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_iter_miss.attrs b/src/tests/modules/pap/pbkfd2_iter_miss.attrs
new file mode 100644 (file)
index 0000000..983db26
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_iter_miss'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/pap/pbkfd2_iter_miss.unlang b/src/tests/modules/pap/pbkfd2_iter_miss.unlang
new file mode 100644 (file)
index 0000000..7f6d46d
--- /dev/null
@@ -0,0 +1,14 @@
+if (&User-Name == 'pbkdf2_iter_miss') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256::E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI='
+       }
+       pap.authorize
+       pap.authenticate {
+               invalid = 1
+       }
+       if (invalid) {
+               test_pass
+       } else {
+               test_fail
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_iter_small.attrs b/src/tests/modules/pap/pbkfd2_iter_small.attrs
new file mode 100644 (file)
index 0000000..af8351b
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_iter_small'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
+
diff --git a/src/tests/modules/pap/pbkfd2_iter_small.unlang b/src/tests/modules/pap/pbkfd2_iter_small.unlang
new file mode 100644 (file)
index 0000000..0d5dee7
--- /dev/null
@@ -0,0 +1,14 @@
+if (&User-Name == 'pbkdf2_iter_small') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAAA:E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI='
+       }
+       pap.authorize
+       pap.authenticate {
+               invalid = 1
+       }
+       if (invalid) {
+               test_pass
+       } else {
+               test_fail
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_salt0.attrs b/src/tests/modules/pap/pbkfd2_salt0.attrs
new file mode 100644 (file)
index 0000000..7e6d209
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_salt0'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_salt0.unlang b/src/tests/modules/pap/pbkfd2_salt0.unlang
new file mode 100644 (file)
index 0000000..14626f1
--- /dev/null
@@ -0,0 +1,14 @@
+if (&User-Name == 'pbkdf2_salt0') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAnEA::4RJEKVFQ5nE8126aURI0cJO9tqy/DIAhq64piBEwshA='
+       }
+       pap.authorize
+       pap.authenticate {
+               invalid = 1
+       }
+       if (invalid) {
+               test_pass
+       } else {
+               test_fail
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_salt1.attrs b/src/tests/modules/pap/pbkfd2_salt1.attrs
new file mode 100644 (file)
index 0000000..20ff1fe
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_salt1'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_salt1.unlang b/src/tests/modules/pap/pbkfd2_salt1.unlang
new file mode 100644 (file)
index 0000000..c21089d
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_salt1') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAnEA:qg==:KQzCdedgOZYFwx+mQp1TKA8VM4fwf02pqSdJEh2ekwM='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_salt1024.attrs b/src/tests/modules/pap/pbkfd2_salt1024.attrs
new file mode 100644 (file)
index 0000000..30f2706
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_salt1024'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_salt1024.unlang b/src/tests/modules/pap/pbkfd2_salt1024.unlang
new file mode 100644 (file)
index 0000000..7c81c82
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_salt1024') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAnEA:/IUrkJKe+1kzJNBw7aAMbnQuSFZpjbCqPeKso3cbuSUzWinxngxjK8yyZLiWwF+WE/0Gplfx25zZEQNTdRTvjZZNefoxQBR8Hht0FpdU9YiEBaeErwVo63EDEu83+ycvB18uH0IXpJKGSSkIPRfGpHT3BkwJDGo5SqjRJadDsyQzkc/WJCMrrfJ0igaWMxb5eR5J8qfXIjBFepRrOOU6acZGtANW8qvDYLJwN+TMd9Jb1wDDY14eoAlKglTF21S3kewNMkDDyeP+oDYv29t1S/soFUnnB+Pb5IdR6pDy2VDGx4jFZMQGshSHWTYQFqgulavS/tGEF8TvzcorrJZKuksAjKdTSmfZ6j4aBY3U+oMSQ+2lO131pkNfNQuMsDfr72r9wUA2xRgUiL/J7CgKn7mamL2OCaksl0Rw2PGqqIaHvAYS6Q1EoIzsmLNrWBYYqTRLyCGZw6+hUOahYRon2lglGmnuWHPfowU+LgcaR5gF1QjvTXhXQ8I39mB3ePgdi+7TUn644Z1FB+JTqGJbue92x4V40Zyyy+Qdt52QsR49iYokbKAwQRiqfVJ7J8NzCY/kIQnqT9RE0NCxZoMBRzboZxVPchxdpmWGQ9dXP06PqIuDCFFiJlVQUfyPMgOAxIlVJ/9NAmj5MWFdWMrmlBNDx9ihEV1FdTv23iFZH5Ejg+x4D3qN5oOyCDL2i9lobzFXh5z4EDpbbogQaFkUzqKEaxRGPBrfYVOi6XXYujVUnxHJaRxbs2UqjpJNsXMg8f7P78aRvOKCIbW70CHWlt7nF0pA5+kFUQRLXKuq7bW+ivoXKeDW5o4FVP3+Pcr67+DOsUXuehALLj9Mu2ICWlMIV/AWcM2szaqk1bwSo7bAeG4RtDKmNjGA7gpnT+w2x+/qS1eWbc832Sumqc1IA8aY6HNVDPsJZf99To4BR+N0rCoQQ/KIZybI31mQagR3+FR9yNzqWzKIl+qf69RTc1CbUCkKVF8pxWZ0ocP+CAdoKadgpdF8evQIiGcUD73HiJ0RsDWo21y0tN0P5jfzWo3WMhCk9e2wl6o1JAfKw54uHzWJnNlGLBK1LXF+R2m+WvNGBgvUhh4PtYV9gPSudumFdk614oak/Aqcn6xi+YZqOMPkW4WYaiczhHyS7qAyefqKaQkRVYS0Af+79CSjlxZJq57HrD7/1E+d/i0gKmSAbPe80uGHs2a13V3VxztFMBi4xD7zj9Mq7+0goVPD4MNXcR651MZ7vxDRGbvPPmclddZe/nkTEn1YB/909b9mC5P/XzximZYW8gEhBReZouukADRTAjuH8zgSIv6/uyTURnmSVoOumVLBpL7veJIzDm4dZ38BWiasiBnzgMuG9A==:RUoCF5O11OgwLFMTqnKY/yRJy6DYh+yNq4xHZC7COGM='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_salt64.attrs b/src/tests/modules/pap/pbkfd2_salt64.attrs
new file mode 100644 (file)
index 0000000..493a61b
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_salt64'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_salt64.unlang b/src/tests/modules/pap/pbkfd2_salt64.unlang
new file mode 100644 (file)
index 0000000..ebf0448
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_salt64') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAnEA:msGxE1XuC+wlgRr+H4+ioyxZuiN3KYLUSky2FINDTq7KJylKt4XnqloV+FuHGXUbOu1EWcsFp51u2z8wdXVnQQ==:rAV9BeEJH5kt9uZ6pJt0o5pYpN5LQRe4MAYyk2jvjpU='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_salt_big.attrs b/src/tests/modules/pap/pbkfd2_salt_big.attrs
new file mode 100644 (file)
index 0000000..ccb593e
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_salt_big'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_salt_big.unlang b/src/tests/modules/pap/pbkfd2_salt_big.unlang
new file mode 100644 (file)
index 0000000..52105b9
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_salt_big') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:E+VXOSsE8RwyYGdygQoW9QA==:pF23EcxNBhJLQ+9JRtd9wQ1Gz+k4i6YjeNZq+7DRBX8='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_salt_small.attrs b/src/tests/modules/pap/pbkfd2_salt_small.attrs
new file mode 100644 (file)
index 0000000..1c2fa20
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_salt_small'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_salt_small.unlang b/src/tests/modules/pap/pbkfd2_salt_small.unlang
new file mode 100644 (file)
index 0000000..4429ab1
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_salt_small') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:E+VXOSsE8RwyYGdygQoW9Q=:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_sha1.attrs b/src/tests/modules/pap/pbkfd2_sha1.attrs
new file mode 100644 (file)
index 0000000..ef7538f
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_sha1'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_sha1.unlang b/src/tests/modules/pap/pbkfd2_sha1.unlang
new file mode 100644 (file)
index 0000000..f377548
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_sha1') {
+       update control {
+               PBKDF2-Password := 'HMACSHA1:AAAD6A:Xw1P133xrwk=:dtQBXQRiR/No5A8Ip3JFGF/qUC0='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_sha2_224.attrs b/src/tests/modules/pap/pbkfd2_sha2_224.attrs
new file mode 100644 (file)
index 0000000..413f893
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_sha2_224'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_sha2_224.unlang b/src/tests/modules/pap/pbkfd2_sha2_224.unlang
new file mode 100644 (file)
index 0000000..3345796
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_sha2_224') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+224:AAAnEA:UHScBrg/ZWOyBKqQdAh7bw==:tcFp6CDrkIYdhwa60g24U4ko+mBxzAiFxlpPnA=='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_sha2_256.attrs b/src/tests/modules/pap/pbkfd2_sha2_256.attrs
new file mode 100644 (file)
index 0000000..3066682
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_sha2_256'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_sha2_256.unlang b/src/tests/modules/pap/pbkfd2_sha2_256.unlang
new file mode 100644 (file)
index 0000000..92506f5
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_sha2_256') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+256:AAAnEA:a/8HbYW2HWsMthN27JI+Ew==:3nPlXYOlOuDCFOfethUomHxTXkG9JCivOdvh6FDNdGw='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_sha2_384.attrs b/src/tests/modules/pap/pbkfd2_sha2_384.attrs
new file mode 100644 (file)
index 0000000..9e43450
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_sha2_384'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_sha2_384.unlang b/src/tests/modules/pap/pbkfd2_sha2_384.unlang
new file mode 100644 (file)
index 0000000..8888039
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_sha2_384') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+384:AAAnEA:pyHRsYLfNZdjszRcu6eHrA==:ktGfNmZ6PyD8FNEgPzFK1fypKERZ13pgvFl+PQdyKouaMXsXIiWPuTMXHqDUCWsx'
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}
diff --git a/src/tests/modules/pap/pbkfd2_sha2_512.attrs b/src/tests/modules/pap/pbkfd2_sha2_512.attrs
new file mode 100644 (file)
index 0000000..b908615
--- /dev/null
@@ -0,0 +1,10 @@
+#
+#  Input packet
+#
+User-Name = 'pbkdf2_sha2_512'
+User-Password = 'password'
+
+#
+#  Expected answer
+#
+Response-Packet-Type == Access-Accept
diff --git a/src/tests/modules/pap/pbkfd2_sha2_512.unlang b/src/tests/modules/pap/pbkfd2_sha2_512.unlang
new file mode 100644 (file)
index 0000000..2647679
--- /dev/null
@@ -0,0 +1,12 @@
+if (&User-Name == 'pbkdf2_sha2_512') {
+       update control {
+               PBKDF2-Password := 'HMACSHA2+512:AAAnEA:TG8Mb94NEmfPLaePwi5CFA==:SYSFeRf9jr4Uo5DB4NvNUEuc1gmEiLjTac5J4WgyKa7mO58KHKWop9xWmcFeuLtUN/iexLTNSgcubOugAyZcog=='
+       }
+       pap.authorize
+       pap.authenticate
+       if (!ok) {
+               test_fail
+       } else {
+               test_pass
+       }
+}