From: Nikos Mavrogiannopoulos Date: Wed, 23 Jan 2002 21:14:21 +0000 (+0000) Subject: Added a minimal string library to assist in safer ASN.1 parsing X-Git-Tag: gnutls_0_3_90~199 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7438d42ecc08c8c68df032ce815fdf1508b5c392;p=thirdparty%2Fgnutls.git Added a minimal string library to assist in safer ASN.1 parsing --- diff --git a/NEWS b/NEWS index 76b1a9429d..b3cc0ecf4a 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ Version ?.?.? to gnutls_dh_(set/get)_bits() - gnutls_anon_set_server_cred() was deprecated by gnutls_dh_set_bits() - gnutls_x509pki_set_trust_(file/mem) can now be called multiple times +- Added a minimal string library to assist in ASN.1 parsing Version 0.3.5 - Corrected the RSA key exchange method, to avoid attacks against diff --git a/doc/TODO b/doc/TODO index c114519996..b6163eb538 100644 --- a/doc/TODO +++ b/doc/TODO @@ -6,7 +6,6 @@ Current list: + Audit the code + Add support for certificates with DSS parameters + OpenPGP certificate support -* Create a local string library and use it for ASN.1 parsing * Add function to clone GNUTLS_STATE structures * Minimize footprint. * Improve support for compression diff --git a/lib/Makefile.am b/lib/Makefile.am index 55170c81c2..ff816415de 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -18,7 +18,7 @@ EXTRA_DIST = debug.h gnutls_compress.h defines.h pkcs1.asn pkix.asn \ gnutls_privkey.h gnutls_constate.h gnutls_global.h x509_verify.h \ gnutls_sig.h gnutls_mem.h x509_extensions.h gnutls_ui.h \ gnutls-api.tex io_debug.h ext_max_record.h gnutls_session_pack.h \ - gnutls_alert.h asn1-api.tex + gnutls_alert.h asn1-api.tex gnutls_str.h lib_LTLIBRARIES = libgnutls.la @@ -36,7 +36,8 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c \ gnutls_global.c gnutls_privkey.c gnutls_constate.c gnutls_anon_cred.c \ x509_sig_check.c pkix_asn1_tab.c pkcs1_asn1_tab.c gnutls_mem.c \ x509_extensions.c auth_x509.c gnutls_ui.c gnutls_sig.c auth_dhe_rsa.c \ - gnutls_dh_primes.c ext_max_record.c gnutls_alert.c gnutls_int_compat.c + gnutls_dh_primes.c ext_max_record.c gnutls_alert.c gnutls_int_compat.c \ + gnutls_str.c # Separate so we can create the documentation COBJECTS2 = x509_ASN.y x509_asn1.c x509_der.c diff --git a/lib/auth_srp.c b/lib/auth_srp.c index 0275624dd1..47e5d1e70b 100644 --- a/lib/auth_srp.c +++ b/lib/auth_srp.c @@ -27,6 +27,7 @@ #include "debug.h" #include "gnutls_num.h" #include "auth_srp.h" +#include int gen_srp_server_kx2(GNUTLS_STATE, opaque **); int gen_srp_client_kx0(GNUTLS_STATE, opaque **); @@ -85,8 +86,7 @@ int gen_srp_server_hello(GNUTLS_STATE state, opaque ** data) info = _gnutls_get_auth_info( state); username = info->username; - strncpy( username, state->security_parameters.extensions.srp_username, MAX_SRP_USERNAME); - username[ MAX_SRP_USERNAME - 1] = 0; + _gnutls_str_cpy( username, MAX_SRP_USERNAME, state->security_parameters.extensions.srp_username); pwd_entry = _gnutls_srp_pwd_read_entry( state->gnutls_key, username, &err); diff --git a/lib/auth_srp_passwd.c b/lib/auth_srp_passwd.c index 63becca31d..4963200909 100644 --- a/lib/auth_srp_passwd.c +++ b/lib/auth_srp_passwd.c @@ -30,6 +30,7 @@ #include "gnutls_random.h" #include "gnutls_dh.h" #include "debug.h" +#include /* this function parses tpasswd.conf file. Format is: * string(username):base64(v):base64(salt):int(index) @@ -307,7 +308,7 @@ GNUTLS_SRP_PWD_ENTRY* _gnutls_randomize_pwd_entry() { _gnutls_srp_clear_pwd_entry( pwd_entry); return NULL; } - strcpy( pwd_entry->username, RNDUSER); /* Flawfinder: ignore */ + _gnutls_str_cpy( pwd_entry->username, MAX_SRP_USERNAME, RNDUSER); /* Flawfinder: ignore */ pwd_entry->v = _gnutls_mpi_new(160); if (pwd_entry->v==NULL) { diff --git a/lib/crypt_srpsha1.c b/lib/crypt_srpsha1.c index 7215396796..7c81637d9b 100644 --- a/lib/crypt_srpsha1.c +++ b/lib/crypt_srpsha1.c @@ -40,7 +40,7 @@ char *crypt_srpsha1(const char *username, const char *passwd, int vsize, hash_len = gnutls_hash_get_algo_len(GNUTLS_MAC_SHA); opaque *tmp; uint8 *rtext, *csalt; - int rsalt_size, len; + int rsalt_size, len, tmpsize; passwd_len = strlen(passwd); /* we do not want the null */ diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 23ad5b2841..bfc8d0a861 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef DEBUG # warning MAX ALGORITHM PARAMS == 2, ok for RSA @@ -638,12 +639,12 @@ static int _read_rsa_params(opaque * der, int dersize, MPI * params) } #define _READ(a, aa, b, c, d, e, res, f) \ - result = _IREAD(a, aa, b, c, d, e, res, sizeof(res)-1, f); \ + result = _IREAD(a, aa, sizeof(aa), b, c, d, e, res, sizeof(res)-1, f); \ if (result<0) return result; \ if (result==1) continue -int _IREAD(node_asn * rasn, char *name3, char *rstr, char *OID, +int _IREAD(node_asn * rasn, char *name3, int name3_size, char *rstr, char *OID, char *ANAME, char *TYPE, char *res, int res_size, int CHOICE) { char name2[256]; @@ -653,10 +654,10 @@ int _IREAD(node_asn * rasn, char *name3, char *rstr, char *OID, if (strcmp(rstr, OID) == 0) { - strcpy(str, "PKIX1Implicit88."); /* Flawfinder: ignore */ - strcat(str, ANAME); /* Flawfinder: ignore */ - strcpy(name2, "temp-structure-"); /* Flawfinder: ignore */ - strcat(name2, TYPE); + _gnutls_str_cpy(str, sizeof(str), "PKIX1Implicit88."); + _gnutls_str_cat(str, sizeof(str), ANAME); + _gnutls_str_cpy(name2, sizeof(name2), "temp-structure-"); + _gnutls_str_cat(name2, sizeof(name2), TYPE); if ((result = asn1_create_structure(_gnutls_get_pkix(), str, @@ -665,7 +666,7 @@ int _IREAD(node_asn * rasn, char *name3, char *rstr, char *OID, return GNUTLS_E_ASN1_ERROR; } - len = sizeof(str) - 1; + len = sizeof(str) -1; if ((result = asn1_read_value(rasn, name3, str, &len)) != ASN_OK) { asn1_delete_structure(tmpasn); @@ -676,7 +677,7 @@ int _IREAD(node_asn * rasn, char *name3, char *rstr, char *OID, asn1_delete_structure(tmpasn); return 1; } - strcpy(name3, name2); /* Flawfinder: ignore */ + _gnutls_str_cpy(name3, name3_size, name2); len = sizeof(str) - 1; if ((result = asn1_read_value(tmpasn, name3, str, &len)) != ASN_OK) { /* CHOICE */ @@ -687,12 +688,12 @@ int _IREAD(node_asn * rasn, char *name3, char *rstr, char *OID, if (CHOICE == 0) { str[len] = 0; /* strlen(str) < res_size, checked above */ - strcpy(res, str); /* Flawfinder: ignore */ + _gnutls_str_cpy(res, res_size, str); } else { /* CHOICE */ str[len] = 0; - strcat(name3, "."); /* Flawfinder: ignore */ - strcat(name3, str); + _gnutls_str_cat(name3, name3_size, "."); + _gnutls_str_cat(name3, name3_size, str); len = sizeof(str) - 1; if ((result = @@ -703,7 +704,7 @@ int _IREAD(node_asn * rasn, char *name3, char *rstr, char *OID, } str[len] = 0; if ( len < res_size) - strcpy(res, str); /* Flawfinder: ignore */ + _gnutls_str_cpy(res, res_size, str); } asn1_delete_structure(tmpasn); @@ -719,7 +720,7 @@ void _gnutls_int2str(int k, char *data) if (k > 999) data[0] = 0; else - sprintf(data, "%d", k); /* Flawfinder: ignore */ + sprintf(data, "%d", k); } /* This function will attempt to read a Name @@ -739,10 +740,10 @@ int _gnutls_get_name_type(node_asn * rasn, char *root, gnutls_DN * dn) do { k++; - strcpy(name, root); /* Flawfinder: ignore */ - strcat(name, ".rdnSequence.?"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name, sizeof(name), root); + _gnutls_str_cat(name, sizeof(name), ".rdnSequence.?"); _gnutls_int2str(k, counter); - strcat(name, counter); /* Flawfinder: ignore */ + _gnutls_str_cat(name, sizeof(name), counter); len = sizeof(str) - 1; @@ -761,10 +762,10 @@ int _gnutls_get_name_type(node_asn * rasn, char *root, gnutls_DN * dn) do { k2++; - strcpy(name2, name); /* Flawfinder: ignore */ - strcat(name2, ".?"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name2, sizeof(name2), name); + _gnutls_str_cat(name2, sizeof(name2), ".?"); _gnutls_int2str(k2, counter); - strcat(name2, counter); /* Flawfinder: ignore */ + _gnutls_str_cat(name2, sizeof(name2), counter); len = sizeof(str) - 1; result = asn1_read_value(rasn, name2, str, &len); @@ -776,8 +777,8 @@ int _gnutls_get_name_type(node_asn * rasn, char *root, gnutls_DN * dn) return GNUTLS_E_ASN1_PARSING_ERROR; } - strcpy(name3, name2); - strcat(name3, ".type"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name3, sizeof(name3), name2); + _gnutls_str_cat(name3, sizeof(name3), ".type"); len = sizeof(str) - 1; result = asn1_read_value(rasn, name3, str, &len); @@ -789,8 +790,8 @@ int _gnutls_get_name_type(node_asn * rasn, char *root, gnutls_DN * dn) return GNUTLS_E_ASN1_PARSING_ERROR; } - strcpy(name3, name2); - strcat(name3, ".value"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name3, sizeof(name3), name2); + _gnutls_str_cat(name3, sizeof(name3), ".value"); if (result == ASN_OK) { #ifdef DEBUG @@ -840,9 +841,9 @@ time_t _gnutls_get_time(node_asn * c2, char *root, char *when) time_t ctime; int len, result; - strcpy(name, root); - strcat(name, ".tbsCertificate.validity."); /* Flawfinder: ignore */ - strcat(name, when); + _gnutls_str_cpy(name, sizeof(name), root); + _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity."); + _gnutls_str_cat(name, sizeof(name), when); len = sizeof(ttime) - 1; if ((result = asn1_read_value(c2, name, ttime, &len)) < 0) { @@ -851,22 +852,22 @@ time_t _gnutls_get_time(node_asn * c2, char *root, char *when) } /* CHOICE */ - strcpy(name, root); + _gnutls_str_cpy(name, sizeof(name), root); if (strcmp(ttime, "GeneralizedTime") == 0) { - strcat(name, ".tbsCertificate.validity."); /* Flawfinder: ignore */ - strcat(name, when); - strcat(name, ".generalTime"); /* Flawfinder: ignore */ + _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity."); + _gnutls_str_cat(name, sizeof(name), when); + _gnutls_str_cat(name, sizeof(name), ".generalTime"); len = sizeof(ttime) - 1; result = asn1_read_value(c2, name, ttime, &len); if (result == ASN_OK) ctime = _gnutls_generalTime2gtime(ttime); } else { /* UTCTIME */ - strcat(name, ".tbsCertificate.validity."); /* Flawfinder: ignore */ - strcat(name, when); - strcat(name, ".utcTime"); /* Flawfinder: ignore */ + _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity."); + _gnutls_str_cat(name, sizeof(name), when); + _gnutls_str_cat(name, sizeof(name), ".utcTime"); len = sizeof(ttime) - 1; result = asn1_read_value(c2, name, ttime, &len); if (result == ASN_OK) @@ -886,8 +887,8 @@ int _gnutls_get_version(node_asn * c2, char *root) char name[1024]; int len, result; - strcpy(name, root); - strcat(name, ".tbsCertificate.version"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name, sizeof(name), root); + _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.version"); len = sizeof(gversion) - 1; if ((result = asn1_read_value(c2, name, gversion, &len)) < 0) { diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c new file mode 100644 index 0000000000..a0fd25ea61 --- /dev/null +++ b/lib/gnutls_str.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2002 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include + +/* These function are like strcat, strcpy. They only + * do bound checking (they shouldn't cause buffer overruns), + * and they always produce null terminated strings. + */ +void _gnutls_str_cat( char* dest, size_t dest_tot_size, const char* src) { +size_t str_size = strlen(src); +size_t dest_size = strlen(dest); + + if ( dest_tot_size - dest_size > str_size) { + strcat( dest, src); + } else { + if ( dest_tot_size - dest_size > 0) { + strncat( dest, src, (dest_tot_size - dest_size) -1); + dest[dest_tot_size-1] = 0; + } + } +} + +void _gnutls_str_cpy( char* dest, size_t dest_tot_size, const char* src) { +size_t str_size = strlen(src); + + if ( dest_tot_size > str_size) { + strcpy( dest, src); + } else { + if ( dest_tot_size > 0) { + strncpy( dest, src, (dest_tot_size) -1); + dest[dest_tot_size-1] = 0; + } + } +} + diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h new file mode 100644 index 0000000000..c5f0af3bd0 --- /dev/null +++ b/lib/gnutls_str.h @@ -0,0 +1,2 @@ +void _gnutls_str_cpy( char* dest, size_t dest_tot_size, const char* src); +void _gnutls_str_cat( char* dest, size_t dest_tot_size, const char* src); diff --git a/lib/x509_extensions.c b/lib/x509_extensions.c index 6667ae6b59..1e109633fe 100644 --- a/lib/x509_extensions.c +++ b/lib/x509_extensions.c @@ -26,6 +26,7 @@ #include #include #include "debug.h" +#include /* Here we only extract the KeyUsage field @@ -162,10 +163,10 @@ int _gnutls_get_ext_type(node_asn * rasn, char *root, gnutls_cert * cert) do { k++; - strcpy(name, root); - strcat(name, ".?"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name, sizeof(name), root); + _gnutls_str_cat(name, sizeof(name), ".?"); _gnutls_int2str(k, counter); - strcat(name, counter); /* Flawfinder: ignore */ + _gnutls_str_cat(name, sizeof(name), counter); len = sizeof(str) - 1; result = asn1_read_value(rasn, name, str, &len); @@ -178,8 +179,8 @@ int _gnutls_get_ext_type(node_asn * rasn, char *root, gnutls_cert * cert) do { - strcpy(name2, name); - strcat(name2, ".extnID"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name2, sizeof(name2), name); + _gnutls_str_cat(name2, sizeof(name2), ".extnID"); len = sizeof(extnID) - 1; result = @@ -192,8 +193,8 @@ int _gnutls_get_ext_type(node_asn * rasn, char *root, gnutls_cert * cert) return GNUTLS_E_ASN1_PARSING_ERROR; } - strcpy(name2, name); - strcat(name2, ".critical"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name2, sizeof(name2), name); + _gnutls_str_cat(name2, sizeof(name2), ".critical"); len = sizeof(critical) - 1; result = @@ -206,8 +207,8 @@ int _gnutls_get_ext_type(node_asn * rasn, char *root, gnutls_cert * cert) return GNUTLS_E_ASN1_PARSING_ERROR; } - strcpy(name2, name); - strcat(name2, ".extnValue"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name2, sizeof(name2), name); + _gnutls_str_cat(name2, sizeof(name2), ".extnValue"); len = sizeof(extnValue) - 1; result = @@ -290,10 +291,10 @@ int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, do { k++; - strcpy(name, "certificate2"); /* Flawfinder: ignore */ - strcat(name, ".?"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name, sizeof(name), "certificate2"); + _gnutls_str_cat(name, sizeof(name), ".?"); _gnutls_int2str(k, counter); - strcat(name, counter); /* Flawfinder: ignore */ + _gnutls_str_cat(name, sizeof(name), counter); len = sizeof(str) - 1; result = asn1_read_value(rasn, name, str, &len); @@ -306,8 +307,8 @@ int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, do { - strcpy(name2, name); - strcat(name2, ".extnID"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name2, sizeof(name2), name); + _gnutls_str_cat(name2, sizeof(name2), ".extnID"); len = sizeof(extnID) - 1; result = @@ -320,8 +321,8 @@ int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, return GNUTLS_E_ASN1_PARSING_ERROR; } - strcpy(name2, name); - strcat(name2, ".critical"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name2, sizeof(name2), name); + _gnutls_str_cat(name2, sizeof(name2), ".critical"); len = sizeof(critical) - 1; result = @@ -335,8 +336,8 @@ int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, return GNUTLS_E_ASN1_PARSING_ERROR; } - strcpy(name2, name); - strcat(name2, ".extnValue"); /* Flawfinder: ignore */ + _gnutls_str_cpy(name2, sizeof(name2), name); + _gnutls_str_cat(name2, sizeof(name2), ".extnValue"); len = sizeof(extnValue) - 1; result = diff --git a/lib/x509_sig_check.c b/lib/x509_sig_check.c index 1c45c9a4c9..e6f1d7f3ab 100644 --- a/lib/x509_sig_check.c +++ b/lib/x509_sig_check.c @@ -31,6 +31,7 @@ #include #include #include +#include static gnutls_datum _gnutls_get_tbs( gnutls_cert* cert) { node_asn *c2; @@ -273,9 +274,9 @@ int _pkcs1_rsa_generate_sig( MACAlgorithm hash_algo, gnutls_private_key *pkey, c gnutls_datum der; if (hash_algo==GNUTLS_MAC_MD5) - strcpy(OID, "1 2 840 113549 2 5"); /* Flawfinder: ignore */ + _gnutls_str_cpy(OID, sizeof(OID), "1 2 840 113549 2 5"); else if (hash_algo==GNUTLS_MAC_SHA) - strcpy(OID, "1 3 14 3 2 26"); /* Flawfinder: ignore */ + _gnutls_str_cpy(OID, sizeof(OID), "1 3 14 3 2 26"); else { gnutls_assert(); return GNUTLS_E_UNKNOWN_MAC_ALGORITHM; diff --git a/lib/x509_verify.c b/lib/x509_verify.c index 380713395a..e4fb67e369 100644 --- a/lib/x509_verify.c +++ b/lib/x509_verify.c @@ -26,6 +26,7 @@ #include "gnutls_global.h" #include "gnutls_num.h" /* GMAX */ #include +#include /* TIME functions */ @@ -206,7 +207,7 @@ int compare_dn(gnutls_cert * cert, gnutls_cert * issuer_cert) } - strcpy( tmpstr, "certificate2.tbsCertificate.issuer"); /* Flawfinder: ignore */ + _gnutls_str_cpy( tmpstr, sizeof(tmpstr), "certificate2.tbsCertificate.issuer"); result = asn1_get_start_end_der( c2, cert->raw.data, cert->raw.size, tmpstr, &start1, &end1); asn1_delete_structure( c2); @@ -219,7 +220,7 @@ int compare_dn(gnutls_cert * cert, gnutls_cert * issuer_cert) len1 = end1 - start1 + 1; - strcpy( tmpstr, "certificate2.tbsCertificate.subject"); /* Flawfinder: ignore */ + _gnutls_str_cpy( tmpstr, sizeof(tmpstr), "certificate2.tbsCertificate.subject"); result = asn1_get_start_end_der( c3, issuer_cert->raw.data, issuer_cert->raw.size, tmpstr, &start2, &end2); asn1_delete_structure( c3);