~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/smbd/mangle_hash.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   Unix SMB/CIFS implementation.
3
 
   Name mangling
4
 
   Copyright (C) Andrew Tridgell 1992-2002
5
 
   Copyright (C) Simo Sorce 2001
6
 
   Copyright (C) Andrew Bartlett 2002
7
 
   
8
 
   This program is free software; you can redistribute it and/or modify
9
 
   it under the terms of the GNU General Public License as published by
10
 
   the Free Software Foundation; either version 2 of the License, or
11
 
   (at your option) any later version.
12
 
   
13
 
   This program is distributed in the hope that it will be useful,
14
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
   GNU General Public License for more details.
17
 
   
18
 
   You should have received a copy of the GNU General Public License
19
 
   along with this program; if not, write to the Free Software
20
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 
*/
22
 
 
23
 
#include "includes.h"
24
 
 
25
 
/* -------------------------------------------------------------------------- **
26
 
 * Other stuff...
27
 
 *
28
 
 * magic_char     - This is the magic char used for mangling.  It's
29
 
 *                  global.  There is a call to lp_magicchar() in server.c
30
 
 *                  that is used to override the initial value.
31
 
 *
32
 
 * MANGLE_BASE    - This is the number of characters we use for name mangling.
33
 
 *
34
 
 * basechars      - The set characters used for name mangling.  This
35
 
 *                  is static (scope is this file only).
36
 
 *
37
 
 * mangle()       - Macro used to select a character from basechars (i.e.,
38
 
 *                  mangle(n) will return the nth digit, modulo MANGLE_BASE).
39
 
 *
40
 
 * chartest       - array 0..255.  The index range is the set of all possible
41
 
 *                  values of a byte.  For each byte value, the content is a
42
 
 *                  two nibble pair.  See BASECHAR_MASK below.
43
 
 *
44
 
 * ct_initialized - False until the chartest array has been initialized via
45
 
 *                  a call to init_chartest().
46
 
 *
47
 
 * BASECHAR_MASK  - Masks the upper nibble of a one-byte value.
48
 
 *
49
 
 * isbasecahr()   - Given a character, check the chartest array to see
50
 
 *                  if that character is in the basechars set.  This is
51
 
 *                  faster than using strchr_m().
52
 
 *
53
 
 */
54
 
 
55
 
char magic_char = '~';
56
 
 
57
 
static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
58
 
#define MANGLE_BASE       (sizeof(basechars)/sizeof(char)-1)
59
 
 
60
 
static unsigned char chartest[256]  = { 0 };
61
 
static BOOL          ct_initialized = False;
62
 
 
63
 
#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
64
 
#define BASECHAR_MASK 0xf0
65
 
#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK )
66
 
 
67
 
static TDB_CONTEXT *tdb_mangled_cache;
68
 
 
69
 
/* -------------------------------------------------------------------- */
70
 
 
71
 
static NTSTATUS has_valid_83_chars(const smb_ucs2_t *s, BOOL allow_wildcards)
72
 
{
73
 
        if (!*s) {
74
 
                return NT_STATUS_INVALID_PARAMETER;
75
 
        }
76
 
 
77
 
        if (!allow_wildcards && ms_has_wild_w(s)) {
78
 
                return NT_STATUS_UNSUCCESSFUL;
79
 
        }
80
 
 
81
 
        while (*s) {
82
 
                if(!isvalid83_w(*s)) {
83
 
                        return NT_STATUS_UNSUCCESSFUL;
84
 
                }
85
 
                s++;
86
 
        }
87
 
 
88
 
        return NT_STATUS_OK;
89
 
}
90
 
 
91
 
static NTSTATUS has_illegal_chars(const smb_ucs2_t *s, BOOL allow_wildcards)
92
 
{
93
 
        if (!allow_wildcards && ms_has_wild_w(s)) {
94
 
                return NT_STATUS_UNSUCCESSFUL;
95
 
        }
96
 
 
97
 
        while (*s) {
98
 
                if (*s <= 0x1f) {
99
 
                        /* Control characters. */
100
 
                        return NT_STATUS_UNSUCCESSFUL;
101
 
                }
102
 
                switch(*s) {
103
 
                        case UCS2_CHAR('\\'):
104
 
                        case UCS2_CHAR('/'):
105
 
                        case UCS2_CHAR('|'):
106
 
                        case UCS2_CHAR(':'):
107
 
                                return NT_STATUS_UNSUCCESSFUL;
108
 
                }
109
 
                s++;
110
 
        }
111
 
 
112
 
        return NT_STATUS_OK;
113
 
}
114
 
 
115
 
