Skip to content

Commit

Permalink
Public API functions OPENSSL_str[n]casecmp
Browse files Browse the repository at this point in the history
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from openssl#18069)
  • Loading branch information
beldmit committed Apr 22, 2022
1 parent 5adddcd commit 4b2bd27
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 2 deletions.
78 changes: 78 additions & 0 deletions crypto/ctype.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@
#include "crypto/ctype.h"
#include <openssl/ebcdic.h>

#include "internal/e_os.h"
#include "internal/core.h"

#ifndef OPENSSL_SYS_WINDOWS
#include <strings.h>
#endif
#include <locale.h>

#ifdef OPENSSL_SYS_MACOSX
#include <xlocale.h>
#endif

/*
* Define the character classes for each character in the seven bit ASCII
* character set. This is independent of the host's character set, characters
Expand Down Expand Up @@ -278,3 +290,69 @@ int ossl_ascii_isdigit(const char inchar) {
return 1;
return 0;
}

/* str[n]casecmp_l is defined in POSIX 2008-01. Value is taken accordingly
* https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */

#if (defined OPENSSL_SYS_WINDOWS) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L)

# if defined OPENSSL_SYS_WINDOWS
# define locale_t _locale_t
# define freelocale _free_locale
# define strcasecmp_l _stricmp_l
# define strncasecmp_l _strnicmp_l
# endif
static locale_t loc;

# ifndef FIPS_MODULE
void *ossl_c_locale() {
return (void *)loc;
}
# endif

int ossl_init_casecmp_int() {
# ifdef OPENSSL_SYS_WINDOWS
loc = _create_locale(LC_COLLATE, "C");
# else
loc = newlocale(LC_COLLATE_MASK, "C", (locale_t) 0);
# endif
return (loc == (locale_t) 0) ? 0 : 1;
}

void ossl_deinit_casecmp() {
freelocale(loc);
}

int OPENSSL_strcasecmp(const char *s1, const char *s2)
{
return strcasecmp_l(s1, s2, (locale_t)ossl_c_locale());
}

int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n)
{
return strncasecmp_l(s1, s2, n, (locale_t)ossl_c_locale());
}
#else
# ifndef FIPS_MODULE
void *ossl_c_locale() {
return NULL;
}
# endif

int ossl_init_casecmp_int() {
return 1;
}

void ossl_deinit_casecmp() {
}

int OPENSSL_strcasecmp(const char *s1, const char *s2)
{
return strcasecmp(s1, s2);
}

int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n)
{
return strncasecmp(s1, s2, n);
}
#endif
18 changes: 18 additions & 0 deletions crypto/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "crypto/store.h"
#include <openssl/cmp_util.h> /* for OSSL_CMP_log_close() */
#include <openssl/trace.h>
#include "crypto/ctype.h"

static int stopped = 0;
static uint64_t optsdone = 0;
Expand Down Expand Up @@ -270,6 +271,15 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_async)
return 1;
}

static CRYPTO_ONCE casecmp = CRYPTO_ONCE_STATIC_INIT;
static int casecmp_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_casecmp)
{
int ret = ossl_init_casecmp_int();

casecmp_inited = 1;
return ret;
}
#ifndef OPENSSL_NO_ENGINE
static CRYPTO_ONCE engine_openssl = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl)
Expand Down Expand Up @@ -387,6 +397,11 @@ void OPENSSL_cleanup(void)
async_deinit();
}

if (casecmp_inited) {
OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_deinit_casecmp()\n");
ossl_deinit_casecmp();
}

