Hi,

you can set various keys/passphrases using ifconfig(8), e.g. WPA key:

    # ifconfig iwn0 wpakey 'hunter2'

The problem with that is that any local user can scan the process table
and see this password. Here's a retarded shell script which continously
scans the output of ps and prints out all ifconfig invocations and can
be used to peek on keys:

    #!/bin/sh
    last_pid=""
    while true; do
            pid=$(pgrep -u 0 ifconfig)
            if [ "$pid" ] && [ "$pid" != "$last_pid" ]; then
                    ps -p $pid
                    last_pid="$pid"
            fi
    done

I don't think this is a major issue since I doubt there are any OBSD
machines out there which would have all the neccessary conditions for
this to be a problem. But it makes me uncomfortable that I can't
prevent this information leaking from happening even if I wanted to.


I would change ifconfig(8) so that you can interactively enter the key
similarily how you can do that with passwd(1).


What the diff does:
If the key is not supplied on command line, use readpassphrase(3) to
read it from tty/stdin. Echo is turned on because some keys can be very
long and highly error-prone (wpa hexkey). After we're done, bzero the
key as it is recommended in readpassphrase(3) manpage.


Tested only wpakey, only on i386.


Further ideas:
* Maybe depracate and disable the ability to pass the key on the
command line at all?
* The resulting awkwardness of 'nwkey persist' (i.e. you can type

    # ifconfig iwn0 nwkey
    enter the key:

it asks you for a key but you can enter 'persist' and it'll be the same
as typing

    # ifconfig iwn nwkey persist
)
the awkwardness of this all is probably a hint that in case this diff
or some form of it goes in, the 'persist' should somehow be reworked,
maybe into it's own separate subcommand, e.g.:

    # ifconfig iwn0 nwkeypersist
    enter the key: 



Also, what other programs are there which allow to set some kind of a
key from command line? They should be fixed too.





Index: ifconfig.8
===================================================================
RCS file: /OpenBSD/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.219
diff -u -p -r1.219 ifconfig.8
--- ifconfig.8  9 Jul 2011 08:44:54 -0000       1.219
+++ ifconfig.8  5 Sep 2011 20:58:04 -0000
@@ -726,7 +726,7 @@ Start the bridge forwarding packets.
 .Op Cm carpnodes Ar vhid:advskew,vhid:advskew,...
 .Op Cm carpdev Ar iface
 .Op Oo Fl Oc Ns Cm carppeer Ar peer_address
-.Op Cm pass Ar passphrase
+.Op Cm pass Op Ar passphrase
 .Op Cm state Ar state
 .Op Cm vhid Ar host-id
 .Ek
@@ -780,9 +780,11 @@ with IPv4 multicast traffic.
 .It Fl carppeer
 Send the advertisements to the default carp multicast
 group.
-.It Cm pass Ar passphrase
+.It Cm pass Op Ar passphrase
 Set the authentication key to
 .Ar passphrase .
+If the passphrase is not supplied on the command line, user will be
+prompted to enter it on the standard input.
 There is no passphrase by default.
 .It Cm state Ar state
 Explicitly force the interface to enter this state.
@@ -820,7 +822,7 @@ will begin advertising as master.
 .Op Oo Fl Oc Ns Cm chan Op Ar n
 .Op Oo Fl Oc Ns Cm nwflag Ar flag
 .Op Oo Fl Oc Ns Cm nwid Ar id
-.Op Oo Fl Oc Ns Cm nwkey Ar key
+.Op Oo Fl Oc Ns Cm nwkey Op Ar key
 .Op Oo Fl Oc Ns Cm powersave Op Ar duration
 .Op Cm scan
 .Op Oo Fl Oc Ns Cm txpower Ar dBm
@@ -828,7 +830,7 @@ will begin advertising as master.
 .Op Cm wpaakms Ar akm,akm,...
 .Op Cm wpaciphers Ar cipher,cipher,...
 .Op Cm wpagroupcipher Ar cipher
-.Op Oo Fl Oc Ns Cm wpakey Ar passphrase | hexkey
+.Op Oo Fl Oc Ns Cm wpakey Op Ar passphrase | hexkey
 .Op Cm wpaprotos Ar proto,proto,...
 .Ek
 .nr nS 0
