Skip to content

Commit 130de70

Browse files
committed
Public API functions OPENSSL_str[n]casecmp
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from #18103)
1 parent 455e158 commit 130de70

File tree

10 files changed

+171
-3
lines changed

10 files changed

+171
-3
lines changed

crypto/context.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "internal/core.h"
1515
#include "internal/bio.h"
1616
#include "internal/provider.h"
17+
#include "crypto/ctype.h"
1718

1819
struct ossl_lib_ctx_onfree_list_st {
1920
ossl_lib_ctx_onfree_fn *fn;
@@ -150,7 +151,8 @@ static CRYPTO_THREAD_LOCAL default_context_thread_local;
150151
DEFINE_RUN_ONCE_STATIC(default_context_do_init)
151152
{
152153
return CRYPTO_THREAD_init_local(&default_context_thread_local, NULL)
153-
&& context_init(&default_context_int);
154+
&& context_init(&default_context_int)
155+
&& ossl_init_casecmp();
154156
}
155157

156158
void ossl_lib_ctx_default_deinit(void)

crypto/ctype.c

+100
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@
1212
#include "crypto/ctype.h"
1313
#include <openssl/ebcdic.h>
1414

15+
#include <openssl/crypto.h>
16+
#include "internal/core.h"
17+
#include "internal/thread_once.h"
18+
19+
#ifndef OPENSSL_SYS_WINDOWS
20+
#include <strings.h>
21+
#endif
22+
#include <locale.h>
23+
24+
#ifdef OPENSSL_SYS_MACOSX
25+
#include <xlocale.h>
26+
#endif
27+
1528
/*
1629
* Define the character classes for each character in the seven bit ASCII
1730
* character set. This is independent of the host's character set, characters
@@ -278,3 +291,90 @@ int ossl_ascii_isdigit(const char inchar) {
278291
return 1;
279292
return 0;
280293
}
294+
295+
/* str[n]casecmp_l is defined in POSIX 2008-01. Value is taken accordingly
296+
* https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */
297+
298+
#if (defined OPENSSL_SYS_WINDOWS) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L)
299+
300+
# if defined OPENSSL_SYS_WINDOWS
301+
# define locale_t _locale_t
302+
# define freelocale _free_locale
303+
# define strcasecmp_l _stricmp_l
304+
# define strncasecmp_l _strnicmp_l
305+
# endif
306+
307+
# ifndef FIPS_MODULE
308+
static locale_t loc;
309+
310+
static int locale_base_inited = 0;
311+
static CRYPTO_ONCE locale_base = CRYPTO_ONCE_STATIC_INIT;
312+
static CRYPTO_ONCE locale_base_deinit = CRYPTO_ONCE_STATIC_INIT;
313+
314+
void *ossl_c_locale() {
315+
return (void *)loc;
316+
}
317+
318+
DEFINE_RUN_ONCE_STATIC(ossl_init_locale_base)
319+
{
320+
# ifdef OPENSSL_SYS_WINDOWS
321+
loc = _create_locale(LC_COLLATE, "C");
322+
# else
323+
loc = newlocale(LC_COLLATE_MASK, "C", (locale_t) 0);
324+
# endif
325+
locale_base_inited = 1;
326+
return (loc == (locale_t) 0) ? 0 : 1;
327+
}
328+
329+
DEFINE_RUN_ONCE_STATIC(ossl_deinit_locale_base)
330+
{
331+
if (locale_base_inited && loc) {
332+
freelocale(loc);
333+
loc = NULL;
334+
}
335+
return 1;
336+
}
337+
338+
int ossl_init_casecmp()
339+
{
340+
return RUN_ONCE(&locale_base, ossl_init_locale_base);
341+
}
342+
343+
void ossl_deinit_casecmp() {
344+
(void)RUN_ONCE(&locale_base_deinit, ossl_deinit_locale_base);
345+
}
346+
# endif
347+
348+
int OPENSSL_strcasecmp(const char *s1, const char *s2)
349+
{
350+
return strcasecmp_l(s1, s2, (locale_t)ossl_c_locale());
351+
}
352+
353+
int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n)
354+
{
355+
return strncasecmp_l(s1, s2, n, (locale_t)ossl_c_locale());
356+
}
357+
#else
358+
# ifndef FIPS_MODULE
359+
void *ossl_c_locale() {
360+
return NULL;
361+
}
362+
# endif
363+
364+
int ossl_init_casecmp() {
365+
return 1;
366+
}
367+
368+
void ossl_deinit_casecmp() {
369+
}
370+
371+
int OPENSSL_strcasecmp(const char *s1, const char *s2)
372+
{
373+
return strcasecmp(s1, s2);
374+
}
375+
376+
int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n)
377+
{
378+
return strncasecmp(s1, s2, n);
379+
}
380+
#endif

