Small demonstration of the kinds of things we'll have to mop up for
weeks more.

>From OpenSSL CHANGES file:

  *) Introduce safe string copy and catenation functions
     (BUF_strlcpy() and BUF_strlcat()).
     [Ben Laurie (CHATS) and Richard Levitte]

That's from back in 2002.

These functions work just like ours in OpenBSD.  The return values
indicate overflow.  We've been advising people to check for overflow
from the start, which is why we designed these like snprintf.

Good move, but then let's see how they used them:

./apps/ca.c:            BUF_strlcpy(tofree, s, len);
./apps/ca.c:            BUF_strlcat(tofree, "/", len);
./apps/ca.c:            BUF_strlcat(tofree, CONFIG_FILE, len);
./apps/ca.c:                    BUF_strlcat(buf[2], "/", sizeof(buf[2]));
./apps/ca.c:    BUF_strlcpy(row[DB_file], "unknown", 8);
./apps/ca.c:            BUF_strlcpy(row[DB_file], "unknown", 8);
./apps/ca.c:    BUF_strlcpy(str, (char *) revtm->data, i);
./apps/ca.c:            BUF_strlcat(str, ",", i);
./apps/ca.c:            BUF_strlcat(str, reason, i);
./apps/ca.c:            BUF_strlcat(str, ",", i);
./apps/ca.c:            BUF_strlcat(str, other, i);
./apps/apps.c:  BUF_strlcpy(out, p, size);
./apps/apps.c:          BUF_strlcpy(buf[0], serialfile, BSIZE);
./apps/engine.c:                BUF_strlcat(*buf, ", ", *size);
./apps/engine.c:        BUF_strlcat(*buf, s, *size);
./apps/pkcs12.c:                        BUF_strlcpy(macpass, pass, sizeof 
macpass);
./apps/pkcs12.c:                BUF_strlcpy(macpass, pass, sizeof macpass);
./apps/req.c:           BUF_strlcpy(buf, value, sizeof buf);
./apps/req.c:           BUF_strlcat(buf, "\n", sizeof buf);
./apps/req.c:           BUF_strlcpy(buf, def, sizeof buf);
./apps/req.c:           BUF_strlcat(buf, "\n", sizeof buf);
./apps/req.c:           BUF_strlcpy(buf, value, sizeof buf);
./apps/req.c:           BUF_strlcat(buf, "\n", sizeof buf);
./apps/req.c:           BUF_strlcpy(buf, def, sizeof buf);
./apps/req.c:           BUF_strlcat(buf, "\n", sizeof buf);
./apps/s_socket.c:              BUF_strlcpy(*host, h1->h_name, 
strlen(h1->h_name) + 1);
./apps/srp.c:                   BUF_strlcpy(tofree, s, len);
./apps/srp.c:                   BUF_strlcat(tofree, "/", len);
./apps/srp.c:                   BUF_strlcat(tofree, CONFIG_FILE, len);
./apps/x509.c:          BUF_strlcpy(buf, CAfile, len);
./apps/x509.c:          BUF_strlcat(buf, POSTFIX, len);
./apps/x509.c:          BUF_strlcpy(buf, serialfile, len);
./crypto/asn1/a_time.c: if (t->data[0] >= '5') BUF_strlcpy(str, "19", newlen);
./crypto/asn1/a_time.c: else BUF_strlcpy(str, "20", newlen);
./crypto/asn1/a_time.c: BUF_strlcat(str, (char *)t->data, newlen);
./crypto/bio/b_dump.c:          BUF_strlcpy(buf, str, sizeof buf);
./crypto/bio/b_dump.c:          BUF_strlcat(buf, tmp, sizeof buf);
./crypto/bio/b_dump.c:                          BUF_strlcat(buf, "   ", sizeof 
buf);
./crypto/bio/b_dump.c:                          BUF_strlcat(buf, tmp, sizeof 
buf);
./crypto/bio/b_dump.c:          BUF_strlcat(buf, "  ", sizeof buf);
./crypto/bio/b_dump.c:                  BUF_strlcat(buf, tmp, sizeof buf);
./crypto/bio/b_dump.c:          BUF_strlcat(buf, "\n", sizeof buf);
./crypto/bio/bss_file.c:                                BUF_strlcpy(p, "a+", 
sizeof p);
./crypto/bio/bss_file.c:                        else    BUF_strlcpy(p, "a", 
sizeof p);
./crypto/bio/bss_file.c:                        BUF_strlcpy(p, "r+", sizeof p);
./crypto/bio/bss_file.c:                        BUF_strlcpy(p, "w", sizeof p);
./crypto/bio/bss_file.c:                        BUF_strlcpy(p, "r", sizeof p);
./crypto/buffer/buf_str.c:BUF_strlcpy(char *dst, const char *src, size_t size)
./crypto/buffer/buf_str.c:BUF_strlcat(char *dst, const char *src, size_t size)
./crypto/buffer/buffer.h:size_t BUF_strlcpy(char *dst, const char *src, size_t 
siz);
./crypto/buffer/buffer.h:size_t BUF_strlcat(char *dst, const char *src, size_t 
siz);
./crypto/conf/conf_def.c:       BUF_strlcpy(section,"default",10);
./crypto/conf/conf_def.c:                       
BUF_strlcpy(v->name,pname,strlen(pname)+1);
./crypto/dso/dso_lib.c: BUF_strlcpy(copied, filename, strlen(filename) + 1);
./crypto/dso/dso_lib.c:         BUF_strlcpy(result, filename, strlen(filename) 
+ 1);
./crypto/err/err.c:                     BUF_strlcat(str,a,(size_t)s+1);
./crypto/evp/evp_pbe.c:         if (!pbe_obj) BUF_strlcpy (obj_tmp, "NULL", 
sizeof obj_tmp);
./crypto/objects/obj_dat.c:                             
BUF_strlcpy(buf,s,buf_len);
./crypto/objects/obj_dat.c:                             
BUF_strlcpy(buf,bndec,buf_len);
./crypto/objects/obj_dat.c:                             
BUF_strlcpy(buf,tbuf,buf_len);
./crypto/pem/pem_lib.c: BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE);
./crypto/pem/pem_lib.c: BUF_strlcat(buf,str,PEM_BUFSIZE);
./crypto/pem/pem_lib.c: BUF_strlcat(buf,"\n",PEM_BUFSIZE);
./crypto/pem/pem_lib.c: BUF_strlcat(buf,"DEK-Info: ",PEM_BUFSIZE);
./crypto/pem/pem_lib.c: BUF_strlcat(buf,type,PEM_BUFSIZE);
./crypto/pem/pem_lib.c: BUF_strlcat(buf,",",PEM_BUFSIZE);
./crypto/rand/randfile.c:       if (BUF_strlcpy(buf,"/dev/urandom",size) >= 
size)
./crypto/ui/ui_lib.c:           BUF_strlcpy(prompt, prompt1, len + 1);
./crypto/ui/ui_lib.c:           BUF_strlcat(prompt, object_desc, len + 1);
./crypto/ui/ui_lib.c:                   BUF_strlcat(prompt, prompt2, len + 1);
./crypto/ui/ui_lib.c:                   BUF_strlcat(prompt, object_name, len + 
1);
./crypto/ui/ui_lib.c:           BUF_strlcat(prompt, prompt3, len + 1);
./crypto/ui/ui_lib.c:           BUF_strlcpy(uis->result_buf, result,
./crypto/x509v3/v3_info.c:              BUF_strlcpy(ntmp, objtmp, nlen);
./crypto/x509v3/v3_info.c:              BUF_strlcat(ntmp, " - ", nlen);
./crypto/x509v3/v3_info.c:              BUF_strlcat(ntmp, vtmp->name, nlen);

Lots of overflow checks missing.  It is possible that some of those
are range-checked beforehands, but I'd put the odds as low.

About 100 snprintf's are handled the same way...

The OpenSSL developers are not responsible programmers.  They are
uneducated regarding the concept of 'best practice'.

Reply via email to