xcrypt 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +106 -0
- data/ext/libxcrypt/AUTHORS +38 -0
- data/ext/libxcrypt/COPYING.LIB +502 -0
- data/ext/libxcrypt/ChangeLog +239 -0
- data/ext/libxcrypt/INSTALL +380 -0
- data/ext/libxcrypt/LICENSING +152 -0
- data/ext/libxcrypt/Makefile.am +704 -0
- data/ext/libxcrypt/Makefile.in +4110 -0
- data/ext/libxcrypt/NEWS +630 -0
- data/ext/libxcrypt/README +1 -0
- data/ext/libxcrypt/README.md +179 -0
- data/ext/libxcrypt/THANKS +13 -0
- data/ext/libxcrypt/TODO +1 -0
- data/ext/libxcrypt/TODO.md +100 -0
- data/ext/libxcrypt/aclocal.m4 +2617 -0
- data/ext/libxcrypt/autogen.sh +33 -0
- data/ext/libxcrypt/autom4te.cache/output.0 +19884 -0
- data/ext/libxcrypt/autom4te.cache/output.1 +19884 -0
- data/ext/libxcrypt/autom4te.cache/output.2 +19884 -0
- data/ext/libxcrypt/autom4te.cache/output.3 +19885 -0
- data/ext/libxcrypt/autom4te.cache/requests +714 -0
- data/ext/libxcrypt/autom4te.cache/traces.0 +4088 -0
- data/ext/libxcrypt/autom4te.cache/traces.1 +1060 -0
- data/ext/libxcrypt/autom4te.cache/traces.2 +4088 -0
- data/ext/libxcrypt/autom4te.cache/traces.3 +1060 -0
- data/ext/libxcrypt/build-aux/ci/ci-log-dependency-versions +79 -0
- data/ext/libxcrypt/build-aux/ci/ci-log-logfiles +22 -0
- data/ext/libxcrypt/build-aux/ci/clang-gcov-wrapper +2 -0
- data/ext/libxcrypt/build-aux/ci/configure-wrapper +10 -0
- data/ext/libxcrypt/build-aux/ci/summarize-coverage +24 -0
- data/ext/libxcrypt/build-aux/m4/ax_append_compile_flags.m4 +46 -0
- data/ext/libxcrypt/build-aux/m4/ax_append_flag.m4 +50 -0
- data/ext/libxcrypt/build-aux/m4/ax_check_compile_flag.m4 +53 -0
- data/ext/libxcrypt/build-aux/m4/ax_check_vscript.m4 +142 -0
- data/ext/libxcrypt/build-aux/m4/ax_gcc_func_attribute.m4 +246 -0
- data/ext/libxcrypt/build-aux/m4/ax_require_defined.m4 +37 -0
- data/ext/libxcrypt/build-aux/m4/ax_valgrind_check.m4 +239 -0
- data/ext/libxcrypt/build-aux/m4/libtool.m4 +8488 -0
- data/ext/libxcrypt/build-aux/m4/ltoptions.m4 +467 -0
- data/ext/libxcrypt/build-aux/m4/ltsugar.m4 +124 -0
- data/ext/libxcrypt/build-aux/m4/ltversion.m4 +24 -0
- data/ext/libxcrypt/build-aux/m4/lt~obsolete.m4 +99 -0
- data/ext/libxcrypt/build-aux/m4/pkg_compat.m4 +88 -0
- data/ext/libxcrypt/build-aux/m4/zw_alignment.m4 +90 -0
- data/ext/libxcrypt/build-aux/m4/zw_automodern.m4 +307 -0
- data/ext/libxcrypt/build-aux/m4/zw_detect_asan.m4 +24 -0
- data/ext/libxcrypt/build-aux/m4/zw_endianness.m4 +152 -0
- data/ext/libxcrypt/build-aux/m4/zw_ld_wrap.m4 +47 -0
- data/ext/libxcrypt/build-aux/m4/zw_prog_perl.m4 +40 -0
- data/ext/libxcrypt/build-aux/m4/zw_simple_warnings.m4 +150 -0
- data/ext/libxcrypt/build-aux/m4/zw_static_assert.m4 +68 -0
- data/ext/libxcrypt/build-aux/m4-autogen/compile +364 -0
- data/ext/libxcrypt/build-aux/m4-autogen/config.guess +1815 -0
- data/ext/libxcrypt/build-aux/m4-autogen/config.sub +2354 -0
- data/ext/libxcrypt/build-aux/m4-autogen/depcomp +792 -0
- data/ext/libxcrypt/build-aux/m4-autogen/install-sh +541 -0
- data/ext/libxcrypt/build-aux/m4-autogen/ltmain.sh +11524 -0
- data/ext/libxcrypt/build-aux/m4-autogen/missing +236 -0
- data/ext/libxcrypt/build-aux/m4-autogen/test-driver +160 -0
- data/ext/libxcrypt/build-aux/scripts/BuildCommon.pm +712 -0
- data/ext/libxcrypt/build-aux/scripts/check-perlcritic-config +76 -0
- data/ext/libxcrypt/build-aux/scripts/compute-symver-floor +116 -0
- data/ext/libxcrypt/build-aux/scripts/expand-selected-hashes +80 -0
- data/ext/libxcrypt/build-aux/scripts/gen-crypt-h +131 -0
- data/ext/libxcrypt/build-aux/scripts/gen-crypt-hashes-h +141 -0
- data/ext/libxcrypt/build-aux/scripts/gen-crypt-symbol-vers-h +150 -0
- data/ext/libxcrypt/build-aux/scripts/gen-libcrypt-map +67 -0
- data/ext/libxcrypt/build-aux/scripts/move-if-change +84 -0
- data/ext/libxcrypt/build-aux/scripts/skip-if-exec-format-error +78 -0
- data/ext/libxcrypt/codecov.yml +4 -0
- data/ext/libxcrypt/config.h.in +303 -0
- data/ext/libxcrypt/configure +19885 -0
- data/ext/libxcrypt/configure.ac +549 -0
- data/ext/libxcrypt/doc/crypt.3 +512 -0
- data/ext/libxcrypt/doc/crypt.5 +343 -0
- data/ext/libxcrypt/doc/crypt_checksalt.3 +106 -0
- data/ext/libxcrypt/doc/crypt_gensalt.3 +285 -0
- data/ext/libxcrypt/doc/crypt_gensalt_ra.3 +1 -0
- data/ext/libxcrypt/doc/crypt_gensalt_rn.3 +1 -0
- data/ext/libxcrypt/doc/crypt_preferred_method.3 +68 -0
- data/ext/libxcrypt/doc/crypt_r.3 +1 -0
- data/ext/libxcrypt/doc/crypt_ra.3 +1 -0
- data/ext/libxcrypt/doc/crypt_rn.3 +1 -0
- data/ext/libxcrypt/lib/alg-des-tables.c +3858 -0
- data/ext/libxcrypt/lib/alg-des.c +269 -0
- data/ext/libxcrypt/lib/alg-des.h +74 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-const.h +313 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-core.c +238 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-core.h +51 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-hmac.c +78 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-hmac.h +46 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-precalc.h +1426 -0
- data/ext/libxcrypt/lib/alg-gost3411-2012-ref.h +67 -0
- data/ext/libxcrypt/lib/alg-hmac-sha1.c +140 -0
- data/ext/libxcrypt/lib/alg-hmac-sha1.h +35 -0
- data/ext/libxcrypt/lib/alg-md4.c +270 -0
- data/ext/libxcrypt/lib/alg-md4.h +43 -0
- data/ext/libxcrypt/lib/alg-md5.c +291 -0
- data/ext/libxcrypt/lib/alg-md5.h +43 -0
- data/ext/libxcrypt/lib/alg-sha1.c +288 -0
- data/ext/libxcrypt/lib/alg-sha1.h +34 -0
- data/ext/libxcrypt/lib/alg-sha256.c +630 -0
- data/ext/libxcrypt/lib/alg-sha256.h +123 -0
- data/ext/libxcrypt/lib/alg-sha512.c +311 -0
- data/ext/libxcrypt/lib/alg-sha512.h +81 -0
- data/ext/libxcrypt/lib/alg-sm3-hmac.c +113 -0
- data/ext/libxcrypt/lib/alg-sm3-hmac.h +42 -0
- data/ext/libxcrypt/lib/alg-sm3.c +449 -0
- data/ext/libxcrypt/lib/alg-sm3.h +63 -0
- data/ext/libxcrypt/lib/alg-yescrypt-common.c +713 -0
- data/ext/libxcrypt/lib/alg-yescrypt-opt.c +1568 -0
- data/ext/libxcrypt/lib/alg-yescrypt-platform.c +106 -0
- data/ext/libxcrypt/lib/alg-yescrypt.h +360 -0
- data/ext/libxcrypt/lib/byteorder.h +164 -0
- data/ext/libxcrypt/lib/crypt-bcrypt.c +1061 -0
- data/ext/libxcrypt/lib/crypt-des-obsolete.c +215 -0
- data/ext/libxcrypt/lib/crypt-des.c +491 -0
- data/ext/libxcrypt/lib/crypt-gensalt-static.c +40 -0
- data/ext/libxcrypt/lib/crypt-gost-yescrypt.c +182 -0
- data/ext/libxcrypt/lib/crypt-md5.c +232 -0
- data/ext/libxcrypt/lib/crypt-nthash.c +134 -0
- data/ext/libxcrypt/lib/crypt-obsolete.h +40 -0
- data/ext/libxcrypt/lib/crypt-pbkdf1-sha1.c +260 -0
- data/ext/libxcrypt/lib/crypt-port.h +514 -0
- data/ext/libxcrypt/lib/crypt-scrypt.c +247 -0
- data/ext/libxcrypt/lib/crypt-sha256.c +308 -0
- data/ext/libxcrypt/lib/crypt-sha512.c +323 -0
- data/ext/libxcrypt/lib/crypt-sm3-yescrypt.c +189 -0
- data/ext/libxcrypt/lib/crypt-sm3.c +308 -0
- data/ext/libxcrypt/lib/crypt-static.c +44 -0
- data/ext/libxcrypt/lib/crypt-sunmd5.c +314 -0
- data/ext/libxcrypt/lib/crypt-yescrypt.c +177 -0
- data/ext/libxcrypt/lib/crypt.c +421 -0
- data/ext/libxcrypt/lib/crypt.h.in +249 -0
- data/ext/libxcrypt/lib/gen-des-tables.c +363 -0
- data/ext/libxcrypt/lib/hashes.conf +59 -0
- data/ext/libxcrypt/lib/libcrypt.map.in +48 -0
- data/ext/libxcrypt/lib/libcrypt.minver +97 -0
- data/ext/libxcrypt/lib/libxcrypt.pc.in +15 -0
- data/ext/libxcrypt/lib/util-base64.c +26 -0
- data/ext/libxcrypt/lib/util-gensalt-sha.c +88 -0
- data/ext/libxcrypt/lib/util-get-random-bytes.c +154 -0
- data/ext/libxcrypt/lib/util-make-failure-token.c +48 -0
- data/ext/libxcrypt/lib/util-xbzero.c +43 -0
- data/ext/libxcrypt/lib/util-xstrcpy.c +42 -0
- data/ext/libxcrypt/lib/xcrypt.h.in +58 -0
- data/ext/libxcrypt/libxcrypt.spec.rpkg +481 -0
- data/ext/libxcrypt/rpkg.conf +2 -0
- data/ext/libxcrypt/rpkg.macros +86 -0
- data/ext/libxcrypt/test/TestCommon.pm +326 -0
- data/ext/libxcrypt/test/alg-des.c +80 -0
- data/ext/libxcrypt/test/alg-gost3411-2012-hmac.c +90 -0
- data/ext/libxcrypt/test/alg-gost3411-2012.c +191 -0
- data/ext/libxcrypt/test/alg-hmac-sha1.c +187 -0
- data/ext/libxcrypt/test/alg-md4.c +111 -0
- data/ext/libxcrypt/test/alg-md5.c +134 -0
- data/ext/libxcrypt/test/alg-pbkdf-hmac-sha256.c +269 -0
- data/ext/libxcrypt/test/alg-sha1.c +111 -0
- data/ext/libxcrypt/test/alg-sha256.c +141 -0
- data/ext/libxcrypt/test/alg-sha512.c +170 -0
- data/ext/libxcrypt/test/alg-sm3-hmac.c +149 -0
- data/ext/libxcrypt/test/alg-sm3.c +168 -0
- data/ext/libxcrypt/test/alg-yescrypt.c +466 -0
- data/ext/libxcrypt/test/badsalt.c +726 -0
- data/ext/libxcrypt/test/badsetting.c +350 -0
- data/ext/libxcrypt/test/byteorder.c +254 -0
- data/ext/libxcrypt/test/checksalt.c +265 -0
- data/ext/libxcrypt/test/compile-strong-alias.c +43 -0
- data/ext/libxcrypt/test/crypt-badargs.c +392 -0
- data/ext/libxcrypt/test/crypt-gost-yescrypt.c +149 -0
- data/ext/libxcrypt/test/crypt-nested-call.c +180 -0
- data/ext/libxcrypt/test/crypt-sm3-yescrypt.c +149 -0
- data/ext/libxcrypt/test/crypt-too-long-phrase.c +157 -0
- data/ext/libxcrypt/test/des-cases.h +196 -0
- data/ext/libxcrypt/test/des-obsolete.c +206 -0
- data/ext/libxcrypt/test/des-obsolete_r.c +207 -0
- data/ext/libxcrypt/test/explicit-bzero.c +334 -0
- data/ext/libxcrypt/test/gensalt-bcrypt_x.c +54 -0
- data/ext/libxcrypt/test/gensalt-extradata.c +246 -0
- data/ext/libxcrypt/test/gensalt-nested-call.c +126 -0
- data/ext/libxcrypt/test/gensalt-nthash.c +65 -0
- data/ext/libxcrypt/test/gensalt.c +599 -0
- data/ext/libxcrypt/test/getrandom-fallbacks.c +295 -0
- data/ext/libxcrypt/test/getrandom-interface.c +211 -0
- data/ext/libxcrypt/test/ka-table-gen.py +945 -0
- data/ext/libxcrypt/test/ka-table.inc +5849 -0
- data/ext/libxcrypt/test/ka-tester.c +240 -0
- data/ext/libxcrypt/test/preferred-method.c +133 -0
- data/ext/libxcrypt/test/short-outbuf.c +119 -0
- data/ext/libxcrypt/test/special-char-salt.c +1160 -0
- data/ext/libxcrypt/test/symbols-compat.pl +137 -0
- data/ext/libxcrypt/test/symbols-renames.pl +107 -0
- data/ext/libxcrypt/test/symbols-static.pl +87 -0
- data/ext/xcrypt/xcrypt.c +9 -0
- data/lib/xcrypt/ffi.rb +76 -0
- data/lib/xcrypt/version.rb +5 -0
- data/lib/xcrypt.rb +89 -0
- metadata +267 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#! /usr/bin/perl
|
|
2
|
+
# Written by Zack Weinberg <zackw at panix.com> in 2017 and 2020.
|
|
3
|
+
# To the extent possible under law, Zack Weinberg has waived all
|
|
4
|
+
# copyright and related or neighboring rights to this work.
|
|
5
|
+
#
|
|
6
|
+
# See https://creativecommons.org/publicdomain/zero/1.0/ for further
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
# This test is only run if we are building a shared library intended
|
|
10
|
+
# to be binary backward compatible with GNU libc (libcrypt.so.1).
|
|
11
|
+
# It locates any installed version of libcrypt.so.1, and verifies that
|
|
12
|
+
# each public symbol exposed by that library is also exposed by our
|
|
13
|
+
# libcrypt.so.1 with a matching symbol version.
|
|
14
|
+
#
|
|
15
|
+
# Due to limitations in Automake, this program takes parameters from
|
|
16
|
+
# the environment:
|
|
17
|
+
# $lib_la - full pathname of libcrypt.la
|
|
18
|
+
# $SYMBOL_PREFIX - prefix, if any, added to global symbols defined from C
|
|
19
|
+
# $CC, $NM - names of tools to run (defaults to 'cc' and 'nm' respectively)
|
|
20
|
+
# $CFLAGS, $LDFLAGS - options to pass to $CC when linking (default: empty)
|
|
21
|
+
|
|
22
|
+
use v5.14; # implicit use strict, use feature ':5.14'
|
|
23
|
+
use warnings FATAL => 'all';
|
|
24
|
+
use utf8;
|
|
25
|
+
use open qw(:std :utf8);
|
|
26
|
+
no if $] >= 5.022, warnings => 'experimental::re_strict';
|
|
27
|
+
use if $] >= 5.022, re => 'strict';
|
|
28
|
+
|
|
29
|
+
use FindBin ();
|
|
30
|
+
use lib $FindBin::Bin;
|
|
31
|
+
use TestCommon qw(
|
|
32
|
+
compare_symbol_lists
|
|
33
|
+
ensure_C_locale
|
|
34
|
+
find_real_library
|
|
35
|
+
get_symbols
|
|
36
|
+
popen
|
|
37
|
+
sh_split
|
|
38
|
+
skip
|
|
39
|
+
subprocess_error
|
|
40
|
+
which
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
# Some differences between the symbols exported by heritage libcrypt.so.1
|
|
44
|
+
# and our libcrypt.so.1 are expected:
|
|
45
|
+
#
|
|
46
|
+
# * All of the symbols we define with GLIBC_2.xx version tags are
|
|
47
|
+
# compatibility symbols (nm prints only one @); naturally,
|
|
48
|
+
# glibc-provided libcrypt.so.1 defines some of those symbols as
|
|
49
|
+
# linkable symbols (two @).
|
|
50
|
+
#
|
|
51
|
+
# * Older versions of libcrypt defined five symbols as linkable,
|
|
52
|
+
# with the XCRYPT_2.0 version tag, which are now compatibility-only:
|
|
53
|
+
# crypt_gensalt_r, xcrypt, xcrypt_gensalt, xcrypt_gensalt_r, and
|
|
54
|
+
# xcrypt_r.
|
|
55
|
+
#
|
|
56
|
+
# This sub is applied to the symbol listing from the system-provided
|
|
57
|
+
# libcrypt.so.1; it edits that listing so that the comparison below
|
|
58
|
+
# succeeds despite any expected differences.
|
|
59
|
+
sub filter_expected_differences {
|
|
60
|
+
my $symbols = shift;
|
|
61
|
+
my %filtered;
|
|
62
|
+
my $formerly_linkable = qr{
|
|
63
|
+
^ (?: crypt_gensalt_r
|
|
64
|
+
| xcrypt(?: _r)?
|
|
65
|
+
| xcrypt_gensalt(?: _r)?
|
|
66
|
+
) @@
|
|
67
|
+
}x;
|
|
68
|
+
for my $s (keys %{$symbols}) {
|
|
69
|
+
$s =~ s/\b@@(?=GLIBC_)/@/;
|
|
70
|
+
$s =~ s/\b@@(?=XCRYPT_2\.0)/@/ if $s =~ $formerly_linkable;
|
|
71
|
+
$filtered{$s} = 1;
|
|
72
|
+
}
|
|
73
|
+
return \%filtered;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
sub find_system_libcrypt {
|
|
77
|
+
# Ask the compiler whether a libcrypt.so.1 exists in its search
|
|
78
|
+
# path. The compiler option -print-file-name should be supported
|
|
79
|
+
# on all operating systems where there's an older libcrypt that we
|
|
80
|
+
# can be backward compatible with.
|
|
81
|
+
state @CC;
|
|
82
|
+
if (!@CC) {
|
|
83
|
+
@CC = which($ENV{CC} || 'cc');
|
|
84
|
+
skip('C compiler not available') unless @CC;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
state @CFLAGS;
|
|
88
|
+
if (!@CFLAGS) {
|
|
89
|
+
@CFLAGS = sh_split($ENV{CFLAGS} || q{});
|
|
90
|
+
}
|
|
91
|
+
state @LDFLAGS;
|
|
92
|
+
if (!@LDFLAGS) {
|
|
93
|
+
@LDFLAGS = sh_split($ENV{LDFLAGS} || q{});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
my $fh =
|
|
97
|
+
popen('-|', @CC, @CFLAGS, @LDFLAGS, '-print-file-name=libcrypt.so.1');
|
|
98
|
+
my $path;
|
|
99
|
+
{
|
|
100
|
+
local $/ = undef; # slurp
|
|
101
|
+
$path = <$fh>;
|
|
102
|
+
}
|
|
103
|
+
close $fh or subprocess_error($CC[0]);
|
|
104
|
+
|
|
105
|
+
chomp $path;
|
|
106
|
+
# If we get back either the empty string or the same string we put
|
|
107
|
+
# in, it means there is no libcrypt.so.1 on this system.
|
|
108
|
+
if ($path eq q{} || $path eq 'libcrypt.so.1') {
|
|
109
|
+
skip('no system-provided libcrypt.so.1');
|
|
110
|
+
}
|
|
111
|
+
return $path;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
sub get_our_symbols {
|
|
115
|
+
return get_symbols(find_real_library(shift, 'shared'));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
sub get_their_symbols {
|
|
119
|
+
return filter_expected_differences(get_symbols(find_system_libcrypt()));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
#
|
|
123
|
+
# Main
|
|
124
|
+
#
|
|
125
|
+
my $lib_la = $ENV{lib_la} || '/nonexistent';
|
|
126
|
+
if (!-f $lib_la) {
|
|
127
|
+
print {*STDERR} "usage: lib_la=/path/to/library.la $0";
|
|
128
|
+
exit 1;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
ensure_C_locale();
|
|
132
|
+
exit compare_symbol_lists(
|
|
133
|
+
get_our_symbols($lib_la),
|
|
134
|
+
get_their_symbols(),
|
|
135
|
+
'symbol versions',
|
|
136
|
+
1, # extra symbols are allowed
|
|
137
|
+
);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#! /usr/bin/perl
|
|
2
|
+
# Written by Zack Weinberg <zackw at panix.com> in 2017 and 2020.
|
|
3
|
+
# To the extent possible under law, Zack Weinberg has waived all
|
|
4
|
+
# copyright and related or neighboring rights to this work.
|
|
5
|
+
#
|
|
6
|
+
# See https://creativecommons.org/publicdomain/zero/1.0/ for further
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
# Check that all of the symbols renamed by crypt-port.h
|
|
10
|
+
# still appear somewhere in the source code. This test does not attempt
|
|
11
|
+
# to parse the source code, so it can get false negatives (e.g. a word used
|
|
12
|
+
# in a comment will be enough).
|
|
13
|
+
#
|
|
14
|
+
# Due to limitations in Automake, this program takes parameters from
|
|
15
|
+
# the environment:
|
|
16
|
+
# $lib_la - full pathname of libcrypt.la
|
|
17
|
+
# $SYMBOL_PREFIX - prefix, if any, added to global symbols defined from C
|
|
18
|
+
# $NM, $CPP, $CPPFLAGS - nm utility, C preprocessor, and parameters
|
|
19
|
+
|
|
20
|
+
use v5.14; # implicit use strict, use feature ':5.14'
|
|
21
|
+
use warnings FATAL => 'all';
|
|
22
|
+
use utf8;
|
|
23
|
+
use open qw(:std :utf8);
|
|
24
|
+
no if $] >= 5.022, warnings => 'experimental::re_strict';
|
|
25
|
+
use if $] >= 5.022, re => 'strict';
|
|
26
|
+
|
|
27
|
+
use File::Temp ();
|
|
28
|
+
|
|
29
|
+
use FindBin ();
|
|
30
|
+
use lib $FindBin::Bin;
|
|
31
|
+
use TestCommon qw(
|
|
32
|
+
compare_symbol_lists
|
|
33
|
+
ensure_C_locale
|
|
34
|
+
find_real_library
|
|
35
|
+
get_symbols
|
|
36
|
+
popen
|
|
37
|
+
sh_split
|
|
38
|
+
skip
|
|
39
|
+
subprocess_error
|
|
40
|
+
which
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
sub list_library_internals {
|
|
44
|
+
# We are only interested in symbols with the internal prefix,
|
|
45
|
+
# _crypt_.
|
|
46
|
+
return get_symbols(find_real_library(shift, 'static'),
|
|
47
|
+
sub { $_[0] =~ /^_crypt_/ });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
sub list_symbol_renames {
|
|
51
|
+
state @CPP;
|
|
52
|
+
if (!@CPP) {
|
|
53
|
+
@CPP = which($ENV{CPP} || 'cc -E');
|
|
54
|
+
skip('C compiler not available') unless @CPP;
|
|
55
|
+
}
|
|
56
|
+
state @CPPFLAGS;
|
|
57
|
+
if (!@CPPFLAGS) {
|
|
58
|
+
@CPPFLAGS = sh_split($ENV{CPPFLAGS} || q{});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
my $tmp = File::Temp->new(
|
|
62
|
+
DIR => '.',
|
|
63
|
+
TEMPLATE => 'symbols-renames-XXXXXX',
|
|
64
|
+
SUFFIX => '.c',
|
|
65
|
+
EXLOCK => 0,
|
|
66
|
+
);
|
|
67
|
+
print {$tmp} qq{#include "crypt-port.h"\n};
|
|
68
|
+
|
|
69
|
+
my $fh = popen('-|', @CPP, @CPPFLAGS, '-dD', $tmp->filename);
|
|
70
|
+
local $_;
|
|
71
|
+
my %symbols;
|
|
72
|
+
my $pp_define = qr{
|
|
73
|
+
^\#define \s+
|
|
74
|
+
[a-zA-Z_][a-zA-Z0-9_(),]* \s+
|
|
75
|
+
(_crypt_[a-zA-Z0-9_]*) \b
|
|
76
|
+
}x;
|
|
77
|
+
while (<$fh>) {
|
|
78
|
+
chomp;
|
|
79
|
+
s/\s+$//;
|
|
80
|
+
if ($_ =~ $pp_define) {
|
|
81
|
+
print {*STDERR} "| $1\n";
|
|
82
|
+
$symbols{$1} = 1;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
close $fh or subprocess_error($CPP[0]);
|
|
86
|
+
return \%symbols;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# Main
|
|
91
|
+
#
|
|
92
|
+
my $lib_la = $ENV{lib_la} || '/nonexistent';
|
|
93
|
+
if (!-f $lib_la) {
|
|
94
|
+
print {*STDERR} "usage: lib_la=/path/to/library.la $0";
|
|
95
|
+
exit 1;
|
|
96
|
+
}
|
|
97
|
+
if (($ENV{HAVE_CPP_dD} // 'yes') eq 'no') {
|
|
98
|
+
skip('cpp -dD not available');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
ensure_C_locale();
|
|
102
|
+
exit compare_symbol_lists(
|
|
103
|
+
list_library_internals($lib_la),
|
|
104
|
+
list_symbol_renames(),
|
|
105
|
+
'renames',
|
|
106
|
+
0, # extra symbols not allowed
|
|
107
|
+
);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#! /usr/bin/perl
|
|
2
|
+
# Written by Zack Weinberg <zackw at panix.com> in 2017 and 2020.
|
|
3
|
+
# To the extent possible under law, Zack Weinberg has waived all
|
|
4
|
+
# copyright and related or neighboring rights to this work.
|
|
5
|
+
#
|
|
6
|
+
# See https://creativecommons.org/publicdomain/zero/1.0/ for further
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
# Test that all global symbols in the static version of the library
|
|
10
|
+
# (libcrypt.a) are either listed as global and supported for new code
|
|
11
|
+
# in libcrypt.map.in, or begin with a _crypt prefix. Also test that
|
|
12
|
+
# all of the global, supported for new code, symbols mentioned in
|
|
13
|
+
# libcrypt.map.in are in fact defined.
|
|
14
|
+
#
|
|
15
|
+
# Due to limitations in Automake, this program takes parameters from
|
|
16
|
+
# the environment:
|
|
17
|
+
# $lib_la - full pathname of libcrypt.la
|
|
18
|
+
# $lib_map - full pathname of libcrypt.map.in
|
|
19
|
+
# $SYMBOL_PREFIX - prefix, if any, added to global symbols defined from C
|
|
20
|
+
# $NM, $CPP, $CPPFLAGS - nm utility, C preprocessor, and parameters
|
|
21
|
+
|
|
22
|
+
use v5.14; # implicit use strict, use feature ':5.14'
|
|
23
|
+
use warnings FATAL => 'all';
|
|
24
|
+
use utf8;
|
|
25
|
+
use open qw(:std :utf8);
|
|
26
|
+
no if $] >= 5.022, warnings => 'experimental::re_strict';
|
|
27
|
+
use if $] >= 5.022, re => 'strict';
|
|
28
|
+
|
|
29
|
+
use FindBin ();
|
|
30
|
+
use lib $FindBin::Bin;
|
|
31
|
+
use TestCommon qw(
|
|
32
|
+
error
|
|
33
|
+
ensure_C_locale
|
|
34
|
+
find_real_library
|
|
35
|
+
get_symbols
|
|
36
|
+
compare_symbol_lists
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
my $symbol_prefix = $ENV{SYMBOL_PREFIX} || q{};
|
|
40
|
+
|
|
41
|
+
sub list_library_globals {
|
|
42
|
+
# Symbols that begin with _crypt_ are private to the library.
|
|
43
|
+
# Symbols that begin with _[_A-Y] are private to the C
|
|
44
|
+
# implementation. All other symbols (including any that begin
|
|
45
|
+
# with _Z, which are C++ mangled names) are part of the library's
|
|
46
|
+
# public interface.
|
|
47
|
+
return get_symbols(
|
|
48
|
+
find_real_library(shift, 'static'),
|
|
49
|
+
sub { $_[0] !~ /^_(?:[_A-Y]|crypt_)/ },
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
sub list_expected_globals {
|
|
54
|
+
my ($lib_map) = @_;
|
|
55
|
+
open my $fh, '<', $lib_map
|
|
56
|
+
or error("$lib_map: $!");
|
|
57
|
+
|
|
58
|
+
local $_;
|
|
59
|
+
my %symbols;
|
|
60
|
+
while (<$fh>) {
|
|
61
|
+
chomp;
|
|
62
|
+
s/\s+$//;
|
|
63
|
+
next if /^($|#|%chain\b)/;
|
|
64
|
+
|
|
65
|
+
my @fields = split;
|
|
66
|
+
$symbols{$fields[0]} = 1 if $fields[1] ne '-';
|
|
67
|
+
}
|
|
68
|
+
return \%symbols;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
# Main
|
|
73
|
+
#
|
|
74
|
+
my $lib_la = $ENV{lib_la} || '/nonexistent';
|
|
75
|
+
my $lib_map = $ENV{lib_map} || '/nonexistent';
|
|
76
|
+
if (!-f $lib_la || !-f $lib_map) {
|
|
77
|
+
print {*STDERR} "usage: lib_la=/p/lib.la lib_map=/p/lib.map $0";
|
|
78
|
+
exit 1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
ensure_C_locale();
|
|
82
|
+
exit compare_symbol_lists(
|
|
83
|
+
list_library_globals($lib_la),
|
|
84
|
+
list_expected_globals($lib_map),
|
|
85
|
+
'globals',
|
|
86
|
+
0, # extra symbols not allowed
|
|
87
|
+
);
|
data/ext/xcrypt/xcrypt.c
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xcrypt.c — compilation stub for ffi-compiler.
|
|
3
|
+
*
|
|
4
|
+
* The actual implementation lives in libxcrypt (ext/libxcrypt), which is
|
|
5
|
+
* linked statically into this shared library at build time. Ruby code
|
|
6
|
+
* reaches the libxcrypt API through Ruby-FFI (see lib/xcrypt/ffi.rb); no
|
|
7
|
+
* wrapper functions are needed here.
|
|
8
|
+
*/
|
|
9
|
+
#include "crypt.h"
|
data/lib/xcrypt/ffi.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ffi"
|
|
4
|
+
require "ffi-compiler/loader"
|
|
5
|
+
|
|
6
|
+
module XCrypt
|
|
7
|
+
# Low-level FFI bindings for libxcrypt.
|
|
8
|
+
#
|
|
9
|
+
# Consumers should use the high-level {XCrypt} module methods instead of
|
|
10
|
+
# calling into this module directly.
|
|
11
|
+
#
|
|
12
|
+
# The shared library loaded here is compiled from the libxcrypt submodule
|
|
13
|
+
# (ext/libxcrypt) via ffi-compiler. Run <tt>bundle exec rake compile</tt>
|
|
14
|
+
# to build it before loading this gem.
|
|
15
|
+
module FFI
|
|
16
|
+
extend ::FFI::Library
|
|
17
|
+
|
|
18
|
+
# Size constants mirrored from <crypt.h>.
|
|
19
|
+
CRYPT_OUTPUT_SIZE = 384
|
|
20
|
+
CRYPT_MAX_PASSPHRASE_SIZE = 512
|
|
21
|
+
CRYPT_GENSALT_OUTPUT_SIZE = 192
|
|
22
|
+
CRYPT_DATA_RESERVED_SIZE = 767
|
|
23
|
+
CRYPT_DATA_INTERNAL_SIZE = 30_720
|
|
24
|
+
|
|
25
|
+
# sizeof(struct crypt_data) == 32768 bytes, as guaranteed by the header.
|
|
26
|
+
CRYPT_DATA_SIZE = 32_768
|
|
27
|
+
|
|
28
|
+
# crypt_checksalt(3) return codes.
|
|
29
|
+
CRYPT_SALT_OK = 0
|
|
30
|
+
CRYPT_SALT_INVALID = 1
|
|
31
|
+
CRYPT_SALT_METHOD_DISABLED = 2
|
|
32
|
+
CRYPT_SALT_METHOD_LEGACY = 3
|
|
33
|
+
CRYPT_SALT_TOO_CHEAP = 4
|
|
34
|
+
|
|
35
|
+
# Load the native extension compiled from the libxcrypt submodule.
|
|
36
|
+
# FFI::Compiler::Loader searches for lib<arch>-<os>/libxcrypt.{bundle,so}
|
|
37
|
+
# relative to this file's location.
|
|
38
|
+
begin
|
|
39
|
+
ffi_lib ::FFI::Compiler::Loader.find("xcrypt")
|
|
40
|
+
rescue LoadError
|
|
41
|
+
raise LoadError,
|
|
42
|
+
"XCrypt native extension not found. " \
|
|
43
|
+
"Build it with: rake compile"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# char *crypt_rn(const char *phrase, const char *setting,
|
|
47
|
+
# void *data, int size)
|
|
48
|
+
#
|
|
49
|
+
# Thread-safe variant that writes to a caller-supplied buffer. Returns
|
|
50
|
+
# NULL on error instead of a magic error string.
|
|
51
|
+
attach_function :crypt_rn, [:string, :string, :pointer, :int], :pointer
|
|
52
|
+
|
|
53
|
+
# char *crypt_gensalt_rn(const char *prefix, unsigned long count,
|
|
54
|
+
# const char *rbytes, int nrbytes,
|
|
55
|
+
# char *output, int output_size)
|
|
56
|
+
#
|
|
57
|
+
# Thread-safe salt generator that writes to a caller-supplied buffer.
|
|
58
|
+
# Pass NULL for rbytes to let the library obtain entropy from the OS.
|
|
59
|
+
attach_function :crypt_gensalt_rn,
|
|
60
|
+
[:string, :ulong, :pointer, :int, :pointer, :int],
|
|
61
|
+
:pointer
|
|
62
|
+
|
|
63
|
+
# int crypt_checksalt(const char *setting)
|
|
64
|
+
#
|
|
65
|
+
# Inspects a setting string and reports whether it is valid.
|
|
66
|
+
attach_function :crypt_checksalt, [:string], :int
|
|
67
|
+
|
|
68
|
+
# const char *crypt_preferred_method(void)
|
|
69
|
+
#
|
|
70
|
+
# Returns the prefix string of the library's preferred (strongest)
|
|
71
|
+
# hashing method.
|
|
72
|
+
attach_function :crypt_preferred_method, [], :string
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private_constant :FFI
|
|
76
|
+
end
|
data/lib/xcrypt.rb
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module XCrypt
|
|
4
|
+
require "xcrypt/version"
|
|
5
|
+
require "xcrypt/ffi"
|
|
6
|
+
|
|
7
|
+
Error ||= Class.new(StandardError)
|
|
8
|
+
|
|
9
|
+
ALGORITHMS = {
|
|
10
|
+
yescrypt: "$y$",
|
|
11
|
+
gost_yescrypt: "$gy$",
|
|
12
|
+
scrypt: "$7$",
|
|
13
|
+
bcrypt: "$2b$",
|
|
14
|
+
sha512: "$6$",
|
|
15
|
+
sha256: "$5$",
|
|
16
|
+
sha1: "$sha1$",
|
|
17
|
+
sun_md5: "$md5",
|
|
18
|
+
md5: "$1$",
|
|
19
|
+
bsdi_des: "_",
|
|
20
|
+
des: "",
|
|
21
|
+
}.freeze
|
|
22
|
+
|
|
23
|
+
PREFIXES = ALGORITHMS.invert.freeze
|
|
24
|
+
private_constant :ALGORITHMS, :PREFIXES
|
|
25
|
+
|
|
26
|
+
extend self
|
|
27
|
+
|
|
28
|
+
ALGORITHMS.each_key do |algorithm|
|
|
29
|
+
define_method(algorithm) do |phrase, setting = nil, cost: nil|
|
|
30
|
+
if setting
|
|
31
|
+
setting_algorithm = detect_algorithm(setting)
|
|
32
|
+
if setting_algorithm != algorithm
|
|
33
|
+
raise ArgumentError, "setting algorithm #{setting_algorithm.inspect} does not match expected #{algorithm.inspect}"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
crypt(phrase, setting, algorithm:, cost:)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def algorithms = ALGORITHMS.keys
|
|
41
|
+
|
|
42
|
+
def detect_algorithm(setting) = PREFIXES[setting[/\A\$\w+\$?|_/].to_s]
|
|
43
|
+
|
|
44
|
+
def crypt(phrase, setting = nil, algorithm: nil, cost: nil)
|
|
45
|
+
setting, algorithm = nil, setting if setting.is_a? Symbol
|
|
46
|
+
setting ||= generate_setting(algorithm, cost:)
|
|
47
|
+
data = ::FFI::MemoryPointer.new(:uint8, FFI::CRYPT_DATA_SIZE)
|
|
48
|
+
result_ptr = FFI.crypt_rn(phrase, setting, data, FFI::CRYPT_DATA_SIZE)
|
|
49
|
+
raise Error, "crypt failed: invalid setting or unsupported algorithm" if result_ptr.null?
|
|
50
|
+
result_ptr.read_string
|
|
51
|
+
ensure
|
|
52
|
+
data&.clear
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def verify(phrase, hash)
|
|
56
|
+
return false if hash.nil? || hash.empty? || hash.start_with?("*")
|
|
57
|
+
result = crypt(phrase, hash)
|
|
58
|
+
secure_compare(result, hash)
|
|
59
|
+
rescue Error
|
|
60
|
+
false
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def generate_setting(algorithm = nil, cost: nil)
|
|
64
|
+
prefix = ALGORITHMS.fetch(algorithm) { raise ArgumentError, "unknown algorithm: #{algorithm.inspect}" } if algorithm
|
|
65
|
+
cost ||= 0
|
|
66
|
+
|
|
67
|
+
output = ::FFI::MemoryPointer.new(:char, FFI::CRYPT_GENSALT_OUTPUT_SIZE)
|
|
68
|
+
result_ptr = FFI.crypt_gensalt_rn(prefix, cost, nil, 0, output, FFI::CRYPT_GENSALT_OUTPUT_SIZE)
|
|
69
|
+
raise Error, "crypt_gensalt failed: unknown prefix or unsupported algorithm" if result_ptr.null?
|
|
70
|
+
|
|
71
|
+
result_ptr.read_string
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def secure_compare(trusted, untrusted)
|
|
77
|
+
return false unless trusted.respond_to? :to_str and trusted = trusted.to_str.b
|
|
78
|
+
return false unless untrusted.respond_to? :to_str and untrusted = untrusted.to_str.b
|
|
79
|
+
|
|
80
|
+
# avoid ability for attacker to guess length of string by timing attack
|
|
81
|
+
comparable = trusted[0, untrusted.bytesize].ljust(untrusted.bytesize, "\0".b)
|
|
82
|
+
|
|
83
|
+
result = defined?(OpenSSL.fixed_length_secure_compare) ?
|
|
84
|
+
OpenSSL.fixed_length_secure_compare(comparable, untrusted) :
|
|
85
|
+
comparable.each_byte.zip(untrusted.each_byte).reduce(0) { |acc, (a, b)| acc | (a ^ b) }.zero?
|
|
86
|
+
|
|
87
|
+
trusted.bytesize == untrusted.bytesize and result
|
|
88
|
+
end
|
|
89
|
+
end
|