crypto/init.c

+7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "crypto/store.h"
3333
#include <openssl/cmp_util.h> /* for OSSL_CMP_log_close() */
3434
#include <openssl/trace.h>
35+
#include "crypto/ctype.h"
3536

3637
static int stopped = 0;
3738
static uint64_t optsdone = 0;
@@ -447,6 +448,9 @@ void OPENSSL_cleanup(void)
447448
OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_trace_cleanup()\n");
448449
ossl_trace_cleanup();
449450

451+
OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_deinit_casecmp()\n");
452+
ossl_deinit_casecmp();
453+
450454
base_inited = 0;
451455
}
452456

@@ -460,6 +464,9 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
460464
uint64_t tmp;
461465
int aloaddone = 0;
462466

467+
if (!ossl_init_casecmp())
468+
return 0;
469+
463470
/* Applications depend on 0 being returned when cleanup was already done */
464471
if (stopped) {
465472
if (!(opts & OPENSSL_INIT_BASE_ONLY))

doc/build.info

+6
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,10 @@ DEPEND[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
15311531
GENERATE[html/man3/OPENSSL_secure_malloc.html]=man3/OPENSSL_secure_malloc.pod
15321532
DEPEND[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
15331533
GENERATE[man/man3/OPENSSL_secure_malloc.3]=man3/OPENSSL_secure_malloc.pod
1534+
DEPEND[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
1535+
GENERATE[html/man3/OPENSSL_strcasecmp.html]=man3/OPENSSL_strcasecmp.pod
1536+
DEPEND[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
1537+
GENERATE[man/man3/OPENSSL_strcasecmp.3]=man3/OPENSSL_strcasecmp.pod
15341538
DEPEND[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
15351539
GENERATE[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
15361540
DEPEND[man/man3/OSSL_CMP_CTX_new.3]=man3/OSSL_CMP_CTX_new.pod
@@ -3110,6 +3114,7 @@ html/man3/OPENSSL_load_builtin_modules.html \
31103114
html/man3/OPENSSL_malloc.html \
31113115
html/man3/OPENSSL_s390xcap.html \
31123116
html/man3/OPENSSL_secure_malloc.html \
3117+
html/man3/OPENSSL_strcasecmp.html \
31133118
html/man3/OSSL_CMP_CTX_new.html \
31143119
html/man3/OSSL_CMP_HDR_get0_transactionID.html \
31153120
html/man3/OSSL_CMP_ITAV_set0.html \
@@ -3704,6 +3709,7 @@ man/man3/OPENSSL_load_builtin_modules.3 \
37043709
man/man3/OPENSSL_malloc.3 \
37053710
man/man3/OPENSSL_s390xcap.3 \
37063711
man/man3/OPENSSL_secure_malloc.3 \
3712+
man/man3/OPENSSL_strcasecmp.3 \
37073713
man/man3/OSSL_CMP_CTX_new.3 \
37083714
man/man3/OSSL_CMP_HDR_get0_transactionID.3 \
37093715
man/man3/OSSL_CMP_ITAV_set0.3 \

doc/man3/OPENSSL_strcasecmp.pod

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
=pod
2+
3+
=head1 NAME
4+
5+
OPENSSL_strcasecmp, OPENSSL_strncasecmp - compare two strings ignoring case
6+
7+
=head1 SYNOPSIS
8+
9+
#include <openssl/crypto.h>
10+
11+
int OPENSSL_strcasecmp(const char *s1, const char *s2);
12+
int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n);
13+
14+
=head1 DESCRIPTION
15+
16+
The OPENSSL_strcasecmp function performs a byte-by-byte comparison of the strings
17+
B<s1> and B<s2>, ignoring the case of the characters.
18+
19+
The OPENSSL_strncasecmp function is similar, except that it compares no more than
20+
B<n> bytes of B<s1> and B<s2>.
21+
22+
In POSIX-compatible system and on Windows these functions use "C" locale for
23+
case insensitive. Otherwise the comparison is done in current locale.
24+
25+
=head1 RETURN VALUES
26+
27+
Both functions return an integer less than, equal to, or greater than zero if
28+
s1 is found, respectively, to be less than, to match, or be greater than s2.
29+
30+
=head1 NOTES
31+
32+
OpenSSL extensively uses case insensitive comparison of ASCII strings. Though
33+
OpenSSL itself is locale-agnostic, the applications using OpenSSL libraries may
34+
unpredictably suffer when they use localization (e.g. Turkish locale is
35+
well-known with a specific I/i cases). These functions use C locale for string
36+
comparison.
37+
38+
=head1 COPYRIGHT
39+
40+
Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
41+
42+
Licensed under the Apache License 2.0 (the "License"). You may not use
43+
this file except in compliance with the License. You can obtain a copy
44+
in the file LICENSE in the source distribution or at
45+
L<https://www.openssl.org/source/license.html>.
46+
47+
=cut

e_os.h

-2
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,6 @@ FILE *__iob_func();
249249
/***********************************************/
250250

251251
# if defined(OPENSSL_SYS_WINDOWS)
252-
# define strcasecmp _stricmp
253-
# define strncasecmp _strnicmp
254252
# if (_MSC_VER >= 1310) && !defined(_WIN32_WCE)
255253
# define open _open
256254
# define fdopen _fdopen

include/crypto/ctype.h

+2
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,6 @@ int ossl_ascii_isdigit(const char inchar);
8080
# define ossl_isbase64(c) (ossl_ctype_check((c), CTYPE_MASK_base64))
8181
# define ossl_isasn1print(c) (ossl_ctype_check((c), CTYPE_MASK_asn1print))
8282

83+
int ossl_init_casecmp(void);
84+
void ossl_deinit_casecmp(void);
8385
#endif

include/internal/core.h

+2
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,6 @@ __owur int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx);
6363
int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx);
6464
int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx);
6565

66+
void *ossl_c_locale(void);
67+
6668
#endif

include/openssl/crypto.h.in

+2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen,
133133
const char *str, const char sep);
134134
unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen);
135135
int OPENSSL_hexchar2int(unsigned char c);
136+
int OPENSSL_strcasecmp(const char *s1, const char *s2);
137+
int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n);
136138

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

util/libcrypto.num

+2
Original file line numberDiff line numberDiff line change
@@ -5425,3 +5425,5 @@ ASN1_item_d2i_ex 5552 3_0_0 EXIST::FUNCTION:
54255425
ASN1_TIME_print_ex 5553 3_0_0 EXIST::FUNCTION:
54265426
EVP_PKEY_get0_provider 5554 3_0_0 EXIST::FUNCTION:
54275427
EVP_PKEY_CTX_get0_provider 5555 3_0_0 EXIST::FUNCTION:
5428+
OPENSSL_strcasecmp ? 3_0_3 EXIST::FUNCTION:
5429+
OPENSSL_strncasecmp ? 3_0_3 EXIST::FUNCTION:

0 commit comments

Comments
 (0)