@@ -893,9 +895,11 @@ Note that network ID is synonymous with 
 .It Fl nwid
 Set the network ID to the empty string to allow the interface to connect
 to any available access point.
-.It Cm nwkey Ar key
+.It Cm nwkey Op Ar key
 Enable WEP encryption using the specified
 .Ar key .
+If the key is not supplied on the command line, user will be
+prompted to enter it on the standard input.
 The
 .Ar key
 can either be a string, a series of hexadecimal digits (preceded by
@@ -922,12 +926,17 @@ The length of each key must be either 40
 Disable WEP encryption.
 .It Cm nwkey Cm persist
 Enable WEP encryption using the persistent key stored in the network card.
-.It Cm nwkey Cm persist : Ns Ar key
+.It Cm nwkey Op Cm persist : Ns Ar key
 Write
 .Ar key
 to the persistent memory of the network card, and
 enable WEP encryption using that
 .Ar key .
+If the key is not supplied on the command line, user will be
+prompted to enter it on the standard input (the whole expression
+must be entered, e.g.
+.Dq Cm persist : Ns Ar key
+).
 .It Cm powersave Op Ar duration
 Enable 802.11 power saving mode.
 Optionally set the receiver sleep duration (in milliseconds).
@@ -1016,8 +1025,10 @@ The
 .Cm wpagroupcipher
 option is available in Host AP mode only.
 A station will always use the group cipher of the BSS.
-.It Cm wpakey Ar passphrase | hexkey
+.It Cm wpakey Op Ar passphrase | hexkey
 Set the WPA key and enable WPA.
+If the key is not supplied on the command line, user will be prompted
+to enter it on the standard input.
 The key can be given using either a passphrase or a full length hex key,
 starting with 0x.
 If a passphrase is used the
@@ -1244,11 +1255,11 @@ Broadcast the packets using multicast.
 .Bk -words
 .Nm ifconfig
 .Ar pppoe-interface
-.Op Cm authkey Ar key
+.Op Cm authkey Op Ar key
 .Op Cm authname Ar name
 .Op Cm authproto Ar proto
 .Op Oo Fl Oc Ns Cm peerflag Ar flag
-.Op Cm peerkey Ar key
+.Op Cm peerkey Op Ar key
 .Op Cm peername Ar name
 .Op Cm peerproto Ar proto
 .Op Oo Fl Oc Ns Cm pppoeac Ar access-concentrator
@@ -1288,11 +1299,11 @@ Clear a previously set service name.
 .Bk -words
 .Nm
 .Ar sppp-interface
-.Op Cm authkey Ar key
+.Op Cm authkey Op Ar key
 .Op Cm authname Ar name
 .Op Cm authproto Ar proto
 .Op Oo Fl Oc Ns Cm peerflag Ar flag
-.Op Cm peerkey Ar key
+.Op Cm peerkey Op Ar key
 .Op Cm peername Ar name
 .Op Cm peerproto Ar proto
 .Ek
@@ -1304,8 +1315,10 @@ or
 .Xr pppoe 4
 interface:
 .Bl -tag -width Ds
-.It Cm authkey Ar key
+.It Cm authkey Op Ar key
 Set the client key or password for the PPP authentication protocol.
+If the key is not supplied on the command line, user will be prompted to enter
+it on the standard input.
 .It Cm authname Ar name
 Set the client name for the PPP authentication protocol.
 .It Cm authproto Ar proto
@@ -1337,8 +1350,10 @@ This is used to work around broken peer 
 grok being re-challenged once the connection is up.
 .It Fl peerflag Ar flag
 Remove a specified PPP flag for the remote authenticator.
-.It Cm peerkey Ar key
+.It Cm peerkey Op Ar key
 Set the authenticator key or password for the PPP authentication protocol.
+If the key is not supplied on the command line, user will be prompted to
+enter it on the standard input.
 .It Cm peername Ar name
 Set the authenticator name for the PPP authentication protocol.
 .It Cm peerproto Ar proto
Index: ifconfig.c
===================================================================
RCS file: /OpenBSD/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.249
diff -u -p -r1.249 ifconfig.c
--- ifconfig.c  21 Aug 2011 06:28:31 -0000      1.249
+++ ifconfig.c  5 Sep 2011 20:58:05 -0000
@@ -101,6 +101,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <ifaddrs.h>
+#include <readpassphrase.h>
 
 #include "brconfig.h"
 #include "pbkdf2.h"
@@ -304,7 +305,7 @@ const struct        cmd {
        { "-nwid",      -1,             0,              setifnwid },
        { "bssid",      NEXTARG,        0,              setifbssid },
        { "-bssid",     -1,             0,              setifbssid },
-       { "nwkey",      NEXTARG,        0,              setifnwkey },
+       { "nwkey",      NEXTARG0,       A_SILENT,       setifnwkey },
        { "-nwkey",     -1,             0,              setifnwkey },
        { "wpa",        1,              0,              setifwpa },
        { "-wpa",       0,              0,              setifwpa },
@@ -312,7 +313,7 @@ const struct        cmd {
        { "wpaciphers", NEXTARG,        0,              setifwpaciphers },
        { "wpagroupcipher", NEXTARG,    0,              setifwpagroupcipher },
        { "wpaprotos",  NEXTARG,        0,              setifwpaprotos },
-       { "wpakey",     NEXTARG,        0,              setifwpakey },
+       { "wpakey",     NEXTARG0,       A_SILENT,       setifwpakey },
        { "-wpakey",    -1,             0,              setifwpakey },
        { "chan",       NEXTARG0,       0,              setifchan },
        { "-chan",      -1,             0,              setifchan },
@@ -352,7 +353,7 @@ const struct        cmd {
        { "advskew",    NEXTARG,        0,              setcarp_advskew },
        { "carppeer",   NEXTARG,        0,              setcarppeer },
        { "-carppeer",  1,              0,              unsetcarppeer },
-       { "pass",       NEXTARG,        0,              setcarp_passwd },
+       { "pass",       NEXTARG0,       A_SILENT,       setcarp_passwd },
        { "vhid",       NEXTARG,        0,              setcarp_vhid },
        { "vlanprio",   NEXTARG,        0,              setvlanprio },
        { "state",      NEXTARG,        0,              setcarp_state },
@@ -387,10 +388,10 @@ const struct      cmd {
        { "trunkproto", NEXTARG,        0,              settrunkproto },
        { "authproto",  NEXTARG,        0,              setspppproto },
        { "authname",   NEXTARG,        0,              setspppname },
-       { "authkey",    NEXTARG,        0,              setspppkey },
+       { "authkey",    NEXTARG0,       A_SILENT,       setspppkey },
        { "peerproto",  NEXTARG,        0,              setsppppeerproto },
        { "peername",   NEXTARG,        0,              setsppppeername },
-       { "peerkey",    NEXTARG,        0,              setsppppeerkey },
+       { "peerkey",    NEXTARG0,       A_SILENT,       setsppppeerkey },
        { "peerflag",   NEXTARG,        0,              setsppppeerflag },
        { "-peerflag",  NEXTARG,        0,              unsetsppppeerflag },
        { "nwflag",     NEXTARG,        0,              setifnwflag },
@@ -570,7 +571,6 @@ main(int argc, char *argv[])
        int gflag = 0;
 #endif
        int i;
-       int noprint = 0;
 
        /* If no args at all, print all interfaces.  */
        if (argc < 2) {
@@ -700,9 +700,10 @@ main(int argc, char *argv[])
                                } else
                                        noarg = 0;
 
-                               if (noarg == 0)
+                               if (noarg == 0) {
                                        (*p->c_func)(NULL, 0);
-                               else
+                                       actions = actions | p->c_action;
+                               } else
                                        goto nextarg;
                        } else if (p->c_parameter == NEXTARG) {
 nextarg:
@@ -729,7 +730,7 @@ nextarg:
                argc--, argv++;
        }
 
-       if (argc == 0 && actions == 0 && !noprint) {
+       if (argc == 0 && actions == 0) {
                printif(ifr.ifr_name, aflag ? ifaliases : 1);
                exit(0);
        }
@@ -1518,12 +1519,25 @@ setifbssid(const char *val, int d)
                warn("SIOCS80211BSSID");
 }
 
+char *
+read_key(char *buf, size_t bufsize)
+{
+       if (readpassphrase("enter the key: ",
+           buf, bufsize, RPP_ECHO_ON) == NULL)
+               err(1, "readpassphrase");
+       return buf;
+}
+
 void
 setifnwkey(const char *val, int d)
 {
        int i, len;
        struct ieee80211_nwkey nwkey;
        u_int8_t keybuf[IEEE80211_WEP_NKID][16];
+       char key[sizeof keybuf * 2 + sizeof "persist:0:,,,"];
+
+       if (val == NULL && d != -1)
+               val = read_key(key, sizeof key);
 
        bzero(&nwkey, sizeof(nwkey));
        bzero(&keybuf, sizeof(keybuf));
@@ -1561,13 +1575,18 @@ setifnwkey(const char *val, int d)
                        }
                        if (*val != '\0') {
                                warnx("SIOCS80211NWKEY: too many keys.");
+                               bzero(key, sizeof key);
+                               bzero(keybuf, sizeof keybuf);
                                return;
                        }
                } else {
                        len = sizeof(keybuf[0]);
                        val = get_string(val, NULL, keybuf[0], &len);
-                       if (val == NULL)
+                       if (val == NULL) {
+                               bzero(key, sizeof key);
+                               bzero(keybuf, sizeof keybuf);
                                return;
+                       }
                        nwkey.i_key[0].i_keylen = len;
                        nwkey.i_key[0].i_keydat = keybuf[0];
                        i = 1;
@@ -1576,6 +1595,8 @@ setifnwkey(const char *val, int d)
        (void)strlcpy(nwkey.i_name, name, sizeof(nwkey.i_name));
        if (ioctl(s, SIOCS80211NWKEY, (caddr_t)&nwkey) == -1)
                warn("SIOCS80211NWKEY");
+       bzero(key, sizeof key);
+       bzero(keybuf, sizeof keybuf);
 }
 
 /* ARGSUSED */
@@ -1734,14 +1755,21 @@ setifwpakey(const char *val, int d)
        struct ieee80211_wpapsk psk;
        struct ieee80211_nwid nwid;
        int passlen;
+       char keybuf[sizeof "0x" + 2 * sizeof psk.i_psk];
+       const char *key;
+
+       if (val == NULL && d != -1)
+               val = read_key(keybuf, sizeof keybuf);
 
        memset(&psk, 0, sizeof(psk));
        if (d != -1) {
                memset(&ifr, 0, sizeof(ifr));
                ifr.ifr_data = (caddr_t)&nwid;
                strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
-               if (ioctl(s, SIOCG80211NWID, (caddr_t)&ifr))
+               if (ioctl(s, SIOCG80211NWID, (caddr_t)&ifr)) {
+                       bzero(keybuf, sizeof keybuf);
                        err(1, "SIOCG80211NWID");
+               }
 
                passlen = strlen(val);
                if (passlen == 2 + 2 * sizeof(psk.i_psk) &&
@@ -1749,35 +1777,57 @@ setifwpakey(const char *val, int d)
                        /* Parse a WPA hex key (must be full-length) */
                        passlen = sizeof(psk.i_psk);
                        val = get_string(val, NULL, psk.i_psk, &passlen);
-                       if (val == NULL || passlen != sizeof(psk.i_psk))
+                       if (val == NULL || passlen != sizeof(psk.i_psk)) {
+                               bzero(keybuf, sizeof keybuf);
+                               bzero(&psk, sizeof psk);
                                errx(1, "wpakey: invalid pre-shared key");
+                       }
                } else {
                        /* Parse a WPA passphrase */ 
-                       if (passlen < 8 || passlen > 63)
+                       if (passlen < 8 || passlen > 63) {
+                               bzero(keybuf, sizeof keybuf);
                                errx(1, "wpakey: passphrase must be between "
                                    "8 and 63 characters");
-                       if (nwid.i_len == 0)
+                       }
+                       if (nwid.i_len == 0) {
+                               bzero(keybuf, sizeof keybuf);
                                errx(1, "wpakey: nwid not set");
+                       }
                        if (pkcs5_pbkdf2(val, passlen, nwid.i_nwid, nwid.i_len,
-                           psk.i_psk, sizeof(psk.i_psk), 4096) != 0)
+                           psk.i_psk, sizeof(psk.i_psk), 4096) != 0) {
+                               bzero(keybuf, sizeof keybuf);
+                               bzero(&psk, sizeof psk);
                                errx(1, "wpakey: passphrase hashing failed");
+                       }
                }
                psk.i_enabled = 1;
        } else
                psk.i_enabled = 0;
 
        (void)strlcpy(psk.i_name, name, sizeof(psk.i_name));
-       if (ioctl(s, SIOCS80211WPAPSK, (caddr_t)&psk) < 0)
+       if (ioctl(s, SIOCS80211WPAPSK, (caddr_t)&psk) < 0) {
+               bzero(keybuf, sizeof keybuf);
+               bzero(&psk, sizeof psk);
                err(1, "SIOCS80211WPAPSK");
+       }
 
        /* And ... automatically enable or disable WPA */
        memset(&wpa, 0, sizeof(wpa));
        (void)strlcpy(wpa.i_name, name, sizeof(wpa.i_name));
-       if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0)
+       if (ioctl(s, SIOCG80211WPAPARMS, (caddr_t)&wpa) < 0) {
+               bzero(keybuf, sizeof keybuf);
+               bzero(&psk, sizeof psk);
                err(1, "SIOCG80211WPAPARMS");
+       }
        wpa.i_enabled = psk.i_enabled;
