Full_Name: Hallvard B Furuseth Version: OS: URL: Submission from: (NULL) (129.240.6.233) Submitted by: hallvard
Given these declarations: #include <lber.h> #define LBER_EXBUFSIZ 4060 /* from liblber/io.c */ static char data[8000]; struct berval bv; BerElement *ber;
Buffer overrun i ber_flatten(,,0): ber = der_alloc(); ber_printf(ber, "o", data, LBER_EXBUFSIZ - 4); ber_flatten2(ber, &bv, 0); ber_flatten2(,,0) \0-terminates the Ber buffer, but does not grow it first at need. Simplest fix is to allocate an extra byte in ber_realloc(), and reduce LBER_EXBUFSIZ by 1 to compensate. I don't know how kosher it is to write into the ber buffer in the first place though.
Coredump - write through NULL pointer: ber_flatten2(der_alloc(), &bv, 0); A fresh Ber has no buffers yet, the buffer pointers are NULL. \0-terminating a NULL pointer doesn't work too well. Don't know if it should be called a bug though, since ber_flatten2() doesn't work right on an incomplete Ber element either (due to seqorset stuff).
The NULL pointers in a fresh ber also mean ber_write, ber_len() & co do pointer arithmetic on NULL pointers, which is not valid. Oh well, it seems to work on most machines.
Buffer overrun in ber_write(): ber = der_alloc(); ber_printf(ber, "{"); ber_write(ber, data, 6000, 0);
ber_write() needs buffer space and calls ber_realloc(ber, 6000). However "{" has moved ber->ber_sos->sos_ptr (the write destination) 6 bytes beyond ber->ber_end, so 6006 bytes are actually needed. ber_realloc() does not know that, and allocates 6000 bytes.
It cannot happen with ber_write() called from liblber: Next liblber write after "{" will be just a few bytes with the next element's tag. ber_realloc() always allocates 4060 bytes or more - moving sos_ptr beyond ber_end again.
This can only happen if a caller outside liblber generates a complete "tag, length, contents" element >= 4060 bytes and ber_write()s it in one operation. There are ber_write()s in libldap and slapd/connection.c, but haven't checked if any are at risk.
Don't know where to fix it: - in ber_realloc(), most techinically correct. - in ber_write() - simpler since it already knows about sos_ptr. - in ber_start_seqorset() - always alloc a buffer, never point beyond allocated data. Cleanest but most space-costly.