/* return False if something fail and
116
 
 * return 2 alloced unicode strings that contain prefix and extension
117
 
 */
118
 
 
119
 
static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix,
120
 
                smb_ucs2_t **extension, BOOL allow_wildcards)
121
 
{
122
 
        size_t ext_len;
123
 
        smb_ucs2_t *p;
124
 
 
125
 
        *extension = 0;
126
 
        *prefix = strdup_w(ucs2_string);
127
 
        if (!*prefix) {
128
 
                return NT_STATUS_NO_MEMORY;
129
 
        }
130
 
        if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) {
131
 
                ext_len = strlen_w(p+1);
132
 
                if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) &&
133
 
                    (NT_STATUS_IS_OK(has_valid_83_chars(p+1,allow_wildcards)))) /* check extension */ {
134
 
                        *p = 0;
135
 
                        *extension = strdup_w(p+1);
136
 
                        if (!*extension) {
137
 
                                SAFE_FREE(*prefix);
138
 
                                return NT_STATUS_NO_MEMORY;
139
 
                        }
140
 
                }
141
 
        }
142
 
        return NT_STATUS_OK;
143
 
}
144
 
 
145
 
/* ************************************************************************** **
146
 
 * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name.
147
 
 * or contains illegal characters.
148
 
 *
149
 
 *  Input:  fname - String containing the name to be tested.
150
 
 *
151
 
 *  Output: NT_STATUS_UNSUCCESSFUL, if the condition above is true.
152
 
 *
153
 
 *  Notes:  This is a static function called by is_8_3(), below.
154
 
 *
155
 
 * ************************************************************************** **
156
 
 */
157
 
 
158
 
static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards, BOOL only_8_3)
159
 
{
160
 
        smb_ucs2_t *str, *p;
161
 
        size_t num_ucs2_chars;
162
 
        NTSTATUS ret = NT_STATUS_OK;
163
 
 
164
 
        if (!fname || !*fname)
165
 
                return NT_STATUS_INVALID_PARAMETER;
166
 
 
167
 
        /* . and .. are valid names. */
168
 
        if (strcmp_wa(fname, ".")==0 || strcmp_wa(fname, "..")==0)
169
 
                return NT_STATUS_OK;
170
 
 
171
 
        if (only_8_3) {
172
 
                ret = has_valid_83_chars(fname, allow_wildcards);
173
 
                if (!NT_STATUS_IS_OK(ret))
174
 
                        return ret;
175
 
        }
176
 
 
177
 
        ret = has_illegal_chars(fname, allow_wildcards);
178
 
        if (!NT_STATUS_IS_OK(ret))
179
 
                return ret;
180
 
 
181
 
        /* Name can't end in '.' or ' ' */
182
 
        num_ucs2_chars = strlen_w(fname);
183
 
        if (fname[num_ucs2_chars-1] == UCS2_CHAR('.') || fname[num_ucs2_chars-1] == UCS2_CHAR(' ')) {
184
 
                return NT_STATUS_UNSUCCESSFUL;
185
 
        }
186
 
 
187
 
        str = strdup_w(fname);
188
 
 
189
 
        /* Truncate copy after the first dot. */
190
 
        p = strchr_w(str, UCS2_CHAR('.'));
191
 
        if (p) {
192
 
                *p = 0;
193
 
        }
194
 
 
195
 
        strupper_w(str);
196
 
        p = &str[1];
197
 
 
198
 
        switch(str[0])
199
 
        {
200
 
        case UCS2_CHAR('A'):
201
 
                if(strcmp_wa(p, "UX") == 0)
202
 
                        ret = NT_STATUS_UNSUCCESSFUL;
203
 
                break;
204
 
        case UCS2_CHAR('C'):
205
 
                if((strcmp_wa(p, "LOCK$") == 0)
206
 
                || (strcmp_wa(p, "ON") == 0)
207
 
                || (strcmp_wa(p, "OM1") == 0)
208
 
                || (strcmp_wa(p, "OM2") == 0)
209
 
                || (strcmp_wa(p, "OM3") == 0)
210
 
                || (strcmp_wa(p, "OM4") == 0)
211
 
                )
212
 
                        ret = NT_STATUS_UNSUCCESSFUL;
213
 
                break;
214
 
        case UCS2_CHAR('L'):
215
 
                if((strcmp_wa(p, "PT1") == 0)
216
 
                || (strcmp_wa(p, "PT2") == 0)
217
 
                || (strcmp_wa(p, "PT3") == 0)
218
 
                )
219
 
                        ret = NT_STATUS_UNSUCCESSFUL;
220
 
                break;
221
 
        case UCS2_CHAR('N'):
222
 
                if(strcmp_wa(p, "UL") == 0)
223
 
                        ret = NT_STATUS_UNSUCCESSFUL;
224
 
                break;
225
 
        case UCS2_CHAR('P'):
226
 
                if(strcmp_wa(p, "RN") == 0)
227
 
                        ret = NT_STATUS_UNSUCCESSFUL;
228
 
                break;
229
 
        default:
230
 
                break;
231
 
        }
232
 
 
233
 
        SAFE_FREE(str);
234
 
        return ret;
235
 
}
236
 
 
237
 
