From 5a4881bf396e691524329bcd6aa1ae4a7f4084ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 27 Dec 2005 20:52:36 +0000 Subject: r12522: Try and fix bug #2926 by removing setlocale(LC_ALL, "C") and replace calls to isupper/islower/toupper/tolower with ASCII equivalents (mapping into _w variants). Jeremy. (This used to be commit c2752347eb2deeb2798c580ec7fc751a847717e9) --- source3/auth/pass_check.c | 4 ++-- source3/client/clitar.c | 2 +- source3/include/smb.h | 3 +++ source3/lib/charcnv.c | 11 +-------- source3/lib/replace.c | 2 +- source3/lib/username.c | 4 ++-- source3/lib/util_str.c | 16 ++++++------- source3/lib/util_unistr.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ source3/passdb/passdb.c | 8 +++---- source3/passdb/pdb_pgsql.c | 2 +- source3/smbd/mangle_hash.c | 6 ++--- source3/smbd/mangle_hash2.c | 12 +++++----- source3/web/swat.c | 2 +- 13 files changed, 89 insertions(+), 39 deletions(-) (limited to 'source3') diff --git a/source3/auth/pass_check.c b/source3/auth/pass_check.c index 0425e01cdc..507e8a3836 100644 --- a/source3/auth/pass_check.c +++ b/source3/auth/pass_check.c @@ -452,9 +452,9 @@ static NTSTATUS string_combinations2(char *s, int offset, NTSTATUS (*fn) (const for (i = offset; i < (len - (N - 1)); i++) { char c = s[i]; - if (!islower(c)) + if (!islower_ascii(c)) continue; - s[i] = toupper(c); + s[i] = toupper_ascii(c); if (!NT_STATUS_EQUAL(nt_status = string_combinations2(s, i + 1, fn, N - 1),NT_STATUS_WRONG_PASSWORD)) { return (nt_status); } diff --git a/source3/client/clitar.c b/source3/client/clitar.c index 5afe154cbb..c15d24d619 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -482,7 +482,7 @@ static int strslashcmp(char *s1, char *s2) { char *s1_0=s1; - while(*s1 && *s2 && (*s1 == *s2 || tolower(*s1) == tolower(*s2) || + while(*s1 && *s2 && (*s1 == *s2 || tolower_ascii(*s1) == tolower_ascii(*s2) || (*s1 == '\\' && *s2=='/') || (*s1 == '/' && *s2=='\\'))) { s1++; s2++; } diff --git a/source3/include/smb.h b/source3/include/smb.h index fc256c6f69..4f378f822e 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -172,6 +172,9 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; /* turn a 7 bit character into a ucs2 character */ #define UCS2_CHAR(c) ((c) << UCS2_SHIFT) +/* return an ascii version of a ucs2 character */ +#define UCS2_TO_CHAR(c) ((c) & 0xff) + /* Copy into a smb_ucs2_t from a possibly unaligned buffer. Return the copied smb_ucs2_t */ #define COPY_UCS2_CHAR(dest,src) (((unsigned char *)(dest))[0] = ((unsigned char *)(src))[0],\ ((unsigned char *)(dest))[1] = ((unsigned char *)(src))[1], (dest)) diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 0c806167f4..c4eeab135e 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -84,15 +84,6 @@ static const char *charset_name(charset_t ch) } ret = ln; } -#ifdef HAVE_SETLOCALE - /* We set back the locale to C to get ASCII-compatible toupper/lower functions. - For now we do not need any other POSIX localisations anyway. When we should - really need localized string functions one day we need to write our own - ascii_tolower etc. - */ - setlocale(LC_ALL, "C"); - #endif - #endif if (!ret || !*ret) ret = "ASCII"; @@ -747,7 +738,7 @@ char *strdup_upper(const char *s) while (1) { if (*p & 0x80) break; - *q++ = toupper(*p); + *q++ = toupper_ascii(*p); if (!*p) break; p++; diff --git a/source3/lib/replace.c b/source3/lib/replace.c index 57ee6ea11e..120fd3a468 100644 --- a/source3/lib/replace.c +++ b/source3/lib/replace.c @@ -390,7 +390,7 @@ char *rep_inet_ntoa(struct in_addr ip) if (isdigit(c)) c -= '0'; else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; + c -= isupper_ascii(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) diff --git a/source3/lib/username.c b/source3/lib/username.c index ecfd5fef9e..7d66b320ad 100644 --- a/source3/lib/username.c +++ b/source3/lib/username.c @@ -716,9 +716,9 @@ static struct passwd *uname_string_combinations2(char *s,int offset,struct passw for (i=offset;i<(len-(N-1));i++) { char c = s[i]; - if (!islower((int)c)) + if (!islower_ascii((int)c)) continue; - s[i] = toupper(c); + s[i] = toupper_ascii(c); ret = uname_string_combinations2(s,i+1,fn,N-1); if(ret) return(ret); diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 80bb2ff2ad..0b02487f77 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -201,8 +201,8 @@ int StrCaseCmp(const char *s, const char *t) /* not ascii anymore, do it the hard way from here on in */ break; - us = toupper(*ps); - ut = toupper(*pt); + us = toupper_ascii(*ps); + ut = toupper_ascii(*pt); if (us == ut) continue; else if (us < ut) @@ -309,7 +309,7 @@ int strwicmp(const char *psz1, const char *psz2) psz1++; while (isspace((int)*psz2)) psz2++; - if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' + if (toupper_ascii(*psz1) != toupper_ascii(*psz2) || *psz1 == '\0' || *psz2 == '\0') break; psz1++; @@ -680,7 +680,7 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con for(i = 0; i < len; i++) { int val = (src[i] & 0xff); - if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val)) + if (isupper_ascii(val) || islower_ascii(val) || isdigit(val) || strchr_m(other_safe_chars, val)) dest[i] = src[i]; else dest[i] = '_'; @@ -774,12 +774,12 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex) continue; } - if (!(p1 = strchr_m(hexchars, toupper(strhex[i])))) + if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i])))) break; i++; /* next hex digit */ - if (!(p2 = strchr_m(hexchars, toupper(strhex[i])))) + if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i])))) break; /* get the two nybbles */ @@ -1510,7 +1510,7 @@ void strlower_m(char *s) (ie. they match for the first 128 chars) */ while (*s && !(((unsigned char)s[0]) & 0x80)) { - *s = tolower((unsigned char)*s); + *s = tolower_ascii((unsigned char)*s); s++; } @@ -1544,7 +1544,7 @@ void strupper_m(char *s) (ie. they match for the first 128 chars) */ while (*s && !(((unsigned char)s[0]) & 0x80)) { - *s = toupper((unsigned char)*s); + *s = toupper_ascii((unsigned char)*s); s++; } diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index b979745d36..880416a549 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -51,6 +51,7 @@ static uint8 doschar_table[8192]; /* 65536 characters / 8 bits/byte */ void load_case_tables(void) { static int initialised; + char *old_locale = NULL, *saved_locale = NULL; int i; if (initialised) { @@ -61,6 +62,17 @@ void load_case_tables(void) upcase_table = map_file(lib_path("upcase.dat"), 0x20000); lowcase_table = map_file(lib_path("lowcase.dat"), 0x20000); +#ifdef HAVE_SETLOCALE + /* Get the name of the current locale. */ + old_locale = setlocale(LC_ALL, NULL); + + /* Save it as it is in static storage. */ + saved_locale = SMB_STRDUP(old_locale); + + /* We set back the locale to C to get ASCII-compatible toupper/lower functions. */ + setlocale(LC_ALL, "C"); +#endif + /* we would like Samba to limp along even if these tables are not available */ if (!upcase_table) { @@ -92,6 +104,12 @@ void load_case_tables(void) lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i); } } + +#ifdef HAVE_SETLOCALE + /* Restore the old locale. */ + setlocale (LC_ALL, saved_locale); + SAFE_FREE(saved_locale); +#endif } /* @@ -997,3 +1015,41 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) return dst; } + +/************************************************************* + ascii only toupper - saves the need for smbd to be in C locale. +*************************************************************/ + +int toupper_ascii(int c) +{ + smb_ucs2_t uc = toupper_w(UCS2_CHAR(c)); + return UCS2_TO_CHAR(uc); +} + +/************************************************************* + ascii only tolower - saves the need for smbd to be in C locale. +*************************************************************/ + +int tolower_ascii(int c) +{ + smb_ucs2_t uc = tolower_w(UCS2_CHAR(c)); + return UCS2_TO_CHAR(uc); +} + +/************************************************************* + ascii only isupper - saves the need for smbd to be in C locale. +*************************************************************/ + +int isupper_ascii(int c) +{ + return isupper_w(UCS2_CHAR(c)); +} + +/************************************************************* + ascii only islower - saves the need for smbd to be in C locale. +*************************************************************/ + +int islower_ascii(int c) +{ + return islower_w(UCS2_CHAR(c)); +} diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 006161b663..ac4d255597 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -566,8 +566,8 @@ BOOL pdb_gethexpwd(const char *p, unsigned char *pwd) return (False); for (i = 0; i < 32; i += 2) { - hinybble = toupper(p[i]); - lonybble = toupper(p[i + 1]); + hinybble = toupper_ascii(p[i]); + lonybble = toupper_ascii(p[i + 1]); p1 = strchr(hexchars, hinybble); p2 = strchr(hexchars, lonybble); @@ -616,8 +616,8 @@ BOOL pdb_gethexhours(const char *p, unsigned char *hours) } for (i = 0; i < 42; i += 2) { - hinybble = toupper(p[i]); - lonybble = toupper(p[i + 1]); + hinybble = toupper_ascii(p[i]); + lonybble = toupper_ascii(p[i + 1]); p1 = strchr(hexchars, hinybble); p2 = strchr(hexchars, lonybble); diff --git a/source3/passdb/pdb_pgsql.c b/source3/passdb/pdb_pgsql.c index 632903c1ac..196fe8f855 100644 --- a/source3/passdb/pdb_pgsql.c +++ b/source3/passdb/pdb_pgsql.c @@ -368,7 +368,7 @@ static NTSTATUS pgsqlsam_getsampwnam ( struct pdb_methods *methods, SAM_ACCOUNT lowercasename = smb_xstrdup(sname); l = strlen(lowercasename); for(i = 0; i < l; i++) { - lowercasename[i] = tolower(lowercasename[i]); + lowercasename[i] = tolower_ascii(lowercasename[i]); } result = pgsqlsam_select_by_field( methods, user, SQL_SEARCH_USER_NAME, lowercasename ) ; diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index 30befd2c84..2092f430c0 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -372,8 +372,8 @@ static BOOL is_mangled(const char *s, int snum) magic = strchr_m( s, magic_char ); while( magic && magic[1] && magic[2] ) { /* 3 chars, 1st is magic. */ if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */ - && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */ - && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */ + && isbasechar( toupper_ascii(magic[1]) ) /* is 2nd char basechar? */ + && isbasechar( toupper_ascii(magic[2]) ) ) /* is 3rd char basechar? */ return( True ); /* If all above, then true, */ magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */ } @@ -426,7 +426,7 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name ) s1 = strrchr( mangled_name_key, '.' ); if( s1 && (s2 = strrchr( raw_name, '.' )) ) { size_t i = 1; - while( s1[i] && (tolower( s1[i] ) == s2[i]) ) + while( s1[i] && (tolower_ascii( s1[i] ) == s2[i]) ) i++; if( !s1[i] && !s2[i] ) { /* Truncate at the '.' */ diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 335ba8e2ef..0a161c9e76 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -560,7 +560,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) { lead_chars[i] = '_'; } - lead_chars[i] = toupper(lead_chars[i]); + lead_chars[i] = toupper_ascii(lead_chars[i]); } for (;i