From f9323b198d961bbe1be549ecb12dcf87602ce1b6 Mon Sep 17 00:00:00 2001 From: Durand Fabrice Date: Sat, 28 Dec 2024 22:47:46 -0500 Subject: [PATCH] Added unbound dpsk support --- lib/pf/Switch/Juniper/{Mist.pm => MistAP.pm} | 81 +++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) rename lib/pf/Switch/Juniper/{Mist.pm => MistAP.pm} (81%) diff --git a/lib/pf/Switch/Juniper/Mist.pm b/lib/pf/Switch/Juniper/MistAP.pm similarity index 81% rename from lib/pf/Switch/Juniper/Mist.pm rename to lib/pf/Switch/Juniper/MistAP.pm index 486df18bcd7..f08860918cc 100644 --- a/lib/pf/Switch/Juniper/Mist.pm +++ b/lib/pf/Switch/Juniper/MistAP.pm @@ -42,6 +42,8 @@ use pf::node; use pf::util::radius qw(perform_disconnect); use pf::radius::constants; use pf::locationlog qw(locationlog_get_session); +use pf::util::wpa; +use pf::log; sub description { 'Juniper Mist Access Point' } @@ -209,7 +211,6 @@ sub returnRadiusAccessAccept { push @av_pairs, "url-redirect=".$redirect_url; } } - $self->addDPSK($args, $radius_reply_ref, \@av_pairs); $radius_reply_ref->{'Cisco-AVPair'} = \@av_pairs; @@ -418,6 +419,84 @@ sub parseExternalPortalRequest { } +=head2 generate_dpsk_attribute_value + +Generates the RADIUS attribute value for Ruckus-DPSK given an SSID name and the passphrase + +=cut + +sub generate_dpsk_attribute_value { + my ($self, $ssid, $dpsk) = @_; + + my $pbkdf2 = Crypt::PBKDF2->new( + iterations => 4096, + output_len => 32, + ); + + my $hash = $pbkdf2->PBKDF2_hex($ssid, $dpsk); + return "0x00".$hash; +} + +sub find_user_by_psk { + my ($self, $radius_request, $args) = @_; + my $ssid = $radius_request->{'Eleven-EAPOL-SSID'}; + my $bssid = pack("H*", sprintf("%v02x", $radius_request->{"Eleven-EAPOL-APMAC"}) =~ s/\.//rg); + my $username = pack("H*", sprintf("%v02x", $radius_request->{'Eleven-EAPOL-STMAC'}) =~ s/\.//rg); + my $anonce = pack('H*', sprintf("%v02x", $radius_request->{'Eleven-EAPOL-Anonce'}) =~ s/\.//rg); + my $snonce = pf::util::wpa::snonce_from_eapol_key_frame(pack("H*",sprintf("%v02x",$radius_request->{"Eleven-EAPOL-Frame-2"}) =~ s/\.//rg)); + my $eapol_key_frame = pack("H*", sprintf("%v02x", $radius_request->{"Eleven-EAPOL-Frame-2"}) =~ s/\.//rg); + + my $cache = $self->cache; + if (exists $args->{'owner'} && $args->{'owner'}->{'pid'} ne "" && exists $args->{'owner'}->{'psk'} && defined $args->{'owner'}->{'psk'} && $args->{'owner'}->{'psk'} ne "") { + if (check_if_radius_request_psk_matches($cache, $radius_request, $args->{'owner'}->{'psk'}, $ssid, $bssid, $username, $anonce, $snonce, $eapol_key_frame)) { + get_logger->info("PSK matches the pid associated with the mac ".$args->{'owner'}->{'pid'}); + return $args->{'owner'}->{'pid'}; + } + } + + my ($status, $iter) = pf::dal::person->search( + -where => { + psk => {'!=' => [-and => '', undef]}, + }, + -columns => [qw(pid psk)], + -no_default_join => 1, + ); + + my $matched = 0; + my $pid; + # Try first the pid of the mac address + while(my $person = $iter->next) { + get_logger->warn("User ".$person->{pid}." has a PSK. Checking if it matches the one in the packet"); + if (check_if_radius_request_psk_matches($cache, $radius_request, $person->{'psk'}, $ssid, $bssid, $username, $anonce, $snonce, $eapol_key_frame)) { + get_logger->info("PSK matches the one of ".$person->{pid}); + $pid = $person->{pid}; + last; + } + } + return $pid; +} + +sub check_if_radius_request_psk_matches { + my ($cache, $radius_request, $psk, $ssid, $bssid, $username, $anonce, $snonce, $eapol_key_frame) = @_; + + my $pmk = $cache->compute( + "MistAP::check_if_radius_request_psk_matches::PMK::$ssid+$psk", + {expires_in => '1 month', expires_variance => '.20'}, + sub { pf::util::wpa::calculate_pmk($ssid, $psk) }, + ); + + return pf::util::wpa::match_mic( + pf::util::wpa::calculate_ptk( + $pmk, + $bssid, + $username, + $anonce, + $snonce, + ), + $eapol_key_frame, + ); +} + =back =head1 AUTHOR