2014-09-30 14:27 GMT+04:00 Stefan Sperling <s...@openbsd.org>:
> On Tue, Sep 30, 2014 at 11:59:25AM +0200, Martin Pieuchot wrote:
>> Hey Vadim, I'm happy to see you've put some efforts into improving
>> how wireless networks are configured on OpenBSD.  I have some questions
>> below.
>>
>> On 26/09/14(Fri) 21:38, Vadim Zhukov wrote:
>> >
>> > This is a proof-of-concept patch that implements network "profiles"
>> > in kernel, using IEEE 802.11 network name and/or BSSID.
>>
>> Why did you choose to put this in the kernel, did you encounter any
>> technical problem, or was it easier/better that way?
>
> Note also that there is an existing 'autoassoc' behaviour.
> The net80211 stack will try to automatically associate with
> an open wireless network as soon as the interface is brought up.
> I think it would make sense to try to keep this behaviour for
> encrypted networks for which the key has been pre-loaded into
> kernel memory somehow. The primary focus of the kernel should be
> on trying to get link on an interface, like it does with open wifi.

Yes, I've seen that behaviour. And it actually bothers me - what if I
get associated with untrusted network, and my already opened
Ajax-enabled browser will start to transfer data via it without
notification?.. This can be avoided by forcing some unlikely nwid in
hostname.if, but this is not "secure by default". Or maybe I search
for security in the wrong place, dunno...

> Below is a diff I once wrote which caches network keys in the kernel.
> It's not perfect either because it still requires users to enter the
> nwid they want to associate with if a network is encrypted. In other words,
> it doesn't require users to enter a wep/wpa key more than once while the
> system is accumulating uptime. But there is no automatic association
> with an encrypted network found during a scan, and no integration with
> userland via routing sockets (an idea which I like a lot because it
> opens up the possibility for desktop integration and other nice things).

I'll look at it in the evening, thanks!

