Print this page
NEX-19025 CIFS gets confused with filenames containing enhanced Unicode
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
and: (fix build, check-rtime)
NEX-4458 Incorrect directory listing response for non-UNICODE clients
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2460 libfksmbd should not link with libsmb
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/common/smbsrv/smb_oem.c
+++ new/usr/src/common/smbsrv/smb_oem.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * Support for oem <-> unicode translations.
30 30 */
31 31
32 32 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
33 33 #include <stdlib.h>
34 34 #include <thread.h>
35 35 #include <synch.h>
36 36 #include <string.h>
37 37 #else
38 +#include <sys/types.h>
38 39 #include <sys/ksynch.h>
40 +#include <sys/sunddi.h>
39 41 #endif /* _KERNEL */
40 42
41 43 #include <sys/byteorder.h>
42 44 #include <smbsrv/alloc.h>
43 45 #include <smbsrv/string.h>
44 46
45 47 /*
46 48 * cpid The oemcpg_table index for this oempage.
47 49 * value The conversion values.
48 50 */
49 51 typedef struct oempage {
50 52 uint32_t cpid;
51 53 smb_wchar_t *value;
52 54 } oempage_t;
53 55
54 56 /*
55 57 * filename The actual filename contains the codepage.
56 58 * bytesperchar The codepage uses double or single bytes per char.
57 59 * oempage The oempage is used to convert Unicode characters to
58 60 * OEM characters. Memory needs to be allocated for
59 61 * the value field of oempage to store the table.
60 62 * ucspage The unicode page is used to convert OEM characters
61 63 * to Unicode characters. Memory needs to be allocated
62 64 * for the value field of ucspage to store the table.
63 65 * valid True if the codepage has been initialized.
64 66 */
65 67 typedef struct oem_codepage {
66 68 char *filename;
67 69 uint32_t bytesperchar;
68 70 oempage_t oempage;
69 71 oempage_t ucspage;
70 72 boolean_t valid;
71 73 } oem_codepage_t;
72 74
73 75 static oem_codepage_t oemcpg_table[] = {
74 76 {"850.cpg", 1, {0, 0}, {0, 0}, 0}, /* Multilingual Latin1 */
75 77 {"950.cpg", 2, {1, 0}, {1, 0}, 0}, /* Chinese Traditional */
76 78 {"1252.cpg", 1, {2, 0}, {2, 0}, 0}, /* MS Latin1 */
77 79 {"949.cpg", 2, {3, 0}, {3, 0}, 0}, /* Korean */
78 80 {"936.cpg", 2, {4, 0}, {4, 0}, 0}, /* Chinese Simplified */
79 81 {"932.cpg", 2, {5, 0}, {5, 0}, 0}, /* Japanese */
80 82 {"852.cpg", 1, {6, 0}, {6, 0}, 0}, /* Multilingual Latin2 */
81 83 {"1250.cpg", 1, {7, 0}, {7, 0}, 0}, /* MS Latin2 */
82 84 {"1253.cpg", 1, {8, 0}, {8, 0}, 0}, /* MS Greek */
83 85 {"737.cpg", 1, {9, 0}, {9, 0}, 0}, /* Greek */
84 86 {"1254.cpg", 1, {10, 0}, {10, 0}, 0}, /* MS Turkish */
85 87 {"857.cpg", 1, {11, 0}, {11, 0}, 0}, /* Multilingual Latin5 */
86 88 {"1251.cpg", 1, {12, 0}, {12, 0}, 0}, /* MS Cyrillic */
87 89 {"866.cpg", 1, {13, 0}, {13, 0}, 0}, /* Cyrillic II */
88 90 {"1255.cpg", 1, {14, 0}, {14, 0}, 0}, /* MS Hebrew */
89 91 {"862.cpg", 1, {15, 0}, {15, 0}, 0}, /* Hebrew */
90 92 {"1256.cpg", 1, {16, 0}, {16, 0}, 0}, /* MS Arabic */
91 93 {"720.cpg", 1, {17, 0}, {17, 0}, 0} /* Arabic */
92 94 };
93 95
94 96 #define MAX_OEMPAGES (sizeof (oemcpg_table) / sizeof (oemcpg_table[0]))
95 97 #define MAX_UNICODE_IDX 65536
96 98
97 99 /*
98 100 * The default SMB OEM codepage for English is codepage 850.
99 101 */
100 102 const smb_wchar_t oem_codepage_850[256] = {
101 103 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
102 104 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
103 105 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
104 106 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
105 107 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
106 108 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
107 109 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
108 110 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
109 111 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
110 112 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
111 113 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
112 114 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
113 115 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
114 116 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
115 117 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
116 118 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
117 119 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
118 120 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
119 121 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
120 122 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
121 123 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
122 124 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
123 125 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
124 126 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
125 127 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
126 128 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
127 129 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
128 130 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
129 131 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
130 132 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
131 133 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
132 134 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
133 135 };
134 136
135 137 /*
136 138 * The default telnet OEM codepage for English is codepage 1252.
137 139 */
138 140 const smb_wchar_t oem_codepage_1252[256] = {
139 141 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
140 142 0x9, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x10,
141 143 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
142 144 0x19, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x20,
143 145 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
144 146 0x29, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x30,
145 147 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
146 148 0x39, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x40,
147 149 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
148 150 0x49, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x50,
149 151 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
150 152 0x59, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x60,
151 153 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
152 154 0x69, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x70,
153 155 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
154 156 0x79, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC,
155 157 0x81, 0x201A, 0x192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6,
156 158 0x2030, 0x160, 0x2039, 0x152, 0x8D, 0x017D, 0x8F, 0x90,
157 159 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC,
158 160 0x2122, 0x161, 0x203A, 0x153, 0x9D, 0x017E, 0x178, 0x00A0,
159 161 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8,
160 162 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0,
161 163 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8,
162 164 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0,
163 165 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8,
164 166 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0,
165 167 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8,
166 168 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0,
167 169 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8,
168 170 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0,
169 171 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8,
170 172 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
171 173 };
172 174
173 175 static oempage_t *oem_get_oempage(uint32_t);
174 176 static oempage_t *oem_get_ucspage(uint32_t);
175 177 static void oem_codepage_init(uint32_t);
176 178 static void oem_codepage_setup(uint32_t);
177 179
178 180 /*
179 181 * Convert a unicode string to an oem string.
180 182 *
181 183 * The conversion will stop at the end of the unicode string
182 184 * or when (nbytes - 1) oem characters have been stored.
183 185 *
184 186 * The number of converted unicode characters is returned,
185 187 * or 0 on error.
186 188 */
187 189 size_t
188 190 ucstooem(char *oem, const smb_wchar_t *ucs, size_t nbytes, uint32_t cpid)
189 191 {
190 192 oempage_t *ucspage;
191 193 uint32_t count = 0;
192 194 smb_wchar_t oemchar;
193 195
194 196 if (ucs == NULL || oem == NULL)
195 197 return (0);
196 198
197 199 if ((ucspage = oem_get_ucspage(cpid)) == NULL)
198 200 return (0);
199 201
200 202 while (nbytes != 0 && (oemchar = ucspage->value[*ucs]) != 0) {
201 203 if (oemchar & 0xff00 && nbytes >= MTS_MB_CHAR_MAX) {
202 204 *oem++ = oemchar >> 8;
203 205 *oem++ = (char)oemchar;
204 206 nbytes -= 2;
205 207 } else if (nbytes > 1) {
206 208 *oem++ = (char)oemchar;
207 209 nbytes--;
208 210 } else {
209 211 break;
210 212 }
211 213
212 214 count++;
213 215 ucs++;
214 216 }
215 217
216 218 *oem = '\0';
217 219 return (count);
218 220 }
219 221
220 222 /*
221 223 * Convert an oem string to a unicode string.
222 224 *
223 225 * The conversion will stop at the end of the oem string or
224 226 * when nwchars - 1 have been converted.
225 227 *
226 228 * The number of converted oem chars is returned, or 0 on error.
227 229 * An oem char may be either 1 or 2 bytes.
228 230 */
229 231 size_t
230 232 oemtoucs(smb_wchar_t *ucs, const char *oem, size_t nwchars, uint32_t cpid)
231 233 {
232 234 oempage_t *oempage;
233 235 size_t count = nwchars;
234 236 smb_wchar_t oemchar;
235 237
236 238 if (ucs == NULL || oem == NULL)
237 239 return (0);
238 240
239 241 if ((oempage = oem_get_oempage(cpid)) == NULL)
240 242 return (0);
241 243
242 244 while ((oemchar = (smb_wchar_t)*oem++ & 0xff) != 0) {
243 245 /*
244 246 * Cannot find one byte oemchar in table.
245 247 * Must be a lead byte. Try two bytes.
246 248 */
247 249 if ((oempage->value[oemchar] == 0) && (oemchar != 0)) {
248 250 oemchar = oemchar << 8 | (*oem++ & 0xff);
249 251 if (oempage->value[oemchar] == 0) {
250 252 *ucs = 0;
251 253 break;
252 254 }
253 255 }
254 256 #ifdef _BIG_ENDIAN
255 257 *ucs = LE_IN16(&oempage->value[oemchar]);
256 258 #else
257 259 *ucs = oempage->value[oemchar];
258 260 #endif
259 261 count--;
260 262 ucs++;
261 263 }
262 264
263 265 *ucs = 0;
264 266 return (nwchars - count);
265 267 }
266 268
267 269 /*
268 270 * Get a pointer to the oem page for the specific codepage id.
269 271 */
270 272 static oempage_t *
271 273 oem_get_oempage(uint32_t cpid)
272 274 {
273 275 if (cpid >= MAX_OEMPAGES)
274 276 return (NULL);
275 277
276 278 if (!oemcpg_table[cpid].valid) {
277 279 oem_codepage_init(cpid);
278 280
279 281 if (!oemcpg_table[cpid].valid)
280 282 return (NULL);
281 283 }
282 284
283 285 return (&oemcpg_table[cpid].oempage);
284 286 }
285 287
286 288 /*
287 289 * Get a pointer to the ucs page for the specific codepage id.
288 290 */
289 291 static oempage_t *
290 292 oem_get_ucspage(uint32_t cpid)
291 293 {
292 294 if (cpid >= MAX_OEMPAGES)
293 295 return (NULL);
294 296
295 297 if (!oemcpg_table[cpid].valid) {
296 298 oem_codepage_init(cpid);
297 299
298 300 if (!oemcpg_table[cpid].valid)
299 301 return (NULL);
300 302 }
301 303
302 304 return (&oemcpg_table[cpid].ucspage);
303 305 }
304 306
305 307 /*
306 308 * Initialize the oem page in the oem table.
307 309 */
308 310 static void
309 311 oem_codepage_init(uint32_t cpid)
310 312 {
311 313 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
312 314 static mutex_t mutex;
313 315
314 316 (void) mutex_lock(&mutex);
315 317 oem_codepage_setup(cpid);
316 318 (void) mutex_unlock(&mutex);
317 319 #else
318 320 static kmutex_t mutex;
319 321
320 322 mutex_enter(&mutex);
321 323 oem_codepage_setup(cpid);
322 324 mutex_exit(&mutex);
323 325 #endif /* _KERNEL */
324 326 }
325 327
326 328 static void
327 329 oem_codepage_setup(uint32_t cpid)
328 330 {
329 331 const smb_wchar_t *default_oem_cp;
330 332 oem_codepage_t *oemcpg;
331 333 uint32_t bytesperchar;
332 334 uint32_t max_oem_index;
333 335 int i;
334 336
335 337 switch (cpid) {
336 338 case OEM_CPG_850:
337 339 default_oem_cp = oem_codepage_850;
338 340 break;
339 341 case OEM_CPG_1252:
340 342 default_oem_cp = oem_codepage_1252;
341 343 default:
342 344 return;
343 345 }
344 346
345 347 oemcpg = &oemcpg_table[cpid];
346 348 if (oemcpg->valid)
347 349 return;
348 350
349 351 /*
350 352 * max_oem_index will be 256 or 65536 dependent
351 353 * on the OEM codepage.
352 354 */
353 355 bytesperchar = oemcpg_table[cpid].bytesperchar;
354 356 max_oem_index = 1 << (bytesperchar * 8);
355 357
356 358 oemcpg->oempage.value =
357 359 MEM_ZALLOC("oem", max_oem_index * sizeof (smb_wchar_t));
358 360 if (oemcpg->oempage.value == NULL)
359 361 return;
360 362
361 363 oemcpg->ucspage.value =
362 364 MEM_ZALLOC("oem", MAX_UNICODE_IDX * sizeof (smb_wchar_t));
363 365 if (oemcpg->ucspage.value == NULL) {
364 366 MEM_FREE("oem", oemcpg->oempage.value);
365 367 oemcpg->oempage.value = NULL;
366 368 return;
367 369 }
368 370
369 371 for (i = 0; i < max_oem_index; i++) {
370 372 oemcpg->oempage.value[i] = default_oem_cp[i];
371 373 oemcpg->ucspage.value[default_oem_cp[i]] = (smb_wchar_t)i;
372 374 }
373 375
374 376 oemcpg->valid = B_TRUE;
375 377 }
|
↓ open down ↓ |
327 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX