ATTRIBUTE Packet-Authentication-Vector 1088 octets
ATTRIBUTE Time-Of-Day 1089 string
ATTRIBUTE Request-Processing-Stage 1090 string
+ATTRIBUTE SHA2-Password 1092 octets
ATTRIBUTE SHA-Password 1093 octets
ATTRIBUTE SSHA-Password 1094 octets
ATTRIBUTE SHA1-Password 1093 octets
#define PW_TIME_OF_DAY 1089
#define PW_REQUEST_PROCESSING_STAGE 1090
+#define PW_SHA2_PASSWORD 1092
#define PW_SHA_PASSWORD 1093
#define PW_SSHA_PASSWORD 1094
#define PW_MD5_PASSWORD 1095
{
int i;
-#ifdef HAVE_OPENSSL_EVP_H
- /*
- * Enable all ciphers and digests.
- */
- OpenSSL_add_all_algorithms();
-#endif
-
ssl_mutexes = rad_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
if (!ssl_mutexes) {
ERROR("Error allocating memory for SSL mutexes!");
*/
void tls_global_init(void)
{
- SSL_library_init();
- SSL_load_error_strings();
+ SSL_load_error_strings(); /* readable error messages (examples show call before library_init) */
+ SSL_library_init(); /* initialize library */
+#ifdef HAVE_OPENSSL_EVP_H
+ OpenSSL_add_all_algorithms(); /* required for SHA2 in OpenSSL < 0.9.8o and 1.0.0.a */
+#endif
}
/*
* @copyright 2002 Alan DeKok <aland@ox.org>
*/
RCSID("$Id$")
+USES_APPLE_DEPRECATED_API
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/md5.h>
#include <freeradius-devel/base64.h>
#include <freeradius-devel/modules.h>
+#ifdef HAVE_OPENSSL_EVP_H
+# include <openssl/evp.h>
+#endif
+
#include <ctype.h>
#include "rlm_expr.h"
return strlen(out);
}
+/** Calculate any digest supported by OpenSSL EVP_MD
+ *
+ * Example: "%{sha256:foo}" == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
+ */
+#ifdef HAVE_OPENSSL_EVP_H
+static ssize_t evp_md_xlat(UNUSED void *instance, UNUSED REQUEST *request,
+ char const *fmt, char *out, size_t outlen, EVP_MD const *md)
+{
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned int digestlen;
+ ssize_t i, len, inlen;
+ uint8_t const *p;
+
+ EVP_MD_CTX *ctx;
+
+ /*
+ * We need room for at least one octet of output.
+ */
+ if (outlen < 3) {
+ *out = '\0';
+ return 0;
+ }
+
+ inlen = xlat_fmt_to_ref(&p, request, fmt);
+ if (inlen < 0) {
+ return -1;
+ }
+
+ ctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(ctx, md, NULL);
+ EVP_DigestUpdate(ctx, p, inlen);
+ EVP_DigestFinal_ex(ctx, digest, &digestlen);
+ EVP_MD_CTX_destroy(ctx);
+
+ /*
+ * Each digest octet takes two hex digits, plus one for
+ * the terminating NUL.
+ */
+ len = (outlen / 2) - 1;
+ if (len > digestlen) len = digestlen;
+
+ for (i = 0; i < len; i++) {
+ snprintf(out + i * 2, 3, "%02x", digest[i]);
+ }
+ return strlen(out);
+}
+
+# define EVP_MD_XLAT(_md) \
+static ssize_t _md##_xlat(UNUSED void *instance, UNUSED REQUEST *request, char const *fmt, char *out, size_t outlen)\
+{\
+ return evp_md_xlat(instance, request, fmt, out, outlen, EVP_##_md());\
+}
+
+EVP_MD_XLAT(sha256);
+EVP_MD_XLAT(sha512);
+#endif
+
/** Calculate the SHA1 hash of a string or attribute.
*
* Example: "%{sha1:foo}" == "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
xlat_register("tolower", lc_xlat, NULL, inst);
xlat_register("toupper", uc_xlat, NULL, inst);
xlat_register("md5", md5_xlat, NULL, inst);
+#ifdef HAVE_OPENSSL_EVP_H
+ xlat_register("sha256", sha256_xlat, NULL, inst);
+ xlat_register("sha512", sha512_xlat, NULL, inst);
+#endif
xlat_register("sha1", sha1_xlat, NULL, inst);
xlat_register("base64", base64_xlat, NULL, inst);
xlat_register("base64tohex", base64_to_hex_xlat, NULL, inst);
* @copyright 2001 Kostas Kalevras <kkalev@noc.ntua.gr>
*/
RCSID("$Id$")
+USES_APPLE_DEPRECATED_API
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
#include "../../include/md5.h"
#include "../../include/sha1.h"
+#ifdef HAVE_OPENSSL_EVP_H
+# include <openssl/evp.h>
+#endif
+
/*
* Define a structure for our module configuration.
*
{ "{base64_md5}", PW_MD5_PASSWORD },
{ "{smd5}", PW_SMD5_PASSWORD },
{ "{crypt}", PW_CRYPT_PASSWORD },
+#ifdef HAVE_OPENSSL_EVP_H
+ { "{sha2}", PW_SHA2_PASSWORD },
+ { "{sha256}", PW_SHA2_PASSWORD },
+ { "{sha512}", PW_SHA2_PASSWORD },
+#endif
{ "{sha}", PW_SHA_PASSWORD },
{ "{ssha}", PW_SSHA_PASSWORD },
{ "{nt}", PW_NT_PASSWORD },
found_pw = true;
break;
+#ifdef HAVE_OPENSSL_EVP_H
+ case PW_SHA2_PASSWORD:
+ if (inst->normify) {
+ normify(request, vp, 28); /* ensure it's in the right format */
+ }
found_pw = true;
break;
+#endif
case PW_SHA_PASSWORD:
case PW_SSHA_PASSWORD:
return RLM_MODULE_OK;
}
+
+#ifdef HAVE_OPENSSL_EVP_H
+static int pap_auth_sha2(rlm_pap_t *inst, REQUEST *request, VALUE_PAIR *vp)
+{
+ EVP_MD_CTX *ctx;
+ EVP_MD const *md;
+ char const *name;
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned int digestlen;
+
+ if (inst->normify) {
+ normify(request, vp, 28);
+ }
+
+ /*
+ * All the SHA-2 algorithms produce digests of different lengths,
+ * so it's trivial to determine which EVP_MD to use.
+ */
+ switch (vp->length) {
+ /* SHA-224 */
+ case 28:
+ name = "SHA-224";
+ md = EVP_sha224();
+ break;
+
+ /* SHA-256 */
+ case 32:
+ name = "SHA-256";
+ md = EVP_sha256();
+ break;
+
+ /* SHA-384 */
+ case 48:
+ name = "SHA-384";
+ md = EVP_sha384();
+ break;
+
+ /* SHA-512 */
+ case 64:
+ name = "SHA-512";
+ md = EVP_sha512();
+ break;
+
+ default:
+ REDEBUG("\"known good\" digest length (%zu) does not match output length of any SHA-2 digests",
+ vp->length);
+ return RLM_MODULE_INVALID;
+ }
+
+ ctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(ctx, md, NULL);
+ EVP_DigestUpdate(ctx, request->password->vp_octets, request->password->length);
+ EVP_DigestFinal_ex(ctx, digest, &digestlen);
+ EVP_MD_CTX_destroy(ctx);
+
+ fr_assert(digestlen == (size_t) vp->length); /* This would be an OpenSSL bug... */
+
+ if (rad_digest_cmp(digest, vp->vp_octets, vp->length) != 0) {
+ REDEBUG("%s digest does not match \"known good\" digest", name);
return RLM_MODULE_REJECT;
}
return RLM_MODULE_OK;
}
+#endif
static int pap_auth_nt(rlm_pap_t *inst, REQUEST *request, VALUE_PAIR *vp)
{
auth_func = &pap_auth_smd5;
break;
+#ifdef HAVE_OPENSSL_EVP_H
+ case PW_SHA2_PASSWORD:
+ auth_func = &pap_auth_sha2;
+ break;
+#endif
+
case PW_SHA_PASSWORD:
auth_func = &pap_auth_sha;
break;
--- /dev/null
+#
+# PRE: update if
+#
+update {
+ control:Cleartext-Password := 'hello'
+ request:Tmp-String-0 := "This is a string\n"
+ request:Tmp-Octets-0 := 0x000504030201
+}
+
+update reply {
+ Filter-Id := 'filter'
+}
+
+#
+# Put "This is a string" into a file and call "sha1sum" on it.
+# You should get this string.
+#
+if ("%{sha256:This is a string\n}" != 'b3716a1ab53042bb392034f29071e13b0c38aa19b4edd75d9a76022f91189124') {
+ update reply {
+ Filter-Id += 'fail'
+ }
+}
+
+if ("%{sha256:&Tmp-String-0}" != 'b3716a1ab53042bb392034f29071e13b0c38aa19b4edd75d9a76022f91189124') {
+ update reply {
+ Filter-Id += 'fail'
+ }
+}
+
+if ("%{sha256:&request:Tmp-String-0}" != 'b3716a1ab53042bb392034f29071e13b0c38aa19b4edd75d9a76022f91189124') {
+ update reply {
+ Filter-Id += 'fail'
+ }
+}
+
+if ("%{sha256:%{Tmp-String-0}}" != 'b3716a1ab53042bb392034f29071e13b0c38aa19b4edd75d9a76022f91189124') {
+ update reply {
+ Filter-Id += 'fail'
+ }
+}
+
+#
+# SHA256 should also be able to cope with references to octet attributes
+#
+if ("%{sha256:&request:Tmp-Octets-0}" != 'f307e202b881fded70e58017aa0c4d7b29c76ab25d02bf078301a5f6635187eb') {
+ update reply {
+ Filter-Id += 'fail'
+ }
+}
+
+#
+# SHA512 and SHA256 share common code paths, so the tests don't need to be
+# as exhaustive.
+#
+if ("%{sha512:This is a string\n}" != '56b57df5cce42d4e35c644649798ea23ec16f4f4626e78faf4d2d8f430ea349bcc28cd5532457c82f0aa66bf68988346039fe75b900a92ff94fd53993d45990f') {
+ update reply {
+ Filter-Id += 'fail'
+ }
+}
+
+if ("%{sha512:&Tmp-String-0}" != '56b57df5cce42d4e35c644649798ea23ec16f4f4626e78faf4d2d8f430ea349bcc28cd5532457c82f0aa66bf68988346039fe75b900a92ff94fd53993d45990f') {
+ update reply {
+ Filter-Id += 'fail'
+ }
+}
+
+if ("%{sha512:&request:Tmp-Octets-0}" != 'de80271eb5e03a1c24dd0cd823a22305a743ee3a54f1de5bf97adbf56984561154bfb6928b1da4ccc3f5dde9f4032ad461937b60b9ace4ad3898cf45c90596d7') {
+ update reply {
+ Filter-Id += 'fail'
+ }
+}