https://noname.com.ua/mediawiki/api.php?action=feedcontributions&user=Sirmax&feedformat=atomnoname.com.ua - Вклад [ru]2024-03-29T02:21:11ZВкладMediaWiki 1.36.1https://noname.com.ua/mediawiki/index.php?title=Ssl&diff=12993Ssl2024-03-26T10:55:35Z<p>Sirmax: /* Валидация */</p>
<hr />
<div>[[Категория:Linux]]<br />
[[Категория:OpenSSL]]<br />
[[Категория:SSL]]<br />
<br />
<br />
=OpenSSL=<br />
Заметки на полях что б каждый раз не читать мануал (ssl, openssl)<br />
<br />
==Получить сертефикат==<br />
<PRE><br />
openssl s_client -connect example.com:443 <br />
</PRE><br />
<PRE><br />
echo -n | openssl s_client -showcerts -connect api.diffbot.com:443 -servername api.diffbot.com<br />
</PRE><br />
<PRE><br />
CONNECTED(00000003)<br />
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1<br />
verify error:num=20:unable to get local issuer certificate<br />
verify return:0<br />
---<br />
Certificate chain<br />
0 s:/CN=api.diffbot.com<br />
i:/C=US/O=Let's Encrypt/CN=R3<br />
-----BEGIN CERTIFICATE-----<br />
MIIFJDCCBAygAwIBAgISBFLfLeNzhyHJCOLtTTFsrh7gMA0GCSqGSIb3DQEBCwUA<br />
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD<br />
EwJSMzAeFw0yMTA4MTIwNzI4NDRaFw0yMTExMTAwNzI4NDJaMBoxGDAWBgNVBAMT<br />
D2FwaS5kaWZmYm90LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB<br />
AKyP5dzpbQO2yXzpc0eC3t8iRbFdGVn0TG5lTQVbBDchcZ0MLrvBtdv7L+4xqc5A<br />
rg8nn+83De9wF/JVQL0qIMJnfdx3BZmuWc3HMRPBCIBTt4vHL6hxd1wHJecR0b+B<br />
tnAJ+Te/ADL3kyLbKUdXNWUkWaO+k+6Cunz7DRx+zMx2BzBfkcd5ypf0NcRPy6VC<br />
N9N6oIwGHTQGxf/dTnq1hwN1JuXzGsCCIe0ownbHF/sDzWulA+3hCzNQmI2+ukL7<br />
BCENjTt8NW5LD7e7cDrtWzbd5LrzAY5iFRSDvvchuiwHD+HR99XRgpuS/tNG6iA2<br />
zVpcSRlbRY2DqbrlpdlnKI0CAwEAAaOCAkowggJGMA4GA1UdDwEB/wQEAwIFoDAd<br />
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNV<br />
HQ4EFgQUPWDfcOnHKf8rBeP12YqMbz2RI1UwHwYDVR0jBBgwFoAUFC6zF7dYVsuu<br />
UAlA5h+vnYsUwsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8v<br />
cjMuby5sZW5jci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9y<br />
Zy8wGgYDVR0RBBMwEYIPYXBpLmRpZmZib3QuY29tMEwGA1UdIARFMEMwCAYGZ4EM<br />
AQIBMDcGCysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0<br />
c2VuY3J5cHQub3JnMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYARJRlLrDuzq/E<br />
QAfYqP4owNrmgr7YyzG1P9MzlrW2gagAAAF7OXpX4QAABAMARzBFAiAVsfnYo6fv<br />
8qaUwrhZizSiZmM7ZlBN0oIeiERCqyXeHwIhAJiH2DUFuYahKMb/OlFlr2oKrfma<br />
Pn5kzu7VR87GbpnXAHYAfT7y+I//iFVoJMLAyp5SiXkrxQ54CX8uapdomX4i8NcA<br />
AAF7OXpX/AAABAMARzBFAiEAm5P2UOS0sRX4LqlzXTe7saP82TfKtjFXrvt6Jfzw<br />
RAcCIGhLBkhXnL/nkQoc2cosVHj0YinkdT4lPyfOJthggSaUMA0GCSqGSIb3DQEB<br />
CwUAA4IBAQAr1MkfbXbGXLd0O8+w+JVGotlaJkwLUpBfL2jZ9ydPdBgTYm7sEnsa<br />
w+OttVwgQwIDIONngL6fdgRDEm/XzoPEOQ6PxKuJCUHEAtPFt2ADL1upC7gbZbut<br />
KlfQ15CkCF6EZJaVo612IsRVskVbkA8eTcNp/5LojhSW9eOhWV9lLeLnLo8ZA9n2<br />
S5Y3Lhr01rXnYRcSELjEqtVHSGje6vICMt7F287SyawYSDtPsR9zKMwmhaQn7YP6<br />
sikfWDCp+l33+csanvnNq6Jl/BqGVxR/k3zklm6XpsRP01/ix1nT5jf/h1FWlNF8<br />
wbiXI+outWMvqpD0pIbDsRHu8Xs2BS5n<br />
-----END CERTIFICATE-----<br />
1 s:/C=US/O=Let's Encrypt/CN=R3<br />
i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1<br />
-----BEGIN CERTIFICATE-----<br />
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw<br />
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh<br />
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw<br />
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg<br />
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK<br />
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP<br />
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx<br />
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm<br />
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg<br />
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG<br />
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC<br />
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB<br />
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA<br />
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw<br />
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw<br />
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB<br />
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W<br />
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl<br />
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz<br />
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm<br />
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4<br />
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2<br />
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O<br />
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids<br />
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+<br />
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv<br />
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX<br />
nLRbwHOoq7hHwg==<br />
-----END CERTIFICATE-----<br />
2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1<br />
i:/O=Digital Signature Trust Co./CN=DST Root CA X3<br />
-----BEGIN CERTIFICATE-----<br />
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/<br />
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT<br />
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow<br />
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh<br />
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB<br />
AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC<br />
ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL<br />
wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D<br />
LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK<br />
4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5<br />
bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y<br />
sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ<br />
Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4<br />
FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc<br />
SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql<br />
PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND<br />
TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw<br />
SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1<br />
c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx<br />
+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB<br />
ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu<br />
b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E<br />
U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu<br />
MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC<br />
5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW<br />
9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG<br />
WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O<br />
he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC<br />
Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5<br />
-----END CERTIFICATE-----<br />
---<br />
Server certificate<br />
subject=/CN=api.diffbot.com<br />
issuer=/C=US/O=Let's Encrypt/CN=R3<br />
---<br />
No client certificate CA names sent<br />
---<br />
SSL handshake has read 4702 bytes and written 445 bytes<br />
---<br />
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384<br />
Server public key is 2048 bit<br />
Secure Renegotiation IS supported<br />
Compression: NONE<br />
Expansion: NONE<br />
SSL-Session:<br />
Protocol : TLSv1.2<br />
Cipher : ECDHE-RSA-AES256-GCM-SHA384<br />
Session-ID: 11834EAF003B0B311A756947F00C5FF07A14AEB57FE9374DBC2D2E51C805E1F0<br />
Session-ID-ctx:<br />
Master-Key: 261A38BACE36C1386B29F64D596D097AE428CAC303A377B9D6682ED304C1929336F96616405182D5B0E512D925B459EA<br />
Key-Arg : None<br />
PSK identity: None<br />
PSK identity hint: None<br />
SRP username: None<br />
TLS session ticket lifetime hint: 300 (seconds)<br />
TLS session ticket:<br />
0000 - d5 bf f6 94 74 53 bb 5c-51 54 4e 62 fe dc af 7b ....tS.\QTNb...{<br />
0010 - f2 45 52 46 d6 c1 84 cf-34 e1 b6 3b e1 3d b5 26 .ERF....4..;.=.&<br />
0020 - f8 4a b6 d6 1e ae bc 89-a8 7f d0 dc 84 83 a9 6b .J.............k<br />
0030 - d9 f4 9b ef 9a 82 da f3-bd e8 8b 8f 25 43 eb 96 ............%C..<br />
0040 - 6b f6 b7 7f 16 ab 4e b0-11 b0 a9 0c f8 1f 13 15 k.....N.........<br />
0050 - 1d fe 68 3f 0c f8 83 f0-50 45 1c b7 2f f2 ea 31 ..h?....PE../..1<br />
0060 - 33 4a dc 35 63 46 cd a7-07 78 8f d1 40 f6 b2 ad 3J.5cF...x..@...<br />
0070 - c6 06 90 b3 76 2d 61 61-ca c4 92 46 a2 78 72 59 ....v-aa...F.xrY<br />
0080 - 53 dd eb cc f5 cb 91 a8-58 6c 64 58 4e 4d fd 5b S.......XldXNM.[<br />
0090 - ef 98 89 0d 30 8a 57 18-1b c0 f6 c2 ea 2f 63 e4 ....0.W....../c.<br />
00a0 - 6a d2 da 6c 34 c8 b6 a3-f7 79 25 d2 07 d1 08 18 j..l4....y%.....<br />
00b0 - 0d 50 0f 9f e9 eb f6 16-ee c1 f9 dc 84 83 75 57 .P............uW<br />
<br />
Start Time: 1633343371<br />
Timeout : 300 (sec)<br />
Verify return code: 20 (unable to get local issuer certificate)<br />
---<br />
DONE<br />
</PRE><br />
<br />
==Перевести в текст==<br />
<PRE><br />
openssl x509 -in FileName.pem -text<br />
</PRE><br />
<br />
==Валидация==<br />
<PRE><br />
openssl verify -verbose -CAfile rootCA.pem intermediateCA.cert.pem<br />
intermediateCA.cert.pem: OK<br />
</PRE><br />
Валидация с подробностями когда в gd_bundle-g2-g1.crt содержится цепочка сертефикатов<br />
<PRE><br />
openssl verify -verbose -no-CAfile -no-CApath -show_chain -CAfile gd_bundle-g2-g1.crt c97444e03355f98c.crt<br />
<br />
c97444e03355f98c.crt: OK<br />
Chain:<br />
depth=0: CN = container-cloud-auth.int.mirantis.com (untrusted)<br />
depth=1: C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certs.godaddy.com/repository/, CN = Go Daddy Secure Certificate Authority - G2<br />
depth=2: C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go Daddy Root Certificate Authority - G2<br />
depth=3: C = US, O = "The Go Daddy Group, Inc.", OU = Go Daddy Class 2 Certification Authority<br />
</PRE><br />
<br />
<br />
<PRE><br />
openssl verify -verbose -no-CAfile -no-CApath -no-CAstore -show_chain -partial_chain -CAfile root intermidiate<br />
intermidiate: OK<br />
Chain:<br />
depth=0: C = NL, O = Booking.com, CN = Booking.com Services Authority (untrusted)<br />
depth=1: C = NL, O = Booking.com, CN = Booking.com Authority X1<br />
</PRE><br />
<br />
==Проверка ключа==<br />
<PRE><br />
openssl x509 -noout -modulus -in cert.crt | openssl md5<br />
openssl rsa -noout -modulus -in privkey.txt | openssl md5<br />
</PRE><br />
Должно совпадать<br />
<br />
==Удаление пароля из ключа==<br />
openssl rsa -in [original.key] -out [new.key]<br />
<br />
=1=<br />
<PRE><br />
Verifying the certificate subject and issuer<br />
<br />
This section describes how to get the subject and issuer of the certificates and verify that you have a valid certificate chain.<br />
<br />
Run the following OpenSSL command to get the Subject and Issuer for each certificate in the chain from entity to root and verify that they form a proper certificate chain:<br />
<br />
openssl x509 -text -in certificate | grep -E '(Subject|Issuer):'<br />
<br />
Where certificate is the name of the certificate.<br />
Verify that the certificates in the chain adhere to the following guidelines:<br />
Subject of each certificate matches the Issuer of the preceding certificate in the chain (except for the Entity certificate).<br />
Subject and Issuer are the same for the root certificate.<br />
If the certificates in the chain adhere to these guidelines, then the certificate chain is considered to be complete and valid.<br />
<br />
Sample certificate chain validation<br />
<br />
The following example is the output of the OpenSSL commands for a sample certificate chain containing three certificates:<br />
<br />
Entity certificate<br />
<br />
<br />
openssl x509 -text -in entity.pem | grep -E '(Subject|Issuer):'<br />
<br />
Issuer: C = US, O = Google Trust Services, CN = GTS CA 1O1<br />
Subject: C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.enterprise.apigee.com<br />
<br />
Intermediate certificate<br />
<br />
<br />
openssl x509 -text -in intermediate.pem | grep -E '(Subject|Issuer):'<br />
<br />
Issuer: OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign<br />
Subject: C = US, O = Google Trust Services, CN = GTS CA 1O1<br />
<br />
Root certificate<br />
<br />
<br />
openssl x509 -text -in root.pem | grep -E '(Subject|Issuer):'<br />
<br />
Issuer: OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign<br />
Subject: OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign<br />
<br />
In the example shown above, notice the following:<br />
<br />
The Subject of the intermediate certificate matches the Issuer of the entity certificate.<br />
The Subject of the root certificate matches the Issuer of the intermediate certificate.<br />
The Subject and Issuer are the same in the root certificate.<br />
From the example above, you can confirm that the sample certificate chain is valid.<br />
Verifying the certificate subject and issuer hash<br />
<br />
This section explains how to get the hash of the subject and issuer of the certificates and verify that you have a valid certificate chain.<br />
<br />
It is always a good practice to verify the hash sequence of certificates as it can help in identifying issues such as the Common Name (CN) of the certificate having unwanted space or special characters.<br />
<br />
Run the following OpenSSL command to get the hash sequence for each certificate in the chain from entity to root and verify that they form a proper certificate chain.<br />
<br />
openssl x509 -hash -issuer_hash -noout -in certificate<br />
<br />
Where certificate is the name of the certificate.<br />
<br />
Verify that the certificates in the chain adhere to the following guidelines:<br />
Subject of each certificate matches the Issuer of the preceding certificate in the chain (except for the Entity certificate).<br />
Subject and Issuer are the same for the root certificate.<br />
If the certificates in the chain adhere to these guidelines, then the certificate chain is considered to be complete and valid.<br />
<br />
Sample certificate chain validation through hash sequence<br />
<br />
The following example is the output of the OpenSSL commands for a sample certificate chain containing three certificates:<br />
<br />
<br />
openssl x509 -in entity.pem -hash -issuer_hash -noout<br />
c54c66ba #this is subject hash<br />
99bdd351 #this is issuer hash<br />
<br />
<br />
openssl x509 -in intermediate.pem -hash -issuer_hash -noout<br />
99bdd351<br />
4a6481c9<br />
<br />
<br />
openssl x509 -in root.pem -hash -issuer_hash -noout<br />
4a6481c9<br />
4a6481c9<br />
<br />
In the example shown above, notice the following:<br />
<br />
The subject hash of the intermediate certificate matches the issuer hash of the entity certificate.<br />
The subject hash of the root certificate matches the issuer hash of the issuer certificate.<br />
The subject and issuer hash are the same in the root certificate.<br />
From the example above, you can confirm that the sample certificate chain is valid.<br />
<br />
Verifying the certificate expiry<br />
<br />
This section explains how to verify whether or not all the certificates in the chain are expired using of the following methods:<br />
<br />
Get the start and end date of the certificate.<br />
Get the expiry status.<br />
START AND END DATE<br />
EXPIRY STATUS<br />
Run the following OpenSSL command to get the start and end date for each certificate in the chain from entity to root and verify that all the certificates in the chain are in force (start date is before today) and are not expired.<br />
<br />
Sample certificate expiry validation through start and end dates<br />
<br />
<br />
openssl x509 -startdate -enddate -noout -in entity.pem<br />
notBefore=Feb 6 21:57:21 2020 GMT<br />
notAfter=Feb 4 21:57:21 2021 GMT<br />
<br />
openssl x509 -startdate -enddate -noout -in intermediate.pem<br />
notBefore=Jun 15 00:00:42 2017 GMT<br />
notAfter=Dec 15 00:00:42 2021 GMT<br />
<br />
openssl x509 -startdate -enddate -noout -in root.pem<br />
notBefore=Apr 13 10:00:00 2011 GMT<br />
notAfter=Apr 13 10:00:00 2022 GMT<br />
</PRE><br />
<br />
=Ссылки=<br />
* Consul SSL: http://russellsimpkins.blogspot.com/2015/10/consul-adding-tls-using-self-signed.html</div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=Cisco_Nat&diff=12992Cisco Nat2024-03-26T08:19:18Z<p>Sirmax: /* Ссылки */</p>
<hr />
<div>[[Категория:Cisco]]<br />
[[Категория:Nat]]<br />
[[Категория:ASR1001]]<br />
[[Категория:CGNat]]<br />
=Настрока NAT на ASR1001=<br />
Заметка появилась по-тому что нормальной инструкции я не нашел и как всегда пришлось писать самому<br />
<BR><br />
Всего настройка состоит из нескольких частей<br />
<BR><br />
Тут просто пример самой простой настройки "выпускать клиентов в мир через НАТ", без хитрых схем "тут натим, тут не натим"<br />
<br />
=Вообще про NAT в Cisco=<br />
Если коротко, то для человека вскомленного <code>iptables</code> это полный пиздец. <BR><br />
Более-менее внятный мануал как обычно [https://linkmeup.gitbook.io/sdsm/5.-acl-i-nat/01-nat Сети Для Самых Маленьких]<br />
<BR><br />
<br />
<br />
==Static==<br />
<br />
* Статический это один-к-одному, в этом случае на один внешний адрес приходится один внутренний (и наоборот) и работает оно сразу в обе стороны<br />
<PRE><br />
ip nat inside source static 172.16.6.5 198.51.100.2<br />
</PRE><br />
Самый тупой из возможных вариантов - один-в-один, причем насколько я понимаю, в двух направлениях<br />
<br />
==Dynamic==<br />
<PRE><br />
ip nat inside source list 100 pool pool_name<br />
</PRE><br />
* IP адреса Access List 100 снатить в адреса определенные в pool_name<br />
* Кому адресов не хватило - не работаеют<br />
* Что бы работало нужно включить трансляцию портов <code>overload</code><br />
* Можно НАТить "в интерфейс" : <code>ip nat inside source list 101 interface fa0/1 overload</code> (но, как обьычно, все это специфично для платформы)<br />
<br />
==Проброс внешних портов на внутренние==<br />
* Примеры<br />
** <code>ip nat inside source static tcp 172.16.6.61 3389 198.51.100.2 3389</code><br />
** <code>ip nat inside source static tcp 172.16.6.66 3389 198.51.100.2 3398</code><br />
<br />
==Особенности==<br />
Вообще для разных железок настройки совершенно разные<br />
* https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_nat/configuration/xe-16/nat-xe-16-book/iadnat-addr-consv.html<br />
<br />
=Как связаны объекты в конфиге=<br />
<br />
* "Что натить?" - <code>ACL </code>(в терминах iptables это -s / -d <IP> или список из ipset, т.е. условия), какие адреса будут подвергнуты нату - определяет обычный access-list (acl), при этом deny в этом acl означает "не делать нат" а не "дропнуть пакет"<br />
* "Во что натить?" - <code>NAT POOL</code> (в терминах iptables это <code>-j SNAT --to-source <IP></code>) определяет <code>ip nat pool</code><br />
* "Соответствия <code>NAT POOL</code> - <ACL>?" - <code>ip nat inside</code>, определяет настройку вида "этих натим в один адрес, а тех в другой<br />
* "На каких интерфейсах применять?"<br />
*<br />
<br />
=<code>ACL</code>=<br />
Простая конфигурация, предпологает что трафик между "своими" сетями никак не натится, а натится только трафик в "мир"<br />
* <code>deny</code> означает "не натить", а не "дропнуть" трафик<br />
<PRE><br />
no access-list extended ACL-allow-nat-for-100-64-1-0-and-192.168.128.0<br />
ip access-list extended ACL-allow-nat-for-100-64-1-0-and-192.168.128.0<br />
deny ip any 192.168.0.0 0.0.255.255<br />
deny ip any 172.16.0.0 0.15.255.255<br />
deny ip any 10.0.0.0 0.255.255.255<br />
deny ip any 100.64.0.0 0.0.255.255<br />
deny ip any 94.154.39.0 0.255.255.255<br />
permit ip 192.168.128.0 0.255.255.255 any<br />
permit ip 100.64.1.0 0.0.255.255 any<br />
deny ip any any<br />
exit<br />
</PRE><br />
<br />
=<code>ip nat pool</code>=<br />
Определяет адрес или адреса "в которые натить"<BR><br />
Формат такой: <BR><br />
<br />
<code>ip nat pool <Имя Пула> <Начальный Адрес> <Конечный Адрес> prefix-length <Длинна префикса от 1 до 30> </code><br />
<br />
* Имя - все понятно<br />
* Начальный/конечный адреса определяют размер пула и могут быть одинаковыми, если нужен нат в 1 адрес<br />
* <code>prefix-length</code> (или <code>netmask</code> что одно и то же, минимальная маска 255.255.255.252) - наиболее непонятная часть<br />
<br />
<br />
==<code>prefix-length</code>==<br />
<br />
<br />
<code>prefix-length</code> нужен для того что бы определить размер сети, в которую делается NAT и исключить начальный адрес и широковещательный<BR><br />
Это лучше пояснить на примере, так как звучит как бред:<br />
<br />
* есть интерфейс, который смотрит во внешний мир, на нем есть адрес 1 - 198.18.0.254/24<br />
* есть пул с начальным адресом 198.18.0.0 и конечным 198.18.0.255, и вот что бы при нате не занимать первый и последний адреса и придумана эта маска<br />
* Но для моего случая ASR1001 это похуй - "Do not configure the interface IP address as part of the IP address NAT pool." (https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_nat/configuration/xe-16/nat-xe-16-book/iadnat-addr-consv.html)<br />
<br />
==<code>ip nat pool</code> - пример==<br />
<br />
<PRE><br />
ip nat pool NAT-POOL-for-100-64-1-0-and-192-168-128-0 100.127.255.1 100.127.255.1 prefix-length 24<br />
</PRE><br />
* <code>NAT-POOL-for-100-64-1-0-and-192-168-128-0</code> - имя пула, по которому на него можно ссылаться<br />
* <code>100.127.255.1 100.127.255.1</code> - диапазон адресов, в примере один адрес<br />
* <code>prefix-length 24</code> - значение длинны префикса взято от фонаря, так как для этой платформы адрес не должен быть назначен на интерфейсе (см выше)<br />
<br />
=<code>ip nat inside</code>=<br />
==Правила ната==<br />
<PRE><br />
ip nat inside source list ACL-allow-nat-for-100-64-1-0-and-192.168.128.0 pool NAT-POOL-for-100-64-1-0-and-192.168.128.0 overload<br />
</PRE><br />
<br />
* <code>ip nat inside </code> - ключевые слова<br />
* <code>source list ACL-allow-nat-for-100-64-1-0-and-192.168.128.0 </code> ACL под который должен попадать источник<br />
* <code>pool NAT-POOL-for-100-64-1-0-and-192.168.128.0</code> какой pool использовать для этого ACL<br />
* <code>overload</code> - "перегрузка", если требуется натить более чем одного клиента в один внешний адрес<br />
<br />
=Интерфейсы=<br />
Ключевые для NAT параметры интерфейсов тут:<br />
* <code> ip nat inside </code><br />
* <code> ip nat outside</code><br />
==Внутренний==<br />
<br />
<PRE><br />
interface Port-channel1.101<br />
encapsulation dot1Q 101<br />
ip dhcp relay information trusted<br />
ip dhcp relay information policy-action keep<br />
ip unnumbered Loopback101<br />
ip helper-address 100.100.100.1<br />
ip helper-address 100.100.100.11<br />
ip helper-address 192.168.88.1<br />
ip nat inside<br />
service-policy type control ISG-CUSTOMERS-POLICY<br />
ip subscriber routed<br />
initiator unclassified ip-address ipv4<br />
</PRE><br />
<br />
==Внешний==<br />
<PRE><br />
interface Port-channel1.54<br />
description Uplink<br />
encapsulation dot1Q 54<br />
ip address 172.31.100.194 255.255.255.252<br />
ip nat outside<br />
!<br />
</PRE><br />
<br />
<br />
=PAP: Paired-Address-Pooling Support in NAT=<br />
[[File:Paired-Address-Pooling-Support-in-NAT.pdf]]<br />
<br />
<br />
Способность NAT последовательно представлять локальный IP-адрес как один глобальный IP-адрес называется объединением парных адресов.<br />
<BR><br />
Объединение парных адресов поддерживается только при трансляции адресов портов (PAT).</BR><br />
До введения функции поддержки пула парных адресов, если у вас есть конфигурация PAT и <BR><br />
вам нужен новый глобальный адрес или порт, выделяется следующий доступный адрес в пуле IP-адресов. <BR><br />
<BR><br />
Другими словами при наличии пула адресов в который делается нат может возникнуть ситуация когда один внутрений адрес выходит в мир сразу с нескольких внешних адресов.<br />
<BR><br />
<BR><br />
Не существовало механизма, гарантирующего, что локальный адрес последовательно сопоставляется с одним глобальным адресом. <BR><br />
Функция поддержки пула парных адресов обеспечивает возможность согласованного сопоставления локального адреса с глобальным адресом.<BR><br />
<BR><br />
Начиная с версии IOS XE Polaris 16.8, вы можете указать пул NAT, для которого необходимо активировать поддержку PAP.<br />
<BR><br />
<BR><br />
Эта функция полезна, когда вам нужно применить поддержку PAP к определенному потоку трафика динамического NAT.<br />
<br />
=Полезные команды=<br />
<PRE><br />
sh ip nat translations filter entry-type half all<br />
</PRE><br />
<PRE><br />
show platform hardware qfp active feature nat datapath pool<br />
</PRE><br />
<br />
=Всякие примеры тонкой настройки=<br />
* <code>no ip nat settings support mapping outside</code> <BR><br />
You can configure CGN by using the ip nat settings mode cgn command. <BR><br />
Use the ip nat settings mode default command to change to the default or traditional NAT operating mode. <BR><br />
In the CGN mode, you cannot configure any NAT outside mappings. <BR><br />
Mode changes on an active NAT device are not allowed. <BR><br />
However, when you change from the default NAT mode to CGN mode, all existing outside mappings have to be removed. <BR><br />
Use the no ip nat settings support mapping outside command to remove all outside mappings and to prevent any new outside mappings from being configured. <BR><br />
You can also remove outside mappings by using the no form of commands used to configure NAT outside. <BR><br />
In case there are specific ports configured with TCP or UDP timeout values, remove the configuration of ip nat translation port protocol port timeout <BR><br />
completely and configure the timeout values for these protocols using the same command. <BR><br />
Alternatively, reload the device. Note, if you specify a destination port to configure timeout in CGN mode, the destination port is ignored and the local port is considered for timeout.<br />
<br />
* <code>show platform hardware qfp active feature alg statistics</code>, <code>show platform hardware qfp active feature alg ... </code><br />
<br />
==1==<br />
https://forum.nag.ru/index.php?/topic/88510-cisco-asr-1000-nat-overload/page/2/<br />
<PRE><br />
ip nat settings mode cgn<br />
no ip nat settings support mapping outside<br />
ip nat translation timeout 14400<br />
ip nat translation tcp-timeout 3600<br />
ip nat translation pptp-timeout 7200<br />
ip nat translation udp-timeout 3600<br />
ip nat translation max-entries all-host 1000<br />
ip nat pool White_pool_for_NAT xx.xx.xx.xx xx.xx.xx.xx netmask xx.xx.xx.xx<br />
ip nat inside source list 100 pool White_pool_for_NAT overload<br />
</PRE><br />
<br />
==2==<br />
* https://forum.nag.ru/index.php?/topic/88510-cisco-asr-1000-nat-overload/#comment-884456<br />
что-то на 3.11.1 прошивке FTP не работает через NAT.<br />
<br />
<PRE><br />
ip nat settings mode cgn<br />
no ip nat settings support mapping outside<br />
ip nat settings pap limit 1000<br />
ip nat translation timeout 300<br />
ip nat translation tcp-timeout 180<br />
ip nat translation udp-timeout 180<br />
ip nat translation syn-timeout 180<br />
ip nat translation dns-timeout 120<br />
ip nat translation icmp-timeout 120<br />
ip nat translation max-entries 2000000<br />
ip nat translation max-entries all-host 500<br />
ip nat pool 1300 X.X.X.1 X.X.X.2 prefix-length 30<br />
ip nat pool 1301 X.X.X.5 X.X.X.6 prefix-length 30<br />
ip nat pool 1302 X.X.X.9 X.X.X.10 prefix-length 30<br />
<br />
ip nat inside source list 1300 pool 1300 overload<br />
ip nat inside source list 1301 pool 1301 overload<br />
ip nat inside source list 1302 pool 1302 overload<br />
</PRE><br />
после отключения alg nat ftp (no ip nat service ftp) пассивный ftp режим ожил, активный естественно нет.<br />
<br />
<br />
==3==<br />
* https://forum.nag.ru/index.php?/topic/88510-cisco-asr-1000-nat-overload/page/3/<br />
Всем привет!<BR><br />
Продолжу тему ната.<BR><br />
А как там с количество nat трансляций на asr-1001x, сколько максимально возможно ?<BR><br />
И еще есть вопрос по работе ната , на ericson есть команда exclude well-known которая исключает из работы ната порты до 1024, ну то есть на белых адресах которые используются для ната исключаются из работы эти порты.<br />
<BR><br />
Как с этим на цисках, никто не знает?<BR><br />
<BR><br />
Отвечу сам себе, настроил Nat<br />
<PRE><br />
ip nat settings mode cgn<br />
no ip nat settings support mapping outside<br />
ip nat settings pap limit 60 <br />
ip nat translation timeout 300<br />
ip nat translation tcp-timeout 1800<br />
ip nat translation pptp-timeout 1800<br />
ip nat translation udp-timeout 60<br />
ip nat translation finrst-timeout 10<br />
ip nat translation syn-timeout 10<br />
ip nat translation dns-timeout 10<br />
ip nat translation icmp-timeout 10<br />
ip nat translation port-timeout tcp 80 360<br />
ip nat translation port-timeout tcp 8080 360<br />
ip nat translation port-timeout tcp 1600 180<br />
ip nat translation port-timeout tcp 110 180<br />
ip nat translation port-timeout tcp 25 180<br />
ip nat translation max-entries all-host 2000<br />
ip nat pool NAT_POOL_180.10.42 180.10.42.0 180.10.42.254 netmask 255.255.255.0<br />
ip nat inside source list ACL_NAT_180.10.42 pool NAT_POOL_180.10.42 overload<br />
ip forward-protocol nd<br />
</PRE><br />
Циска умная, сама исключает порты до 1024:<br />
<PRE><br />
Router#sh ip nat translations <br />
Pro Inside global Inside local Outside local Outside global<br />
tcp 180.10.42.0:1050 10.90.0.33:61737 --- ---<br />
tcp 180.10.42.0:1027 10.90.0.33:61712 --- ---<br />
tcp 180.10.42.0:1029 10.90.0.33:62011 --- ---<br />
tcp 180.10.42.0:1045 10.90.0.33:61770 --- ---<br />
tcp 180.10.42.0:1036 10.90.0.33:62013 --- ---<br />
tcp 180.10.42.0:1049 10.90.0.33:61846 --- ---<br />
tcp 180.10.42.0:1033 10.90.0.33:61692 --- ---<br />
tcp 180.10.42.0:1046 10.90.0.33:61772 --- ---<br />
tcp 180.10.42.0:1039 10.90.0.33:61721 --- ---<br />
tcp 180.10.42.0:1048 10.90.0.33:61960 --- ---<br />
tcp 180.10.42.0:1032 10.90.0.33:61691 --- ---<br />
tcp 180.10.42.0:1025 10.90.0.33:61680 --- ---<br />
tcp 180.10.42.0:1041 10.90.0.33:62014 --- ---<br />
tcp 180.10.42.0:1031 10.90.0.33:61671 --- ---<br />
icmp 180.10.42.0:1 10.90.0.33:18 --- ---<br />
tcp 180.10.42.0:1051 10.90.0.33:61777 --- ---<br />
tcp 180.10.42.0:1035 10.90.0.33:61696 --- ---<br />
tcp 180.10.42.0:1026 10.90.0.33:61668 --- ---<br />
tcp 180.10.42.0:1042 10.90.0.33:61905 --- ---<br />
tcp 180.10.42.0:1028 10.90.0.33:62010 --- ---<br />
tcp 180.10.42.0:1037 10.90.0.33:61784 --- ---<br />
</PRE><br />
<br />
==4==<br />
<br />
<code>asr1002x-universalk9.03.13.02.S.154-3.S2-ext.SPA.bin</code><br><br />
аптайм был больше года, на днях выключали чтобы вторую 10Г плату всунуть. 1К абонентов, пул такой-же.<br />
<PRE><br />
ip nat settings mode cgn<br />
no ip nat settings support mapping outside<br />
ip nat log translations flow-export v9 udp destination x.x.x.8 8889 source Loopback0<br />
ip nat translation timeout 3600<br />
ip nat translation tcp-timeout 3600<br />
ip nat translation pptp-timeout 3600<br />
ip nat translation udp-timeout 60<br />
ip nat translation icmp-timeout 30<br />
ip nat pool nat_pool x.x.x.65 x.x.x.191 netmask 255.255.255.0<br />
ip nat inside source list nat pool nat_pool overload<br />
ip access-list extended nat<br />
deny ip any host x.x.x.4<br />
deny ip host x.x.x.4 any<br />
deny ip any host x.x.x.13<br />
deny ip host x.x.x.13 any<br />
deny ip any host x.x.x.90<br />
deny ip host x.x.x.90 any<br />
deny ip any host x.x.x.18<br />
deny ip any host x.x.x.3<br />
deny ip any host x.x.x.1<br />
deny ip any 100.64.0.0 0.63.255.255<br />
deny ip any 10.0.0.0 0.255.255.255<br />
deny ip any 172.16.0.0 0.15.255.255<br />
deny ip any 192.168.0.0 0.0.255.255<br />
deny ip any 169.254.0.0 0.0.255.255<br />
permit ip 100.64.0.0 0.63.255.255 any<br />
permit tcp 100.64.0.0 0.63.255.255 any<br />
permit udp 100.64.0.0 0.63.255.255 any<br />
permit icmp 100.64.0.0 0.63.255.255 any<br />
</PRE><br />
==5==<br />
там вроде все доступно написано<br />
<PRE><br />
#ip nat translation max-entries ?<br />
<1-2147483647> Number of entries<br />
all-host Specify maximum number of NAT entries for each host<br />
all-vrf Specify maximum number of NAT entries for each vrf<br />
host Specify per-host NAT entry limit<br />
list Specify access list based NAT entry limit<br />
redundancy Specify maximum number of NAT entries for RG<br />
vrf Specify per-VRF NAT entry limit<br />
</PRE><br />
<br />
можно сделать all-host с одним значением, типа для каждого по умолчанию, и отдельно накатывать исключения через list / host и т.д.<br />
==6==<br />
Если все начинает работать после сброса трансляций, то вероятнее всего надо выставить таймауты, чтобы таблица трансляций сама своевременно подчищалась. У меня настроено так:<br />
<PRE><br />
ip nat translation timeout 400<br />
ip nat translation tcp-timeout 240<br />
ip nat translation udp-timeout 120<br />
ip nat translation icmp-timeout 20<br />
ip nat translation port-timeout tcp 22 3600<br />
</PRE><br />
Еще полезно ограничить кол-во записей в НАТе, например:<br />
<PRE><br />
ip nat translation max-entries 50000<br />
ip nat translation max-entries all-host 900<br />
</PRE><br />
==7==<br />
=Настройка на реальном железе (ASR1001) с тестированием=<br />
<br />
<PRE><br />
ip nat pool NAT-POOL-for-100-64-0-0-and-192.168.128.0 prefix-length 24<br />
address 100.127.255.101 100.127.255.116<br />
address 100.127.255.240 100.127.255.250<br />
exit<br />
</PRE><br />
<br />
<br />
<br />
<PRE><br />
ip nat inside source list ACL-allow-nat-for-all-customers-100-64-0-0-and-192.168.128.0 pool NAT-POOL-for-100-64-0-0-and-192.168.128.0 overload<br />
</PRE><br />
<br />
<PRE><br />
no ip access-list extended ACL-allow-nat-for-all-customers-100-64-0-0-and-192.168.128.0<br />
ip access-list extended ACL-allow-nat-for-all-customers-100-64-0-0-and-192.168.128.0<br />
deny ip any 192.168.0.0 0.0.255.255<br />
deny ip any 172.16.0.0 0.15.255.255<br />
deny ip any 10.0.0.0 0.255.255.255<br />
deny ip any 100.64.0.0 0.0.255.255<br />
deny ip any 94.154.39.0 0.255.255.255<br />
permit ip 192.168.128.0 0.0.255.255 any<br />
permit ip 100.64.0.0 0.0.255.255 any<br />
deny ip any any<br />
exit<br />
</PRE><br />
<br />
<br />
=111=<br />
* <code>ip nat settings pap limit 60</code><br />
* <code>ip nat settings nonpatdrop</code><br />
* <code>ip nat translation timeout 300</code><br />
* <code>ip nat translation tcp-timeout 300</code><br />
* <code>ip nat translation pptp-timeout 300</code><br />
* <code>ip nat translation udp-timeout 30</code><br />
* <code>ip nat translation finrst-timeout 10</code><br />
* <code>ip nat translation syn-timeout 10</code><br />
* <code>ip nat translation dns-timeout 10</code><br />
* <code>ip nat translation icmp-timeout 6</code><br />
* <code>ip nat translation max-entries ...</code><br />
* <code>ip nat translation max-entries all-host 10000</code><br />
* <code>ino ip nat service all-algs</code><br />
* <code>iip nat service pptp</code><br />
<br />
<br />
<br />
* <code>ip nat log translations flow-export v9 udp destination ... </code><br />
<br />
=Ссылки=<br />
* ASR: https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_nat/configuration/xe-16/nat-xe-16-book/iadnat-addr-consv.html<br />
* ASR: https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_nat/configuration/xe-16-9/nat-xe-16-9-book/iadnat-cgn.html<br />
* https://forum.nag.ru/index.php?/topic/186433-asr1001-ne-mogu-nastroit-nat/<br />
* https://www.dnzydn.com/2019/02/27/asr1000-cgnat-port-allocation-for-subscribers/<br />
https://www.dnzydn.com/2019/02/27/asr1000-cgnat-port-allocation-for-subscribers/</div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=Cisco_Nat&diff=12991Cisco Nat2024-03-26T08:17:16Z<p>Sirmax: /* 111 */</p>
<hr />
<div>[[Категория:Cisco]]<br />
[[Категория:Nat]]<br />
[[Категория:ASR1001]]<br />
[[Категория:CGNat]]<br />
=Настрока NAT на ASR1001=<br />
Заметка появилась по-тому что нормальной инструкции я не нашел и как всегда пришлось писать самому<br />
<BR><br />
Всего настройка состоит из нескольких частей<br />
<BR><br />
Тут просто пример самой простой настройки "выпускать клиентов в мир через НАТ", без хитрых схем "тут натим, тут не натим"<br />
<br />
=Вообще про NAT в Cisco=<br />
Если коротко, то для человека вскомленного <code>iptables</code> это полный пиздец. <BR><br />
Более-менее внятный мануал как обычно [https://linkmeup.gitbook.io/sdsm/5.-acl-i-nat/01-nat Сети Для Самых Маленьких]<br />
<BR><br />
<br />
<br />
==Static==<br />
<br />
* Статический это один-к-одному, в этом случае на один внешний адрес приходится один внутренний (и наоборот) и работает оно сразу в обе стороны<br />
<PRE><br />
ip nat inside source static 172.16.6.5 198.51.100.2<br />
</PRE><br />
Самый тупой из возможных вариантов - один-в-один, причем насколько я понимаю, в двух направлениях<br />
<br />
==Dynamic==<br />
<PRE><br />
ip nat inside source list 100 pool pool_name<br />
</PRE><br />
* IP адреса Access List 100 снатить в адреса определенные в pool_name<br />
* Кому адресов не хватило - не работаеют<br />
* Что бы работало нужно включить трансляцию портов <code>overload</code><br />
* Можно НАТить "в интерфейс" : <code>ip nat inside source list 101 interface fa0/1 overload</code> (но, как обьычно, все это специфично для платформы)<br />
<br />
==Проброс внешних портов на внутренние==<br />
* Примеры<br />
** <code>ip nat inside source static tcp 172.16.6.61 3389 198.51.100.2 3389</code><br />
** <code>ip nat inside source static tcp 172.16.6.66 3389 198.51.100.2 3398</code><br />
<br />
==Особенности==<br />
Вообще для разных железок настройки совершенно разные<br />
* https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_nat/configuration/xe-16/nat-xe-16-book/iadnat-addr-consv.html<br />
<br />
=Как связаны объекты в конфиге=<br />
<br />
* "Что натить?" - <code>ACL </code>(в терминах iptables это -s / -d <IP> или список из ipset, т.е. условия), какие адреса будут подвергнуты нату - определяет обычный access-list (acl), при этом deny в этом acl означает "не делать нат" а не "дропнуть пакет"<br />
* "Во что натить?" - <code>NAT POOL</code> (в терминах iptables это <code>-j SNAT --to-source <IP></code>) определяет <code>ip nat pool</code><br />
* "Соответствия <code>NAT POOL</code> - <ACL>?" - <code>ip nat inside</code>, определяет настройку вида "этих натим в один адрес, а тех в другой<br />
* "На каких интерфейсах применять?"<br />
*<br />
<br />
=<code>ACL</code>=<br />
Простая конфигурация, предпологает что трафик между "своими" сетями никак не натится, а натится только трафик в "мир"<br />
* <code>deny</code> означает "не натить", а не "дропнуть" трафик<br />
<PRE><br />
no access-list extended ACL-allow-nat-for-100-64-1-0-and-192.168.128.0<br />
ip access-list extended ACL-allow-nat-for-100-64-1-0-and-192.168.128.0<br />
deny ip any 192.168.0.0 0.0.255.255<br />
deny ip any 172.16.0.0 0.15.255.255<br />
deny ip any 10.0.0.0 0.255.255.255<br />
deny ip any 100.64.0.0 0.0.255.255<br />
deny ip any 94.154.39.0 0.255.255.255<br />
permit ip 192.168.128.0 0.255.255.255 any<br />
permit ip 100.64.1.0 0.0.255.255 any<br />
deny ip any any<br />
exit<br />
</PRE><br />
<br />
=<code>ip nat pool</code>=<br />
Определяет адрес или адреса "в которые натить"<BR><br />
Формат такой: <BR><br />
<br />
<code>ip nat pool <Имя Пула> <Начальный Адрес> <Конечный Адрес> prefix-length <Длинна префикса от 1 до 30> </code><br />
<br />
* Имя - все понятно<br />
* Начальный/конечный адреса определяют размер пула и могут быть одинаковыми, если нужен нат в 1 адрес<br />
* <code>prefix-length</code> (или <code>netmask</code> что одно и то же, минимальная маска 255.255.255.252) - наиболее непонятная часть<br />
<br />
<br />
==<code>prefix-length</code>==<br />
<br />
<br />
<code>prefix-length</code> нужен для того что бы определить размер сети, в которую делается NAT и исключить начальный адрес и широковещательный<BR><br />
Это лучше пояснить на примере, так как звучит как бред:<br />
<br />
* есть интерфейс, который смотрит во внешний мир, на нем есть адрес 1 - 198.18.0.254/24<br />
* есть пул с начальным адресом 198.18.0.0 и конечным 198.18.0.255, и вот что бы при нате не занимать первый и последний адреса и придумана эта маска<br />
* Но для моего случая ASR1001 это похуй - "Do not configure the interface IP address as part of the IP address NAT pool." (https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_nat/configuration/xe-16/nat-xe-16-book/iadnat-addr-consv.html)<br />
<br />
==<code>ip nat pool</code> - пример==<br />
<br />
<PRE><br />
ip nat pool NAT-POOL-for-100-64-1-0-and-192-168-128-0 100.127.255.1 100.127.255.1 prefix-length 24<br />
</PRE><br />
* <code>NAT-POOL-for-100-64-1-0-and-192-168-128-0</code> - имя пула, по которому на него можно ссылаться<br />
* <code>100.127.255.1 100.127.255.1</code> - диапазон адресов, в примере один адрес<br />
* <code>prefix-length 24</code> - значение длинны префикса взято от фонаря, так как для этой платформы адрес не должен быть назначен на интерфейсе (см выше)<br />
<br />
=<code>ip nat inside</code>=<br />
==Правила ната==<br />
<PRE><br />
ip nat inside source list ACL-allow-nat-for-100-64-1-0-and-192.168.128.0 pool NAT-POOL-for-100-64-1-0-and-192.168.128.0 overload<br />
</PRE><br />
<br />
* <code>ip nat inside </code> - ключевые слова<br />
* <code>source list ACL-allow-nat-for-100-64-1-0-and-192.168.128.0 </code> ACL под который должен попадать источник<br />
* <code>pool NAT-POOL-for-100-64-1-0-and-192.168.128.0</code> какой pool использовать для этого ACL<br />
* <code>overload</code> - "перегрузка", если требуется натить более чем одного клиента в один внешний адрес<br />
<br />
=Интерфейсы=<br />
Ключевые для NAT параметры интерфейсов тут:<br />
* <code> ip nat inside </code><br />
* <code> ip nat outside</code><br />
==Внутренний==<br />
<br />
<PRE><br />
interface Port-channel1.101<br />
encapsulation dot1Q 101<br />
ip dhcp relay information trusted<br />
ip dhcp relay information policy-action keep<br />
ip unnumbered Loopback101<br />
ip helper-address 100.100.100.1<br />
ip helper-address 100.100.100.11<br />
ip helper-address 192.168.88.1<br />
ip nat inside<br />
service-policy type control ISG-CUSTOMERS-POLICY<br />
ip subscriber routed<br />
initiator unclassified ip-address ipv4<br />
</PRE><br />
<br />
==Внешний==<br />
<PRE><br />
interface Port-channel1.54<br />
description Uplink<br />
encapsulation dot1Q 54<br />
ip address 172.31.100.194 255.255.255.252<br />
ip nat outside<br />
!<br />
</PRE><br />
<br />
<br />
=PAP: Paired-Address-Pooling Support in NAT=<br />
[[File:Paired-Address-Pooling-Support-in-NAT.pdf]]<br />
<br />
<br />
Способность NAT последовательно представлять локальный IP-адрес как один глобальный IP-адрес называется объединением парных адресов.<br />
<BR><br />
Объединение парных адресов поддерживается только при трансляции адресов портов (PAT).</BR><br />
До введения функции поддержки пула парных адресов, если у вас есть конфигурация PAT и <BR><br />
вам нужен новый глобальный адрес или порт, выделяется следующий доступный адрес в пуле IP-адресов. <BR><br />
<BR><br />
Другими словами при наличии пула адресов в который делается нат может возникнуть ситуация когда один внутрений адрес выходит в мир сразу с нескольких внешних адресов.<br />
<BR><br />
<BR><br />
Не существовало механизма, гарантирующего, что локальный адрес последовательно сопоставляется с одним глобальным адресом. <BR><br />
Функция поддержки пула парных адресов обеспечивает возможность согласованного сопоставления локального адреса с глобальным адресом.<BR><br />
<BR><br />
Начиная с версии IOS XE Polaris 16.8, вы можете указать пул NAT, для которого необходимо активировать поддержку PAP.<br />
<BR><br />
<BR><br />
Эта функция полезна, когда вам нужно применить поддержку PAP к определенному потоку трафика динамического NAT.<br />
<br />
=Полезные команды=<br />
<PRE><br />
sh ip nat translations filter entry-type half all<br />
</PRE><br />
<PRE><br />
show platform hardware qfp active feature nat datapath pool<br />
</PRE><br />
<br />
=Всякие примеры тонкой настройки=<br />
* <code>no ip nat settings support mapping outside</code> <BR><br />
You can configure CGN by using the ip nat settings mode cgn command. <BR><br />
Use the ip nat settings mode default command to change to the default or traditional NAT operating mode. <BR><br />
In the CGN mode, you cannot configure any NAT outside mappings. <BR><br />
Mode changes on an active NAT device are not allowed. <BR><br />
However, when you change from the default NAT mode to CGN mode, all existing outside mappings have to be removed. <BR><br />
Use the no ip nat settings support mapping outside command to remove all outside mappings and to prevent any new outside mappings from being configured. <BR><br />
You can also remove outside mappings by using the no form of commands used to configure NAT outside. <BR><br />
In case there are specific ports configured with TCP or UDP timeout values, remove the configuration of ip nat translation port protocol port timeout <BR><br />
completely and configure the timeout values for these protocols using the same command. <BR><br />
Alternatively, reload the device. Note, if you specify a destination port to configure timeout in CGN mode, the destination port is ignored and the local port is considered for timeout.<br />
<br />
* <code>show platform hardware qfp active feature alg statistics</code>, <code>show platform hardware qfp active feature alg ... </code><br />
<br />
==1==<br />
https://forum.nag.ru/index.php?/topic/88510-cisco-asr-1000-nat-overload/page/2/<br />
<PRE><br />
ip nat settings mode cgn<br />
no ip nat settings support mapping outside<br />
ip nat translation timeout 14400<br />
ip nat translation tcp-timeout 3600<br />
ip nat translation pptp-timeout 7200<br />
ip nat translation udp-timeout 3600<br />
ip nat translation max-entries all-host 1000<br />
ip nat pool White_pool_for_NAT xx.xx.xx.xx xx.xx.xx.xx netmask xx.xx.xx.xx<br />
ip nat inside source list 100 pool White_pool_for_NAT overload<br />
</PRE><br />
<br />
==2==<br />
* https://forum.nag.ru/index.php?/topic/88510-cisco-asr-1000-nat-overload/#comment-884456<br />
что-то на 3.11.1 прошивке FTP не работает через NAT.<br />
<br />
<PRE><br />
ip nat settings mode cgn<br />
no ip nat settings support mapping outside<br />
ip nat settings pap limit 1000<br />
ip nat translation timeout 300<br />
ip nat translation tcp-timeout 180<br />
ip nat translation udp-timeout 180<br />
ip nat translation syn-timeout 180<br />
ip nat translation dns-timeout 120<br />
ip nat translation icmp-timeout 120<br />
ip nat translation max-entries 2000000<br />
ip nat translation max-entries all-host 500<br />
ip nat pool 1300 X.X.X.1 X.X.X.2 prefix-length 30<br />
ip nat pool 1301 X.X.X.5 X.X.X.6 prefix-length 30<br />
ip nat pool 1302 X.X.X.9 X.X.X.10 prefix-length 30<br />
<br />
ip nat inside source list 1300 pool 1300 overload<br />
ip nat inside source list 1301 pool 1301 overload<br />
ip nat inside source list 1302 pool 1302 overload<br />
</PRE><br />
после отключения alg nat ftp (no ip nat service ftp) пассивный ftp режим ожил, активный естественно нет.<br />
<br />
<br />
==3==<br />
* https://forum.nag.ru/index.php?/topic/88510-cisco-asr-1000-nat-overload/page/3/<br />
Всем привет!<BR><br />
Продолжу тему ната.<BR><br />
А как там с количество nat трансляций на asr-1001x, сколько максимально возможно ?<BR><br />
И еще есть вопрос по работе ната , на ericson есть команда exclude well-known которая исключает из работы ната порты до 1024, ну то есть на белых адресах которые используются для ната исключаются из работы эти порты.<br />
<BR><br />
Как с этим на цисках, никто не знает?<BR><br />
<BR><br />
Отвечу сам себе, настроил Nat<br />
<PRE><br />
ip nat settings mode cgn<br />
no ip nat settings support mapping outside<br />
ip nat settings pap limit 60 <br />
ip nat translation timeout 300<br />
ip nat translation tcp-timeout 1800<br />
ip nat translation pptp-timeout 1800<br />
ip nat translation udp-timeout 60<br />
ip nat translation finrst-timeout 10<br />
ip nat translation syn-timeout 10<br />
ip nat translation dns-timeout 10<br />
ip nat translation icmp-timeout 10<br />
ip nat translation port-timeout tcp 80 360<br />
ip nat translation port-timeout tcp 8080 360<br />
ip nat translation port-timeout tcp 1600 180<br />
ip nat translation port-timeout tcp 110 180<br />
ip nat translation port-timeout tcp 25 180<br />
ip nat translation max-entries all-host 2000<br />
ip nat pool NAT_POOL_180.10.42 180.10.42.0 180.10.42.254 netmask 255.255.255.0<br />
ip nat inside source list ACL_NAT_180.10.42 pool NAT_POOL_180.10.42 overload<br />
ip forward-protocol nd<br />
</PRE><br />
Циска умная, сама исключает порты до 1024:<br />
<PRE><br />
Router#sh ip nat translations <br />
Pro Inside global Inside local Outside local Outside global<br />
tcp 180.10.42.0:1050 10.90.0.33:61737 --- ---<br />
tcp 180.10.42.0:1027 10.90.0.33:61712 --- ---<br />
tcp 180.10.42.0:1029 10.90.0.33:62011 --- ---<br />
tcp 180.10.42.0:1045 10.90.0.33:61770 --- ---<br />
tcp 180.10.42.0:1036 10.90.0.33:62013 --- ---<br />
tcp 180.10.42.0:1049 10.90.0.33:61846 --- ---<br />
tcp 180.10.42.0:1033 10.90.0.33:61692 --- ---<br />
tcp 180.10.42.0:1046 10.90.0.33:61772 --- ---<br />
tcp 180.10.42.0:1039 10.90.0.33:61721 --- ---<br />
tcp 180.10.42.0:1048 10.90.0.33:61960 --- ---<br />
tcp 180.10.42.0:1032 10.90.0.33:61691 --- ---<br />
tcp 180.10.42.0:1025 10.90.0.33:61680 --- ---<br />
tcp 180.10.42.0:1041 10.90.0.33:62014 --- ---<br />
tcp 180.10.42.0:1031 10.90.0.33:61671 --- ---<br />
icmp 180.10.42.0:1 10.90.0.33:18 --- ---<br />
tcp 180.10.42.0:1051 10.90.0.33:61777 --- ---<br />
tcp 180.10.42.0:1035 10.90.0.33:61696 --- ---<br />
tcp 180.10.42.0:1026 10.90.0.33:61668 --- ---<br />
tcp 180.10.42.0:1042 10.90.0.33:61905 --- ---<br />
tcp 180.10.42.0:1028 10.90.0.33:62010 --- ---<br />
tcp 180.10.42.0:1037 10.90.0.33:61784 --- ---<br />
</PRE><br />
<br />
==4==<br />
<br />
<code>asr1002x-universalk9.03.13.02.S.154-3.S2-ext.SPA.bin</code><br><br />
аптайм был больше года, на днях выключали чтобы вторую 10Г плату всунуть. 1К абонентов, пул такой-же.<br />
<PRE><br />
ip nat settings mode cgn<br />
no ip nat settings support mapping outside<br />
ip nat log translations flow-export v9 udp destination x.x.x.8 8889 source Loopback0<br />
ip nat translation timeout 3600<br />
ip nat translation tcp-timeout 3600<br />
ip nat translation pptp-timeout 3600<br />
ip nat translation udp-timeout 60<br />
ip nat translation icmp-timeout 30<br />
ip nat pool nat_pool x.x.x.65 x.x.x.191 netmask 255.255.255.0<br />
ip nat inside source list nat pool nat_pool overload<br />
ip access-list extended nat<br />
deny ip any host x.x.x.4<br />
deny ip host x.x.x.4 any<br />
deny ip any host x.x.x.13<br />
deny ip host x.x.x.13 any<br />
deny ip any host x.x.x.90<br />
deny ip host x.x.x.90 any<br />
deny ip any host x.x.x.18<br />
deny ip any host x.x.x.3<br />
deny ip any host x.x.x.1<br />
deny ip any 100.64.0.0 0.63.255.255<br />
deny ip any 10.0.0.0 0.255.255.255<br />
deny ip any 172.16.0.0 0.15.255.255<br />
deny ip any 192.168.0.0 0.0.255.255<br />
deny ip any 169.254.0.0 0.0.255.255<br />
permit ip 100.64.0.0 0.63.255.255 any<br />
permit tcp 100.64.0.0 0.63.255.255 any<br />
permit udp 100.64.0.0 0.63.255.255 any<br />
permit icmp 100.64.0.0 0.63.255.255 any<br />
</PRE><br />
==5==<br />
там вроде все доступно написано<br />
<PRE><br />
#ip nat translation max-entries ?<br />
<1-2147483647> Number of entries<br />
all-host Specify maximum number of NAT entries for each host<br />
all-vrf Specify maximum number of NAT entries for each vrf<br />
host Specify per-host NAT entry limit<br />
list Specify access list based NAT entry limit<br />
redundancy Specify maximum number of NAT entries for RG<br />
vrf Specify per-VRF NAT entry limit<br />
</PRE><br />
<br />
можно сделать all-host с одним значением, типа для каждого по умолчанию, и отдельно накатывать исключения через list / host и т.д.<br />
==6==<br />
Если все начинает работать после сброса трансляций, то вероятнее всего надо выставить таймауты, чтобы таблица трансляций сама своевременно подчищалась. У меня настроено так:<br />
<PRE><br />
ip nat translation timeout 400<br />
ip nat translation tcp-timeout 240<br />
ip nat translation udp-timeout 120<br />
ip nat translation icmp-timeout 20<br />
ip nat translation port-timeout tcp 22 3600<br />
</PRE><br />
Еще полезно ограничить кол-во записей в НАТе, например:<br />
<PRE><br />
ip nat translation max-entries 50000<br />
ip nat translation max-entries all-host 900<br />
</PRE><br />
==7==<br />
=Настройка на реальном железе (ASR1001) с тестированием=<br />
<br />
<PRE><br />
ip nat pool NAT-POOL-for-100-64-0-0-and-192.168.128.0 prefix-length 24<br />
address 100.127.255.101 100.127.255.116<br />
address 100.127.255.240 100.127.255.250<br />
exit<br />
</PRE><br />
<br />
<br />
<br />
<PRE><br />
ip nat inside source list ACL-allow-nat-for-all-customers-100-64-0-0-and-192.168.128.0 pool NAT-POOL-for-100-64-0-0-and-192.168.128.0 overload<br />
</PRE><br />
<br />
<PRE><br />
no ip access-list extended ACL-allow-nat-for-all-customers-100-64-0-0-and-192.168.128.0<br />
ip access-list extended ACL-allow-nat-for-all-customers-100-64-0-0-and-192.168.128.0<br />
deny ip any 192.168.0.0 0.0.255.255<br />
deny ip any 172.16.0.0 0.15.255.255<br />
deny ip any 10.0.0.0 0.255.255.255<br />
deny ip any 100.64.0.0 0.0.255.255<br />
deny ip any 94.154.39.0 0.255.255.255<br />
permit ip 192.168.128.0 0.0.255.255 any<br />
permit ip 100.64.0.0 0.0.255.255 any<br />
deny ip any any<br />
exit<br />
</PRE><br />
<br />
<br />
=111=<br />
* <code>ip nat settings pap limit 60</code><br />
* <code>ip nat settings nonpatdrop</code><br />
* <code>ip nat translation timeout 300</code><br />
* <code>ip nat translation tcp-timeout 300</code><br />
* <code>ip nat translation pptp-timeout 300</code><br />
* <code>ip nat translation udp-timeout 30</code><br />
* <code>ip nat translation finrst-timeout 10</code><br />
* <code>ip nat translation syn-timeout 10</code><br />
* <code>ip nat translation dns-timeout 10</code><br />
* <code>ip nat translation icmp-timeout 6</code><br />
* <code>ip nat translation max-entries ...</code><br />
* <code>ip nat translation max-entries all-host 10000</code><br />
* <code>ino ip nat service all-algs</code><br />
* <code>iip nat service pptp</code><br />
<br />
<br />
<br />
* <code>ip nat log translations flow-export v9 udp destination ... </code><br />
<br />
=Ссылки=<br />
* ASR: https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/ipaddr_nat/configuration/xe-16/nat-xe-16-book/iadnat-addr-consv.html<br />
* https://forum.nag.ru/index.php?/topic/186433-asr1001-ne-mogu-nastroit-nat/</div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12990FreeRadius Notes2024-03-20T18:16:26Z<p>Sirmax: /* По шагам */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов <br />
* authorize<br />
* authenticate<br />
* post-auth<br />
и этот список атрибутов <code>control</code> используется для передачи атрибутов между разными разделами.<br />
<br />
==<code>authorize</code>==<br />
Секция <code>authorize</code> предназначена для сборки информации о пользователе.<br />
Например в этой секции:<br />
* Может происходить запрос к базе данных для проверки существования пользователя и получения его пароля.<br />
* В этой секции определяется значение атрибута <code>Auth-Type</code> на основании которого будет производиться дальнейшая обработка запроса в секции <code>authentication</code><br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> это секция где происходит вызов модуля <code>authentication</code>.<br />
<BR><br />
Какой именно модуль будет использоваться определяется значением атрибута <code>Auth-Type</code><br />
<BR><br />
Например<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
При этом значение <code>Auth-Type</code>=<code>ISG</code> выставляет модуль в секции <code> authorize</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
python3_isg<br />
}<br />
</PRE><br />
Пример кода из <code>rlm_python</code><br />
<PRE><br />
...<br />
config = ( ('Auth-Type', 'ISG') )<br />
...<br />
</PRE><br />
<br />
==<code>Post-Auth</code>==<br />
<code>Post-Auth</code> используется в основном для логгирования и примерения других политик (а может и вообще не использоваться), список модулей запускаемых в этой секции определяются результатами работы модулей в секции <code>authenticate</code><br />
<br />
==По шагам==<br />
* Модули в секции <code>authorize</code> проверяют запрос <br />
* Если запрос удовлетворяет условиям (модуль "думает" что знает как работать с запросом на стадии <code> authenticate</code>) и атрибут <code>Auth-Type</code> еще не установлен то модуль выставляет атрибут <code>Auth-Type </code> (значение атрибута зависит от модуля)<br />
* В случае модуля <code>rlm_pap</code> модуль выставляет атрибут <code>Auth-Type</code> в значение <code>PAP</code> если находит в запросе атрибут <code>User-Password</code><br />
* Если ни один из модулей не выставил атрибут <code>Auth-Type</code> то запрос будет отброшен (Rejected)<br />
<br />
<BR><br />
Теперь можно вернуться к вопросу что не так с конструкцией <code> User-Password == "test" </code><br />
* Модуль <code>rlm_pap</code> в секции <code> authorize</code> выставит code>Auth-Type</code> в значение <code>PAP</code> так как в запросе присутствует <code> User-Password</code><br />
* Модуль <code>rlm_pap</code> в секции <code> authenticate</code> попробует сравнить найти в списке атрибутов <br />
<code>config</code> один из "известных хороших" атрибутов с паролем, например <code>Cleartext-Password</code><br />
или любой другой, и не найдя их вернет статус <code>Reject</code><br />
<br />
<BR><br />
Если такое поведение не желательно, то его можно обойти с помощью "волшебного" значения <code>Auth-Type</code>, <code>Accept</code>, <br />
которое позволяет пропустить секцию <code>authenticate</code> <br />
<br />
Если нужно реализовать такое поведение и не вызывать модуль <code>rlm_pap</code>:<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12989FreeRadius Notes2024-03-20T18:16:03Z<p>Sirmax: /* По шагам */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов <br />
* authorize<br />
* authenticate<br />
* post-auth<br />
и этот список атрибутов <code>control</code> используется для передачи атрибутов между разными разделами.<br />
<br />
==<code>authorize</code>==<br />
Секция <code>authorize</code> предназначена для сборки информации о пользователе.<br />
Например в этой секции:<br />
* Может происходить запрос к базе данных для проверки существования пользователя и получения его пароля.<br />
* В этой секции определяется значение атрибута <code>Auth-Type</code> на основании которого будет производиться дальнейшая обработка запроса в секции <code>authentication</code><br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> это секция где происходит вызов модуля <code>authentication</code>.<br />
<BR><br />
Какой именно модуль будет использоваться определяется значением атрибута <code>Auth-Type</code><br />
<BR><br />
Например<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
При этом значение <code>Auth-Type</code>=<code>ISG</code> выставляет модуль в секции <code> authorize</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
python3_isg<br />
}<br />
</PRE><br />
Пример кода из <code>rlm_python</code><br />
<PRE><br />
...<br />
config = ( ('Auth-Type', 'ISG') )<br />
...<br />
</PRE><br />
<br />
==<code>Post-Auth</code>==<br />
<code>Post-Auth</code> используется в основном для логгирования и примерения других политик (а может и вообще не использоваться), список модулей запускаемых в этой секции определяются результатами работы модулей в секции <code>authenticate</code><br />
<br />
==По шагам==<br />
* Модули в секции <code>authorize</code> проверяют запрос <br />
* Если запрос удовлетворяет условиям (модуль "думает" что знает как работать с запросом на стадии <code> authenticate</code>) и атрибут <code>Auth-Type</code> еще не установлен то модуль выставляет атрибут <code>Auth-Type </code> (значение атрибута зависит от модуля)<br />
* В случае модуля <code>rlm_pap</code> модуль выставляет атрибут <code>Auth-Type</code> в значение <code>PAP</code> если находит в запросе атрибут <code>User-Password</code><br />
* Если ни один из модулей не выставил атрибут <code>Auth-Type</code> то запрос будет отброшен (Rejected)<br />
<br />
<BR><br />
Теперь можно вернуться к вопросу что не так с конструкцией <code> User-Password == "test" </code><br />
* Модуль <code>rlm_pap</code> в секции <code> authorize</code> выставит code>Auth-Type</code> в значение <code>PAP</code> так как в запросе присутствует <code> User-Password</code><br />
* Модуль <code>rlm_pap</code> в секции <code> authenticate</code> попробует сравнить найти в списке атрибутов <br />
<code>config</code> один из "известных хороших" атрибутов с паролем, например <code>Cleartext-Password</code><br />
или любой другой, и не найдя их вернет статус <code>Reject</code><br />
<br />
<BR><br />
Если такое поведение не желательно, то его можно обойти с помощью "волшебного" значения <code>Auth-Type</code>, <code>Accept</code>, <br />
которое позволяет пропустить секцию <code>authenticate<code> <br />
<br />
Если нужно реализовать такое поведение и не вызывать модуль <code>rlm_pap</code>:<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12988FreeRadius Notes2024-03-20T18:15:27Z<p>Sirmax: /* По шагам */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов <br />
* authorize<br />
* authenticate<br />
* post-auth<br />
и этот список атрибутов <code>control</code> используется для передачи атрибутов между разными разделами.<br />
<br />
==<code>authorize</code>==<br />
Секция <code>authorize</code> предназначена для сборки информации о пользователе.<br />
Например в этой секции:<br />
* Может происходить запрос к базе данных для проверки существования пользователя и получения его пароля.<br />
* В этой секции определяется значение атрибута <code>Auth-Type</code> на основании которого будет производиться дальнейшая обработка запроса в секции <code>authentication</code><br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> это секция где происходит вызов модуля <code>authentication</code>.<br />
<BR><br />
Какой именно модуль будет использоваться определяется значением атрибута <code>Auth-Type</code><br />
<BR><br />
Например<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
При этом значение <code>Auth-Type</code>=<code>ISG</code> выставляет модуль в секции <code> authorize</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
python3_isg<br />
}<br />
</PRE><br />
Пример кода из <code>rlm_python</code><br />
<PRE><br />
...<br />
config = ( ('Auth-Type', 'ISG') )<br />
...<br />
</PRE><br />
<br />
==<code>Post-Auth</code>==<br />
<code>Post-Auth</code> используется в основном для логгирования и примерения других политик (а может и вообще не использоваться), список модулей запускаемых в этой секции определяются результатами работы модулей в секции <code>authenticate</code><br />
<br />
==По шагам==<br />
* Модули в секции <code>authorize</code> проверяют запрос <br />
* Если запрос удовлетворяет условиям (модуль "думает" что знает как работать с запросом на стадии <code> authenticate</code>) и атрибут <code>Auth-Type</code> еще не установлен то модуль выставляет атрибут <code>Auth-Type </code> (значение атрибута зависит от модуля)<br />
* В случае модуля <code>rlm_pap</code> модуль выставляет атрибут <code>Auth-Type</code> в значение <code>PAP</code> если находит в запросе атрибут <code>User-Password</code><br />
* Если ни один из модулей не выставил атрибут <code>Auth-Type</code> то запрос будет отброшен (Rejected)<br />
<br />
<BR><br />
Теперь можно вернуться к вопросу что не так с конструкцией <code> User-Password == "test" </code><br />
* Модуль <code>rlm_pap</code> в секции <code> authorize</code> выставит code>Auth-Type</code> в значение <code>PAP</code> так как в запросе присутствует <code> User-Password</code><br />
* Модуль <code>rlm_pap</code> в секции <code> authenticate </code> попробует сравнить найти в списке атрибутов <code>config</code> один из "известных хороших" атрибутов с паролем, например <code>Cleartext-Password</code><br />
или любой другой, и не найдя их вернет статус <code>Reject</code><br />
<br />
<BR><br />
Если такое поведение не желательно, то его можно обойти с помощью "волшебного" значения <code>Auth-Type</code>, <code>Accept</code>, <br />
которое позволяет пропустить секцию <code>authenticate<code> <br />
<br />
Если нужно реализовать такое поведение и не вызывать модуль <code>rlm_pap</code>:<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12987FreeRadius Notes2024-03-20T18:06:27Z<p>Sirmax: /* authenticate */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов <br />
* authorize<br />
* authenticate<br />
* post-auth<br />
и этот список атрибутов <code>control</code> используется для передачи атрибутов между разными разделами.<br />
<br />
==<code>authorize</code>==<br />
Секция <code>authorize</code> предназначена для сборки информации о пользователе.<br />
Например в этой секции:<br />
* Может происходить запрос к базе данных для проверки существования пользователя и получения его пароля.<br />
* В этой секции определяется значение атрибута <code>Auth-Type</code> на основании которого будет производиться дальнейшая обработка запроса в секции <code>authentication</code><br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> это секция где происходит вызов модуля <code>authentication</code>.<br />
<BR><br />
Какой именно модуль будет использоваться определяется значением атрибута <code>Auth-Type</code><br />
<BR><br />
Например<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
При этом значение <code>Auth-Type</code>=<code>ISG</code> выставляет модуль в секции <code> authorize</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
python3_isg<br />
}<br />
</PRE><br />
Пример кода из <code>rlm_python</code><br />
<PRE><br />
...<br />
config = ( ('Auth-Type', 'ISG') )<br />
...<br />
</PRE><br />
<br />
==<code>Post-Auth</code>==<br />
<code>Post-Auth</code> используется в основном для логгирования и примерения других политик (а может и вообще не использоваться), список модулей запускаемых в этой секции определяются результатами работы модулей в секции <code>authenticate</code><br />
<br />
==По шагам==<br />
* Модули в секции <code>authorize</code> проверяют запрос <br />
* Если запрос удовлетворяет условиям (модуль "думает" что знает как работать с запросом на стадии <code> authenticate</code>) и атрибут <code>Auth-Type</code> еще не установлен то модуль выставляет атрибут <code>Auth-Type </code> (значение атрибута зависит от модуля)<br />
* В случае модуля <code>rlm_pap</code> модуль выставляет атрибут <code>Auth-Type</code> в значение <code>PAP</code> если находит в запросе атрибут <code>User-Password</code><br />
* Если ни один из модулей не выставил атрибут <code>Auth-Type</code> то запрос будет отброшен (Rejected)<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12986FreeRadius Notes2024-03-20T18:02:14Z<p>Sirmax: /* По шагам */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов <br />
* authorize<br />
* authenticate<br />
* post-auth<br />
и этот список атрибутов <code>control</code> используется для передачи атрибутов между разными разделами.<br />
<br />
==<code>authorize</code>==<br />
Секция <code>authorize</code> предназначена для сборки информации о пользователе.<br />
Например в этой секции:<br />
* Может происходить запрос к базе данных для проверки существования пользователя и получения его пароля.<br />
* В этой секции определяется значение атрибута <code>Auth-Type</code> на основании которого будет производиться дальнейшая обработка запроса в секции <code>authentication</code><br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> это секция где происходит вызов модуля <code>authentication</code>.<br />
<BR><br />
Какой именно модуль будет использоваться определяется значением атрибута <code>Auth-Type</code><br />
<br />
<br />
==<code>Post-Auth</code>==<br />
<code>Post-Auth</code> используется в основном для логгирования и примерения других политик (а может и вообще не использоваться), список модулей запускаемых в этой секции определяются результатами работы модулей в секции <code>authenticate</code><br />
<br />
==По шагам==<br />
* Модули в секции <code>authorize</code> проверяют запрос <br />
* Если запрос удовлетворяет условиям (модуль "думает" что знает как работать с запросом на стадии <code> authenticate</code>) и атрибут <code>Auth-Type</code> еще не установлен то модуль выставляет атрибут <code>Auth-Type </code> (значение атрибута зависит от модуля)<br />
* В случае модуля <code>rlm_pap</code> модуль выставляет атрибут <code>Auth-Type</code> в значение <code>PAP</code> если находит в запросе атрибут <code>User-Password</code><br />
* Если ни один из модулей не выставил атрибут <code>Auth-Type</code> то запрос будет отброшен (Rejected)<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12985FreeRadius Notes2024-03-20T16:38:24Z<p>Sirmax: /* authenticate */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов <br />
* authorize<br />
* authenticate<br />
* post-auth<br />
и этот список атрибутов <code>control</code> используется для передачи атрибутов между разными разделами.<br />
<br />
==<code>authorize</code>==<br />
Секция <code>authorize</code> предназначена для сборки информации о пользователе.<br />
Например в этой секции:<br />
* Может происходить запрос к базе данных для проверки существования пользователя и получения его пароля.<br />
* В этой секции определяется значение атрибута <code>Auth-Type</code> на основании которого будет производиться дальнейшая обработка запроса в секции <code>authentication</code><br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> это секция где происходит вызов модуля <code>authentication</code>.<br />
<BR><br />
Какой именно модуль будет использоваться определяется значением атрибута <code>Auth-Type</code><br />
<br />
<br />
==<code>Post-Auth</code>==<br />
<code>Post-Auth</code> используется в основном для логгирования и примерения других политик (а может и вообще не использоваться), список модулей запускаемых в этой секции определяются результатами работы модулей в секции <code>authenticate</code><br />
<br />
==По шагам==<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12984FreeRadius Notes2024-03-20T16:34:43Z<p>Sirmax: /* authorize */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов <br />
* authorize<br />
* authenticate<br />
* post-auth<br />
и этот список атрибутов <code>control</code> используется для передачи атрибутов между разными разделами.<br />
<br />
==<code>authorize</code>==<br />
Секция <code>authorize</code> предназначена для сборки информации о пользователе.<br />
Например в этой секции:<br />
* Может происходить запрос к базе данных для проверки существования пользователя и получения его пароля.<br />
* В этой секции определяется значение атрибута <code>Auth-Type</code> на основании которого будет производиться дальнейшая обработка запроса в секции <code>authentication</code><br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12983FreeRadius Notes2024-03-20T16:31:37Z<p>Sirmax: /* Auth-Type */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов <br />
* authorize<br />
* authenticate<br />
* post-auth<br />
и этот список атрибутов <code>control</code> используется для передачи атрибутов между разными разделами.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12982FreeRadius Notes2024-03-20T16:30:27Z<p>Sirmax: /* Auth-Type */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> это атрибут который может помещаться только в список атрибутов <code>control</code>, <BR><br />
и никогда не помещаться ни в какие другие списки.<br />
<BR><br />
<br />
На сервере есть три основных раздела для обработки запросов 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12981FreeRadius Notes2024-03-20T16:28:38Z<p>Sirmax: /* User-Password */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
К сожалению, это не так.<br />
<BR><br />
Действительно, пользователей будет соответствовать и пароль на этой стадии пройдет проверку, но далее все равно пользователь (за исключением специальных конфигураций) получит <code>Reject</code><br />
<BR><br />
<BR><br />
Ниже подробности как и почему это происходит.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12980FreeRadius Notes2024-03-20T16:25:37Z<p>Sirmax: /* User-Password */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это атрибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> пользователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
В файле <code>users</code> соответвенно нужно указать:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
<br />
Эта запись означает что при совпадении атрибута <code>User-Name</code> со значением слева (my_username), нужно в словарь <code>contro</code> добавить атрибут <code>Cleartext-Password</code> со значением "known_good_password".<br />
<BR><br />
Соответвенно ответ на вопрос "почему писать так не правильно":<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
такой:<br />
Эта конструкция работает не так как ожидается (не работает авторизация) по-тому что она говорит что при совпадении <code>User-Name</code> в списке атрибутов запроса (которые прислал NAS)следует найти атрибут <br />
<code>Cleartext-Password</code> и сравнить его значение со значением "test".<br />
Так как никакой NAS не присылает такой запрос (атрибут <code>Cleartext-Password</code> отсутствует) то поведение отличается от ожидаемого.<br />
<BR><br />
Можно было бы предположить, что если указать <code>User-Password == "test"</code> то конструкция заработает<BR><br />
. Unfortunately it won't. <br />
If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<BR><br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12979FreeRadius Notes2024-03-20T12:24:57Z<p>Sirmax: /* User-Password */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> это тарибут который должен содержаться только в запросе и более нигде<br />
<BR><br />
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR><br />
<br />
Что бы <code>authenticate</code> подльзователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.<br />
<BR><br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<BR><br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<BR><br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<BR><br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12978FreeRadius Notes2024-03-20T12:21:46Z<p>Sirmax: /* User-Password */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<BR><br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<BR><br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<BR><br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
<BR><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<BR><br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<BR><br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12977FreeRadius Notes2024-03-20T12:21:19Z<p>Sirmax: /* Cleartext-Password */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
По сути, модуль <code>rlm_pap</code> сравнивает значение <code>User-Password</code> которое вставил другой модуль - <code>files</code> как в этом примере или <code>sql</code> или еще какой-то<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12976FreeRadius Notes2024-03-20T12:17:32Z<p>Sirmax: /* Cleartext-Password */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<BR><br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12975FreeRadius Notes2024-03-20T12:17:17Z<p>Sirmax: /* Cleartext-Password */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<br />
<code>Cleartext-Password</code> это один из списка атрибутов известных как <B>'known good' password</B> <BR> который содержит пользовательский пароль в открытом виде.<br />
<BR><br />
Другой пример из этого набора "хорошо известных" <code>SSHA-Password</code> - который содержит salted SHA hash от пользовательского пароля.<br />
<BR><br />
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the <B>'known good' password</B> атрибутов <BR><br />
которые содержаться в списке <code>control</code> модулями которые могут <code>authenticate</code> пользователя - это может быть модуль <code>rlm_pap</code><br />
<BR><br />
или другой - например самописный на python<br />
<PRE><br />
authenticate {<br />
Auth-Type ISG {<br />
python3_isg<br />
}<br />
}<br />
</PRE><br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12974FreeRadius Notes2024-03-20T12:03:29Z<p>Sirmax: /* Cleartext-Password */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> это исключительно <code>control</code> пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12973FreeRadius Notes2024-03-20T11:55:45Z<p>Sirmax: /* How the users file works */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<BR><br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* Если используются операторы присвоения <code>:=</code> or <code>=</code> то пара атрибут-значение обрабатывается как <code>control</code> (добавляется в список)<br />
* Если используются операторы сравнения <code>></code>, <code><</code>, <code>==</code>, <code>>=</code>, <code><=</code>, <code>=~</code> то пара атрибут-значение используются для проверки соответвия<br />
<br />
В примере выше используется только одна пара <code>Cleartext-Password := "hello"</code> где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)<br />
<BR><br />
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12972FreeRadius Notes2024-03-20T11:46:15Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет) <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12971FreeRadius Notes2024-03-20T11:44:26Z<p>Sirmax: /* How the users file works */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the <code>users</code> file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
<BR> <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
Модуль <code>users file</code> определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.<br />
<BR><br />
Пример:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
<br />
</PRE><br />
Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список <code>control</code>, <BR><br />
добавление в список <code>control</code> происходит при полном совпадении всех проверок.<br />
<br />
Пары (в первой строке!) которые проверяются которые добавляются в список <code> control</code> можно отличить по используемым операторам<br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* 123<br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12970FreeRadius Notes2024-03-20T11:08:47Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* 123<br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно)<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного<br />
|| Не применимо<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному<br />
|| Не применимо<br />
|-<br />
| <code> =~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк <br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется)<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия)<br />
|| Не применимо<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12969FreeRadius Notes2024-03-20T10:59:25Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* 123<br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Не применимо<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Не применимо<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Не применимо<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Не применимо<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Не применимо<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Не применимо<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Не применимо<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12968FreeRadius Notes2024-03-20T10:57:39Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* 123<br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12967FreeRadius Notes2024-03-20T10:56:57Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* 123<br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <code>Attribute += Value</code><br />
<PRE><br />
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",<br />
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"<br />
</PRE><br />
|| При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов<br />
|| Текст ячейки<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12966FreeRadius Notes2024-03-20T10:51:07Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
<PRE><br />
authorize {<br />
preprocess<br />
...<br />
}<br />
</PRE><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <br />
Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12965FreeRadius Notes2024-03-20T10:49:10Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе <br />
присутвуют атрибут <code>Service-Type</code> со значением "Framed-User" и <code>Huntgroup-Name</code> со значением "alphen"<br />
<BR><br />
Сам атрибут <code>Huntgroup-Name</code> должен быть установлен дополнительно в модуле <code>preprocess</code><br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <br />
Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12964FreeRadius Notes2024-03-20T10:39:41Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
||<br />
Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<BR><br />
В примере при совпадении <code>User-Name</code> со значением "swilson" и если в запросе присутвуют атрибут Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
||<br />
Не применимо<br />
|-<br />
| <code> +=</code><br />
|| <br />
Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12963FreeRadius Notes2024-03-20T10:33:00Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <PRE><br />
swilson Service-Type == Framed-User, Huntgroup-Name == "alphen"<br />
Framed-IP-Address = 192.0.2.65,<br />
Fall-Through = Yes<br />
</PRE><br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| <code> +=</code><br />
|| <br />
Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12962FreeRadius Notes2024-03-20T10:26:19Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| <code> +=</code><br />
|| <br />
Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12961FreeRadius Notes2024-03-20T10:25:50Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| <code> +=</code><br />
|| <br />
Текст ячейки<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|-<br />
| <code> > </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> >= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
|<br />
<code> < </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> <= </code><br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !~ </code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> =*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|-<br />
| <code> !*</code> <br />
|| Текст ячейки<br />
|| Текст ячейки<br />
|| Текст ячейки<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12960FreeRadius Notes2024-03-20T10:24:30Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| <code> :=</code> <br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| <code> ==</code> <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| <code> +=</code><br />
|| <br />
Текст ячейки<br />
|-<br />
| <code> !=</code><br />
|| Текст ячейки<br />
|-<br />
| </code> > </code> <br />
|| Текст ячейки<br />
|-<br />
| </code> >= </code><br />
|| Текст ячейки<br />
|-<br />
|<br />
</code> < </code><br />
|| Текст ячейки<br />
|-<br />
| </code> <= </code><br />
|| Текст ячейки<br />
|-<br />
| </code> !~ </code> <br />
|| Текст ячейки<br />
|-<br />
| </code> =*</code> <br />
|| Текст ячейки<br />
|-<br />
| </code> !*</code> <br />
|| Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12959FreeRadius Notes2024-03-20T10:22:38Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
<PRE><br />
automate Cleartext-Password := "pppassss"<br />
User-Service-Type := 6<br />
</PRE><br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12958FreeRadius Notes2024-03-20T10:10:33Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
</PRE><br />
* В примере в секции <code> authorize</code> выше модуль <code>files</code> добавит атрибут <code>Cleartext-Password</code>, модуль <code>pap</code> добавит атрибут <code>Auth-Type</code> со значением "PAP"<br />
* И только в секции <code> authenticate </code> будет происходить проверка пароля<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12957FreeRadius Notes2024-03-20T10:06:57Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
* При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера<br />
<br />
<PRE><br />
server {<br />
<br />
authorize {<br />
preprocess<br />
chap<br />
mschap<br />
digest<br />
suffix<br />
files<br />
expiration<br />
pap<br />
}<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
Auth-Type CHAP {<br />
chap<br />
}<br />
Auth-Type MS-CHAP {<br />
mschap<br />
}<br />
digest<br />
# unix<br />
}<br />
</PRE><br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12956FreeRadius Notes2024-03-20T10:04:46Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<PRE><br />
steve Cleartext-Password := "testing"<br />
Service-Type = Framed-User<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В первом примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
<BR><br />
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля <code>:=</code> а не сравнение.<br />
<BR>Тут важно понимать следующее<br />
* Эта запись будет работать если в запросе есть атрибут <code>User-Name</code> со значением "steve"<br />
* В <code>control</code> словарь будет помещен атрибут <code>Cleartext-Password</code> со значением "testing"<br />
* В <code>reply</code> словарь будет помещен атрибут <code>Service-Type</code> со значением "Framed-User"<br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12955FreeRadius Notes2024-03-20T09:56:10Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
||<br />
Для атрибутов в ответе (<code>reply</code>) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12954FreeRadius Notes2024-03-20T09:54:33Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
|| <br />
Всегда совпадает при проверках, и добавляет в <code>control</code> атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения)<br />
В примере пользователь всегда получит <BR> <code>Auth-Type := Reject </code>, если ниже нет другого условия (например для группы), которое переопределит <code>Auth-Type</code><br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12953FreeRadius Notes2024-03-20T09:46:33Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code><BR>(users и тому подобное), или в блоках unlang update<br />
|-<br />
| <code>=</code> <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12952FreeRadius Notes2024-03-20T09:45:54Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !!Использование в <code>check</code> <BR><br />
(users и тому подобное), или в условиях unlang <br />
!! <br />
Использование в <code>reply</code> <br />
(users и тому подобное), или в блоках unlang update<br />
|-<br />
| = <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12951FreeRadius Notes2024-03-20T09:45:37Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример <br />
!!Использование в <code>check</code> <br />
(users и тому подобное), или в условиях unlang <br />
!! <br />
Использование в <code>reply</code> <br />
(users и тому подобное), или в блоках unlang update<br />
|-<br />
| = <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12950FreeRadius Notes2024-03-20T09:45:18Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator <br />
!! Пример <br />
!!Использование в <code>check</code> <br />
(users и тому подобное), или в условиях unlang <br />
!! <br />
Использование в <code>reply</code> <br />
(users и тому подобное), или в блоках unlang update<br />
|-<br />
| = <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12949FreeRadius Notes2024-03-20T09:44:28Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! <br />
Operator <br />
!! <br />
Пример <br />
!! <br />
Использование в <code>check</code> <br />
(users и тому подобное), или в условиях unlang <br />
!! <br />
Использование в <code>reply</code> <br />
(users и тому подобное), или в блоках unlang update<br />
|-<br />
| = <br />
|| <br />
<code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
||<br />
* <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12948FreeRadius Notes2024-03-20T09:38:51Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !! Использование в <code>check</code> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code> (users и тому подобное), или в блоках unlang update<br />
|-<br />
| = || <code>Attribute = Value</code><br />
||<br />
* Используется для установки атрибутов конфигурации сервера (см пример)<br />
* Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
<br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12947FreeRadius Notes2024-03-20T09:37:37Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !! Использование в <code>check</code> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code> (users и тому подобное), или в блоках unlang update<br />
|-<br />
| = || <code>Attribute = Value</code><br />
||<br />
Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
Используется для установки атрибутов конфигурации сервера, например <br />
|-<br />
| :=<br />
||<br />
<PRE> <br />
lameuser Auth-Type := Reject<br />
Reply-Message = "Your account has been disabled."<br />
</PRE><br />
<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12946FreeRadius Notes2024-03-20T09:32:37Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !! Использование в <code>check</code> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code> (users и тому подобное), или в блоках unlang update<br />
|-<br />
| = || <code>Attribute = Value</code><br />
||<br />
Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
Используется для установки атрибутов конфигурации сервера, например <br />
|-<br />
| := || Текст ячейки<br />
|-<br />
| == <br />
|| <br />
|| Операция сравнения для <code>check</code> атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12945FreeRadius Notes2024-03-19T18:04:00Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !! Использование в <code>check</code> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code> (users и тому подобное), или в блоках unlang update<br />
|-<br />
| = || <code>Attribute = Value</code><br />
|| Не допускается для операторов проверки атрибутов (например проверки пароля)<br />
|-<br />
| := || Текст ячейки<br />
|-<br />
| == || Текст ячейки<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmaxhttps://noname.com.ua/mediawiki/index.php?title=FreeRadius_Notes&diff=12944FreeRadius Notes2024-03-19T18:03:17Z<p>Sirmax: /* Описание операторов */</p>
<hr />
<div>[[Категория:FreeRadius]]<br />
=Это просто сборник ссылок и заметок=<br />
* https://shop.nag.ru/article/ericsson-smartedge-freeradius-billing<br />
* https://code.google.com/archive/p/cakebilling/wikis/ConfiguringFreeRadius.wiki<br />
<br />
=Минимальный рабочий конфиг=<br />
Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль<br />
==<code>sites-enabled/default</code>==<br />
<PRE><br />
server default {<br />
listen {<br />
type = auth<br />
ipv4addr = *<br />
port = 1812<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
<br />
listen {<br />
ipv4addr = *<br />
port = 1813<br />
type = acct<br />
}<br />
<br />
<br />
instantiate {<br />
exec<br />
expr<br />
expiration<br />
}<br />
<br />
authorize {<br />
files<br />
pap<br />
}<br />
<br />
authenticate {<br />
Auth-Type PAP {<br />
pap<br />
}<br />
}<br />
} # end of SERVER<br />
</PRE><br />
<br />
==Клиенты <code>clients.conf</code>==<br />
<br />
<PRE><br />
client localhost {<br />
ipaddr = 127.0.0.1<br />
proto = *<br />
secret = secret<br />
require_message_authenticator = no<br />
limit {<br />
max_connections = 16<br />
lifetime = 0<br />
idle_timeout = 30<br />
}<br />
}<br />
</PRE><br />
==Модуль PAP <code>mods-enabled/pap</code>==<br />
<PRE><br />
pap {<br />
# normalise = yes<br />
auto_header = no<br />
}<br />
</PRE><br />
<br />
==Модуль files==<br />
===<code>mods-enabled/files</code>===<br />
<PRE><br />
files {<br />
moddir = ${modconfdir}/${.:instance}<br />
#key = "%{%{Stripped-User-Name}:-%{User-Name}}"<br />
filename = ${moddir}/authorize<br />
usersfile = ${moddir}/authorize<br />
# acctusersfile = ${moddir}/accounting<br />
}<br />
</PRE><br />
===<code>mods-config/files/authorize</code>===<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
<br />
=Проверка работы минимальной конфигурации=<br />
<BR><br />
<br />
* Для проверки использую команду <code>radtest bob hello localhost 0 secret</code><br />
** <code>bob</code> - имя пользователя, атрибут <code>User-Name</code><br />
** <code>hello</code> - пароль, который будет передан в атрибуте <code>User-Password</code><br />
** <code>localhost</code> - адрес куда отправить запрос<br />
** <code>0</code> - номер (виртуального) порта, <code>NAS-Port</code><br />
** <code>secret</code> - radius shared secret, который указан в настройках сервера и клиента<br />
<br />
По сути тут логика такая<br />
* "Пришел" пользователь <code>User-Name = "bob"</code> <code>User-Password = "hello"</code><br />
* Его проверили по файлу (модуль <code>files</code> ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись <code>files: users: Matched entry bob at line 4</code><br />
* Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль <code>files</code> а именно:<br />
<PRE><br />
bob Cleartext-Password := "hello"<br />
Reply-Message := "Hello, %{User-Name}"<br />
</PRE><br />
* При этом модуль <code>files</code> по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (<code>key = "%{%{Stripped-User-Name}:-%{User-Name}}"</code>) находит (или не находит) атрибуты.<br />
<BR><br />
Запись в логах вида:<br />
<PRE><br />
[files] = ok<br />
</PRE><br />
Означает что такой пользователь существует, НО не означает что он успешно авторизован.<br />
* Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - <code>Cleartext-Password</code><br />
<BR><br />
{{#spoiler:show=Выдержка из man rlm_pap |<br />
<br />
<PRE><br />
The module looks for the Password-With-Header control attribute to find the "known good" password. The attribute value comprises the header followed immediately by the password data. The<br />
header is given by the following table.<br />
<br />
Header Attribute Description<br />
------ --------- -----------<br />
{clear} Cleartext-Password Clear-text passwords<br />
{cleartext} Cleartext-Password Clear-text passwords<br />
{crypt} Crypt-Password Unix-style "crypt"ed passwords<br />
{md5} MD5-Password MD5 hashed passwords<br />
{base64_md5} MD5-Password MD5 hashed passwords<br />
{smd5} SMD5-Password MD5 hashed passwords, with a salt<br />
{sha} SHA-Password SHA1 hashed passwords<br />
SHA1-Password SHA1 hashed passwords<br />
{ssha} SSHA-Password SHA1 hashed passwords, with a salt<br />
{sha2} SHA2-Password SHA2 hashed passwords<br />
{sha224} SHA2-Password SHA2 hashed passwords<br />
{sha256} SHA2-Password SHA2 hashed passwords<br />
{sha384} SHA2-Password SHA2 hashed passwords<br />
{sha512} SHA2-Password SHA2 hashed passwords<br />
{ssha224} SSHA2-224-Password SHA2 hashed passwords, with a salt<br />
{ssha256} SSHA2-256-Password SHA2 hashed passwords, with a salt<br />
{ssha384} SSHA2-384-Password SHA2 hashed passwords, with a salt<br />
{ssha512} SSHA2-512-Password SHA2 hashed passwords, with a salt<br />
{nt} NT-Password Windows NT hashed passwords<br />
{nthash} NT-Password Windows NT hashed passwords<br />
{md4} NT-Password Windows NT hashed passwords<br />
{x-nthash} NT-Password Windows NT hashed passwords<br />
{ns-mta-md5} NS-MTA-MD5-Password Netscape MTA MD5 hashed passwords<br />
{x- orcllmv} LM-Password Windows LANMAN hashed passwords<br />
{X- orclntv} NT-Password Windows NT hashed passwords<br />
</PRE><br />
}}<br />
<br />
<br />
* Собственно на этом все.<br />
<br />
<PRE><br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Name = "bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) User-Password = "hello"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-IP-Address = 10.90.1.213<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) NAS-Port = 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) authorize {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message<br />
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:<br />
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,<br />
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: --> Hello, bob<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from files (rlm_files)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [files] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authorize]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # authorize = updated<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Auth-Type PAP {<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: calling pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) modsingle[authenticate]: returned from pap (rlm_pap)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) [pap] = ok<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) } # Auth-Type PAP = ok<br />
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default". Using default return values.<br />
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Reply-Message = "Hello, bob"<br />
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request<br />
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.<br />
</PRe><br />
<br />
<br />
=Ошибочная конфигурация=<br />
Если переставить модули местами и вместо<br />
<PRE><br />
authorize {<br />
files<br />
pap<br />
}<br />
</PRE><br />
Написать модули в обратном порядке<br />
<PRE><br />
authorize {<br />
pap<br />
files<br />
}<br />
</PRE><br />
<br />
То на момент проверки пароля модулем PAP, атрибут <code>Cleartext-Password</code> еще не будет доступен о чем и будет сказано в логах:<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user. Not setting Auth-Type<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available<br />
...<br />
<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password<br />
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type<br />
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject<br />
</PRE><br />
Не смотря на то что модуль <code>files</code> говорит что "все хорошо" авторизация не работает.<br />
<PRE><br />
Sat Jul 15 12:49:59 2023 : Debug: (0) [files] = ok <br />
</PRE><br />
<br />
<br />
=How the users file works=<br />
<br />
For the answer below, pairs is referring to Attribute Value Pairs (AVPs), that is, a tuple consisting of an attribute an operator and a value.<br />
<br />
Существуют три списка атрибутов (точнее пар атрибут - значение ) <br />
There are three lists of attribute(s) (pairs) that are accessible from the users file. <br />
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов<br />
These are bound to the request the server is currently processing, and they don't persist across multiple request/response rounds.<br />
<br />
* <code>request</code> - содержит список атрибут-значение которые получены в запросе от NAS<br />
* <code>control</code> - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью <code>ulang</code><br />
* <code>reply</code> - содержит список атрибутов которые будут отправлены назад на NAS<br />
<br />
The users file module determines the list it's going to use for inserting/searching, by where the pair is listed in the entry, and the operator.<br />
<br />
The first line of the entry contains check pairs that must match in order for the entry to be used. The first line also contains control pairs, those you want to be inserted into the control list if all the check pairs match.<br />
<br />
Note: It doesn't matter which order the pairs are listed in. control pairs will not be inserted unless all the check pairs evaluate to true.<br />
<br />
check and control pairs are distinguished by the operator used. <br />
<br />
* If an assignment operator is used i.e. ':=' or '=' then the pair will be treated as a control pair.<br />
* If an equality operator such as '>', '<', '==', '>=', '<=', '=~' is used, the pair will be treated as a check pair.<br />
==Описание операторов==<br />
{| class="wikitable"<br />
|+ Файлы<br />
|-<br />
! Operator !! Пример !! Использование в <code>check</code> (users и тому подобное), или в условиях unlang !! Использование в <code>reply</code> (users и тому подобное), или в блоках unlang update<br />
|-<br />
| = || Текст ячейки<br />
|| Не допускается для операторов проверки (например проверки пароля)<br />
|-<br />
| := || Текст ячейки<br />
|-<br />
| == || Текст ячейки<br />
|-<br />
| += || Текст ячейки<br />
|-<br />
| != || Текст ячейки<br />
|-<br />
| > || Текст ячейки<br />
|-<br />
| >= || Текст ячейки<br />
|-<br />
| < || Текст ячейки<br />
|-<br />
| <= || Текст ячейки<br />
|-<br />
| !~ || Текст ячейки<br />
|-<br />
| =* || Текст ячейки<br />
|-<br />
| !* || Текст ячейки<br />
<br />
<br />
|}<br />
<br />
<br />
Subsequent lines in the same entry contain only reply pairs. If all check pairs match, reply pairs will be inserted into the reply list.<br />
<br />
==<code>Cleartext-Password</code>==<br />
<br />
<code>Cleartext-Password</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
<code>Cleartext-Password</code> is one of a set of attributes, which should contain the 'reference' (or 'known good') password, that is, the local copy of the users password. An example of another pair in this set is <code>SSHA-Password</code> - this contains a salted SHA hash of the users password.<br />
<br />
The reference password pairs are searched for (in the control list) by modules capable of with authenticating users using the <code>User-Password</code> pair. In this case that module is 'rlm_pap'.<br />
<br />
==<code>User-Password</code>==<br />
<br />
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.<br />
<br />
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.<br />
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.<br />
<br />
In a users file entry when setting reference passwords you'll see entries like:<br />
<PRE><br />
my_username Cleartext-Password := "known_good_password"<br />
</PRE><br />
That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".<br />
<br />
To answer the first question the reason why:<br />
<PRE><br />
shad Cleartext-Password == "test"<br />
</PRE><br />
Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.<br />
<br />
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.<br />
<br />
==<code>Auth-Type</code>==<br />
<br />
<code>Auth-Type</code> is strictly a control pair. It should not be present in any of the other lists.<br />
<br />
There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.<br />
<br />
==<code>authorize</code>==<br />
<code>authorize</code> is the information gathering section.<br />
This is where database lookups are done to authorise the user, and to retrieve reference passwords.<br />
It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.<br />
<br />
==<code>authenticate</code>==<br />
<code>Authenticate</code> is where a specific module is called to perform authentication. The module is determined by Auth-Type.<br />
<br />
<br />
<code>Post-Auth</code> is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.<br />
<br />
The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.<br />
<br />
If no <code>Auth-Type</code> is set the request will be rejected.<br />
<br />
So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.<br />
<br />
When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.<br />
<br />
There's also a 'magic' <code>Auth-Type</code>, <code>Accept</code>, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:<br />
<br />
<PRE><br />
shad Auth-Type := Accept, User-Password == "test"<br />
</PRE></div>Sirmax