> Index: ieee80211_crypto.c
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_crypto.c,v
> retrieving revision 1.60
> diff -u -p -r1.60 ieee80211_crypto.c
> --- ieee80211_crypto.c  11 Jan 2011 15:42:05 -0000      1.60
> +++ ieee80211_crypto.c  21 Aug 2013 14:17:25 -0000
> @@ -65,6 +65,7 @@ ieee80211_crypto_attach(struct ifnet *if
>         struct ieee80211com *ic = (void *)ifp;
>
>         TAILQ_INIT(&ic->ic_pmksa);
> +       TAILQ_INIT(&ic->ic_pws);
>         if (ic->ic_caps & IEEE80211_C_RSN) {
>                 ic->ic_rsnprotos = IEEE80211_PROTO_WPA | IEEE80211_PROTO_RSN;
>                 ic->ic_rsnakms = IEEE80211_AKM_PSK;
> @@ -91,6 +92,8 @@ ieee80211_crypto_detach(struct ifnet *if
>                 free(pmk, M_DEVBUF);
>         }
>
> +       ieee80211_passwd_remove_all(ic);
> +
>         /* clear all group keys from memory */
>         for (i = 0; i < IEEE80211_GROUP_NKID; i++) {
>                 struct ieee80211_key *k = &ic->ic_nw_keys[i];
> @@ -648,4 +651,159 @@ ieee80211_pmksa_find(struct ieee80211com
>                         break;
>         }
>         return pmk;
> +}
> +
> +#define IEEE80211_PW_CACHE_SIZE 16
> +
> +#define IEEE80211_PW_DEBUG
> +
> +/*
> + * Cache a WPA PSK for the current desired ESSID.
> + * If PSK is NULL, clear the cached PSK.
> + */
> +struct ieee80211_passwd *
> +ieee80211_passwd_psk(struct ieee80211com *ic, u_int8_t *psk)
> +{
> +       struct ieee80211_passwd *pw;
> +#ifdef IEEE80211_PW_DEBUG
> +       char essid[IEEE80211_NWID_LEN + 1];
> +#endif
> +
> +       if (ic->ic_npws >= IEEE80211_PW_CACHE_SIZE) {
> +               /* TODO expire least recently used entry instead of return */
> +               return NULL;
> +       }
> +
> +       if (ic->ic_des_esslen == 0)
> +               return NULL;
> +
> +#ifdef IEEE80211_PW_DEBUG
> +       memcpy(essid, pw->pw_nwid, IEEE80211_NWID_LEN);
> +       essid[IEEE80211_NWID_LEN] = '\0';
> +#endif
> +
> +       pw = ieee80211_passwd_find(ic);
> +       if (pw == NULL) {
> +               if (psk == NULL)
> +                       return NULL;
> +#ifdef IEEE80211_PW_DEBUG
> +               printf("%s: new wpa psk for %s\n", __func__, essid);
> +#endif
> +               pw = malloc(sizeof(*pw), M_DEVBUF, M_ZERO|M_NOWAIT);
> +               if (pw == NULL)
> +                       return NULL;
> +               memcpy(pw->pw_nwid, ic->ic_des_essid, IEEE80211_NWID_LEN);
> +               TAILQ_INSERT_TAIL(&ic->ic_pws, pw, pw_next);
> +               ic->ic_npws++;
> +       }
> +#ifdef IEEE80211_PW_DEBUG
> +       else
> +               printf("%s: changing wpa psk for %s\n", __func__, essid);
> +#endif
> +
> +       if (psk) {
> +               memcpy(pw->pw_psk, psk, IEEE80211_PMK_LEN);
> +               pw->pw_flags |= IEEE80211_PASSWD_HAVE_PSK;
> +       } else if (pw->pw_flags & IEEE80211_PASSWD_HAVE_PSK) {
> +               explicit_bzero(pw->pw_psk, IEEE80211_PMK_LEN);
> +               pw->pw_flags &= ~IEEE80211_PASSWD_HAVE_PSK;
> +       }
> +
> +       return pw;
> +}
> +
> +/*
> + * Cache WEP keys for the current desired ESSID.
> + * Clear cached keys if KEYS is NULL.
> + */
> +struct ieee80211_passwd *
> +ieee80211_passwd_wep(struct ieee80211com *ic, struct ieee80211_key *keys,
> +    int def_txkey)
> +{
> +       struct ieee80211_passwd *pw;
> +#ifdef IEEE80211_PW_DEBUG
> +       char essid[IEEE80211_NWID_LEN + 1];
> +#endif
> +       int i;
> +
> +       if (ic->ic_npws >= IEEE80211_PW_CACHE_SIZE) {
> +               /* TODO expire least recently used entry instead of return */
> +               return NULL;
> +       }
> +
> +       if (ic->ic_des_esslen == 0)
> +               return NULL;
> +
> +#ifdef IEEE80211_PW_DEBUG
> +       memcpy(essid, pw->pw_nwid, IEEE80211_NWID_LEN);
> +       essid[IEEE80211_NWID_LEN] = '\0';
> +#endif
> +
> +       pw = ieee80211_passwd_find(ic);
> +       if (pw == NULL) {
> +               if (keys == NULL)
> +                       return NULL;
> +#ifdef IEEE80211_PW_DEBUG
> +               printf("%s: new wep keys for %s\n", __func__, essid);
> +#endif
> +               pw = malloc(sizeof(*pw), M_DEVBUF, M_ZERO|M_NOWAIT);
> +               if (pw == NULL)
> +                       return NULL;
> +               memcpy(pw->pw_nwid, ic->ic_des_essid, IEEE80211_NWID_LEN);
> +               TAILQ_INSERT_TAIL(&ic->ic_pws, pw, pw_next);
> +               ic->ic_npws++;
> +       }
> +#ifdef IEEE80211_PW_DEBUG
> +       else
> +               printf("%s: changing wep keys for %s\n", __func__, essid);
> +#endif
> +
> +       if (keys) {
> +               for (i = 0; i < IEEE80211_WEP_NKID; i++)
> +                       memcpy(&pw->pw_nw_keys[i], &keys[i],
> +                           sizeof(struct ieee80211_key));
> +               pw->pw_def_txkey = def_txkey;
> +               pw->pw_flags |= IEEE80211_PASSWD_HAVE_NWKEYS;
> +       } else if (pw->pw_flags & IEEE80211_PASSWD_HAVE_NWKEYS) {
> +               for (i = 0; i < IEEE80211_WEP_NKID; i++)
> +                       explicit_bzero(&pw->pw_nw_keys[i],
> +                           sizeof(struct ieee80211_key));
> +               pw->pw_flags &= ~IEEE80211_PASSWD_HAVE_NWKEYS;
> +       }
> +
> +       return pw;
> +}
> +
> +/* Find a WEP/WPA password cache entry for desired ESSID of IC. */
> +struct ieee80211_passwd *
> +ieee80211_passwd_find(struct ieee80211com *ic)
> +{
> +       struct ieee80211_passwd *pw;
> +
> +       if (ic->ic_npws == 0 || ic->ic_des_esslen == 0)
> +               return NULL;
> +
> +       TAILQ_FOREACH(pw, &ic->ic_pws, pw_next) {
> +               if (memcmp(pw->pw_nwid, ic->ic_des_essid,
> +                       IEEE80211_NWID_LEN) == 0)
> +                       break;
> +       }
> +
> +       return pw;
> +}
> +
> +/*
> + * Purge the WEP/WPA password cache.
> + */
> +void
> +ieee80211_passwd_remove_all(struct ieee80211com *ic)
> +{
> +       struct ieee80211_passwd *pw;
> +
> +       while ((pw = TAILQ_FIRST(&ic->ic_pws)) != NULL) {
> +               TAILQ_REMOVE(&ic->ic_pws, pw, pw_next);
> +               explicit_bzero(pw, sizeof(*pw));
> +               free(pw, M_DEVBUF);
> +               ic->ic_npws--;
> +       }
>  }
> Index: ieee80211_crypto.h
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_crypto.h,v
> retrieving revision 1.22
> diff -u -p -r1.22 ieee80211_crypto.h
> --- ieee80211_crypto.h  26 Jan 2009 19:09:41 -0000      1.22
> +++ ieee80211_crypto.h  21 Aug 2013 14:13:56 -0000
> @@ -178,4 +178,11 @@ struct     mbuf *ieee80211_bip_encap(struct
>  struct mbuf *ieee80211_bip_decap(struct ieee80211com *, struct mbuf *,
>             struct ieee80211_key *);
>
> +struct ieee80211_passwd *ieee80211_passwd_psk(struct ieee80211com *,
> +            u_int8_t *);
> +struct ieee80211_passwd *ieee80211_passwd_wep(struct ieee80211com *,
> +            struct ieee80211_key *, int);
> +struct ieee80211_passwd *ieee80211_passwd_find(struct ieee80211com *);
> +void   ieee80211_passwd_remove_all(struct ieee80211com *);
> +
>  #endif /* _NET80211_IEEE80211_CRYPTO_H_ */
> Index: ieee80211_ioctl.c
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_ioctl.c,v
> retrieving revision 1.34
> diff -u -p -r1.34 ieee80211_ioctl.c
> --- ieee80211_ioctl.c   29 Sep 2010 20:00:51 -0000      1.34
> +++ ieee80211_ioctl.c   21 Aug 2013 14:16:12 -0000
> @@ -176,6 +176,8 @@ ieee80211_ioctl_setnwkeys(struct ieee802
>         ic->ic_def_txkey = nwkey->i_defkid - 1;
>         ic->ic_flags |= IEEE80211_F_WEPON;
>
> +       ieee80211_passwd_wep(ic, ic->ic_nw_keys, ic->ic_def_txkey);
> +
>         return ENETRESET;
>  }
>
> @@ -330,6 +332,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_lon
>         int i, error = 0;
>         struct ieee80211_nwid nwid;
>         struct ieee80211_wpapsk *psk;
> +       struct ieee80211_passwd *pw;
>         struct ieee80211_wmmparams *wmm;
>         struct ieee80211_keyavail *ka;
>         struct ieee80211_keyrun *kr;
> @@ -363,6 +366,26 @@ ieee80211_ioctl(struct ifnet *ifp, u_lon
>                 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
>                 ic->ic_des_esslen = nwid.i_len;
>                 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);
> +               pw = ieee80211_passwd_find(ic);
> +               if (pw && (pw->pw_flags & IEEE80211_PASSWD_HAVE_PSK)) {
> +                       memcpy(ic->ic_psk, pw->pw_psk, sizeof(ic->ic_psk));
> +                       ic->ic_flags |= IEEE80211_F_PSK;
> +               }
> +               if (pw && (pw->pw_flags & IEEE80211_PASSWD_HAVE_NWKEYS)) {
> +                       struct ieee80211_key *k;
> +
> +                       for (i = 0; i < IEEE80211_WEP_NKID; i++) {
> +                               k = &ic->ic_nw_keys[i];
> +                               if (k->k_cipher != IEEE80211_CIPHER_NONE)
> +                                       (*ic->ic_delete_key)(ic, NULL, k);
> +                               memcpy(k, &pw->pw_nw_keys[i], sizeof(*k));
> +                               error = (*ic->ic_set_key)(ic, NULL, k);
> +                               if (error != 0)
> +                                       return error;
> +                       }
> +                       ic->ic_def_txkey = pw->pw_def_txkey;
> +                       ic->ic_flags |= IEEE80211_F_WEPON;
> +               }
>                 error = ENETRESET;
>                 break;
>         case SIOCG80211NWID:
> @@ -421,6 +444,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_lon
>                 if (psk->i_enabled) {
>                         ic->ic_flags |= IEEE80211_F_PSK;
>                         memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk));
> +                       ieee80211_passwd_psk(ic, ic->ic_psk);
>                 } else {
>                         ic->ic_flags &= ~IEEE80211_F_PSK;
>                         memset(ic->ic_psk, 0, sizeof(ic->ic_psk));
> Index: ieee80211_proto.c
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_proto.c,v
> retrieving revision 1.46
> diff -u -p -r1.46 ieee80211_proto.c
> --- ieee80211_proto.c   18 Jan 2012 14:35:56 -0000      1.46
> +++ ieee80211_proto.c   21 Aug 2013 10:26:58 -0000
> @@ -804,6 +804,8 @@ ieee80211_newstate(struct ieee80211com *
>                                 RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
>                                         if (ni->ni_associd == 0)
>                                                 continue;
> +                                       printf("%s: sending assoc_leave to 
> node %s\n",
> +                                           __func__, 
> ether_sprintf(ni->ni_macaddr));
>                                         IEEE80211_SEND_MGMT(ic, ni,
>                                             IEEE80211_FC0_SUBTYPE_DISASSOC,
>                                             IEEE80211_REASON_ASSOC_LEAVE);
> @@ -828,6 +830,8 @@ ieee80211_newstate(struct ieee80211com *
>                         case IEEE80211_M_HOSTAP:
>                                 s = splnet();
>                                 RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
> +                                       printf("%s: sending auth_leave to 
> node %s\n",
> +                                           __func__, 
> ether_sprintf(ni->ni_macaddr));
>                                         IEEE80211_SEND_MGMT(ic, ni,
>                                             IEEE80211_FC0_SUBTYPE_DEAUTH,
>                                             IEEE80211_REASON_AUTH_LEAVE);
> Index: ieee80211_var.h
> ===================================================================
> RCS file: /cvs/src/sys/net80211/ieee80211_var.h,v
> retrieving revision 1.62
> diff -u -p -r1.62 ieee80211_var.h
> --- ieee80211_var.h     21 Jan 2012 19:42:16 -0000      1.62
> +++ ieee80211_var.h     21 Aug 2013 13:57:55 -0000
> @@ -190,6 +190,21 @@ struct ieee80211_defrag {
>
>  #define IEEE80211_GROUP_NKID   6
>
> +/*
> + * Entry in the WEP/WPA password cache.
> + */
> +struct ieee80211_passwd {
> +       u_int8_t                pw_nwid[IEEE80211_NWID_LEN];
> +       u_int8_t                pw_psk[IEEE80211_PMK_LEN];
> +       struct ieee80211_key    pw_nw_keys[IEEE80211_WEP_NKID];
> +       int                     pw_def_txkey;
> +       u_int8_t                pw_flags;
> +#define        IEEE80211_PASSWD_HAVE_PSK       0x01
> +#define        IEEE80211_PASSWD_HAVE_NWKEYS    0x02
> +
> +       TAILQ_ENTRY(ieee80211_passwd) pw_next;
> +};
> +
>  struct ieee80211com {
>         struct arpcom           ic_ac;
>         LIST_ENTRY(ieee80211com) ic_list;       /* chain of all ieee80211com 
> */
> @@ -321,6 +336,8 @@ struct ieee80211com {
>         u_int8_t                ic_dialog_token;
>
>         LIST_HEAD(, ieee80211_vap) ic_vaps;
> +       TAILQ_HEAD(, ieee80211_passwd) ic_pws;
> +       int                     ic_npws;
>  };
>  #define        ic_if           ic_ac.ac_if
>  #define        ic_softc        ic_if.if_softc
>

--
  WBR,
  Vadim Zhukov

Reply via email to