class

Krikri::PluginHelpers::CryptHash::CryptFacade

Inherits Reference < Object

The runtime half: which crypt library got loaded, and whether it is libxcrypt (has crypt_gensalt) or a bare libc crypt() (musl).

Constants

CANDIDATE_LIBRARIES = begin libs = ["libcrypt.so.1", "libcrypt.dylib", "libcrypt.so"] of String | ::Nil {% if flag?(:darwin) %} libs.concat([ "/opt/homebrew/opt/libxcrypt/lib/libcrypt.dylib", "/usr/local/opt/libxcrypt/lib/libcrypt.dylib", ]) {% else %} libs << nil libs.concat([ "libc.musl-x86_64.so.1", "libc.musl-aarch64.so.1", "libc.musl-riscv64.so.1", ]) {% end %} libs end

Same order as ansible's _CRYPT_LIBS: libxcrypt by soname first, then (non-darwin only) the process's own libc - where a musl host's crypt() lives - then macOS's two Homebrew libxcrypt paths. The musl-specific sonames stand in for ansible's bare ctypes.CDLL(None): dlopen'ing a glibc libc.so by name into a static musl process would initialize a second libc, which is not something to risk.

CRYPT_DATA_SIZE = 131072

libxcrypt's own struct crypt_data is small, but musl's crypt_r expects ~128K of it and ansible allocates that size, so match it.

FAILURE_TOKENS = {"*", "*0", "*1"}

crypt(3)'s "invalid salt"/"unsupported scheme" return values.

GENSALT_OUTPUT_SIZE = 256

ansible's own output buffer for crypt_gensalt_rn.

Constructors

facade
Source
new(lib_names : Array(String | Nil) = CANDIDATE_LIBRARIES, use_gensalt : Bool = true)
Source

Class methods

current

Test seam (and the only reason this is a property): a spec can point the module at a facade built from a specific library list.

Source
current=(current : CryptFacade | Nil)

Test seam (and the only reason this is a property): a spec can point the module at a facade built from a specific library list.

Source

Instance methods

available?

Ansible's HAS_CRYPT: no library at all means password_hash cannot be used on this host.

Source
crypt(word : String, salt : String) : String | Nil

crypt(): nil for every outcome ansible turns into an error (a null pointer, an empty string, or crypt's "*" failure tokens).

Source
crypt_gensalt(prefix : String, count : UInt64, rbytes : Bytes) : String | Nil

crypt_gensalt(): nil when the library has no gensalt entry point at all or when it refuses the prefix/rounds.

Source
has_crypt_gensalt?

Ansible's _crypt_facade.has_crypt_gensalt: false on a musl host, so the salt string gets built by hand instead of by libxcrypt.

Source

Nested types