28RCSID(
"$Id: ac6ae5af39783e4aa4ab2bb60f9bdb77e913f5e5 $")
30#define LOG_PREFIX mctx->mi->name
32#include <freeradius-devel/server/base.h>
33#include <freeradius-devel/server/exec_legacy.h>
34#include <freeradius-devel/server/module_rlm.h>
35#include <freeradius-devel/server/password.h>
36#include <freeradius-devel/tls/strerror.h>
37#include <freeradius-devel/util/debug.h>
38#include <freeradius-devel/radius/defs.h>
40#include <freeradius-devel/util/base16.h>
41#include <freeradius-devel/util/md4.h>
42#include <freeradius-devel/util/md5.h>
43#include <freeradius-devel/util/misc.h>
44#include <freeradius-devel/util/sha1.h>
46#include <freeradius-devel/unlang/function.h>
47#include <freeradius-devel/unlang/xlat_func.h>
54#ifdef WITH_AUTH_WINBIND
60# include <freeradius-devel/tls/openssl_user_macros.h>
61# include <openssl/rc4.h>
70#define ACB_DISABLED 0x00010000
71#define ACB_HOMDIRREQ 0x00020000
72#define ACB_PWNOTREQ 0x00040000
73#define ACB_TEMPDUP 0x00080000
74#define ACB_NORMAL 0x00100000
75#define ACB_MNS 0x00200000
76#define ACB_DOMTRUST 0x00400000
77#define ACB_WSTRUST 0x00800000
78#define ACB_SVRTRUST 0x01000000
79#define ACB_PWNOEXP 0x02000000
80#define ACB_AUTOLOCK 0x04000000
81#define ACB_FR_EXPIRED 0x00020000
88#ifdef WITH_AUTH_WINBIND
97#ifdef WITH_AUTH_WINBIND
132#ifdef WITH_AUTH_WINBIND
138#define MSCHAP_CALL_ENV(_x) \
139static const call_env_method_t mschap_ ## _x ## _method_env = { \
140 FR_CALL_ENV_METHOD_OUT(mschap_ ## _x ## _call_env_t), \
141 .env = (call_env_parser_t[]){ \
142 { FR_CALL_ENV_SUBSECTION("attributes", NULL, CALL_ENV_FLAG_REQUIRED, _x ## _call_env) }, \
143 CALL_ENV_TERMINATOR \
147#define MSCHAP_COMMON_CALL_ENV(_x) \
148{ FR_CALL_ENV_PARSE_ONLY_OFFSET("chap_challenge", FR_TYPE_OCTETS, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, mschap_ ## _x ## _call_env_t, chap_challenge), \
149 .pair.dflt = "Vendor-Specific.Microsoft.CHAP-Challenge", .pair.dflt_quote = T_BARE_WORD }, \
150{ FR_CALL_ENV_PARSE_ONLY_OFFSET("chap_response", FR_TYPE_OCTETS, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, mschap_ ## _x ## _call_env_t, chap_response), \
151 .pair.dflt = "Vendor-Specific.Microsoft.CHAP-Response", .pair.dflt_quote = T_BARE_WORD }, \
152{ FR_CALL_ENV_PARSE_ONLY_OFFSET("chap2_response", FR_TYPE_OCTETS, CALL_ENV_FLAG_ATTRIBUTE | CALL_ENV_FLAG_REQUIRED, mschap_ ## _x ## _call_env_t, chap2_response), \
153 .pair.dflt = "Vendor-Specific.Microsoft.CHAP2-Response", .pair.dflt_quote = T_BARE_WORD }
155#define MSCHAP_OPT_CALL_ENV(_opt, _x) \
156{ FR_CALL_ENV_PARSE_ONLY_OFFSET(STRINGIFY(_opt), FR_TYPE_OCTETS, CALL_ENV_FLAG_ATTRIBUTE, mschap_ ## _x ## _call_env_t, _opt) }
273 REDEBUG(
"No user identity found in current request");
288 if (*p !=
'[')
return 0;
290 for (p++; *p && !
done; p++) {
382 bool tainted =
false;
390 if (
strncasecmp(arg->vb_strvalue,
"Challenge", 9) == 0) {
393 if (!chap_challenge) {
394 REDEBUG(
"No MS-CHAP-Challenge in the request");
397 tainted = chap_challenge->vp_tainted;
403 if (chap_challenge->vp_length == 8) {
404 RDEBUG2(
"mschap1: %02x", chap_challenge->vp_octets[0]);
405 data = chap_challenge->vp_octets;
412 }
else if (chap_challenge->vp_length == 16) {
415 char const *username_str;
421 REDEBUG(
"Vendor-Specific.Microsoft.CHAP2-Response is required to calculate MS-CHAPv1 challenge");
434 if (response->vp_length < 50) {
435 REDEBUG(
"Vendor-Specific.Microsoft.CHAP-Response has the wrong format");
452 name_vp = response_name ? response_name : user_name;
457 username_str = memchr(name_vp->vp_strvalue,
'\\', name_vp->vp_length);
458 if (username_str != NULL) {
459 if (
inst->with_ntdomain_hack) {
462 RWDEBUG2(
"NT Domain delimiter found, should 'with_ntdomain_hack' be enabled?");
463 username_str = name_vp->vp_strvalue;
466 username_str = name_vp->vp_strvalue;
468 username_len = name_vp->vp_length - (username_str - name_vp->vp_strvalue);
471 ((user_name->vp_length != response_name->vp_length) ||
472 (memcmp(user_name->vp_strvalue, response_name->vp_strvalue, user_name->vp_length) != 0))) {
473 RWDEBUG2(
"%pP is not the same as %pP from EAP-MSCHAPv2", user_name, response_name);
481 RDEBUG2(
"Creating challenge with username \"%pV\"",
484 username_str, username_len);
488 REDEBUG(
"Invalid MS-CHAP challenge length");
496 }
else if (
strncasecmp(arg->vb_strvalue,
"NT-Response", 11) == 0) {
502 REDEBUG(
"No MS-CHAP-Response or MS-CHAP2-Response was found in the request");
505 tainted = response->vp_tainted;
512 REDEBUG(
"No NT-Response in MS-CHAP-Response");
516 if (response->vp_length < 50) {
517 REDEBUG(
"Vendor-Specific.Microsoft.CHAP-Response has the wrong format");
526 data = response->vp_octets + 26;
533 }
else if (
strncasecmp(arg->vb_strvalue,
"LM-Response", 11) == 0) {
537 REDEBUG(
"No MS-CHAP-Response was found in the request");
540 tainted = response->vp_tainted;
542 if (response->vp_length < 50) {
543 REDEBUG(
"Vendor-Specific.Microsoft.CHAP-Response has the wrong format");
550 if ((response->vp_octets[1] & 0x01) != 0) {
551 REDEBUG(
"No LM-Response in MS-CHAP-Response");
554 data = response->vp_octets + 2;
562 }
else if (
strncasecmp(arg->vb_strvalue,
"Domain-Name", 11) == 0) {
574 if (strncmp(user_name->vp_strvalue,
"host/", 5) == 0) {
581 p = strchr(user_name->vp_strvalue,
'.');
583 RDEBUG2(
"setting Domain-Name to same as machine name");
591 p = strchr(user_name->vp_strvalue,
'\\');
593 REDEBUG(
"No domain name was found in the User-Name");
612 }
else if (
strncasecmp(arg->vb_strvalue,
"NT-Domain", 9) == 0) {
624 if (strncmp(user_name->vp_strvalue,
"host/", 5) == 0) {
631 p = strchr(user_name->vp_strvalue,
'.');
633 RDEBUG2(
"setting NT-Domain to same as machine name");
647 p = strchr(user_name->vp_strvalue,
'\\');
649 REDEBUG(
"No NT-Domain was found in the User-Name");
668 }
else if (
strncasecmp(arg->vb_strvalue,
"User-Name", 9) == 0) {
680 if (strncmp(user_name->vp_strvalue,
"host/", 5) == 0) {
681 p = user_name->vp_strvalue + 5;
704 p = strchr(user_name->vp_strvalue,
'\\');
708 p = user_name->vp_strvalue;
719 }
else if (
strncasecmp(arg->vb_strvalue,
"NT-Hash", 7) == 0) {
720 arg = fr_value_box_list_next(
in, arg);
721 if ((!arg) || (arg->vb_length == 0))
725 REDEBUG(
"Failed generating Password.NT");
732 RDEBUG2(
"NT-Hash of \"known-good\" password: %pV", vb);
739 }
else if (
strncasecmp(arg->vb_strvalue,
"LM-Hash", 7) == 0) {
740 arg = fr_value_box_list_next(
in, arg);
741 if ((!arg) || (arg->vb_length == 0))
748 RDEBUG2(
"LM-Hash of %s = %pV", arg->vb_strvalue, vb);
752 REDEBUG(
"Unknown expansion string '%pV'", arg);
760 RWDEBUG2(
"Failed to do anything intelligent");
772#ifdef WITH_AUTH_WINBIND
778 wbcCtxFree(wbctx->
ctx);
787 wbctx->
ctx = wbcCtxCreate();
815static int write_all(
int fd,
char const *buf,
size_t len)
818 char const *end = buf + len;
823 slen = write(fd, p, end - p);
824 if (slen <= 0)
return -1;
826 fr_assert((
size_t) slen <= (
size_t) (end - p));
831 if (write(fd,
"\n", 1) <= 0)
return -1;
871 int status, len, to_child=-1, from_child=-1;
872 pid_t pid, child_pid;
877 RDEBUG2(
"Doing MS-CHAPv2 password change via ntlm_auth helper");
885 REDEBUG(
"could not exec ntlm_auth cpw command");
893 vb = fr_value_box_list_head(&cpw_ctx->
cpw_user);
894 if (!vb)
goto ntlm_auth_err;
896 if (
write_all(to_child, vb->vb_strvalue, vb->vb_length) < 0) {
897 REDEBUG(
"Failed to write username to child");
902 vb = fr_value_box_list_head(&cpw_ctx->
cpw_domain);
903 if (!vb)
goto no_domain;
905 if (
write_all(to_child, vb->vb_strvalue, vb->vb_length) < 0) {
906 REDEBUG(
"Failed to write domain to child");
911 RWDEBUG2(
"No ntlm_auth domain set, username must be full-username to work");
915 size =
snprintf(buf,
sizeof(buf),
"new-nt-password-blob: ");
918 if (
write_all(to_child, buf, size) < 0) {
919 RDEBUG2(
"failed to write new password blob to child");
923 size =
snprintf(buf,
sizeof(buf),
"old-nt-hash-blob: ");
926 if (
write_all(to_child, buf, size) < 0) {
927 REDEBUG(
"Failed to write old hash blob to child");
935 size =
snprintf(buf,
sizeof(buf),
"new-lm-password-blob: %01032i", 0);
936 if (
write_all(to_child, buf, size) < 0) {
937 REDEBUG(
"Failed to write dummy LM password to child");
940 size =
snprintf(buf,
sizeof(buf),
"old-lm-hash-blob: %032i", 0);
941 if (
write_all(to_child, buf, size) < 0) {
942 REDEBUG(
"Failed to write dummy LM hash to child");
946 REDEBUG(
"Failed to send finish to child");
958 REDEBUG(
"Failure reading from child");
965 RDEBUG2(
"ntlm_auth said: %s", buf);
967 child_pid =
waitpid(pid, &status, 0);
968 if (child_pid == 0) {
969 REDEBUG(
"Timeout waiting for child");
972 if (child_pid != pid) {
977 if (strstr(buf,
"Password-Change: Yes")) {
978 RDEBUG2(
"ntlm_auth password change succeeded");
982 pmsg = strstr(buf,
"Password-Change-Error: ");
984 emsg =
strsep(&pmsg,
"\n");
986 emsg =
"could not find error";
988 REDEBUG(
"ntlm auth password change failed: %s", emsg);
1012 RDEBUG2(
"Doing MS-CHAPv2 password change locally");
1018 }
else if (vb->vb_length == 0) {
1019 REDEBUG(
"Local MS-CHAPv2 password change - didn't give any result, assuming failure");
1023 RDEBUG2(
"MS-CHAPv2 password change succeeded: %pV", vb);
1039 REDEBUG(
"MS-CHAPv2 password change not configured");
1062 switch (auth_ctx->
method) {
1075 REDEBUG(
"FAILED: No Password.NT/LM. Cannot perform authentication");
1106 true,
true,
inst->ntlm_auth_timeout);
1115 p = strcasestr(
buffer,
"0xC0000");
1120 if (strcmp(p,
"224") == 0) {
1123 }
else if (strcmp(p,
"234") == 0) {
1126 }
else if (strcmp(p,
"072") == 0) {
1146 if (strcasestr(
buffer,
"0xC0000224") ||
1147 strcasestr(
buffer,
"Password expired") ||
1148 strcasestr(
buffer,
"Password has expired") ||
1149 strcasestr(
buffer,
"Password must be changed") ||
1150 strcasestr(
buffer,
"Must change password")) {
1154 if (strcasestr(
buffer,
"0xC0000234") ||
1155 strcasestr(
buffer,
"Account locked out")) {
1160 if (strcasestr(
buffer,
"0xC0000072") ||
1161 strcasestr(
buffer,
"Account disabled")) {
1166 if (strcasestr(
buffer,
"0xC000005E") ||
1167 strcasestr(
buffer,
"No logon servers")) {
1172 if (strcasestr(
buffer,
"could not obtain winbind separator") ||
1173 strcasestr(
buffer,
"Reading winbind reply failed")) {
1178 RDEBUG2(
"External script failed");
1179 p = strchr(
buffer,
'\n');
1192 if (memcmp(
buffer,
"NT_KEY: ", 8) != 0) {
1193 REDEBUG(
"Invalid output from ntlm_auth: expecting 'NT_KEY: ' prefix");
1200 len = strlen(
buffer + 8);
1202 REDEBUG2(
"Invalid output from ntlm_auth: NT_KEY too short, expected 32 bytes got %zu bytes",
1213 REDEBUG(
"Invalid output from ntlm_auth: NT_KEY has non-hex values");
1219#ifdef WITH_AUTH_WINBIND
1228 RERROR(
"Internal error: Unknown mschap auth method (%d)", auth_ctx->
method);
1240 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1246 { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
1247 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
1248 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
1249 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
1252 { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
1253 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
1254 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
1257 { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
1258 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
1259 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
1260 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
1261 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
1262 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
1263 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
1264 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
1265 0x6b, 0x65, 0x79, 0x2e };
1268 { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
1269 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
1270 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
1271 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
1272 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
1273 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
1274 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
1275 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
1276 0x6b, 0x65, 0x79, 0x2e };
1291 memcpy(masterkey, digest, 16);
1296 int keylen,
int issend)
1302 memset(digest, 0, 20);
1317 memcpy(sesskey, digest, keylen);
1349 memcpy (sendkey, enckey1, 16);
1350 memcpy (recvkey, enckey2, 16);
1379 RDEBUG2(
"Found MS-CHAP-Challenge, but no MS-CHAP response or Change-Password");
1383 if (!
inst->auth_type) {
1384 WARN(
"No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup MS-CHAP authentication",
1395 unsigned char ident,
int mschap_result,
int mschap_version,
fr_pair_t *smb_ctrl,
1401 char const *message = NULL;
1404 char new_challenge[33],
buffer[128];
1407 if ((mschap_result == -648) ||
1408 ((mschap_result == 0) &&
1410 REDEBUG(
"Password has expired. User should retry authentication");
1417 message =
"Password expired";
1426 }
else if ((mschap_result == -691) ||
1427 (smb_ctrl && (((smb_ctrl->vp_uint32 &
ACB_DISABLED) != 0) ||
1429 REDEBUG(
"SMB-Account-Ctrl (or ntlm_auth) "
1430 "says that the account is disabled, "
1431 "or is not a normal or workstation trust account");
1434 message =
"Account disabled";
1440 }
else if ((mschap_result == -647) ||
1441 (smb_ctrl && ((smb_ctrl->vp_uint32 &
ACB_AUTOLOCK) != 0))) {
1442 REDEBUG(
"SMB-Account-Ctrl (or ntlm_auth) "
1443 "says that the account is locked out");
1446 message =
"Account locked out";
1449 }
else if (mschap_result < 0) {
1452 retry =
inst->allow_retry;
1453 message =
"Authentication failed";
1459 switch (mschap_version) {
1461 for (p = new_challenge, i = 0; i < 2; i++) p +=
snprintf(p, 9,
"%08x",
fr_rand());
1463 error, retry, new_challenge);
1467 for (p = new_challenge, i = 0; i < 4; i++) p +=
snprintf(p, 9,
"%08x",
fr_rand());
1469 error, retry, new_challenge, message);
1510 if (request->parent) {
1514 if (password)
goto found_password;
1520 RWDEBUG2(
"No control.%s.%s or control.%s.%s found. Cannot create Password.NT",
1544 RERROR(
"Failed generating Password.NT");
1546 if (ephemeral) TALLOC_FREE(password);
1551 RDEBUG3(
"Hashed control.%pP to create %s = %pV",
1557 if (ephemeral) TALLOC_FREE(password);
1567 RDEBUG3(
"Found control.%pP", password);
1594 REDEBUG(
"Password change failed");
1605 RDEBUG2(
"Password change successful");
1618 int seq, new_nt_enc_len;
1628 RDEBUG2(
"MS-CHAPv2 password change request received");
1630 if (auth_ctx->
cpw->vp_length != 68) {
1631 REDEBUG(
"%s has the wrong format: length %zu != 68", env_data->
chap2_cpw->name, auth_ctx->
cpw->vp_length);
1635 if (auth_ctx->
cpw->vp_octets[0] != 7) {
1636 REDEBUG(
"%s has the wrong format: code %d != 7", env_data->
chap2_cpw->name, auth_ctx->
cpw->vp_octets[0]);
1653 for (seq = 1; seq < 4; seq++) {
1658 if (nt_enc->vp_length < 4) {
1663 if (nt_enc->vp_octets[0] != 6) {
1668 if ((nt_enc->vp_octets[2] == 0) && (nt_enc->vp_octets[3] == seq)) {
1679 if ((new_nt_enc_len + nt_enc->vp_length - 4) >
sizeof(cpw_ctx->
new_nt_encrypted)) {
1684 memcpy(cpw_ctx->
new_nt_encrypted + new_nt_enc_len, nt_enc->vp_octets + 4, nt_enc->vp_length - 4);
1685 new_nt_enc_len += nt_enc->vp_length - 4;
1688 if (new_nt_enc_len != 516) {
1689 REDEBUG(
"Unpacked %s length is %d - should be 516", env_data->
chap_nt_enc_pw->name, new_nt_enc_len);
1709 RDEBUG2(
"Password change payload valid");
1723 *mschap_version = 1;
1725 RDEBUG2(
"Processing MS-CHAPv1 response");
1730 if (challenge->vp_length < 8) {
1738 if (response->vp_length < 50) {
1747 if (!(response->vp_octets[1] & 0x01)) {
1748 REDEBUG2(
"Client used unsupported method LM-Password");
1757 mschap_result =
do_mschap(
inst, request, auth_ctx, challenge->vp_octets, response->vp_octets + offset, nthashhash);
1762 return mschap_error(p_result,
inst, request, *response->vp_octets, mschap_result, *mschap_version, auth_ctx->
smb_ctrl, env_data);
1772 fr_pair_t *user_name, *name_vp, *response_name, *peer_challenge_attr;
1773 uint8_t const *peer_challenge;
1774 char const *username_str;
1775 size_t username_len;
1780 *mschap_version = 2;
1782 RDEBUG2(
"Processing MS-CHAPv2 response");
1787 if (challenge->vp_length < 16) {
1795 if (response->vp_length < 50) {
1816 name_vp = response_name ? response_name : user_name;
1821 if ((username_str = strchr(name_vp->vp_strvalue,
'\\')) != NULL) {
1822 if (
inst->with_ntdomain_hack) {
1825 RWDEBUG2(
"NT Domain delimiter found, should 'with_ntdomain_hack' be enabled?");
1826 username_str = name_vp->vp_strvalue;
1829 username_str = name_vp->vp_strvalue;
1831 username_len = name_vp->vp_length - (username_str - name_vp->vp_strvalue);
1833 if (response_name && ((user_name->vp_length != response_name->vp_length) ||
1834 (
strncasecmp(user_name->vp_strvalue, response_name->vp_strvalue, user_name->vp_length) != 0))) {
1835 RWDEBUG(
"%pP is not the same as %pP from EAP-MSCHAPv2", user_name, response_name);
1848 RDEBUG2(
"No Password.NT available. Trying OpenDirectory Authentication");
1849 od_mschap_auth(p_result, request, challenge, user_name, env_data);
1853 peer_challenge = response->vp_octets + 2;
1856 if (peer_challenge_attr) {
1857 RDEBUG2(
"Overriding peer challenge");
1858 peer_challenge = peer_challenge_attr->vp_octets;
1868 RDEBUG2(
"Creating challenge with username \"%pV\"",
1872 challenge->vp_octets,
1873 username_str, username_len);
1875 mschap_result =
do_mschap(
inst, request, auth_ctx, mschap_challenge, response->vp_octets + 26, nthashhash);
1881 mschap_result, *mschap_version, auth_ctx->
smb_ctrl, env_data);
1884#ifdef WITH_AUTH_WINBIND
1885 if (
inst->wb_retry_with_normalised_username) {
1887 if (response_name) {
1888 if (strcmp(username_str, response_name->vp_strvalue)) {
1889 RDEBUG2(
"Normalising username %pV -> %pV",
1891 &response_name->data);
1892 username_str = response_name->vp_strvalue;
1901 response->vp_octets + 26,
1903 challenge->vp_octets,
1923 int mschap_version = 0;
1927 if (auth_ctx->
cpw) {
1934 REDEBUG(
"Missing Password.NT - required for change password request");
1938 REDEBUG(
"chap_nt_enc_pw option is not set - required for change password request");
1951 RDEBUG2(
"Clearing expiry bit in SMB-Acct-Ctrl to allow authentication");
1952 auth_ctx->
smb_ctrl->vp_uint32 &= ~ACB_FR_EXPIRED;
1964 p[0] = auth_ctx->
cpw->vp_octets[1];
1967 memcpy(p + 2, auth_ctx->
cpw->vp_octets + 18, 48);
1972 REDEBUG(
"control.Auth-Type = %s set for a request that does not contain %s",
1989 &mschap_version, nthashhash,
1992 challenge, response);
1996 &mschap_version, nthashhash,
1999 challenge, response);
2002 REDEBUG(
"control.Auth-Type = %s set for a request that does not contain %s or %s attributes",
2009 if (
inst->use_mppe) {
2014 switch (mschap_version) {
2016 RDEBUG2(
"Generating MS-CHAPv1 MPPE keys");
2017 memset(mppe_sendkey, 0, 32);
2036 RDEBUG2(
"Generating MS-CHAPv2 MPPE keys");
2049 vp->vp_uint32 =
inst->require_encryption ? 2 : 1;
2052 vp->vp_uint32 =
inst->require_strong ? 4 : 6;
2065 EVP_CIPHER_CTX *evp_ctx;
2067 int c, ntlen =
sizeof(nt_pass_decrypted);
2068 size_t passlen, i = 0, len = 0;
2073 MEM(evp_ctx = EVP_CIPHER_CTX_new());
2075 if (
unlikely(EVP_EncryptInit_ex(evp_ctx, EVP_rc4(), NULL, auth_ctx->
nt_password->vp_octets, NULL) != 1)) {
2076 fr_tls_strerror_printf(NULL);
2077 RPERROR(
"Failed initialising RC4 ctx");
2081 if (
unlikely(EVP_CIPHER_CTX_set_key_length(evp_ctx, auth_ctx->
nt_password->vp_length)) != 1) {
2082 fr_tls_strerror_printf(NULL);
2083 RPERROR(
"Failed setting key length");
2088 fr_tls_strerror_printf(NULL);
2089 RPERROR(
"Failed ingesting new password");
2093 EVP_CIPHER_CTX_free(evp_ctx);
2101 passlen = nt_pass_decrypted[512];
2102 passlen += nt_pass_decrypted[513] << 8;
2103 if ((nt_pass_decrypted[514] != 0) ||
2104 (nt_pass_decrypted[515] != 0)) {
2105 REDEBUG(
"Decrypted new password blob claims length > 65536, probably an invalid Password.NT");
2112 if (passlen > 512) {
2113 REDEBUG(
"Decrypted new password blob claims length %zu > 512, "
2114 "probably an invalid Password.NT", passlen);
2118 p = nt_pass_decrypted + 512 - passlen;
2135 REDEBUG(
"Old NT hash value from client does not match our value");
2148 new_pass->vp_length = 0;
2150 while (i < passlen) {
2159 }
else if (c < 0x7ff) {
2172 while (i < passlen) {
2182 }
else if (c < 0x7ff) {
2183 *x++ = 0xc0 + (c >> 6);
2184 *x++ = 0x80 + (c & 0x3f);
2187 *x++ = 0xe0 + (c >> 12);
2188 *x++ = 0x80 + ((c>>6) & 0x3f);
2189 *x++ = 0x80 + (c & 0x3f);
2217#ifdef WITH_AUTH_WINBIND
2218 rlm_mschap_thread_t *t = talloc_get_type_abort(mctx->
thread, rlm_mschap_thread_t);
2232 .method =
inst->method,
2233 .env_data = env_data,
2234#ifdef WITH_AUTH_WINBIND
2257 if (smb_account_ctrl_text) {
2272 RDEBUG2(
"SMB-Account-Ctrl says no password is required");
2292 if (auth_ctx->
cpw) {
2297 REDEBUG(
"Missing Password.NT - required for change password request");
2303 switch (auth_ctx->
method) {
2317 REDEBUG(
"Local MS-CHAPv2 password changes require OpenSSL support");
2323 REDEBUG(
"No ntlm_auth username set, passchange will definitely fail!");
2361 our_mctx.
rctx = auth_ctx;
2377 if (!
inst->auth_type) {
2378 WARN(
"Failed to find 'authenticate %s {...}' section. MS-CHAP authentication will likely not work",
2387 if (
inst->wb_username) {
2388#ifdef WITH_AUTH_WINBIND
2389 inst->method = AUTH_WBCLIENT;
2397 if (
inst->ntlm_auth) {
2401 switch (
inst->method) {
2403 DEBUG(
"Using internal authentication");
2406 DEBUG(
"Using auto password or ntlm_auth");
2409 DEBUG(
"Authenticating by calling 'ntlm_auth'");
2411#ifdef WITH_AUTH_WINBIND
2413 DEBUG(
"Authenticating directly to winbind");
2425 cf_log_err(
conf,
"ntml_auth_timeout '%pVs' is too small (minimum: 1s)",
2430 cf_log_err(
conf,
"ntlm_auth_timeout '%pVs' is too large (maximum: 10s)",
2435#define CHECK_OPTION(_option) cp = cf_pair_find(attrs, STRINGIFY(_option)); \
2437 WARN("Missing option \"" STRINGIFY(_option) "\", setting use_mppe to \"no\""); \
2438 inst->use_mppe = false; \
2439 goto done_mppe_check; \
2446 if (
inst->use_mppe) {
2476#ifdef WITH_AUTH_WINBIND
2480 rlm_mschap_thread_t *t = talloc_get_type_abort(mctx->
thread, rlm_mschap_thread_t);
2483 if (!(t->slab = mschap_slab_list_alloc(t, mctx->
el, &
inst->reuse,
winbind_ctx_alloc, NULL, NULL,
false,
false))) {
2484 ERROR(
"Connection handle pool instantiation failed");
2493 rlm_mschap_thread_t *t = talloc_get_type_abort(mctx->
thread, rlm_mschap_thread_t);
2508#ifdef WITH_AUTH_WINBIND
2509 .thread_inst_size =
sizeof(rlm_mschap_thread_t),
Unlang interpreter actions.
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
static int const char char buffer[256]
int do_auth_wbclient(rlm_mschap_t const *inst, request_t *request, uint8_t const *challenge, uint8_t const *response, uint8_t nthashhash[NT_DIGEST_LENGTH], mschap_auth_ctx_t *auth_ctx)
Check NTLM authentication direct to winbind via Samba's libwbclient library.
#define fr_base16_encode(_out, _in)
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define USES_APPLE_DEPRECATED_API
#define CALL_ENV_TERMINATOR
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
call_env_parser_t const * env
Parsing rules for call method env.
#define FR_CALL_ENV_SUBSECTION(_name, _name2, _flags, _subcs)
Specify a call_env_parser_t which defines a nested subsection.
@ CALL_ENV_FLAG_SUBSECTION
This is a subsection.
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl MUST contain an attribute reference.
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field)
Specify a call_env_parser_t which writes out runtime results to the specified field.
#define FR_CALL_ENV_PARSE_ONLY_OFFSET(_name, _cast_type, _flags, _struct, _parse_field)
Specify a call_env_parser_t which writes out the result of the parsing phase to the field specified.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
@ CONF_FLAG_XLAT
string will be dynamically expanded.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
#define cf_log_err(_cf, _fmt,...)
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
fr_dict_enum_value_t const * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define EXEC_TIMEOUT
Default wait time for exec calls (in seconds).
int radius_exec_program_legacy(char *out, size_t outlen, request_t *request, char const *cmd, fr_pair_list_t *input_pairs, bool exec_wait, bool shell_escape, fr_time_delta_t timeout)
Execute a program.
pid_t radius_start_program_legacy(int *stdin_fd, int *stdout_fd, int *stderr_fd, char const *cmd, request_t *request, bool exec_wait, fr_pair_list_t *input_pairs, bool shell_escape)
Start a process.
int radius_readfrom_program_legacy(int fd, pid_t pid, fr_time_delta_t timeout, char *answer, int left)
Read from the child process.
static xlat_action_t mschap_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Get data from MSCHAP attributes.
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RHEXDUMP1(_data, _len, _fmt,...)
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define RWDEBUG2(fmt,...)
#define REDEBUG2(fmt,...)
#define RINDENT()
Indent R* messages by one level.
waitpid(reap->pid_ev->pid, &status, 0)
void fr_md4_calc(uint8_t out[static MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Calculate the MD4 hash of the contents of a buffer.
#define MD4_DIGEST_LENGTH
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_OCTETS
Raw octets.
int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL data.
int strncasecmp(char *s1, char *s2, int n)
char * strsep(char **stringp, char const *delim)
int strcasecmp(char *s1, char *s2)
void * env_data
Per call environment data.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
void * rctx
Resume ctx that a module previously set.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
bool module_rlm_section_type_set(request_t *request, fr_dict_attr_t const *type_da, fr_dict_enum_value_t const *enumv)
Set the next section type if it's not already set.
module_t common
Common fields presented by all modules.
int mschap_nt_password_hash(uint8_t out[static NT_DIGEST_LENGTH], char const *password)
Converts Unicode password to 16-byte NT hash with MD4.
void mschap_add_reply(request_t *request, uint8_t ident, fr_dict_attr_t const *da, char const *value, size_t len)
void mschap_auth_response(char const *username, size_t username_len, uint8_t const *nt_hash_hash, uint8_t const *ntresponse, uint8_t const *peer_challenge, uint8_t const *auth_challenge, char *response)
void mschap_challenge_hash(uint8_t challenge[static MSCHAP_CHALLENGE_LENGTH], uint8_t const peer_challenge[static MSCHAP_PEER_CHALLENGE_LENGTH], uint8_t const auth_challenge[static MSCHAP_PEER_AUTHENTICATOR_CHALLENGE_LENGTH], char const *user_name, size_t user_name_len)
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_t * fr_pair_parent(fr_pair_t const *vp)
Return a pointer to the parent pair.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int fr_pair_value_bstr_alloc(fr_pair_t *vp, char **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "string" type value pair.
int fr_pair_value_mem_alloc(fr_pair_t *vp, uint8_t **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "octets" type value pair.
static ssize_t normify(normalise_t *action, uint8_t *buffer, size_t bufflen, char const *known_good, size_t len, size_t min_len)
fr_pair_t * password_find(bool *ephemeral, TALLOC_CTX *ctx, request_t *request, fr_dict_attr_t const *allowed_attrs[], size_t allowed_attrs_len, bool normify)
Find a "known good" password in the control list of a request.
static const conf_parser_t config[]
static fr_dict_attr_t const * attr_user_name
#define pair_update_request(_attr, _da)
uint32_t fr_rand(void)
Return a 32-bit random number.
#define RETURN_UNLANG_INVALID
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_REJECT
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
#define RETURN_UNLANG_NOOP
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static const uint8_t SHSpad2[40]
fr_dict_attr_t const * attr_smb_account_ctrl
#define CHECK_OPTION(_option)
static unlang_action_t mschap_process_response(unlang_result_t *p_result, int *mschap_version, uint8_t nthashhash[static NT_DIGEST_LENGTH], rlm_mschap_t const *inst, request_t *request, mschap_auth_ctx_t *auth_ctx, fr_pair_t *challenge, fr_pair_t *response)
static const call_env_parser_t xlat_call_env[]
static void mppe_chap2_get_keys128(uint8_t const *nt_hashhash, uint8_t const *nt_response, uint8_t *sendkey, uint8_t *recvkey)
static void mppe_add_reply(UNUSED rlm_mschap_t const *inst, request_t *request, fr_dict_attr_t const *da, uint8_t const *value, size_t len)
fr_dict_attr_t const * attr_nt_password
fr_dict_attr_t const * attr_ms_chap_new_cleartext_password
fr_dict_autoload_t rlm_mschap_dict[]
#define ACB_MNS
MNS logon user account.
static const call_env_parser_t auth_call_env[]
tmpl_t const * chap_response
static unlang_action_t mschap_process_v2_response(unlang_result_t *p_result, int *mschap_version, uint8_t nthashhash[static NT_DIGEST_LENGTH], rlm_mschap_t const *inst, request_t *request, mschap_auth_ctx_t *auth_ctx, fr_pair_t *challenge, fr_pair_t *response)
fr_dict_attr_t const * attr_eap_identity
tmpl_t const * chap2_response
static unlang_action_t mschap_error(unlang_result_t *p_result, rlm_mschap_t const *inst, request_t *request, unsigned char ident, int mschap_result, int mschap_version, fr_pair_t *smb_ctrl, mschap_auth_call_env_t *env_data)
#define ACB_AUTOLOCK
Account auto locked.
#define MSCHAP_CALL_ENV(_x)
fr_dict_attr_t const * attr_smb_account_ctrl_text
static unlang_action_t mod_authenticate_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
Complete mschap authentication after any tmpls have been expanded.
static const call_env_parser_t autz_call_env[]
#define ACB_TEMPDUP
Temporary duplicate account.
static int pdb_decode_acct_ctrl(char const *p)
static fr_dict_t const * dict_freeradius
static void mppe_GetMasterKey(uint8_t const *nt_hashhash, uint8_t const *nt_response, uint8_t *masterkey)
static const call_env_method_t mschap_auth_method_env
static int nt_password_find(TALLOC_CTX *ctx, fr_pair_t **out, rlm_mschap_t const *inst, request_t *request)
Find a Password.NT value, or create one from a Password.Cleartext, or Password.With-Header attribute.
#define ACB_FR_EXPIRED
Password Expired.
#define ACB_DISABLED
User account disabled.
static unlang_action_t mschap_process_cpw_request(unlang_result_t *p_result, rlm_mschap_t const *inst, request_t *request, mschap_auth_ctx_t *auth_ctx)
static fr_dict_t const * dict_radius
static const uint8_t magic1[27]
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static const uint8_t SHSpad1[40]
fr_dict_attr_t const * attr_auth_type
fr_dict_attr_t const * attr_ms_chap_user_name
tmpl_t const * chap_response
static unlang_action_t mod_authorize(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static void mppe_GetAsymmetricStartKey(uint8_t *masterkey, uint8_t *sesskey, int keylen, int issend)
static xlat_arg_parser_t const mschap_xlat_args[]
fr_dict_attr_t const * attr_ms_chap_use_ntlm_auth
#define ACB_HOMDIRREQ
Home directory required.
tmpl_t const * chap2_response
static int write_all(int fd, char const *buf, size_t len)
fr_dict_attr_t const * attr_cleartext_password
fr_dict_attr_autoload_t rlm_mschap_dict_attr[]
static unlang_action_t mod_authenticate(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static const uint8_t magic3[84]
static int do_mschap_cpw(rlm_mschap_t const *inst, request_t *request, mschap_auth_ctx_t *auth_ctx, uint8_t *new_nt_password, uint8_t *old_nt_hash)
static int do_mschap(rlm_mschap_t const *inst, request_t *request, mschap_auth_ctx_t *auth_ctx, uint8_t const *challenge, uint8_t const *response, uint8_t nthashhash[static NT_DIGEST_LENGTH])
static const uint8_t magic2[84]
#define ACB_DOMTRUST
Interdomain trust account.
#define ACB_WSTRUST
Workstation trust account.
static void mppe_chap2_gen_keys128(uint8_t const *nt_hashhash, uint8_t const *response, uint8_t *sendkey, uint8_t *recvkey)
fr_dict_attr_t const * attr_ms_chap_new_nt_password
#define ACB_NORMAL
Normal user account.
tmpl_t const * chap_challenge
#define ACB_PWNOTREQ
User password not required.
static const conf_parser_t module_config[]
fr_dict_attr_t const * attr_ms_chap_peer_challenge
static int mschap_cpw_prepare(request_t *request, mschap_auth_ctx_t *auth_ctx)
Validate data required for change password requests.
#define MSCHAP_OPT_CALL_ENV(_opt, _x)
static int mod_instantiate(module_inst_ctx_t const *mctx)
#define ACB_PWNOEXP
User password does not expire.
static fr_pair_t * mschap_identity_find(request_t *request, fr_dict_attr_t const *attr_user_name)
static const conf_parser_t passchange_config[]
tmpl_t const * chap_challenge
#define MSCHAP_COMMON_CALL_ENV(_x)
#define ACB_SVRTRUST
Server trust account.
static const conf_parser_t winbind_config[]
uint8_t new_nt_encrypted[516]
MSCHAP_AUTH_METHOD method
tmpl_t const * mppe_encryption_types
tmpl_t const * ntlm_cpw_domain
tmpl_t const * ntlm_cpw_username
tmpl_t const * chap_nt_enc_pw
tmpl_t const * mppe_send_key
rlm_mschap_t const * inst
fr_value_box_list_t cpw_user
tmpl_t const * chap_response
fr_value_box_list_t cpw_domain
tmpl_t const * chap_challenge
tmpl_t const * chap2_response
fr_value_box_list_t local_cpw_result
tmpl_t const * mppe_encryption_policy
mschap_auth_call_env_t * env_data
tmpl_t const * mppe_recv_key
tmpl_t const * chap_error
uint8_t old_nt_hash[NT_DIGEST_LENGTH]
tmpl_t const * chap2_success
mschap_cpw_ctx_t * cpw_ctx
tmpl_t const * chap_mppe_keys
static int instantiate(module_inst_ctx_t const *mctx)
static int winbind_ctx_alloc(winbind_ctx_t *wbctx, UNUSED void *uctx)
static conf_parser_t reuse_winbind_config[]
static int _mod_ctx_free(winbind_ctx_t *wbctx)
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
char const * name
Instance name e.g. user_database.
CONF_SECTION * conf
Module's instance configuration.
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
#define pair_append_control(_attr, _da)
Allocate and append a fr_pair_t to the control list.
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
void fr_sha1_init(fr_sha1_ctx *context)
void fr_sha1_final(uint8_t digest[static SHA1_DIGEST_LENGTH], fr_sha1_ctx *context)
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *in, size_t len)
#define FR_SLAB_CONFIG_CONF_PARSER
conf_parser_t entries to populate user configurable slab values
void smbhash(unsigned char *out, unsigned char const *in, unsigned char *key)
void smbdes_mschap(uint8_t const win_password[16], uint8_t const *challenge, uint8_t *response)
void smbdes_lmpwdhash(char const *password, uint8_t *lmhash)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define talloc_get_type_abort_const
#define fr_time_delta_lt(_a, _b)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_delta_ispos(_a)
#define fr_time_delta_gt(_a, _b)
int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, unlang_tmpl_args_t *args)
Push a tmpl onto the stack for evaluation.
uint8_t required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted, char const *fmt,...)
Print a formatted string using our internal printf wrapper and assign it to a value box.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
#define fr_box_strvalue_len(_val, _len)
#define fr_box_time_delta(_val)
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out
#define fr_box_octets(_val, _len)
void * env_data
Expanded call env data.
module_ctx_t const * mctx
Synthesised module calling ctx.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.