From f1409ba595688d53d2882c129c336ceb035cc95e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 23 Oct 2007 10:54:37 +0000 Subject: [PATCH] 2007-10-23 Dan Williams * libnm-util/nm-utils.c libnm-util/nm-utils.h - (nm_utils_ap_security_compatible): common function for checking whether a specific AP is compatible with an NMConnection git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3001 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 7 ++ libnm-util/nm-utils.c | 170 ++++++++++++++++++++++++++++++++++++++++++ libnm-util/nm-utils.h | 8 ++ 3 files changed, 185 insertions(+) diff --git a/ChangeLog b/ChangeLog index 846534f2bb..e81215aefb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2007-10-23 Dan Williams + + * libnm-util/nm-utils.c + libnm-util/nm-utils.h + - (nm_utils_ap_security_compatible): common function for checking + whether a specific AP is compatible with an NMConnection + 2007-10-23 Dan Williams * libnm-util/nm-setting.c diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c index 8278009475..9a3474adb5 100644 --- a/libnm-util/nm-utils.c +++ b/libnm-util/nm-utils.c @@ -546,3 +546,173 @@ nm_utils_security_valid (NMUtilsSecurityType type, return good; } + +static gboolean +match_cipher (const char *cipher, + const char *expected, + guint32 wpa_flags, + guint32 rsn_flags, + guint32 flag) +{ + if (strcmp (cipher, expected) != 0) + return FALSE; + + if (!(wpa_flags & flag) && !(rsn_flags & flag)) + return FALSE; + + return TRUE; +} + +gboolean +nm_utils_ap_security_compatible (NMConnection *connection, + guint32 ap_flags, + guint32 ap_wpa, + guint32 ap_rsn, + guint32 ap_mode) +{ + NMSettingWireless *s_wireless; + NMSettingWirelessSecurity *s_wireless_sec; + + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_SETTING_WIRELESS); + if (!s_wireless) + return FALSE; + + if (!s_wireless->security) { + if ( (ap_flags & NM_802_11_AP_FLAGS_PRIVACY) + || (ap_wpa != NM_802_11_AP_SEC_NONE) + || (ap_rsn != NM_802_11_AP_SEC_NONE)) + return FALSE; + return TRUE; + } + + if (strcmp (s_wireless->security, NM_SETTING_WIRELESS_SECURITY) != 0) + return FALSE; + + s_wireless_sec = (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_SETTING_WIRELESS_SECURITY); + if (s_wireless_sec == NULL || !s_wireless_sec->key_mgmt) + return FALSE; + + /* Static WEP */ + if (!strcmp (s_wireless_sec->key_mgmt, "none")) { + if ( !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY) + || (ap_wpa != NM_802_11_AP_SEC_NONE) + || (ap_rsn != NM_802_11_AP_SEC_NONE)) + return FALSE; + return TRUE; + } + + /* Adhoc WPA */ + if (!strcmp (s_wireless_sec->key_mgmt, "wpa-none")) { + if (ap_mode != IW_MODE_ADHOC) + return FALSE; + // FIXME: validate ciphers if the BSSID actually puts WPA/RSN IE in + // it's beacon + return TRUE; + } + + /* Stuff after this point requires infrastructure */ + if (ap_mode != IW_MODE_INFRA) + return FALSE; + + /* Dynamic WEP or LEAP */ + if (!strcmp (s_wireless_sec->key_mgmt, "ieee8021x")) { + if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + return FALSE; + + /* If the AP is advertising a WPA IE, make sure it supports WEP ciphers */ + if (ap_wpa != NM_802_11_AP_SEC_NONE) { + gboolean found = FALSE; + GSList *iter; + + if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + + /* quick check; can't use AP if it doesn't support at least one + * WEP cipher in both pairwise and group suites. + */ + if ( !(ap_wpa & (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104)) + || !(ap_wpa & (NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104))) + return FALSE; + + /* Match at least one pairwise cipher with AP's capability */ + for (iter = s_wireless_sec->pairwise; iter; iter = g_slist_next (iter)) { + if ((found = match_cipher (iter->data, "wep40", ap_wpa, ap_wpa, NM_802_11_AP_SEC_PAIR_WEP40))) + break; + if ((found = match_cipher (iter->data, "wep104", ap_wpa, ap_wpa, NM_802_11_AP_SEC_PAIR_WEP104))) + break; + } + if (!found) + return FALSE; + + /* Match at least one group cipher with AP's capability */ + for (iter = s_wireless_sec->group; iter; iter = g_slist_next (iter)) { + if ((found = match_cipher (iter->data, "wep40", ap_wpa, ap_wpa, NM_802_11_AP_SEC_GROUP_WEP40))) + break; + if ((found = match_cipher (iter->data, "wep104", ap_wpa, ap_wpa, NM_802_11_AP_SEC_GROUP_WEP104))) + break; + } + if (!found) + return FALSE; + } + return TRUE; + } + + /* WPA[2]-PSK and WPA[2] Enterprise */ + if ( !strcmp (s_wireless_sec->key_mgmt, "wpa-psk") + || !strcmp (s_wireless_sec->key_mgmt, "wpa-eap")) { + GSList * elt; + gboolean found = FALSE; + + if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)) + return FALSE; + + if (!s_wireless_sec->pairwise || !s_wireless_sec->group) + return FALSE; + + if (!strcmp (s_wireless_sec->key_mgmt, "wpa-psk")) { + if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) + && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK)) + return FALSE; + } else if (!strcmp (s_wireless_sec->key_mgmt, "wpa-eap")) { + if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) + return FALSE; + } + + // FIXME: should handle WPA and RSN separately here to ensure that + // if the Connection only uses WPA we don't match a cipher against + // the AP's RSN IE instead + + /* Match at least one pairwise cipher with AP's capability */ + for (elt = s_wireless_sec->pairwise; elt; elt = g_slist_next (elt)) { + if ((found = match_cipher (elt->data, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_TKIP))) + break; + if ((found = match_cipher (elt->data, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_CCMP))) + break; + } + if (!found) + return FALSE; + + /* Match at least one group cipher with AP's capability */ + for (elt = s_wireless_sec->group; elt; elt = g_slist_next (elt)) { + if ((found = match_cipher (elt->data, "wep40", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP40))) + break; + if ((found = match_cipher (elt->data, "wep104", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP104))) + break; + if ((found = match_cipher (elt->data, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_TKIP))) + break; + if ((found = match_cipher (elt->data, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_CCMP))) + break; + } + if (!found) + return FALSE; + + return TRUE; + } + + return FALSE; +} + diff --git a/libnm-util/nm-utils.h b/libnm-util/nm-utils.h index 283af91985..831b36e170 100644 --- a/libnm-util/nm-utils.h +++ b/libnm-util/nm-utils.h @@ -27,6 +27,8 @@ #include #include +#include "nm-connection.h" + #define nm_print_backtrace() \ G_STMT_START \ { \ @@ -158,5 +160,11 @@ gboolean nm_utils_security_valid (NMUtilsSecurityType type, guint32 ap_wpa, guint32 ap_rsn); +gboolean nm_utils_ap_security_compatible (NMConnection *connection, + guint32 ap_flags, + guint32 ap_wpa, + guint32 ap_rsn, + guint32 ap_mode); + #endif /* NM_UTILS_H */