if (load_crypto_strings_inited) {
OSSL_TRACE(INIT, "OPENSSL_cleanup: err_free_strings_int()\n");
err_free_strings_int();
Expand Down Expand Up @@ -459,6 +474,9 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
{
uint64_t tmp;
int aloaddone = 0;
if (!RUN_ONCE(&casecmp, ossl_init_casecmp))
return 0;


/* Applications depend on 0 being returned when cleanup was already done */
if (stopped) {
Expand Down
6 changes: 6 additions & 0 deletions doc/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -1531,6 +1531,10 @@ DEPEND[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
GENERATE[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
DEPEND[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
GENERATE[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
DEPEND[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
GENERATE[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
DEPEND[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
GENERATE[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
DEPEND[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
GENERATE[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
DEPEND[man/man3/OSSL_CMP_CTX_new.3]=man3/OSSL_CMP_CTX_new.pod
Expand Down Expand Up @@ -3110,6 +3114,7 @@ html/man3/OPENSSL_load_builtin_modules.html \
html/man3/OPENSSL_malloc.html \
html/man3/OPENSSL_s390xcap.html \
html/man3/OPENSSL_secure_malloc.html \
html/man3/OPENSSL_strcasecmp.html \
html/man3/OSSL_CMP_CTX_new.html \
html/man3/OSSL_CMP_HDR_get0_transactionID.html \
html/man3/OSSL_CMP_ITAV_set0.html \
Expand Down Expand Up @@ -3704,6 +3709,7 @@ man/man3/OPENSSL_load_builtin_modules.3 \
man/man3/OPENSSL_malloc.3 \
man/man3/OPENSSL_s390xcap.3 \
man/man3/OPENSSL_secure_malloc.3 \
man/man3/OPENSSL_strcasecmp.3 \
man/man3/OSSL_CMP_CTX_new.3 \
man/man3/OSSL_CMP_HDR_get0_transactionID.3 \
man/man3/OSSL_CMP_ITAV_set0.3 \
Expand Down
47 changes: 47 additions & 0 deletions doc/man3/OPENSSL_strcasecmp.pod
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
=pod

=head1 NAME

OPENSSL_strcasecmp, OPENSSL_strncasecmp - compare two strings ignoring case

=head1 SYNOPSIS

#include <openssl/crypto.h>

int OPENSSL_strcasecmp(const char *s1, const char *s2);
int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n);

=head1 DESCRIPTION

The OPENSSL_strcasecmp function performs a byte-by-byte comparison of the strings
B<s1> and B<s2>, ignoring the case of the characters.

The OPENSSL_strncasecmp function is similar, except that it compares no more than
B<n> bytes of B<s1> and B<s2>.

In POSIX-compatible system and on Windows these functions use "C" locale for
case insensitive. Otherwise the comparison is done in current locale.

=head1 RETURN VALUES

Both functions return an integer less than, equal to, or greater than zero if
s1 is found, respectively, to be less than, to match, or be greater than s2.

=head1 NOTES

OpenSSL extensively uses case insensitive comparison of ASCII strings. Though
OpenSSL itself is locale-agnostic, the applications using OpenSSL libraries may
unpredictably suffer when they use localization (e.g. Turkish locale is
well-known with a specific I/i cases). These functions use C locale for string
comparison.

=head1 COPYRIGHT

Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.

=cut
2 changes: 2 additions & 0 deletions include/crypto/ctype.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,6 @@ int ossl_ascii_isdigit(const char inchar);
# define ossl_isbase64(c) (ossl_ctype_check((c), CTYPE_MASK_base64))
# define ossl_isasn1print(c) (ossl_ctype_check((c), CTYPE_MASK_asn1print))

int ossl_init_casecmp_int(void);
void ossl_deinit_casecmp(void);
#endif
2 changes: 2 additions & 0 deletions include/internal/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,6 @@ __owur int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx);
int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx);
int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx);

void *ossl_c_locale(void);

#endif
2 changes: 0 additions & 2 deletions include/internal/e_os.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,6 @@ FILE *__iob_func();
/***********************************************/

# if defined(OPENSSL_SYS_WINDOWS)
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
# if (_MSC_VER >= 1310) && !defined(_WIN32_WCE)
# define open _open
# define fdopen _fdopen
Expand Down
2 changes: 2 additions & 0 deletions include/openssl/crypto.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen,
const char *str, const char sep);
unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen);
int OPENSSL_hexchar2int(unsigned char c);
int OPENSSL_strcasecmp(const char *s1, const char *s2);
int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n);

# define OPENSSL_MALLOC_MAX_NELEMS(type) (((1U<<(sizeof(int)*8-1))-1)/sizeof(type))

Expand Down
2 changes: 2 additions & 0 deletions util/libcrypto.num
Original file line number Diff line number Diff line change
Expand Up @@ -5438,3 +5438,5 @@ ASYNC_set_mem_functions ? 3_1_0 EXIST::FUNCTION:
ASYNC_get_mem_functions ? 3_1_0 EXIST::FUNCTION:
BIO_ADDR_dup ? 3_1_0 EXIST::FUNCTION:SOCK
CMS_final_digest ? 3_1_0 EXIST::FUNCTION:CMS
OPENSSL_strcasecmp ? 3_0_3 EXIST::FUNCTION:
OPENSSL_strncasecmp ? 3_0_3 EXIST::FUNCTION:

0 comments on commit 4b2bd27

Please sign in to comment.