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