static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards)
238
 
{
239
 
        smb_ucs2_t *pref = 0, *ext = 0;
240
 
        size_t plen;
241
 
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
242
 
 
243
 
        if (!fname || !*fname)
244
 
                return NT_STATUS_INVALID_PARAMETER;
245
 
 
246
 
        if (strlen_w(fname) > 12)
247
 
                return NT_STATUS_UNSUCCESSFUL;
248
 
        
249
 
        if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
250
 
                return NT_STATUS_OK;
251
 
 
252
 
        /* Name cannot start with '.' */
253
 
        if (*fname == UCS2_CHAR('.'))
254
 
                return NT_STATUS_UNSUCCESSFUL;
255
 
        
256
 
        if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards, True)))
257
 
                goto done;
258
 
 
259
 
        if (!NT_STATUS_IS_OK(mangle_get_prefix(fname, &pref, &ext, allow_wildcards)))
260
 
                goto done;
261
 
        plen = strlen_w(pref);
262
 
 
263
 
        if (strchr_wa(pref, '.'))
264
 
                goto done;
265
 
        if (plen < 1 || plen > 8)
266
 
                goto done;
267
 
        if (ext && (strlen_w(ext) > 3))
268
 
                goto done;
269
 
 
270
 
        ret = NT_STATUS_OK;
271
 
 
272
 
done:
273
 
        SAFE_FREE(pref);
274
 
        SAFE_FREE(ext);
275
 
        return ret;
276
 
}
277
 
 
278
 
static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards,
279
 
                   const struct share_params *p)
280
 
{
281
 
        const char *f;
282
 
        smb_ucs2_t *ucs2name;
283
 
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
284
 
        size_t size;
285
 
 
286
 
        magic_char = lp_magicchar(p);
287
 
 
288
 
        if (!fname || !*fname)
289
 
                return False;
290
 
        if ((f = strrchr(fname, '/')) == NULL)
291
 
                f = fname;
292
 
        else
293
 
                f++;
294
 
 
295
 
        if (strlen(f) > 12)
296
 
                return False;
297
 
        
298
 
        size = push_ucs2_allocate(&ucs2name, f);
299
 
        if (size == (size_t)-1) {
300
 
                DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n"));
301
 
                goto done;
302
 
        }
303
 
 
304
 
        ret = is_8_3_w(ucs2name, allow_wildcards);
305
 
 
306
 
done:
307
 
        SAFE_FREE(ucs2name);
308
 
 
309
 
        if (!NT_STATUS_IS_OK(ret)) { 
310
 
                return False;
311
 
        }
312
 
        
313
 
        return True;
314
 
}
315
 
 
316
 
 
317
 
 
318
 
/* -------------------------------------------------------------------------- **
319
 
 * Functions...
320
 
 */
321
 
 
322
 
/* ************************************************************************** **
323
 
 * Initialize the static character test array.
324
 
 *
325
 
 *  Input:  none
326
 
 *
327
 
 *  Output: none
328
 
 *
329
 
 *  Notes:  This function changes (loads) the contents of the <chartest>
330
 
 *          array.  The scope of <chartest> is this file.
331
 
 *
332
 
 * ************************************************************************** **
333
 
 */
334
 
static void init_chartest( void )
335
 
{
336
 
        const unsigned char *s;
337
 
  
338
 
        memset( (char *)chartest, '\0', 256 );
339
 
 
340
 
        for( s = (const unsigned char *)basechars; *s; s++ ) {
341
 
                chartest[*s] |= BASECHAR_MASK;
342
 
        }
343
 
 
344
 
        ct_initialized = True;
345
 
}
346
 
 
347
 