-       if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0)
+       if (ioctl(s, SIOCS80211WPAPARMS, (caddr_t)&wpa) < 0) {
+               bzero(keybuf, sizeof keybuf);
+               bzero(&psk, sizeof psk);
                err(1, "SIOCS80211WPAPARMS");
+       }
+
+       bzero(keybuf, sizeof keybuf);
+       bzero(&psk, sizeof psk);
 }
 
 void
@@ -3411,17 +3461,30 @@ void
 setcarp_passwd(const char *val, int d)
 {
        struct carpreq carpr;
+       char key[sizeof carpr.carpr_key];
+       int rc;
+
+       if (val == NULL && d != -1)
+               val = read_key(key, sizeof key);
 
        bzero(&carpr, sizeof(struct carpreq));
        ifr.ifr_data = (caddr_t)&carpr;
 
-       if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
+       if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) {
+               bzero(key, sizeof key);
+               bzero(&carpr, sizeof carpr);
                err(1, "SIOCGVH");
+       }
 
        /* XXX Should hash the password into the key here, perhaps? */
        strlcpy((char *)carpr.carpr_key, val, CARP_KEY_LEN);
 
-       if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
+       rc = ioctl(s, SIOCSVH, (caddr_t)&ifr);
+
+       bzero(key, sizeof key);
+       bzero(&carpr, sizeof carpr);
+
+       if (rc == -1)
                err(1, "SIOCSVH");
 }
 
@@ -4140,17 +4203,28 @@ void
 setspppkey(const char *val, int d)
 {
        struct sauthreq spa;
+       char key[sizeof spa.secret];
+
+       if (val == NULL && d != -1)
+               val = read_key(key, sizeof key);
 
        spppauthinfo(&spa, d);
 
-       if (spa.proto == 0)
+       if (spa.proto == 0) {
+               bzero(key, sizeof key);
                errx(1, "unspecified protocol");
-       if (strlcpy(spa.secret, val, sizeof(spa.secret)) >= sizeof(spa.secret))
+       }
+       if (strlcpy(spa.secret, val, sizeof(spa.secret)) >= sizeof(spa.secret)) 
{
+               bzero(key, sizeof key);
                errx(1, "setspppkey");
+       }
 
        spa.cmd = d == 0 ? SPPPIOSMAUTH : SPPPIOSHAUTH;
-       if (ioctl(s, SIOCSIFGENERIC, &ifr) == -1)
+       if (ioctl(s, SIOCSIFGENERIC, &ifr) == -1) {
+               bzero(key, sizeof key);
                err(1, "SIOCSIFGENERIC(SPPPIOSXAUTH)");
+       }
+       bzero(key, sizeof key);
 }
 
 void

Reply via email to