Patchwork [RFC,PATCHv7] Use radius supplied PSK / Passphrase for WPA-PSK

login
register
mail settings
Submitter michael-dev@fami-braun.de
Date Dec. 6, 2011, 10:32 a.m.
Message ID <20111206103224.GA9429@dynamic.fami-braun.de>
Download mbox | patch
Permalink /patch/129594/
State Superseded
Headers show

Comments

michael-dev@fami-braun.de - Dec. 6, 2011, 10:32 a.m.
Hi,                                                                                                                                                                                                            
                                                                                                                                                                                                               
I wanted to use the per-device-PSK (WPA) feature in conjunction with a radius server that does the authorization checking and should supply the psk.                                                           
I found RouterOS to have a feature like this (Miktronik-Wireless-PSK or so radius attribute) but no source and a hint on this mailing list                                                                     
that it should not be difficult to implement.                                                                                                                                                                  
Please find a patch against git head attached that compiles fine and is currently under testing.                                                                                                               
                                                                                                                                                                                                               
To use this, one needs to enable the macaddr_acl = RADIUS setting and have wpa_psk_radius=1.                                                                                                                   
For Freeradius, one needs to add                                                                                                                                                                               
 VENDOR          Hostapd        39014                                                                                                                                                                          
 ATTRIBUTE       Hostapd-PSK          1    integer             Hostapd                                                                                                                                         
 ATTRIBUTE       Hostapd-Passphrase          2    string             Hostapd                                                                                                                                   
to the dictionary file and make sure that either Hostapd-Passphrase or Hostapd-PSK (the latter has higher priority) is in the radius reply.                                                                    
The PSK should be supplied hex encoded, the passphrase is turned into a psk by hostapd.                                                                                                                        
The Vendor ID will be changed once assigned by IANA.                                                                                                                                                           

The Service-Type radius attribute is used to easily differentiate between PSK reqests and EAP requests.
                                                                                                                                                                                                               
Regards,                                                                                                                                                                                                       
 M. Braun                                                                                                                                                                                                      
--                                                                                                                                                                                                             
Changes since v1:                                                                                                                                                                                              
 * sent wrong file, changes only apply to documentation part                                                                                                                                                   
Changes since v2:                                                                                                                                                                                              
 * use free enterprise number                                                                                                                                                                                  
Changes since v3:                                                                                                                                                                                              
 * fix typo, make it compile with openwrt                                                                                                                                                                      
Changes since v4:                                                                                                                                                                                              
 * tested on x86, fixed all occuring issues                                                                                                                                                                    
Changes since v5:                                                                                                                                                                                              
 * rebase on git, add Signed-By for Hostapd      
Changes since v6:
 * cleanup psk code doing superflous memcpy/free
Jouni Malinen - Dec. 6, 2011, 11:14 a.m.
On Tue, Dec 06, 2011 at 11:32:24AM +0100, michael-dev@fami-braun.de wrote:
> to the dictionary file and make sure that either Hostapd-Passphrase or Hostapd-PSK (the latter has higher priority) is in the radius reply.

I agree with Alan that this is not acceptable use of RADIUS to send keys
without any kind of protection.

> diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
> @@ -57,6 +57,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
> +	bss->wpa_psk_radius = 0;

This is not needed - the structure is memset to 0 anyway.

> diff --git a/src/radius/radius.c b/src/radius/radius.c
> +#include "ap/ap_config.h"

This is not acceptable. The RADIUS implementation needs to be able to
live without direct access to core AP structures. In this particular
case, this seems to be just for struct hostapd_ssid and that itself
could be replaced by just passing in the SSID and SSID length. However..

> +int radius_msg_get_psk(struct radius_msg *msg, u8* psk, struct hostapd_ssid *ssid)

> +		// Passphrase found
> +		pbkdf2_sha1(strkey, ssid->ssid, ssid->ssid_len, 4096, psk, PMK_LEN);

This does not really have anything to do with RADIUS, so it should not
be in src/radius/radius.c but somewhere in src/ap.
michael-dev@fami-braun.de - Dec. 6, 2011, 1:09 p.m.
Hi Jouni,

thanks for the review.
I'll update the patch ASAP with respect to the latter points.

Regards,
 M. Braun

Patch

commit b0bfdce8a34e7890205a6265514f4f1974cce049
Author: Michael Braun <michael-dev@fami-braun.de>
Date:   Tue Dec 6 11:00:58 2011 +0100

    Add support to get PSK using RADIUS.
    
     Signed-hostap: Michael Braun <michael-dev@fami-braun.de>

diff --git a/hostapd/README b/hostapd/README
index a211cdd..a94bc2a 100644
--- a/hostapd/README
+++ b/hostapd/README
@@ -350,6 +350,11 @@  TODO
 #wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
 #wpa_passphrase=secret passphrase
 
+# Optionally, WPA PSKs can be read from RADIUS (to be used with macaddr_acl set to RADIUS)
+# 0 no
+# 1 may (falls back to the above if no radius attribute is found)
+#wpa_psk_radius=0
+
 # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
 # entries are separated with a space.
 #wpa_key_mgmt=WPA-PSK WPA-EAP
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 5eb7b49..7e226c6 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1052,7 +1052,7 @@  static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
 
 	if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
 	    bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
-	    bss->ssid.wpa_psk_file == NULL) {
+	    bss->ssid.wpa_psk_file == NULL && bss->wpa_psk_radius == 0) {
 		wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
 			   "is not configured.");
 		return -1;
@@ -1629,6 +1629,8 @@  struct hostapd_config * hostapd_config_read(const char *fname)
 				hostapd_config_parse_key_mgmt(line, pos);
 			if (bss->wpa_key_mgmt == -1)
 				errors++;