/* ************************************************************************** **
348
 
 * Return True if the name *could be* a mangled name.
349
 
 *
350
 
 *  Input:  s - A path name - in UNIX pathname format.
351
 
 *
352
 
 *  Output: True if the name matches the pattern described below in the
353
 
 *          notes, else False.
354
 
 *
355
 
 *  Notes:  The input name is *not* tested for 8.3 compliance.  This must be
356
 
 *          done separately.  This function returns true if the name contains
357
 
 *          a magic character followed by excactly two characters from the
358
 
 *          basechars list (above), which in turn are followed either by the
359
 
 *          nul (end of string) byte or a dot (extension) or by a '/' (end of
360
 
 *          a directory name).
361
 
 *
362
 
 * ************************************************************************** **
363
 
 */
364
 
static BOOL is_mangled(const char *s, const struct share_params *p)
365
 
{
366
 
        char *magic;
367
 
 
368
 
        magic_char = lp_magicchar(p);
369
 
 
370
 
        if( !ct_initialized )
371
 
                init_chartest();
372
 
 
373
 
        magic = strchr_m( s, magic_char );
374
 
        while( magic && magic[1] && magic[2] ) {         /* 3 chars, 1st is magic. */
375
 
                if( ('.' == magic[3] || '/' == magic[3] || !(magic[3]))          /* Ends with '.' or nul or '/' ?  */
376
 
                                && isbasechar( toupper_ascii(magic[1]) )           /* is 2nd char basechar?  */
377
 
                                && isbasechar( toupper_ascii(magic[2]) ) )         /* is 3rd char basechar?  */
378
 
                        return( True );                           /* If all above, then true, */
379
 
                magic = strchr_m( magic+1, magic_char );      /*    else seek next magic. */
380
 
        }
381
 
        return( False );
382
 
}
383
 
 
384
 
/***************************************************************************
385
 
 Initializes or clears the mangled cache.
386
 
***************************************************************************/
387
 
 
388
 
static void mangle_reset( void )
389
 
{
390
 
        /* We could close and re-open the tdb here... should we ? The old code did
391
 
           the equivalent... JRA. */
392
 
}
393
 
 
394
 
/***************************************************************************
395
 
 Add a mangled name into the cache.
396
 
 If the extension of the raw name maps directly to the
397
 
 extension of the mangled name, then we'll store both names
398
 
 *without* extensions.  That way, we can provide consistent
399
 
 reverse mangling for all names that match.  The test here is
400
 
 a bit more careful than the one done in earlier versions of
401
 
 mangle.c:
402
 
 
403
 
    - the extension must exist on the raw name,
404
 
    - it must be all lower case
405
 
    - it must match the mangled extension (to prove that no
406
 
      mangling occurred).
407
 
  crh 07-Apr-1998
408
 
**************************************************************************/
409
 
 
410
 
static void cache_mangled_name( const char mangled_name[13], char *raw_name )
411
 
{
412
 
        TDB_DATA data_val;
413
 
        char mangled_name_key[13];
414
 
        char *s1;
415
 
        char *s2;
416
 
 
417
 
        /* If the cache isn't initialized, give up. */
418
 
        if( !tdb_mangled_cache )
419
 
                return;
420
 
 
421
 
        /* Init the string lengths. */
422
 
        safe_strcpy(mangled_name_key, mangled_name, sizeof(mangled_name_key)-1);
423
 
 
424
 
        /* See if the extensions are unmangled.  If so, store the entry
425
 
         * without the extension, thus creating a "group" reverse map.
426
 
         */
427
 
        s1 = strrchr( mangled_name_key, '.' );
428
 
        if( s1 && (s2 = strrchr( raw_name, '.' )) ) {
429
 
                size_t i = 1;
430
 
                while( s1[i] && (tolower_ascii( s1[i] ) == s2[i]) )
431
 
                        i++;
432
 
                if( !s1[i] && !s2[i] ) {
433
 
                        /* Truncate at the '.' */
434
 
                        *s1 = '\0';
435
 
                        *s2 = '\0';
436
 
                }
437
 
        }
438
 
 
439
 
        /* Allocate a new cache entry.  If the allocation fails, just return. */
440
 
        data_val.dptr = raw_name;
441
 
        data_val.dsize = strlen(raw_name)+1;
442
 
        if (tdb_store_bystring(tdb_mangled_cache, mangled_name_key, data_val, TDB_REPLACE) != 0) {
443
 
                DEBUG(0,("cache_mangled_name: Error storing entry %s -> %s\n", mangled_name_key, raw_name));
444
 
        } else {
445
 
                DEBUG(5,("cache_mangled_name: Stored entry %s -> %s\n", mangled_name_key, raw_name));
446
 
        }
447
 
}
448
 
 
449
 
