<html><head><style type='text/css'>p { margin: 0; }</style></head><body><div style='font-family: Arial; font-size: 12pt; color: #000000'><style>p { margin: 0; }</style><div style="font-family: Arial; font-size: 12pt; color: #000000">I've been following the guide at 
http://wiki.freeradius.org/guide/Mac-Auth I completed the section called
 Mac-Auth and 802.1x  The issue im having is with the 
rewrite_calling_station_id.<br><br>If I comment this out and make sure 
the authorized_macs file has the mac listed just like the access point 
sends it everything works.  The problem is not all access points send 
the mac in the same format.  Some may send it in upper case and some in 
lower case and with 30 plus access points I need to make sure its 
formatted correctly Which is what rewrite_calling_station_id should do.<br><br>In the log below authorized_macs has the mac address in lower 
case.  rewrite_calling_station_id should should solve this but does 
not.   In order to get it working I commented out 
rewrite_calling_station_id and changed the mac in the authorized_macs 
file to upper case.<br><br>I'm using ubuntu 10.4, FreeRADIUS Version 2.1.8<br>I noticed this WARNING: Unknown module "tolower" in string expansion "%" in the rejected log.<br>I have searched for a tolower program but can not find one to install.<br><br>What package is tolower part of ?<br>What am I missing?<br><br>Here is the policy.conf file<br><pre># Rewrite called station id attribute into a standard format.
#
rewrite_calling_station_id {
        if (Calling-Station-Id =~ /([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i){
                update request {
                        Calling-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
                }
        }
        else {
                noop
        }
}<br><br></pre>Here is the rejected log<br><br>FreeRADIUS Version 2.1.8, for host i486-pc-linux-gnu, built on Jan  5 2010 at 02:49:11<br>Copyright (C) 1999-2009 The FreeRADIUS server project and contributors. <br>There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A <br>PARTICULAR PURPOSE. <br>You may redistribute copies of FreeRADIUS under the terms of the <br>GNU General Public License v2. <br>Starting - reading configuration files ...<br>including configuration file /etc/freeradius/radiusd.conf<br>including configuration file /etc/freeradius/proxy.conf<br>including configuration file /etc/freeradius/clients.conf<br>including files in directory /etc/freeradius/modules/<br>including configuration file /etc/freeradius/modules/cui<br>including configuration file /etc/freeradius/modules/sqlcounter_expire_on_login<br>including configuration file /etc/freeradius/modules/etc_group<br>including configuration file /etc/freeradius/modules/detail.example.com<br>including configuration file /etc/freeradius/modules/otp<br>including configuration file /etc/freeradius/modules/logintime<br>including configuration file /etc/freeradius/modules/radutmp<br>including configuration file /etc/freeradius/modules/inner-eap<br>including configuration file /etc/freeradius/modules/chap<br>including configuration file /etc/freeradius/modules/ldap<br>including configuration file /etc/freeradius/modules/detail<br>including configuration file /etc/freeradius/modules/attr_rewrite<br>including configuration file /etc/freeradius/modules/mac2vlan<br>including configuration file /etc/freeradius/modules/sql_log<br>including configuration file /etc/freeradius/modules/expr<br>including configuration file /etc/freeradius/modules/checkval<br>including configuration file /etc/freeradius/modules/passwd<br>including configuration file /etc/freeradius/modules/exec<br>including configuration file /etc/freeradius/modules/smsotp<br>including configuration file /etc/freeradius/modules/krb5<br>including configuration file /etc/freeradius/modules/wimax<br>including configuration file /etc/freeradius/modules/perl<br>including configuration file /etc/freeradius/modules/realm<br>including configuration file /etc/freeradius/modules/attr_filter<br>including configuration file /etc/freeradius/modules/smbpasswd<br>including configuration file /etc/freeradius/modules/policy<br>including configuration file /etc/freeradius/modules/ntlm_auth<br>including configuration file /etc/freeradius/modules/files<br>including configuration file /etc/freeradius/modules/counter<br>including configuration file /etc/freeradius/modules/echo<br>including configuration file /etc/freeradius/modules/acct_unique<br>including configuration file /etc/freeradius/modules/unix<br>including configuration file /etc/freeradius/modules/ippool<br>including configuration file /etc/freeradius/modules/mac2ip<br>including configuration file /etc/freeradius/modules/digest<br>including configuration file /etc/freeradius/modules/expiration<br>including configuration file /etc/freeradius/modules/always<br>including configuration file /etc/freeradius/modules/mschap<br>including configuration file /etc/freeradius/modules/detail.log<br>including configuration file /etc/freeradius/modules/sradutmp<br>including configuration file /etc/freeradius/modules/linelog<br>including configuration file /etc/freeradius/modules/pam<br>including configuration file /etc/freeradius/modules/pap<br>including configuration file /etc/freeradius/modules/preprocess<br>including configuration file /etc/freeradius/eap.conf<br>including configuration file /etc/freeradius/policy.conf<br>including files in directory /etc/freeradius/sites-enabled/<br>including configuration file /etc/freeradius/sites-enabled/inner-tunnel<br>including configuration file /etc/freeradius/sites-enabled/default<br>main {<br>    user = "freerad"<br>    group = "freerad"<br>    allow_core_dumps = no<br>}<br>including dictionary file /etc/freeradius/dictionary<br>main {<br>    prefix = "/usr"<br>    localstatedir = "/var"<br>    logdir = "/var/log/freeradius"<br>    libdir = "/usr/lib/freeradius"<br>    radacctdir = "/var/log/freeradius/radacct"<br>    hostname_lookups = no<br>    max_request_time = 30<br>    cleanup_delay = 5<br>    max_requests = 1024<br>    pidfile = "/var/run/freeradius/freeradius.pid"<br>    checkrad = "/usr/sbin/checkrad"<br>    debug_level = 0<br>    proxy_requests = yes<br> log {<br>    stripped_names = no<br>    auth = no<br>    auth_badpass = no<br>    auth_goodpass = no<br> }<br> security {<br>    max_attributes = 200<br>    reject_delay = 1<br>    status_server = yes<br> }<br>}<br>radiusd: #### Loading Realms and Home Servers ####<br> proxy server {<br>    retry_delay = 5<br>    retry_count = 3<br>    default_fallback = no<br>    dead_time = 120<br>    wake_all_if_all_dead = no<br> }<br> home_server localhost {<br>    ipaddr = 127.0.0.1<br>    port = 1812<br>    type = "auth"<br>    secret = "testing123"<br>    response_window = 20<br>    max_outstanding = 65536<br>    require_message_authenticator = no<br>    zombie_period = 40<br>    status_check = "status-server"<br>    ping_interval = 30<br>    check_interval = 30<br>    num_answers_to_alive = 3<br>    num_pings_to_alive = 3<br>    revive_interval = 120<br>    status_check_timeout = 4<br>    irt = 2<br>    mrt = 16<br>    mrc = 5<br>    mrd = 30<br> }<br> home_server_pool my_auth_failover {<br>    type = fail-over<br>    home_server = localhost<br> }<br> realm example.com {<br>    auth_pool = my_auth_failover<br> }<br> realm LOCAL {<br> }<br>radiusd: #### Loading Clients ####<br> client localhost {<br>    ipaddr = 127.0.0.1<br>    require_message_authenticator = no<br>    secret = "testing123"<br>    nastype = "other"<br> }<br> client 10.1.0.66 {<br>    require_message_authenticator = no<br>    secret = "testing123"<br>    shortname = "AP"<br> }<br>radiusd: #### Instantiating modules ####<br> instantiate {<br> Module: Linked to module rlm_exec<br> Module: Instantiating exec<br>  exec {<br>    wait = no<br>    input_pairs = "request"<br>    shell_escape = yes<br>  }<br> Module: Linked to module rlm_expr<br> Module: Instantiating expr<br> Module: Linked to module rlm_expiration<br> Module: Instantiating expiration<br>  expiration {<br>    reply-message = "Password Has Expired  "<br>  }<br> Module: Linked to module rlm_logintime<br> Module: Instantiating logintime<br>  logintime {<br>    reply-message = "You are calling outside your allowed timespan  "<br>    minimum-timeout = 60<br>  }<br> }<br>radiusd: #### Loading Virtual Servers ####<br>server inner-tunnel {<br> modules {<br> Module: Checking authenticate {...} for more modules to load<br> Module: Linked to module rlm_pap<br> Module: Instantiating pap<br>  pap {<br>    encryption_scheme = "auto"<br>    auto_header = no<br>  }<br> Module: Linked to module rlm_chap<br> Module: Instantiating chap<br> Module: Linked to module rlm_mschap<br> Module: Instantiating mschap<br>  mschap {<br>    use_mppe = yes<br>    require_encryption = no<br>    require_strong = no<br>    with_ntdomain_hack = no<br>  }<br> Module: Linked to module rlm_unix<br> Module: Instantiating unix<br>  unix {<br>    radwtmp = "/var/log/freeradius/radwtmp"<br>  }<br> Module: Linked to module rlm_eap<br> Module: Instantiating eap<br>  eap {<br>    default_eap_type = "peap"<br>    timer_expire = 60<br>    ignore_unknown_eap_types = no<br>    cisco_accounting_username_bug = no<br>    max_sessions = 4096<br>  }<br> Module: Linked to sub-module rlm_eap_md5<br> Module: Instantiating eap-md5<br> Module: Linked to sub-module rlm_eap_leap<br> Module: Instantiating eap-leap<br> Module: Linked to sub-module rlm_eap_gtc<br> Module: Instantiating eap-gtc<br>   gtc {<br>    challenge = "Password: "<br>    auth_type = "PAP"<br>   }<br> Module: Linked to sub-module rlm_eap_tls<br> Module: Instantiating eap-tls<br>   tls {<br>    rsa_key_exchange = no<br>    dh_key_exchange = yes<br>    rsa_key_length = 512<br>    dh_key_length = 512<br>    verify_depth = 0<br>    pem_file_type = yes<br>    private_key_file = "/etc/freeradius/certs/server.key"<br>    certificate_file = "/etc/freeradius/certs/server.pem"<br>    CA_file = "/etc/freeradius/certs/ca.pem"<br>    private_key_password = "whatever"<br>    dh_file = "/etc/freeradius/certs/dh"<br>    random_file = "/etc/freeradius/certs/random"<br>    fragment_size = 1024<br>    include_length = yes<br>    check_crl = no<br>    cipher_list = "DEFAULT"<br>    make_cert_command = "/etc/freeradius/certs/bootstrap"<br>    cache {<br>    enable = no<br>    lifetime = 24<br>    max_entries = 255<br>    }<br>   }<br> Module: Linked to sub-module rlm_eap_ttls<br> Module: Instantiating eap-ttls<br>   ttls {<br>    default_eap_type = "md5"<br>    copy_request_to_tunnel = no<br>    use_tunneled_reply = no<br>    virtual_server = "inner-tunnel"<br>    include_length = yes<br>   }<br> Module: Linked to sub-module rlm_eap_peap<br> Module: Instantiating eap-peap<br>   peap {<br>    default_eap_type = "mschapv2"<br>    copy_request_to_tunnel = no<br>    use_tunneled_reply = no<br>    proxy_tunneled_request_as_eap = yes<br>    virtual_server = "inner-tunnel"<br>   }<br> Module: Linked to sub-module rlm_eap_mschapv2<br> Module: Instantiating eap-mschapv2<br>   mschapv2 {<br>    with_ntdomain_hack = no<br>   }<br> Module: Checking authorize {...} for more modules to load<br> Module: Linked to module rlm_realm<br> Module: Instantiating suffix<br>  realm suffix {<br>    format = "suffix"<br>    delimiter = "@"<br>    ignore_default = no<br>    ignore_null = no<br>  }<br> Module: Linked to module rlm_files<br> Module: Instantiating files<br>  files {<br>    usersfile = "/etc/freeradius/users"<br>    acctusersfile = "/etc/freeradius/acct_users"<br>    preproxy_usersfile = "/etc/freeradius/preproxy_users"<br>    compat = "no"<br>  }<br> Module: Checking session {...} for more modules to load<br> Module: Linked to module rlm_radutmp<br> Module: Instantiating radutmp<br>  radutmp {<br>    filename = "/var/log/freeradius/radutmp"<br>    username = "%{User-Name}"<br>    case_sensitive = yes<br>    check_with_nas = yes<br>    perm = 384<br>    callerid = yes<br>  }<br> Module: Checking post-proxy {...} for more modules to load<br> Module: Checking post-auth {...} for more modules to load<br> Module: Linked to module rlm_attr_filter<br> Module: Instantiating attr_filter.access_reject<br>  attr_filter attr_filter.access_reject {<br>    attrsfile = "/etc/freeradius/attrs.access_reject"<br>    key = "%{User-Name}"<br>  }<br> } # modules<br>} # server<br>server {<br> modules {<br> Module: Checking authenticate {...} for more modules to load<br> Module: Checking authorize {...} for more modules to load<br> Module: Linked to module rlm_preprocess<br> Module: Instantiating preprocess<br>  preprocess {<br>    huntgroups = "/etc/freeradius/huntgroups"<br>    hints = "/etc/freeradius/hints"<br>    with_ascend_hack = no<br>    ascend_channels_per_line = 23<br>    with_ntdomain_hack = no<br>    with_specialix_jetstream_hack = no<br>    with_cisco_vsa_hack = no<br>    with_alvarion_vsa_hack = no<br>  }<br> Module: Loading virtual module rewrite_calling_station_id<br> Module: Linked to module rlm_always<br> Module: Instantiating noop<br>  always noop {<br>    rcode = "noop"<br>    simulcount = 0<br>    mpp = no<br>  }<br> Module: Instantiating authorized_macs<br>  files authorized_macs {<br>    usersfile = "/etc/freeradius/authorized_macs"<br>    compat = "no"<br>    key = "%{Calling-Station-ID}"<br>  }<br> Module: Instantiating reject<br>  always reject {<br>    rcode = "reject"<br>    simulcount = 0<br>    mpp = no<br>  }<br> Module: Checking preacct {...} for more modules to load<br> Module: Linked to module rlm_acct_unique<br> Module: Instantiating acct_unique<br>  acct_unique {<br>    key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"<br>  }<br> Module: Checking accounting {...} for more modules to load<br> Module: Linked to module rlm_detail<br> Module: Instantiating detail<br>  detail {<br>    detailfile = "/var/log/freeradius/radacct/%{Client-IP-Address}/detail-%Y%m%d"<br>    header = "%t"<br>    detailperm = 384<br>    dirperm = 493<br>    locking = no<br>    log_packet_header = no<br>  }<br> Module: Instantiating attr_filter.accounting_response<br>  attr_filter attr_filter.accounting_response {<br>    attrsfile = "/etc/freeradius/attrs.accounting_response"<br>    key = "%{User-Name}"<br>  }<br> Module: Checking session {...} for more modules to load<br> Module: Checking post-proxy {...} for more modules to load<br> Module: Checking post-auth {...} for more modules to load<br> } # modules<br>} # server<br>radiusd: #### Opening IP addresses and Ports ####<br>listen {<br>    type = "auth"<br>    ipaddr = *<br>    port = 0<br>}<br>listen {<br>    type = "acct"<br>    ipaddr = *<br>    port = 0<br>}<br>Listening on authentication address * port 1812<br>Listening on accounting address * port 1813<br>Listening on proxy address * port 1814<br>Ready to process requests.<br>rad_recv: Access-Request packet from host 10.1.0.66 port 1520, id=0, length=198<br>    Message-Authenticator = 0x8e5270705f13e5bf4d6bf9b89ee8b33b<br>    Service-Type = Framed-User<br>    User-Name = "aaron"<br>    Framed-MTU = 1488<br>    Called-Station-Id = "40-01-C6-DD-CB-40:test-2.4GHz"<br>    Calling-Station-Id = "00-14-A4-1E-FF-B6"<br>    NAS-Identifier = "Access-Point-22"<br>    NAS-Port-Type = Wireless-802.11<br>    Connect-Info = "CONNECT 54Mbps 802.11g"<br>    EAP-Message = 0x0200000a016161726f6e<br>    NAS-IP-Address = 10.1.0.66<br>    NAS-Port = 1<br>    NAS-Port-Id = "STA port # 1"<br>+- entering group authorize {...}<br>++[preprocess] returns ok<br>++- entering policy rewrite_calling_station_id {...}<br>+++?
 if (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)<br>?
 Evaluating (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)
 -> TRUE<br>+++? if (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)
 -> TRUE<br>+++- entering if (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)
 {...}<br>WARNING: Unknown module "tolower" in string expansion "%"<br>++++[request] returns ok<br>+++-
 if (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)
 returns ok<br>+++ ... skipping else for request 0: Preceding "if" was taken<br>++- policy rewrite_calling_station_id returns ok<br>[authorized_macs]     expand: %{Calling-Station-ID} -> <br>++[authorized_macs] returns noop<br>++? if (!ok)<br>? Evaluating !(ok) -> TRUE<br>++? if (!ok) -> TRUE<br>++- entering if (!ok) {...}<br>+++[reject] returns reject<br>++- if (!ok) returns reject<br>Using Post-Auth-Type Reject<br>+- entering group REJECT {...}<br>[attr_filter.access_reject]     expand: %{User-Name} -> aaron<br> attr_filter: Matched entry DEFAULT at line 11<br>++[attr_filter.access_reject] returns updated<br>Delaying reject of request 0 for 1 seconds<br>Going to the next request<br>Waking up in 0.9 seconds.<br>Sending delayed reject for request 0<br>Sending Access-Reject of id 0 to 10.1.0.66 port 1520<br>Waking up in 4.9 seconds.<br>rad_recv: Access-Request packet from host 10.1.0.66 port 1522, id=0, length=198<br>    Message-Authenticator = 0x770f506840dc4d2173ef986496b52844<br>    Service-Type = Framed-User<br>    User-Name = "aaron"<br>    Framed-MTU = 1488<br>    Called-Station-Id = "40-01-C6-DD-CB-40:test-2.4GHz"<br>    Calling-Station-Id = "00-14-A4-1E-FF-B6"<br>    NAS-Identifier = "Access-Point-22"<br>    NAS-Port-Type = Wireless-802.11<br>    Connect-Info = "CONNECT 54Mbps 802.11g"<br>    EAP-Message = 0x0200000a016161726f6e<br>    NAS-IP-Address = 10.1.0.66<br>    NAS-Port = 1<br>    NAS-Port-Id = "STA port # 1"<br>+- entering group authorize {...}<br>++[preprocess] returns ok<br>++- entering policy rewrite_calling_station_id {...}<br>+++?
 if (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)<br>?
 Evaluating (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)
 -> TRUE<br>+++? if (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)
 -> TRUE<br>+++- entering if (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)
 {...}<br>WARNING: Unknown module "tolower" in string expansion "%"<br>++++[request] returns ok<br>+++-
 if (Calling-Station-Id =~ 
/([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i)
 returns ok<br>+++ ... skipping else for request 1: Preceding "if" was taken<br>++- policy rewrite_calling_station_id returns ok<br>[authorized_macs]     expand: %{Calling-Station-ID} -> <br>++[authorized_macs] returns noop<br>++? if (!ok)<br>? Evaluating !(ok) -> TRUE<br>++? if (!ok) -> TRUE<br>++- entering if (!ok) {...}<br>+++[reject] returns reject<br>++- if (!ok) returns reject<br>Using Post-Auth-Type Reject<br>+- entering group REJECT {...}<br>[attr_filter.access_reject]     expand: %{User-Name} -> aaron<br> attr_filter: Matched entry DEFAULT at line 11<br>++[attr_filter.access_reject] returns updated<br>Delaying reject of request 1 for 1 seconds<br>Going to the next request<br>Waking up in 0.9 seconds.<br>Sending delayed reject for request 1<br>Sending Access-Reject of id 0 to 10.1.0.66 port 1522<br>Waking up in 3.5 seconds.<br>Cleaning up request 0 ID 0 with timestamp +16<br>Waking up in 1.4 seconds.<br>Cleaning up request 1 ID 0 with timestamp +17<br>Ready to process requests.</div></div></body></html>