+		} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
+			bss->wpa_psk_radius = atoi(pos);
 		} else if (os_strcmp(buf, "wpa_pairwise") == 0) {
 			bss->wpa_pairwise =
 				hostapd_config_parse_cipher(line, pos);
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 2a54518..3af8ac6 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -700,6 +700,11 @@  own_ip_addr=127.0.0.1
 # configuration reloads.
 #wpa_psk_file=/etc/hostapd.wpa_psk
 
+# Optionally, WPA PSKs can be read from RADIUS (to be used with macaddr_acl set to RADIUS)
+# 0 no
+# 1 may (falls back to the above if no radius attribute is found)
+wpa_psk_radius=1
+
 # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
 # entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
 # added to enable SHA256-based stronger algorithms.
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index cfb6b2d..bba436a 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -57,6 +57,8 @@  void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 	bss->broadcast_key_idx_max = 2;
 	bss->eap_reauth_period = 3600;
 
+	bss->wpa_psk_radius = 0;
+
 	bss->wpa_group_rekey = 600;
 	bss->wpa_gmk_rekey = 86400;
 	bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 2b201df..c1b6c73 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -219,6 +219,7 @@  struct hostapd_bss_config {
 	/* dot11AssociationSAQueryRetryTimeout (in TUs) */
 	int assoc_sa_query_retry_timeout;
 #endif /* CONFIG_IEEE80211W */
+	int wpa_psk_radius;
 	int wpa_pairwise;
 	int wpa_group;
 	int wpa_group_rekey;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 0352599..ade5c00 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -313,6 +313,8 @@  static void handle_auth(struct hostapd_data *hapd,
 	const u8 *challenge = NULL;
 	u32 session_timeout, acct_interim_interval;
 	int vlan_id = 0;
+        u8 psk[PMK_LEN];
+	int has_psk = 0;
 	u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
 	size_t resp_ies_len = 0;
 
@@ -375,7 +377,8 @@  static void handle_auth(struct hostapd_data *hapd,
 
 	res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
 				      &session_timeout,
-				      &acct_interim_interval, &vlan_id);
+				      &acct_interim_interval, &vlan_id, psk, &has_psk);
+
 	if (res == HOSTAPD_ACL_REJECT) {
 		printf("Station " MACSTR " not allowed to authenticate.\n",
 		       MAC2STR(mgmt->sa));
@@ -412,6 +415,12 @@  static void handle_auth(struct hostapd_data *hapd,
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
 			       HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
 	}
+	if (has_psk && hapd->conf->wpa_psk_radius == 1) {
+		sta->psk = os_zalloc(PMK_LEN);
+		os_memcpy(sta->psk, psk, PMK_LEN);
+	} else {
+		sta->psk = 0;
+	}
 
 	sta->flags &= ~WLAN_STA_PREAUTH;
 	ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index 9b558fa..510d14a 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -40,6 +40,8 @@  struct hostapd_cached_radius_acl {
 	u32 session_timeout;
 	u32 acct_interim_interval;
 	int vlan_id;
+        int has_psk;
+        u8 psk[PMK_LEN];
 };
 
 
@@ -68,7 +70,7 @@  static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
 
 static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
 				 u32 *session_timeout,
-				 u32 *acct_interim_interval, int *vlan_id)
+				 u32 *acct_interim_interval, int *vlan_id, u8* psk, int* has_psk)
 {
 	struct hostapd_cached_radius_acl *entry;
 	struct os_time now;
@@ -89,6 +91,10 @@  static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
 					entry->acct_interim_interval;
 			if (vlan_id)
 				*vlan_id = entry->vlan_id;
+                        if (psk)
+		                os_memcpy(psk, entry->psk, PMK_LEN);
+			if (has_psk)
+				*has_psk = entry->has_psk;
 			return entry->accepted;
 		}
 
@@ -184,6 +190,12 @@  static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
 		goto fail;
 	}
 
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_SERVICE_TYPE,
+				       RADIUS_SERVICE_TYPE_OUTBOUND)) {
+		wpa_printf(MSG_DEBUG, "Could not add Service-Type");
+		goto fail;
+	}
+
 	os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");
 	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
 				 (u8 *) buf, os_strlen(buf))) {
@@ -214,7 +226,7 @@  static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
  */
 int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 			    const u8 *msg, size_t len, u32 *session_timeout,
-			    u32 *acct_interim_interval, int *vlan_id)
+			    u32 *acct_interim_interval, int *vlan_id, u8* psk, int* has_psk)
 {
 	if (session_timeout)
 		*session_timeout = 0;
@@ -222,6 +234,10 @@  int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 		*acct_interim_interval = 0;
 	if (vlan_id)
 		*vlan_id = 0;
+        if (has_psk)
+		*has_psk = 0;
+	if (psk)
+		os_memset(psk, 0, PMK_LEN);
 
 	if (hostapd_maclist_found(hapd->conf->accept_mac,
 				  hapd->conf->num_accept_mac, addr, vlan_id))
@@ -246,7 +262,7 @@  int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 		/* Check whether ACL cache has an entry for this station */
 		int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
 						acct_interim_interval,
-						vlan_id);
+						vlan_id, psk, has_psk);
 		if (res == HOSTAPD_ACL_ACCEPT ||
 		    res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
 			return res;
@@ -396,6 +412,7 @@  hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
 			void *data)
 {
 	struct hostapd_data *hapd = data;
+        struct hostapd_ssid *ssid = &(hapd->conf->ssid);
 	struct hostapd_acl_query_data *query, *prev;
 	struct hostapd_cached_radius_acl *cache;
 	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
@@ -456,6 +473,10 @@  hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
 		}
 
 		cache->vlan_id = radius_msg_get_vlanid(msg);
+                cache->has_psk = radius_msg_get_psk(msg, cache->psk, ssid);
+
+		if (hapd->conf->wpa_psk_radius == 1 && !cache->has_psk)
+			cache->accepted = HOSTAPD_ACL_REJECT;
 	} else
 		cache->accepted = HOSTAPD_ACL_REJECT;
 	cache->next = hapd->acl_cache;