/* ************************************************************************** **
450
 
 * Check for a name on the mangled name stack
451
 
 *
452
 
 *  Input:  s - Input *and* output string buffer.
453
 
 *          maxlen - space in i/o string buffer.
454
 
 *  Output: True if the name was found in the cache, else False.
455
 
 *
456
 
 *  Notes:  If a reverse map is found, the function will overwrite the string
457
 
 *          space indicated by the input pointer <s>.  This is frightening.
458
 
 *          It should be rewritten to return NULL if the long name was not
459
 
 *          found, and a pointer to the long name if it was found.
460
 
 *
461
 
 * ************************************************************************** **
462
 
 */
463
 
 
464
 
static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p )
465
 
{
466
 
        TDB_DATA data_val;
467
 
        char *ext_start = NULL;
468
 
        char *saved_ext = NULL;
469
 
 
470
 
        magic_char = lp_magicchar(p);
471
 
 
472
 
        /* If the cache isn't initialized, give up. */
473
 
        if( !tdb_mangled_cache )
474
 
                return( False );
475
 
 
476
 
        data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
477
 
 
478
 
        /* If we didn't find the name *with* the extension, try without. */
479
 
        if(data_val.dptr == NULL || data_val.dsize == 0) {
480
 
                ext_start = strrchr( s, '.' );
481
 
                if( ext_start ) {
482
 
                        if((saved_ext = SMB_STRDUP(ext_start)) == NULL)
483
 
                                return False;
484
 
 
485
 
                        *ext_start = '\0';
486
 
                        data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
487
 
                        /* 
488
 
                         * At this point s is the name without the
489
 
                         * extension. We re-add the extension if saved_ext
490
 
                         * is not null, before freeing saved_ext.
491
 
                         */
492
 
                }
493
 
        }
494
 
 
495
 
        /* Okay, if we haven't found it we're done. */
496
 
        if(data_val.dptr == NULL || data_val.dsize == 0) {
497
 
                if(saved_ext) {
498
 
                        /* Replace the saved_ext as it was truncated. */
499
 
                        (void)safe_strcat( s, saved_ext, maxlen );
500
 
                        SAFE_FREE(saved_ext);
501
 
                }
502
 
                return( False );
503
 
        }
504
 
 
505
 
        /* If we *did* find it, we need to copy it into the string buffer. */
506
 
        (void)safe_strcpy( s, data_val.dptr, maxlen );
507
 
        if( saved_ext ) {
508
 
                /* Replace the saved_ext as it was truncated. */
509
 
                (void)safe_strcat( s, saved_ext, maxlen );
510
 
                SAFE_FREE(saved_ext);
511
 
        }
512
 
        SAFE_FREE(data_val.dptr);
513
 
        return( True );
514
 
}
515
 
 
516
 
/*****************************************************************************
517
 
 * do the actual mangling to 8.3 format
518
 
 * the buffer must be able to hold 13 characters (including the null)
519
 
 *****************************************************************************
520
 
 */
521
 
static void to_8_3(char *s, int default_case)
522
 
