[sane-devel] possible bin_w_string security issue (not)

2004-10-16 Thread Henning Meier-Geinitz
Hi,

On Fri, Oct 15, 2004 at 03:47:06PM +0200, Johannes Berg wrote:
 I was going to write a mail without the (not) but then discovered that
 this issue is actually a non-issue, but this is totally non-obvious.
 
 Would you know off-hand why?

SIGPIPE (ok, I read your mail before answering) :-)

 bin_w_string contains the following code:
 
   if (w-direction == WIRE_DECODE)
 {
   if (len == 0)
 *s = 0;
   else if (w-status == 0)
 *(*s + len - 1) = '\0';
 }
 
 If I interpret the code correctly, this could be used to bring the
 server (running the binary protocol) into an invalid state:

Nearly any protocol violation from server or client can have strange
results. That's one of the problems with the SANE net protocol.

Also there are still many tests missing for a bad wire status (see bug
#300105).

 * now, the server has a password string that is not zero terminated,
and strcpy()s that string accessing memory beyond the allocated size.

There may be other locations but at least here it tests for the wire
status:

(saned.c l. 356)

  sanei_w_authorization_req (wire, req);
  if (wire.status)
{
  DBG(DBG_ERR, auth_callback: bad status %d\n, wire.status);
  return;
}

  if (req.username)
strcpy (username, req.username);  
[...]

All the wire code expects the caller to test the wire status before he
does anything else. I think there should be tests in all functions of
sanei_net.c also to avoid calling sanei_wire again when the wire is
already bad.

 [Actually, I discovered this while I was documenting the wire protocol.
 I think it is overly complex and the code badly structured, the wire's
 direction thing is really strange!]

I'm still not sure if I have understood all the details of the wire
code. But I guess the idea was to have only one function for each kind
of data. So you don't need one for the server and one for the client
and one for ascii and one for bin and one for sending and one for
receiving...

 Ok, so here's the solution:
 
 The server does
   signal (SIGPIPE, quit);
 
 (which I think is actually another bug, why should sane_close,
 sane_exit, sanei_w_exit and lots of other functions be async signal
 safe?)

They aren't. Only sane_cancel() must be async signal safe.

Yes, I guess that's a bug.

 Still, this is that non-obvious that someone writing a server (or
 client, which could then be attacked by a malevolent server) with the
 sanei library functions could easily oversee this detail, ignore SIGPIPE
 or use sockets that don't raise it.

Nobody should ever use sanei_wire/sanei_net/sanei_codec_* without
really knowing what he does :-)

 Therefore I'm still sending this mail in hope that someone fixes the
 sanei_w_array function to check for status != 0 and clean up after
 itself.

But what should sanei_w_array do? It already exits when the wire is in
bad state. I think that's really up to the caller.

Bye,
  Henning



[sane-devel] possible bin_w_string security issue (not)

2004-10-16 Thread Johannes Berg
--=-yhkGcHckmX4ZO5PEvTHQ
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

Hi,

 SIGPIPE (ok, I read your mail before answering) :-)

:-)

 Nearly any protocol violation from server or client can have strange
 results. That's one of the problems with the SANE net protocol.
=20
 Also there are still many tests missing for a bad wire status (see bug
 #300105).

Will do.

 There may be other locations but at least here it tests for the wire
 status:

Hm. I guess you're right. Seems I missed it, or maybe I was writing this
when I looked at a different location? Sorry.

 I'm still not sure if I have understood all the details of the wire
 code. But I guess the idea was to have only one function for each kind
 of data. So you don't need one for the server and one for the client
 and one for ascii and one for bin and one for sending and one for
 receiving...

Yeah, and then it is also overloaded for freeing allocated data.

 They aren't. Only sane_cancel() must be async signal safe.
=20
 Yes, I guess that's a bug.

Ok.

 Nobody should ever use sanei_wire/sanei_net/sanei_codec_* without
 really knowing what he does :-)

:-)

 But what should sanei_w_array do? It already exits when the wire is in
 bad state. I think that's really up to the caller.

Yes, but before exiting it should free the result buffer and NULL the
pointer. When the wire is in an invalid state during reading, it cannot
be guaranteed that the buffer is in a valid state, so should be
discarded.

johannes

--=-yhkGcHckmX4ZO5PEvTHQ
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-BEGIN PGP SIGNATURE-
Comment: Johannes Berg (SIP Solutions)