diff --git a/src/ap/ieee802_11_auth.h b/src/ap/ieee802_11_auth.h
index b2971e5..ee451f9 100644
--- a/src/ap/ieee802_11_auth.h
+++ b/src/ap/ieee802_11_auth.h
@@ -24,7 +24,7 @@  enum {
 
 int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 			    const u8 *msg, size_t len, u32 *session_timeout,
-			    u32 *acct_interim_interval, int *vlan_id);
+			    u32 *acct_interim_interval, int *vlan_id, u8* psk, int* has_psk);
 int hostapd_acl_init(struct hostapd_data *hapd);
 void hostapd_acl_deinit(struct hostapd_data *hapd);
 
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 18ee747..45509b4 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -509,6 +509,12 @@  static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
 		goto fail;
 	}
 
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_SERVICE_TYPE,
+				       RADIUS_SERVICE_TYPE_FRAMED)) {
+		printf("Could not add Service-Type\n");
+		goto fail;
+	}
+
 	if (sta->flags & WLAN_STA_PREAUTH) {
 		os_strlcpy(buf, "IEEE 802.11i Pre-Authentication",
 			   sizeof(buf));
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index a9981cc..bcea28e 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -228,6 +228,7 @@  void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 	wpabuf_free(sta->p2p_ie);
 
 	os_free(sta->ht_capabilities);
+	os_free(sta->psk);
 
 	os_free(sta);
 }
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 3ad00e2..7514af6 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -98,6 +98,7 @@  struct sta_info {
 	struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
 
 	int vlan_id;
+	u8* psk;
 
 	struct ieee80211_ht_capabilities *ht_capabilities;
 
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index ce2751e..9af82dd 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -132,6 +132,7 @@  struct wpa_auth_config {
 	int wpa;
 	int wpa_key_mgmt;
 	int wpa_pairwise;
+	int wpa_psk_radius;
 	int wpa_group;
 	int wpa_group_rekey;
 	int wpa_strict_rekey;
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 1e9d422..7ef0c07 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -39,6 +39,7 @@  static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
 	wconf->wpa = conf->wpa;
 	wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
 	wconf->wpa_pairwise = conf->wpa_pairwise;
+	wconf->wpa_psk_radius = conf->wpa_psk_radius;
 	wconf->wpa_group = conf->wpa_group;
 	wconf->wpa_group_rekey = conf->wpa_group_rekey;
 	wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
@@ -186,7 +187,10 @@  static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
 					   const u8 *prev_psk)
 {
 	struct hostapd_data *hapd = ctx;
-	return hostapd_get_psk(hapd->conf, addr, prev_psk);
+	struct sta_info *sta = ap_get_sta(hapd, addr);
+	if (sta == NULL || sta->psk == NULL)
+		return hostapd_get_psk(hapd->conf, addr, prev_psk);
+	return sta->psk;
 }
 
 
diff --git a/src/radius/radius.c b/src/radius/radius.c
index fb03a25..65323ab 100644
--- a/src/radius/radius.c
+++ b/src/radius/radius.c
@@ -17,9 +17,10 @@ 
 #include "utils/common.h"
 #include "utils/wpabuf.h"
 #include "crypto/md5.h"
+#include "crypto/sha1.h"
 #include "crypto/crypto.h"
 #include "radius.h"
-
+#include "ap/ap_config.h"
 
 /**
  * struct radius_msg - RADIUS message structure for new and parsed messages
@@ -173,6 +174,7 @@  static struct radius_attr_type radius_attrs[] =
 	{ RADIUS_ATTR_USER_PASSWORD, "User-Password", RADIUS_ATTR_UNDIST },
 	{ RADIUS_ATTR_NAS_IP_ADDRESS, "NAS-IP-Address", RADIUS_ATTR_IP },
 	{ RADIUS_ATTR_NAS_PORT, "NAS-Port", RADIUS_ATTR_INT32 },
+	{ RADIUS_ATTR_SERVICE_TYPE, "Service-Type", RADIUS_ATTR_INT32 },
 	{ RADIUS_ATTR_FRAMED_MTU, "Framed-MTU", RADIUS_ATTR_INT32 },
 	{ RADIUS_ATTR_REPLY_MESSAGE, "Reply-Message", RADIUS_ATTR_TEXT },
 	{ RADIUS_ATTR_STATE, "State", RADIUS_ATTR_UNDIST },
@@ -1275,6 +1277,49 @@  int radius_msg_get_vlanid(struct radius_msg *msg)
 }
 
 
+/**
+ * radius_msg_get_psk - Parse RADIUS attributes for PSK/Passphrase (WPA)
+ * @msg: RADIUS message
+ * @psk: buffer for PSK (len: PMK_LEN)
+ * Returns: 1 if psk found, 0 else
+ */
+int radius_msg_get_psk(struct radius_msg *msg, u8* psk, struct hostapd_ssid *ssid)
+{
+	char* key;
+	char* strkey = 0;
+        size_t keylen;
+
+        key = (char*) radius_msg_get_vendor_attr( msg, RADIUS_VENDOR_ID_HOSTAPD, RADIUS_VENDOR_ATTR_HAP_PSK, &keylen );
+        if (key) {
+		// PSK found, expect hex encoding
+                strkey = os_zalloc(keylen+1);
+		os_memcpy(strkey,key,keylen); 
+		os_free(key); key=NULL;
+
+                int len = os_strlen(strkey);
+                if (len == 64 && hexstr2bin(strkey, psk, PMK_LEN) == 0) {
+			os_free(strkey); strkey=NULL;
+                	return 1;
+                }
+		// PSK had wrong length...
+		os_free(strkey); strkey=NULL;
+	}
+
+        key = (char*) radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_HOSTAPD, RADIUS_VENDOR_ATTR_HAP_PASSPHRASE, &keylen );
+        if (key) {
+                strkey = os_zalloc(keylen+1);
+		os_memcpy(strkey,key,keylen); 
+		os_free(key); key=NULL;
+
+		// Passphrase found
+		pbkdf2_sha1(strkey, ssid->ssid, ssid->ssid_len, 4096, psk, PMK_LEN);
+		os_free(strkey); strkey=NULL;
+		return 1;
+	} 
+	return 0;
+}
+
+
 void radius_free_class(struct radius_class_data *c)
 {
 	size_t i;
diff --git a/src/radius/radius.h b/src/radius/radius.h
index a3cdac0..bc1980b 100644
--- a/src/radius/radius.h
+++ b/src/radius/radius.h
@@ -15,6 +15,8 @@ 
 #ifndef RADIUS_H
 #define RADIUS_H
 
+struct hostapd_ssid;
+
 /* RFC 2865 - RADIUS */
 
 #ifdef _MSC_VER
@@ -52,6 +54,7 @@  enum { RADIUS_ATTR_USER_NAME = 1,
        RADIUS_ATTR_USER_PASSWORD = 2,
        RADIUS_ATTR_NAS_IP_ADDRESS = 4,
        RADIUS_ATTR_NAS_PORT = 5,
+       RADIUS_ATTR_SERVICE_TYPE = 6,
        RADIUS_ATTR_FRAMED_MTU = 12,
        RADIUS_ATTR_REPLY_MESSAGE = 18,
        RADIUS_ATTR_STATE = 24,
@@ -145,6 +148,19 @@  enum { RADIUS_ATTR_USER_NAME = 1,
 #define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2
 #define RADIUS_TUNNEL_MEDIUM_TYPE_802 6
 
+/* Service-Type */
+#define RADIUS_SERVICE_TYPE_LOGIN 1
+#define RADIUS_SERVICE_TYPE_FRAMED 2
+#define RADIUS_SERVICE_TYPE_CALLBACK_LOGIN 3
+#define RADIUS_SERVICE_TYPE_CALLBACK_FRAMED 4
+#define RADIUS_SERVICE_TYPE_OUTBOUND 5
+#define RADIUS_SERVICE_TYPE_ADMINISTRATIVE 6
+#define RADIUS_SERVICE_TYPE_NAS_PROMPT 7
+#define RADIUS_SERVICE_TYPE_AUTHENTICATE_ONLY 8
+#define RADIUS_SERVICE_TYPE_CALLBACK_NAS_PROMPT 9
+#define RADIUS_SERVICE_TYPE_CALL_CHECK 10
+#define RADIUS_SERVICE_TYPE_CALLBACK ADMINISTRATIVE 11
+
 
 struct radius_attr_vendor {
 	u8 vendor_type;
@@ -172,6 +188,11 @@  struct radius_ms_mppe_keys {
 	size_t recv_len;
 };
 
+/* hostapd specific RADIUS Attributes */
+#define RADIUS_VENDOR_ID_HOSTAPD 39014
+enum {  RADIUS_VENDOR_ATTR_HAP_PSK = 1,
+        RADIUS_VENDOR_ATTR_HAP_PASSPHRASE = 2
+};
 
 struct radius_msg;
 
@@ -231,6 +252,7 @@  radius_msg_add_attr_user_password(struct radius_msg *msg,
 				  const u8 *secret, size_t secret_len);
 int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len);
 int radius_msg_get_vlanid(struct radius_msg *msg);
+int radius_msg_get_psk(struct radius_msg *msg, u8* psk, struct hostapd_ssid *ssid);
 
 static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type,
 					    u32 value)