summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorenricop <enricop@computer.org>2012-05-14 15:11:16 -0500
committerenricop <enricop@computer.org>2012-05-14 15:11:16 -0500
commitc1976b8365310f23085adaa53cf00b14039014c8 (patch)
tree0b6b535665ab882850a3631184e62f26025b3629 /usr/src
parent506ea5b80cb420d5edeb6aff19fe035c0a283bb3 (diff)
downloadillumos-gate-c1976b8365310f23085adaa53cf00b14039014c8.tar.gz
405 Can't connect to similarly-named, encrypted wireless networks.
Reviewed by: Milan Jurik <milan.jurik@xylab.cz> Reviewed by: Albert Lee <trisk@nexenta.com> Approved by: Gordon Ross <gwr@nexenta.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/cmd-inet/lib/nwamd/door_if.c3
-rw-r--r--usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c26
-rw-r--r--usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c175
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c2
4 files changed, 118 insertions, 88 deletions
diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c b/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c
index 5ac3cf4fcb..6f3c76b478 100644
--- a/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c
@@ -237,7 +237,8 @@ nwamd_door_req_wlan_set_key(nwamd_door_arg_t *req, ucred_t *ucr,
req->nwda_data.nwdad_wlan_info.nwdad_bssid);
return (nwamd_wlan_set_key
(req->nwda_data.nwdad_wlan_info.nwdad_name,
- req->nwda_data.nwdad_wlan_info.nwdad_essid, NULL,
+ req->nwda_data.nwdad_wlan_info.nwdad_essid,
+ req->nwda_data.nwdad_wlan_info.nwdad_bssid,
req->nwda_data.nwdad_wlan_info.nwdad_security_mode,
req->nwda_data.nwdad_wlan_info.nwdad_keyslot,
req->nwda_data.nwdad_wlan_info.nwdad_key));
diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c b/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c
index 80531aa5cb..adc6020bdb 100644
--- a/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c
@@ -463,32 +463,6 @@ known_wlan_get_keyname(const char *essid, char *name)
return (err);
}
-nwam_error_t
-known_wlan_get_keyslot(const char *essid, uint_t *keyslotp)
-{
- nwam_known_wlan_handle_t kwh = NULL;
- nwam_value_t keyslotval = NULL;
- uint64_t slot;
- nwam_error_t err;
-
- if ((err = nwam_known_wlan_read(essid, 0, &kwh)) != NWAM_SUCCESS)
- return (err);
- if ((err = nwam_known_wlan_get_prop_value(kwh,
- NWAM_KNOWN_WLAN_PROP_KEYSLOT, &keyslotval)) == NWAM_SUCCESS &&
- (err = nwam_value_get_uint64(keyslotval, &slot)) == NWAM_SUCCESS) {
- *keyslotp = (uint_t)slot;
- } else {
- if (err == NWAM_ENTITY_NOT_FOUND)
- err = NWAM_SUCCESS;
- *keyslotp = 1;
- }
- if (keyslotval != NULL)
- nwam_value_free(keyslotval);
- if (kwh != NULL)
- nwam_known_wlan_free(kwh);
- return (err);
-}
-
/* Performs a scan on a wifi link NCU */
/* ARGSUSED */
static int
diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c b/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c
index a5dc0fb9dd..ae1a6d979c 100644
--- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c
+++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c
@@ -351,6 +351,44 @@ key_string_to_secobj_value(char *buf, uint8_t *obj_val, uint_t *obj_lenp,
}
/*
+ * Callback used on each known WLAN:
+ * return 1 if a secobj, linked with an existing kwown wlan, has the same name
+ * of the secobj that is being created.
+ */
+
+static int
+find_keyname_cb(nwam_known_wlan_handle_t kwh, void *new_keyname)
+{
+ nwam_error_t err;
+ nwam_value_t old_key;
+
+ char **old_keyname;
+ uint_t num_old_keyname, i;
+
+ if ((err = nwam_known_wlan_get_prop_value(kwh,
+ NWAM_KNOWN_WLAN_PROP_KEYNAME, &old_key)) != NWAM_SUCCESS) {
+ nlog(LOG_ERR, "find_keyname_cb: nwam_known_wlan_get_prop: %s",
+ nwam_strerror(err));
+ return (0);
+ }
+ if ((err = nwam_value_get_string_array(old_key, &old_keyname,
+ &num_old_keyname))
+ != NWAM_SUCCESS) {
+ nlog(LOG_ERR, "find_keyname_cb: nwam_value_get_string: %s",
+ nwam_strerror(err));
+ nwam_value_free(old_key);
+ return (0);
+ }
+ nwam_value_free(old_key);
+ for (i = 0; i < num_old_keyname; i++) {
+ if (strcmp(old_keyname[i], (const char *)new_keyname) == 0)
+ /* Found matching keyname so terminate walk */
+ return (1);
+ }
+ return (0);
+}
+
+/*
* Print the key name format into the appropriate field, then convert any ":"
* characters to ".", as ":[1-4]" is the slot indicator, which otherwise
* would trip us up. Invalid characters for secobj names are ignored.
@@ -403,9 +441,11 @@ nwamd_wlan_set_key(const char *linkname, const char *essid, const char *bssid,
nwamd_object_t ncu_obj;
nwamd_ncu_t *ncu;
nwamd_link_t *link;
+ int ret = 0;
uint8_t obj_val[DLADM_SECOBJ_VAL_MAX];
uint_t obj_len = sizeof (obj_val);
char obj_name[DLADM_SECOBJ_NAME_MAX];
+ char obj_tempname[DLADM_SECOBJ_NAME_MAX];
dladm_status_t status;
char errmsg[DLADM_STRSIZE];
dladm_secobj_class_t class;
@@ -419,14 +459,6 @@ nwamd_wlan_set_key(const char *linkname, const char *essid, const char *bssid,
ncu = ncu_obj->nwamd_object_data;
link = &ncu->ncu_link;
- nlog(LOG_DEBUG, "nwamd_wlan_set_key: running for link %s", linkname);
- /*
- * Name key object for this WLAN so it can be later retrieved
- * (name is unique for each ESSID/BSSID combination).
- */
- nwamd_set_key_name(essid, bssid, obj_name, sizeof (obj_name));
- nlog(LOG_DEBUG, "store_key: obj_name is %s", obj_name);
-
class = (security_mode == DLADM_WLAN_SECMODE_WEP ?
DLADM_SECOBJ_CLASS_WEP : DLADM_SECOBJ_CLASS_WPA);
if (key_string_to_secobj_value(raw_key, obj_val, &obj_len,
@@ -436,7 +468,38 @@ nwamd_wlan_set_key(const char *linkname, const char *essid, const char *bssid,
return (NWAM_ERROR_INTERNAL);
}
- /* we've validated the new key, so remove the old one */
+ nlog(LOG_DEBUG, "nwamd_wlan_set_key: running for link %s", linkname);
+ /*
+ * Name key object for this WLAN so it can be later retrieved.
+ * (bssid is appended if an object, with the same keyname,
+ * already exists and is associated to a known wlan)
+ */
+ nwamd_set_key_name(essid, NULL, obj_tempname, sizeof (obj_tempname));
+ (void) nwam_walk_known_wlans(find_keyname_cb, obj_tempname, 0, &ret);
+ /*
+ * We also check if the keyval is the same. The user might want
+ * to use the same key for more APs with the same ESSID.
+ * This can result in a known wlan with multiple BSSIDs
+ */
+ if (ret == 1) {
+ dladm_wlan_key_t *old_secobj = nwamd_wlan_get_key_named(
+ obj_tempname, security_mode);
+ nlog(LOG_DEBUG, "found existing obj_name %s", obj_tempname);
+ ret = memcmp((*old_secobj).wk_val, obj_val, obj_len);
+ nwamd_set_key_name(essid, ret ? bssid : NULL, obj_name,
+ sizeof (obj_name));
+ free(old_secobj);
+ } else {
+ nwamd_set_key_name(essid, NULL, obj_name,
+ sizeof (obj_name));
+ }
+ nlog(LOG_DEBUG, "store_key: obj_name is %s", obj_name);
+
+ /*
+ * We have validated the new key, so remove the old one.
+ * This will actually delete the keyobj only if the user had set
+ * a wrong key and is replacing it with a new one for the same AP.
+ */
status = dladm_unset_secobj(dld_handle, obj_name,
DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
if (status != DLADM_STATUS_OK && status != DLADM_STATUS_NOTFOUND) {
@@ -755,8 +818,7 @@ nwamd_wlan_select(const char *linkname, const char *essid, const char *bssid,
nwamd_object_t ncu_obj;
nwamd_ncu_t *ncu;
nwamd_link_t *link;
- char key[DLADM_STRSIZE];
- boolean_t found_old_key = B_FALSE, found_key = B_FALSE;
+ boolean_t found_key = B_FALSE;
if ((ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, linkname))
== NULL) {
@@ -799,55 +861,34 @@ nwamd_wlan_select(const char *linkname, const char *essid, const char *bssid,
/* does this WLAN require a key? If so go to NEED_KEY */
if (NEED_ENC(link->nwamd_link_wifi_security_mode)) {
/*
- * First, if a key name may have been specified for a
- * known WLAN. If so, use it. Otherwise, try both the
- * new nwamd key name format (ESSID) and old (ESSID/BSSID).
- * The user may have set the key without adding a known WLAN,
- * so we need to try all these options to save going to
- * NEED_KEY state.
+ * nwam secobjs can have two formats: nwam-ESSID-BSSID and
+ * nwam-ESSID. There is no reason for searching through known
+ * wlan keynames since this is only the selection process.
*/
- if (known_wlan_get_keyname(link->nwamd_link_wifi_essid,
- link->nwamd_link_wifi_keyname) == NWAM_SUCCESS &&
- (link->nwamd_link_wifi_key = nwamd_wlan_get_key_named
- (link->nwamd_link_wifi_keyname,
- link->nwamd_link_wifi_security_mode)) != NULL) {
- (void) known_wlan_get_keyslot
- (link->nwamd_link_wifi_essid,
- &link->nwamd_link_wifi_key->wk_idx);
- nlog(LOG_DEBUG, "nwamd_wlan_select: got known WLAN "
- "key %s, slot %d", link->nwamd_link_wifi_keyname,
- link->nwamd_link_wifi_key->wk_idx);
- found_key = B_TRUE;
- } else if ((link->nwamd_link_wifi_key = nwamd_wlan_get_key
- (link->nwamd_link_wifi_essid, NULL,
+ if ((link->nwamd_link_wifi_key = nwamd_wlan_get_key
+ (link->nwamd_link_wifi_essid, link->nwamd_link_wifi_bssid,
link->nwamd_link_wifi_security_mode)) != NULL) {
- nwamd_set_key_name(link->nwamd_link_wifi_essid, NULL,
+ /*
+ * Found old key format,
+ * known wlans with similar names might exist
+ */
+ nwamd_set_key_name(link->nwamd_link_wifi_essid,
+ link->nwamd_link_wifi_bssid,
link->nwamd_link_wifi_keyname,
DLADM_SECOBJ_NAME_MAX);
- nlog(LOG_DEBUG, "nwamd_wlan_select: got WLAN key %s",
+ nlog(LOG_DEBUG, "nwamd_wlan_select: got old format "
+ "WLAN key %s",
link->nwamd_link_wifi_keyname);
found_key = B_TRUE;
} else if ((link->nwamd_link_wifi_key = nwamd_wlan_get_key
- (link->nwamd_link_wifi_essid, link->nwamd_link_wifi_bssid,
+ (link->nwamd_link_wifi_essid, NULL,
link->nwamd_link_wifi_security_mode)) != NULL) {
- /*
- * Found old key format - prepare to save
- * it as new ESSID-only key, but don't
- * do it until we're released the object
- * lock (since nwamd_wlan_set_key()
- * takes the object lock).
- */
- (void) strlcpy(key,
- (char *)link->nwamd_link_wifi_key->wk_val,
- link->nwamd_link_wifi_key->wk_len + 1);
- found_old_key = B_TRUE;
- found_key = B_TRUE;
nwamd_set_key_name(link->nwamd_link_wifi_essid, NULL,
link->nwamd_link_wifi_keyname,
DLADM_SECOBJ_NAME_MAX);
- nlog(LOG_DEBUG, "nwamd_wlan_select: got old format "
- "WLAN key, converting to %s",
+ nlog(LOG_DEBUG, "nwamd_wlan_select: got WLAN key %s",
link->nwamd_link_wifi_keyname);
+ found_key = B_TRUE;
} else {
nlog(LOG_ERR, "nwamd_wlan_select: could not "
"find key for WLAN '%s'",
@@ -871,10 +912,6 @@ nwamd_wlan_select(const char *linkname, const char *essid, const char *bssid,
}
nwamd_object_release(ncu_obj);
- if (found_old_key) {
- (void) nwamd_wlan_set_key(linkname, essid, NULL, security_mode,
- 1, key);
- }
return (NWAM_SUCCESS);
}
@@ -882,28 +919,28 @@ nwamd_wlan_select(const char *linkname, const char *essid, const char *bssid,
* See if BSSID is in visited list of BSSIDs for known WLAN. Used for
* strict BSSID matching (depends on wireless_strict_bssid property value).
*/
-static boolean_t
-bssid_match(nwam_known_wlan_handle_t kwh, const char *bssid)
+static int
+bssid_match(nwam_known_wlan_handle_t kwh, void *bssid)
{
nwam_value_t bssidsval;
nwam_error_t err;
char **bssids;
uint_t nelem, i;
- boolean_t found = B_FALSE;
+ int found = 0;
if ((err = nwam_known_wlan_get_prop_value(kwh,
NWAM_KNOWN_WLAN_PROP_BSSIDS, &bssidsval)) != NWAM_SUCCESS) {
nlog(LOG_ERR, "bssid_match: %s", nwam_strerror(err));
- return (B_FALSE);
+ return (0);
}
if ((err = nwam_value_get_string_array(bssidsval, &bssids, &nelem))
!= NWAM_SUCCESS) {
nwam_value_free(bssidsval);
- return (B_FALSE);
+ return (0);
}
for (i = 0; i < nelem; i++) {
- if (strcmp(bssid, bssids[i]) == 0) {
- found = B_TRUE;
+ if (strcmp((const char *)bssid, bssids[i]) == 0) {
+ found = 1;
break;
}
}
@@ -951,7 +988,7 @@ find_best_wlan_cb(nwam_known_wlan_handle_t kwh, void *data)
for (i = 0; i < s->nwamd_wifi_scan_curr_num; i++) {
nwam_wlan_t *cur_wlan = &(s->nwamd_wifi_scan_curr[i]);
- boolean_t b_match = bssid_match(kwh, cur_wlan->nww_bssid);
+ int b_match = bssid_match(kwh, cur_wlan->nww_bssid);
/*
* We need to either match the scanned essid, or in the case
@@ -1332,6 +1369,22 @@ wlan_scan_thread(void *arg)
char keyname[NWAM_MAX_VALUE_LEN];
dladm_wlan_key_t *key = NULL;
+ /*
+ * If strict_bssid is true, we start checking for
+ * known wlans with the same BSSID.
+ * This would prevent the selection of secobjs
+ * that actually are referenced by different kwl
+ * with the same ESSID.
+ */
+ if (wireless_strict_bssid) {
+ int b_match = 0;
+ (void) nwam_walk_known_wlans(bssid_match,
+ s.nwamd_wifi_scan_curr[i].nww_bssid, 0,
+ &b_match);
+ if (b_match == 0)
+ continue;
+ }
+
if (known_wlan_get_keyname
(s.nwamd_wifi_scan_curr[i].nww_essid, keyname)
== NWAM_SUCCESS &&
@@ -1345,6 +1398,8 @@ wlan_scan_thread(void *arg)
nww_security_mode ==
DLADM_WLAN_SECMODE_WEP ?
key->wk_idx : 1;
+ nlog(LOG_DEBUG, "found matching keyname for \
+ %s", s.nwamd_wifi_scan_curr[i].nww_bssid);
free(key);
}
}
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c b/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c
index a262c4e178..2489c678d8 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c
@@ -1364,7 +1364,7 @@ select_wifi_func(int argc, char *argv[])
}
}
- err = nwam_wlan_set_key(linkname, essid, NULL, security_mode,
+ err = nwam_wlan_set_key(linkname, essid, bssid, security_mode,
keyslot, key);
if (err != NWAM_SUCCESS)
die_nwamerr(err, "could not set WiFi key");