"James MacMahon" <[email protected]> writes:
> Hello,
Hi, thanks for your report,
> (sendbug didn't work for me, so I am sending using the same format manually)
>
> Description:
> Recently, I found an OpenBSD bug where pppoe(4) sends echo-req packets with
> bad
> magic numbers. The following tcpdump trace below shows the bad echo-req packet
> with 00-00-00-00:
>
> Nov 1 09:24:59 smyslov /bsd: pppoe0: lcp output <echo-req id=0xea len=8
> 00-00-00-00>
> Nov 1 09:24:59 smyslov /bsd: pppoe0 (8864) state=3, session=0x3d22 output ->
> 00:90:1a:a3:7e:12, len=16
> Nov 1 09:24:59 smyslov /bsd: pppoe0: lcp input(opened): <term-req id=0xbf
> len=4 00-00-00-...-00-00-00>
> Nov 1 09:24:59 smyslov /bsd: pppoe0: lcp opened->stopping
>
> According to RFC 1661, "A Magic-Number of zero is illegal and MUST always be
> Nak'd".
>
> The problem exists in sys/net/if_spppsubr.c:
>
> else if (sp->pp_phase >= PHASE_AUTHENTICATE) {
> unsigned long nmagic = htonl (sp->lcp.magic);
> sp->lcp.echoid = ++sp->pp_seq;
> sppp_cp_send (sp, PPP_LCP, ECHO_REQ,
> sp->lcp.echoid, 4, &nmagic);
> }
>
> The problem here is that sparc64 is big endian and 64 bit, and passing the
> address using '&nmagic' causes sppp_cp_send to see only zeros in the 'first'
> four bytes (most significant bytes).
[...]
Here's a diff, only compile-tested, to treat "magic" as u_int32_t.
I didn't switch "magic" in struct slcp to u_int32_t, that can be done in
another diff (and for other members of this structure) if someone cares.
If this looks right I'd like some reports (LE/BE, ILP32/I32LP64).
Index: if_spppsubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_spppsubr.c,v
retrieving revision 1.113
diff -u -p -r1.113 if_spppsubr.c
--- if_spppsubr.c 20 Nov 2013 08:21:33 -0000 1.113
+++ if_spppsubr.c 26 Nov 2013 00:50:45 -0000
@@ -1312,7 +1312,7 @@ sppp_cp_input(const struct cp *cp, struc
int len = m->m_pkthdr.len;
int rv;
u_char *p;
- u_long nmagic;
+ u_int32_t magic, nmagic;
if (len < 4) {
if (debug)
@@ -1641,10 +1641,10 @@ sppp_cp_input(const struct cp *cp, struc
break;
}
- nmagic = (u_long)p[0] << 24 |
- (u_long)p[1] << 16 | p[2] << 8 | p[3];
+ memcpy(&nmagic, p, sizeof(nmagic));
+ magic = ntohl(nmagic);
- if (nmagic == sp->lcp.magic) {
+ if (magic == sp->lcp.magic) {
/* Line loopback mode detected. */
log(LOG_INFO, SPP_FMT "loopback\n", SPP_ARGS(ifp));
/* Shut down the PPP link. */
@@ -1652,10 +1652,8 @@ sppp_cp_input(const struct cp *cp, struc
break;
}
- p[0] = sp->lcp.magic >> 24;
- p[1] = sp->lcp.magic >> 16;
- p[2] = sp->lcp.magic >> 8;
- p[3] = sp->lcp.magic;
+ nmagic = htonl(sp->lcp.magic);
+ memcpy(p, &nmagic, sizeof(nmagic));
if (debug)
addlog(SPP_FMT "got lcp echo req, sending echo rep\n",
@@ -1679,11 +1677,11 @@ sppp_cp_input(const struct cp *cp, struc
if (debug)
addlog(SPP_FMT "lcp got echo rep\n",
SPP_ARGS(ifp));
-
- nmagic = (u_long)p[0] << 24 |
- (u_long)p[1] << 16 | p[2] << 8 | p[3];
- if (nmagic != sp->lcp.magic)
+ memcpy(&nmagic, p, sizeof(nmagic));
+ magic = ntohl(nmagic);
+
+ if (magic != sp->lcp.magic)
sp->pp_alivecnt = 0;
break;
default:
@@ -2109,7 +2107,7 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
STDDCL;
u_char *buf, *r, *p;
int origlen, rlen;
- u_long nmagic;
+ u_int32_t magic, nmagic;
u_short authproto;
len -= 4;
@@ -2209,11 +2207,11 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
switch (*p) {
case LCP_OPT_MAGIC:
/* Magic number -- extract. */
- nmagic = (u_long)p[2] << 24 |
- (u_long)p[3] << 16 | p[4] << 8 | p[5];
- if (nmagic != sp->lcp.magic) {
+ memcpy(&nmagic, &p[2], sizeof(nmagic));
+ magic = ntohl(nmagic);
+ if (magic != sp->lcp.magic) {
if (debug)
- addlog("0x%lx ", nmagic);
+ addlog("0x%08x ", magic);
continue;
}
if (debug)
@@ -2224,12 +2222,9 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
* we see it later in an NAK packet, we
* suggest a new one.
*/
- nmagic = ~sp->lcp.magic;
+ nmagic = ~sp->lcp.magic & 0xffffffffU;
/* Gonna NAK it. */
- p[2] = nmagic >> 24;
- p[3] = nmagic >> 16;
- p[4] = nmagic >> 8;
- p[5] = nmagic;
+ memcpy(&p[2], &nmagic, sizeof(nmagic));
break;
case LCP_OPT_ASYNC_MAP:
@@ -2376,7 +2371,7 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct
{
STDDCL;
u_char *p;
- u_long magic;
+ u_int32_t magic, nmagic;
len -= 4;
@@ -2395,21 +2390,22 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct
/* Magic number -- renegotiate */
if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) &&
len >= 6 && p[1] == 6) {
- magic = (u_long)p[2] << 24 |
- (u_long)p[3] << 16 | p[4] << 8 | p[5];
+ memcpy(&nmagic, &p[2], sizeof(nmagic));
+ magic = ntohl(nmagic);
+
/*
* If the remote magic is our negated one,
* this looks like a loopback problem.
* Suggest a new magic to make sure.
*/
- if (magic == ~sp->lcp.magic) {
+ if (magic == (~sp->lcp.magic & 0xffffffffU)) {
if (debug)
addlog("magic glitch ");
sp->lcp.magic = arc4random();
} else {
sp->lcp.magic = magic;
if (debug)
- addlog("%lu ", magic);
+ addlog("0x%08x ", magic);
}
}
break;
@@ -2557,6 +2553,7 @@ sppp_lcp_scr(struct sppp *sp)
{
char opt[6 /* magicnum */ + 4 /* mru */ + 5 /* chap */];
int i = 0;
+ u_int32_t nmagic;
u_short authproto;
if (sp->lcp.opts & (1 << LCP_OPT_MAGIC)) {
@@ -2564,10 +2561,9 @@ sppp_lcp_scr(struct sppp *sp)
sp->lcp.magic = arc4random();
opt[i++] = LCP_OPT_MAGIC;
opt[i++] = 6;
- opt[i++] = sp->lcp.magic >> 24;
- opt[i++] = sp->lcp.magic >> 16;
- opt[i++] = sp->lcp.magic >> 8;
- opt[i++] = sp->lcp.magic;
+ nmagic = htonl(sp->lcp.magic);
+ memcpy(&opt[i], &nmagic, sizeof(nmagic));
+ i += 4;
}
if (sp->lcp.opts & (1 << LCP_OPT_MRU)) {
@@ -4488,10 +4484,12 @@ sppp_keepalive(void *dummy)
sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq,
sp->pp_rseq);
else if (sp->pp_phase >= PHASE_AUTHENTICATE) {
- unsigned long nmagic = htonl (sp->lcp.magic);
+ u_int32_t nmagic;
+
+ nmagic = htonl(sp->lcp.magic);
sp->lcp.echoid = ++sp->pp_seq;
- sppp_cp_send (sp, PPP_LCP, ECHO_REQ,
- sp->lcp.echoid, 4, &nmagic);
+ sppp_cp_send(sp, PPP_LCP, ECHO_REQ, sp->lcp.echoid,
+ 4, &nmagic);
}
}
splx(s);
@@ -5223,13 +5221,6 @@ sppp_null(struct sppp *unused)
{
/* do just nothing */
}
-/*
- * This file is large. Tell emacs to highlight it nevertheless.
- *
- * Local Variables:
- * hilit-auto-highlight-maxout: 120000
- * End:
- */
HIDE void
sppp_set_phase(struct sppp *sp)