iQIVAwUAQXEVXaVg1VMiehFYAQLPOw/9E6+OseXpkvwWNMTenxSGxMF28XX/Rl71
s7sYiR4Fg9hdmPQDy0RtTkQrKspY6izzgn1aGlsH7H2eLw2pIF7yqW36vX2gQXWo
kwju+ZF+dIDLWjQ8ICiyuJFgYUNWxjZjDTfLhwe16ByGnVT+nWIx9ZbPYaB1KR0N
PmqH3M9G+s7oaZFh5zKtPiJA6kSBbsgpnhSDZpqzop+Rfe8vrFIPN7UTQS2PqZUx
20kMuH4CQu0ggpJ9yekIfzRdbBAZcHSCxKo7vTuupfratbbib9D2firVgW77aaNO
Lo3gnue+/TgxLJWeaBxrn/unL/q5U/YnNGhUgAsDBlGymjpZJV+ApOYHoVarv5XS
CbyYKKrszzhO8otxfkfA07v7QxqqpDw1CRE2tfxHqXyk2hmyVsy38AHrZOyevMGS
D2du8D63miUyVaU3dlGrjmcSxE7pohki9BpMjZ54hIEiF0zw2H9pC1/363KWNzl+
2rVZcrCmBQMrwoewepWGpvQBJiFZ9sxUkAmaQu/Jv3HEOQnsX8ZmQwKZpKy1qPHm
ARqx2Yex/OJ8R8ViKQfPjpRVyBvYfchle+XNRpJh+lbn2VGwh4KKWNGaaoFqdOJd
Ybwv5LTz7XtYFmR3IOssFp8BjrTULE5oezwrwCFLqyIJAGC64dGnkdTli6xlEp2E
h41UsBd5daQ=
=cJpn
-END PGP SIGNATURE-

--=-yhkGcHckmX4ZO5PEvTHQ--





[sane-devel] possible bin_w_string security issue (not)

2004-10-15 Thread Johannes Berg
--=-8KpxnP81NRNqGGtcVgwN
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

I was going to write a mail without the (not) but then discovered that
this issue is actually a non-issue, but this is totally non-obvious.

Would you know off-hand why?

bin_w_string contains the following code:

  if (w-direction =3D=3D WIRE_DECODE)
{
  if (len =3D=3D 0)
*s =3D 0;
  else if (w-status =3D=3D 0)
*(*s + len - 1) =3D '\0';
}

If I interpret the code correctly, this could be used to bring the
server (running the binary protocol) into an invalid state:

1) send any kind of request that requires a string option at the end,
   for example SANE_NET_AUTHORIZE
2) tell the server that the length is 10 or so
3) send 9 bytes and close the connection

The server will react to this in the following way (if I interpret the
code correctly):
* during sanei_w_array it will notice that the status is
   bad and return
* bin_w_string will not(!) zero-terminate the string
   (because it is assuming that *s is not valid, while
   it actually is)
   sanei_w_array doesn't clear the array if anything
   item fails to read.
* now, the server has a password string that is not zero terminated,
   and strcpy()s that string accessing memory beyond the allocated size.


[Actually, I discovered this while I was documenting the wire protocol.
I think it is overly complex and the code badly structured, the wire's
direction thing is really strange!]





Ok, so here's the solution:

The server does
  signal (SIGPIPE, quit);

(which I think is actually another bug, why should sane_close,
sane_exit, sanei_w_exit and lots of other functions be async signal
safe?)

Still, this is that non-obvious that someone writing a server (or
client, which could then be attacked by a malevolent server) with the
sanei library functions could easily oversee this detail, ignore SIGPIPE
or use sockets that don't raise it.

Therefore I'm still sending this mail in hope that someone fixes the
sanei_w_array function to check for status !=3D 0 and clean up after
itself.

johannes

--=-8KpxnP81NRNqGGtcVgwN
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-BEGIN PGP SIGNATURE-
Comment: Johannes Berg (SIP Solutions)

iQIVAwUAQW/U16Vg1VMiehFYAQItGRAApmPf+qNwUfTzFswVVe1K10VSArYVmcOJ
1wN5J3zAhf9oC7gSavY5q2Y5gCZoyCj2+p+iSWf3sjDAV2+RH8WVIS34IItamOC8
zyj9g8/NgHtaF99tTi7/O2j0/3eMvr9t4/dipDZ7l83EI7C0ZYv2CsGX97dmdXf8
HPJo/9Tl4DA+UsBGMngGsj7flVrjf2zThkJzcPqEAgLv8v2Mv4LW5JNtxZIozgGM
LvLdRgYS7SVtt+owY+2bSLdW3V0dYp/QXwqHNXSvZfFHe1FT9AVZBwvF1573J14v
t+T3AwNV/qRxZC4d/0VD6JsPWJA11HFA3agutUK4TN1G10lH+1BkmoM8NXVWWy9p
9jh1G8FsQsPmnV1WGY6jy6JF4rFLARrjfCIefcDKQt5kEC8s9eMiT0+wayvUYZRr
bhO6oOgunMoPpNX3AxyvDhwzZ1uZmoied7QY+C783pY7kIWtZ45mFFCsznnX6FFN
jwhFjubDeyK03SxTzit7KsBy89wTLXqQIaKKR2IqXc9KlXEUp/UGMoEsQSjBBKth
pUSlKymbhp9kSni0DZ8LGX/G9gYhnK0yMxNUYVzBnp8GWuqC/IO/aHX2rR8n0y+W
ztf389uXOpGU7EHKRPW4NfHuzvnW2CZBN9/ReXwkrMPT4K3enB8dAsh3ipj7Ruzh
FaYv+5kkYgU=
=867r
-END PGP SIGNATURE-

--=-8KpxnP81NRNqGGtcVgwN--