libroot: introduce crypt_r
Change-Id: Ieacd1b383ac078a440227c7954f5531a36fbbd62 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5827 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023, Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _GNU_CRYPT_H_
|
||||||
|
#define _GNU_CRYPT_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <features.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _DEFAULT_SOURCE
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct crypt_data {
|
||||||
|
int initialized;
|
||||||
|
char buf[512];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
char *crypt_rn(const char *key, const char *salt, struct crypt_data *data, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
crypt_r(const char *key, const char *salt, struct crypt_data *data)
|
||||||
|
{
|
||||||
|
return crypt_rn(key, salt, data, sizeof(struct crypt_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _GNU_CRYPT_H_ */
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
SubDir HAIKU_TOP src libs gnu ;
|
SubDir HAIKU_TOP src libs gnu ;
|
||||||
|
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ;
|
||||||
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility gnu ] : true ;
|
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility gnu ] : true ;
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ local architectureObject ;
|
|||||||
for architectureObject in [ MultiArchSubDirSetup ] {
|
for architectureObject in [ MultiArchSubDirSetup ] {
|
||||||
on $(architectureObject) {
|
on $(architectureObject) {
|
||||||
SharedLibrary [ MultiArchDefaultGristFiles libgnu.so ] :
|
SharedLibrary [ MultiArchDefaultGristFiles libgnu.so ] :
|
||||||
|
crypt.cpp
|
||||||
memmem.c
|
memmem.c
|
||||||
qsort.c
|
qsort.c
|
||||||
xattr.cpp
|
xattr.cpp
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include <crypt.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* move this to libroot_private.h ??? */
|
||||||
|
extern "C" char *_crypt_rn(const char* key, const char* setting, struct crypt_data* data, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
crypt_rn(const char* key, const char* setting, struct crypt_data* data, size_t size)
|
||||||
|
{
|
||||||
|
return _crypt_rn(key, setting, data, size);
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ SubDir HAIKU_TOP src system libroot posix crypt ;
|
|||||||
|
|
||||||
UsePrivateHeaders libroot ;
|
UsePrivateHeaders libroot ;
|
||||||
UsePrivateSystemHeaders ;
|
UsePrivateSystemHeaders ;
|
||||||
|
SubDirSysHdrs $(HAIKU_TOP) headers compatibility bsd ;
|
||||||
|
SubDirSysHdrs $(HAIKU_TOP) headers compatibility gnu ;
|
||||||
|
|
||||||
local architectureObject ;
|
local architectureObject ;
|
||||||
for architectureObject in [ MultiArchSubDirSetup ] {
|
for architectureObject in [ MultiArchSubDirSetup ] {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <crypt.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@@ -24,8 +25,8 @@
|
|||||||
#define SALT_STR_BYTES (SALT_BYTES * 2 + 1)
|
#define SALT_STR_BYTES (SALT_BYTES * 2 + 1)
|
||||||
#define DEFAULT_N_LOG2 14
|
#define DEFAULT_N_LOG2 14
|
||||||
|
|
||||||
// $s$99$ salt $ hash \0
|
|
||||||
#define CRYPT_OUTPUT_BYTES (6 + 64 + 1 + 64 + 1)
|
#define CRYPT_OUTPUT_BYTES (6 + 64 + 1 + 64 + 1)
|
||||||
|
#define SALT_OUTPUT_BYTES (6 + 64 + 1 + 1)
|
||||||
|
|
||||||
static const char* kHexAlphabet = "0123456789abcdef";
|
static const char* kHexAlphabet = "0123456789abcdef";
|
||||||
static const int8 kHexLookup[] = {
|
static const int8 kHexLookup[] = {
|
||||||
@@ -97,17 +98,16 @@ fromHex(const char* hex, uint8* outBuffer, size_t outBufferLength)
|
|||||||
|
|
||||||
|
|
||||||
//! Generate a new salt appropriate for crypt().
|
//! Generate a new salt appropriate for crypt().
|
||||||
static char*
|
static int
|
||||||
crypt_gensalt()
|
crypt_gensalt_rn(char *outbuf, size_t bufsize)
|
||||||
{
|
{
|
||||||
static char result[CRYPT_OUTPUT_BYTES];
|
|
||||||
uint8 salt[SALT_BYTES];
|
uint8 salt[SALT_BYTES];
|
||||||
char saltString[SALT_STR_BYTES];
|
char saltString[SALT_STR_BYTES];
|
||||||
size_t totalBytesRead = 0;
|
size_t totalBytesRead = 0;
|
||||||
|
|
||||||
int fd = open("/dev/random", O_RDONLY, 0);
|
int fd = open("/dev/random", O_RDONLY, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
while (totalBytesRead < sizeof(salt)) {
|
while (totalBytesRead < sizeof(salt)) {
|
||||||
const ssize_t bytesRead = read(fd,
|
const ssize_t bytesRead = read(fd,
|
||||||
@@ -115,7 +115,7 @@ crypt_gensalt()
|
|||||||
sizeof(salt) - totalBytesRead);
|
sizeof(salt) - totalBytesRead);
|
||||||
if (bytesRead <= 0) {
|
if (bytesRead <= 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalBytesRead += bytesRead;
|
totalBytesRead += bytesRead;
|
||||||
@@ -123,34 +123,38 @@ crypt_gensalt()
|
|||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
assert(toHex(salt, sizeof(salt), saltString, sizeof(saltString)) == 0);
|
assert(toHex(salt, sizeof(salt), saltString, sizeof(saltString)) == 0);
|
||||||
snprintf(result, sizeof(result), "$s$%d$%s$", DEFAULT_N_LOG2, saltString);
|
snprintf(outbuf, bufsize, "$s$%d$%s$", DEFAULT_N_LOG2, saltString);
|
||||||
return result;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
extern "C" char *
|
||||||
crypt(const char* key, const char* setting)
|
_crypt_rn(const char* key, const char* setting, struct crypt_data* data, size_t size)
|
||||||
{
|
{
|
||||||
static char outBuffer[CRYPT_OUTPUT_BYTES];
|
|
||||||
uint8 saltBinary[SALT_BYTES];
|
uint8 saltBinary[SALT_BYTES];
|
||||||
char saltString[SALT_STR_BYTES];
|
char saltString[SALT_STR_BYTES];
|
||||||
|
char gensaltResult[SALT_OUTPUT_BYTES];
|
||||||
uint8 resultBuffer[32];
|
uint8 resultBuffer[32];
|
||||||
char hexResultBuffer[64 + 1];
|
char hexResultBuffer[64 + 1];
|
||||||
int nLog2 = DEFAULT_N_LOG2;
|
int nLog2 = DEFAULT_N_LOG2;
|
||||||
|
|
||||||
if (setting == NULL) {
|
if (setting == NULL) {
|
||||||
setting = crypt_gensalt();
|
int res = crypt_gensalt_rn(gensaltResult, sizeof(gensaltResult));
|
||||||
if (setting == NULL) {
|
|
||||||
// crypt_gensalt should set errno itself.
|
// crypt_gensalt_r should set errno itself.
|
||||||
|
if (res < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
setting = gensaltResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some idioms existed where the password was also used as the salt.
|
// Some idioms existed where the password was also used as the salt.
|
||||||
// As a crude heuristic, use the old crypt algorithm if the salt is
|
// As a crude heuristic, use the old crypt algorithm if the salt is
|
||||||
// shortish.
|
// shortish.
|
||||||
if (strlen(setting) < 16)
|
if (strlen(setting) < 16) {
|
||||||
return crypt_legacy(key, setting);
|
crypt_legacy(key, setting, data->buf);
|
||||||
|
return data->buf;
|
||||||
|
}
|
||||||
|
|
||||||
// We don't want to fall into the old algorithm by accident somehow, so
|
// We don't want to fall into the old algorithm by accident somehow, so
|
||||||
// if our salt is kind of like our salt, but not exactly, return an
|
// if our salt is kind of like our salt, but not exactly, return an
|
||||||
@@ -183,10 +187,18 @@ crypt(const char* key, const char* setting)
|
|||||||
|
|
||||||
assert(toHex(resultBuffer, sizeof(resultBuffer), hexResultBuffer,
|
assert(toHex(resultBuffer, sizeof(resultBuffer), hexResultBuffer,
|
||||||
sizeof(hexResultBuffer)) == 0);
|
sizeof(hexResultBuffer)) == 0);
|
||||||
snprintf(outBuffer, sizeof(outBuffer), "$s$%d$%s$%s", nLog2, saltString,
|
snprintf(data->buf, size - sizeof(int), "$s$%d$%s$%s", nLog2, saltString,
|
||||||
hexResultBuffer);
|
hexResultBuffer);
|
||||||
|
|
||||||
return outBuffer;
|
return data->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
crypt(const char* key, const char* salt)
|
||||||
|
{
|
||||||
|
static struct crypt_data data;
|
||||||
|
return _crypt_rn(key, salt, &data, sizeof(struct crypt_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *crypt_legacy(const char *key, const char *salt);
|
void crypt_legacy(const char *key, const char *salt, char *outbuf);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -694,10 +694,8 @@ ufc_long *_ufc_dofinalperm(l1, l2, r1, r2)
|
|||||||
* prefixing with the salt
|
* prefixing with the salt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC char *output_conversion(v1, v2, salt)
|
STATIC void output_conversion_r(ufc_long v1, ufc_long v2, const char *salt, char *outbuf)
|
||||||
ufc_long v1, v2;
|
{
|
||||||
char *salt;
|
|
||||||
{ static char outbuf[14];
|
|
||||||
int i, s, shf;
|
int i, s, shf;
|
||||||
|
|
||||||
outbuf[0] = salt[0];
|
outbuf[0] = salt[0];
|
||||||
@@ -718,8 +716,6 @@ STATIC char *output_conversion(v1, v2, salt)
|
|||||||
|
|
||||||
outbuf[12] = bin_to_ascii(s);
|
outbuf[12] = bin_to_ascii(s);
|
||||||
outbuf[13] = 0;
|
outbuf[13] = 0;
|
||||||
|
|
||||||
return outbuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ufc_long *_ufc_doit();
|
ufc_long *_ufc_doit();
|
||||||
@@ -728,9 +724,9 @@ ufc_long *_ufc_doit();
|
|||||||
* UNIX crypt function
|
* UNIX crypt function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *crypt_legacy(key, salt)
|
void crypt_legacy(const char *key, const char *salt, char *outbuf)
|
||||||
const char *key, *salt;
|
{
|
||||||
{ ufc_long *s;
|
ufc_long *s;
|
||||||
char ktab[9];
|
char ktab[9];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -758,7 +754,7 @@ char *crypt_legacy(key, salt)
|
|||||||
/*
|
/*
|
||||||
* And convert back to 6 bit ASCII
|
* And convert back to 6 bit ASCII
|
||||||
*/
|
*/
|
||||||
return output_conversion(s[0], s[1], salt);
|
output_conversion_r(s[0], s[1], salt, outbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -901,7 +897,7 @@ char *crypt16(key, salt)
|
|||||||
/*
|
/*
|
||||||
* And convert back to 6 bit ASCII
|
* And convert back to 6 bit ASCII
|
||||||
*/
|
*/
|
||||||
strcpy (res, output_conversion(s[0], s[1], salt));
|
output_conversion_r(s[0], s[1], salt, res);
|
||||||
|
|
||||||
clearmem(ttab, sizeof ttab);
|
clearmem(ttab, sizeof ttab);
|
||||||
if (strlen (key) > 8) (void)strncpy(ttab, key+8, 8);
|
if (strlen (key) > 8) (void)strncpy(ttab, key+8, 8);
|
||||||
@@ -915,7 +911,7 @@ char *crypt16(key, salt)
|
|||||||
/*
|
/*
|
||||||
* And convert back to 6 bit ASCII
|
* And convert back to 6 bit ASCII
|
||||||
*/
|
*/
|
||||||
strcpy (q, output_conversion(t[0], t[1], salt));
|
output_conversion_r(t[0], t[1], salt, q);
|
||||||
strcpy (res+13, q+2);
|
strcpy (res+13, q+2);
|
||||||
|
|
||||||
clearmem(ktab, sizeof ktab);
|
clearmem(ktab, sizeof ktab);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <crypt.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -87,6 +88,22 @@ CryptTest::TestBadSalt()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CryptTest::TestCryptR()
|
||||||
|
{
|
||||||
|
char tmp[200];
|
||||||
|
|
||||||
|
struct crypt_data data;
|
||||||
|
data.initialized = 0;
|
||||||
|
|
||||||
|
char* buf = crypt_r(PASSWORD, NULL, &data);
|
||||||
|
CPPUNIT_ASSERT(buf != NULL);
|
||||||
|
strlcpy(tmp, buf, sizeof(tmp));
|
||||||
|
buf = crypt(PASSWORD, tmp);
|
||||||
|
CPPUNIT_ASSERT(strcmp(buf, tmp) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CryptTest::AddTests(BTestSuite& parent)
|
CryptTest::AddTests(BTestSuite& parent)
|
||||||
{
|
{
|
||||||
@@ -103,5 +120,8 @@ CryptTest::AddTests(BTestSuite& parent)
|
|||||||
suite.addTest(new CppUnit::TestCaller<CryptTest>(
|
suite.addTest(new CppUnit::TestCaller<CryptTest>(
|
||||||
"CryptTest::TestBadSalt",
|
"CryptTest::TestBadSalt",
|
||||||
&CryptTest::TestBadSalt));
|
&CryptTest::TestBadSalt));
|
||||||
|
suite.addTest(new CppUnit::TestCaller<CryptTest>(
|
||||||
|
"CryptTest::TestCryptR",
|
||||||
|
&CryptTest::TestCryptR));
|
||||||
parent.addTest("CryptTest", &suite);
|
parent.addTest("CryptTest", &suite);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public:
|
|||||||
void TestCustomSalt();
|
void TestCustomSalt();
|
||||||
void TestSaltGeneration();
|
void TestSaltGeneration();
|
||||||
void TestBadSalt();
|
void TestBadSalt();
|
||||||
|
void TestCryptR();
|
||||||
|
|
||||||
static void AddTests(BTestSuite& suite);
|
static void AddTests(BTestSuite& suite);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
SubDir HAIKU_TOP src tests system libroot posix ;
|
SubDir HAIKU_TOP src tests system libroot posix ;
|
||||||
|
|
||||||
UsePrivateHeaders libroot system ;
|
UsePrivateHeaders libroot system ;
|
||||||
|
SubDirSysHdrs $(HAIKU_TOP) headers compatibility bsd ;
|
||||||
|
SubDirSysHdrs $(HAIKU_TOP) headers compatibility gnu ;
|
||||||
|
|
||||||
# filter warnings about strftime()-formats in locale_test
|
# filter warnings about strftime()-formats in locale_test
|
||||||
TARGET_WARNING_C++FLAGS_$(TARGET_PACKAGING_ARCH)
|
TARGET_WARNING_C++FLAGS_$(TARGET_PACKAGING_ARCH)
|
||||||
@@ -87,7 +89,7 @@ UnitTestLib librootposixtest.so :
|
|||||||
|
|
||||||
CryptTest.cpp
|
CryptTest.cpp
|
||||||
|
|
||||||
: be [ TargetLibstdc++ ] [ TargetLibsupc++ ]
|
: be libgnu.so [ TargetLibstdc++ ] [ TargetLibsupc++ ]
|
||||||
;
|
;
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src tests system libroot posix math ;
|
SubInclude HAIKU_TOP src tests system libroot posix math ;
|
||||||
|
|||||||
Reference in New Issue
Block a user