{
523
 
        int csum;
524
 
        char *p;
525
 
        char extension[4];
526
 
        char base[9];
527
 
        int baselen = 0;
528
 
        int extlen = 0;
529
 
 
530
 
        extension[0] = 0;
531
 
        base[0] = 0;
532
 
 
533
 
        p = strrchr(s,'.');  
534
 
        if( p && (strlen(p+1) < (size_t)4) ) {
535
 
                BOOL all_normal = ( strisnormal(p+1, default_case) ); /* XXXXXXXXX */
536
 
 
537
 
                if( all_normal && p[1] != 0 ) {
538
 
                        *p = 0;
539
 
                        csum = str_checksum( s );
540
 
                        *p = '.';
541
 
                } else
542
 
                        csum = str_checksum(s);
543
 
        } else
544
 
                csum = str_checksum(s);
545
 
 
546
 
        strupper_m( s );
547
 
 
548
 
        if( p ) {
549
 
                if( p == s )
550
 
                        safe_strcpy( extension, "___", 3 );
551
 
                else {
552
 
                        *p++ = 0;
553
 
                        while( *p && extlen < 3 ) {
554
 
                                if ( *p != '.') {
555
 
                                        extension[extlen++] = p[0];
556
 
                                }
557
 
                                p++;
558
 
                        }
559
 
                        extension[extlen] = 0;
560
 
                }
561
 
        }
562
 
  
563
 
        p = s;
564
 
 
565
 
        while( *p && baselen < 5 ) {
566
 
                if (isbasechar(*p)) {
567
 
                        base[baselen++] = p[0];
568
 
                }
569
 
                p++;
570
 
        }
571
 
        base[baselen] = 0;
572
 
  
573
 
        csum = csum % (MANGLE_BASE*MANGLE_BASE);
574
 
  
575
 
        (void)slprintf(s, 12, "%s%c%c%c",
576
 
                base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
577
 
  
578
 
        if( *extension ) {
579
 
                (void)pstrcat( s, "." );
580
 
                (void)pstrcat( s, extension );
581
 
        }
582
 
}
583
 
 
584
 
/*****************************************************************************
585
 
 * Convert a filename to DOS format.  Return True if successful.
586
 
 *
587
 
 *  Input:  OutName - Source *and* destination buffer. 
588
 
 *
589
 
 *                    NOTE that OutName must point to a memory space that
590
 
 *                    is at least 13 bytes in size!
591
 
 *
592
 
 *          need83  - If False, name mangling will be skipped unless the
593
 
 *                    name contains illegal characters.  Mapping will still
594
 
 *                    be done, if appropriate.  This is probably used to
595
 
 *                    signal that a client does not require name mangling,
596
 
 *                    thus skipping the name mangling even on shares which
597
 
 *                    have name-mangling turned on.
598
 
 *          cache83 - If False, the mangled name cache will not be updated.
599
 
 *                    This is usually used to prevent that we overwrite
600
 
 *                    a conflicting cache entry prematurely, i.e. before
601
 
 *                    we know whether the client is really interested in the
602
 
 *                    current name.  (See PR#13758).  UKD.
603
 
 *
604
 
 *  Output: Returns False only if the name wanted mangling but the share does
605
 
 *          not have name mangling turned on.
606
 
 *
607
 
 * ****************************************************************************
608
 
 */
609
 
 
610
 
static void name_map(char *OutName, BOOL need83, BOOL cache83,
611
 
                     int default_case, const struct share_params *p)
612
 
{
613
 
        smb_ucs2_t *OutName_ucs2;
614
 
        magic_char = lp_magicchar(p);
615
 
 
616
 
        DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
617
 
                 need83 ? "True" : "False", cache83 ? "True" : "False"));
618
 
        
619
 
        if (push_ucs2_allocate(&OutName_ucs2, OutName) == (size_t)-1) {
620
 
                DEBUG(0, ("push_ucs2_allocate failed!\n"));
621
 
                return;
622
 
        }
623
 
 
624
 
        if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False, False)))
625
 
                need83 = True;
626
 
 
627
 
        /* check if it's already in 8.3 format */
628
 
        if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2, False))) {
629
 
                char *tmp = NULL; 
630
 
 
631
 
                /* mangle it into 8.3 */
632
 
                if (cache83)
633
 
                        tmp = SMB_STRDUP(OutName);
634
 
 
635
 
                to_8_3(OutName, default_case);
636
 
 
637
 
                if(tmp != NULL) {
638
 
                        cache_mangled_name(OutName, tmp);
639
 
                        SAFE_FREE(tmp);
640
 
                }
641
 
        }
642
 
 
643
 
        DEBUG(5,("name_map() ==> [%s]\n", OutName));
644
 
        SAFE_FREE(OutName_ucs2);
645
 
}
646
 
 
647
 
/*
648
 
  the following provides the abstraction layer to make it easier
649
 
  to drop in an alternative mangling implementation
650
 
*/
651
 
static struct mangle_fns mangle_fns = {
652
 
        mangle_reset,
653
 
        is_mangled,
654
 
        is_8_3,
655
 
        check_cache,
656
 
        name_map
657
 
};
658
 
 
659
 
/* return the methods for this mangling implementation */
660
 
struct mangle_fns *mangle_hash_init(void)
661
 
{
662
 
        mangle_reset();
663
 
 
664
 
        /* Create the in-memory tdb using our custom hash function. */
665
 
        tdb_mangled_cache = tdb_open_ex("mangled_cache", 1031, TDB_INTERNAL,
666
 
                                (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash);
667
 
 
668
 
        return &mangle_fns;
669
 
}