~n-muench/ubuntu/oneiric/open-vm-tools/open-vm-tools.fix-836277

« back to all changes in this revision

Viewing changes to modules/freebsd/vmhgfs/cpName.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-11-20 21:56:00 UTC
  • mfrom: (1.1.3 upstream) (2.2.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20081120215600-0jujiv17a2ja92xu
Tags: 2008.11.18-130226-1
* Replacing obsolete dh_clean -k with dh_prep.
* Merging upstream version 2008.11.18-130226.
* Updating debian directory for addition of pvscsi and vmxnet3 modules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include "cpName.h"
32
32
#include "cpNameInt.h"
33
33
#include "vm_assert.h"
 
34
#include "hgfsEscape.h"
34
35
 
35
36
/*
36
37
 *----------------------------------------------------------------------
37
38
 *
38
 
 * CPName_GetComponentGeneric --
 
39
 * CPName_GetComponent --
39
40
 *
40
41
 *    Get the next component of the CP name.
41
42
 *
44
45
 *    any. The "next" pointer is set to "end" if there is no next
45
46
 *    component.
46
47
 *
47
 
 *    'illegal' is a string of characters that are not allowed to
48
 
 *    be present in the pre-converted CP name.
49
 
 *
50
48
 * Results:
51
49
 *    length (not including NUL termination) >= 0 of next
52
50
 *    component on success.
59
57
 */
60
58
 
61
59
int
62
 
CPName_GetComponentGeneric(char const *begin,   // IN: Beginning of buffer
63
 
                           char const *end,     // IN: End of buffer
64
 
                           char const *illegal, // IN: Illegal characters
65
 
                           char const **next)   // OUT: Start of next component
 
60
CPName_GetComponent(char const *begin,   // IN: Beginning of buffer
 
61
                    char const *end,     // IN: End of buffer
 
62
                    char const **next)   // OUT: Start of next component
66
63
{
67
64
   char const *walk;
68
65
   char const *myNext;
71
68
   ASSERT(begin);
72
69
   ASSERT(end);
73
70
   ASSERT(next);
74
 
   ASSERT(illegal);
75
71
   ASSERT(begin <= end);
76
72
 
77
73
   for (walk = begin; ; walk++) {
86
82
         /* Found a NUL */
87
83
 
88
84
         if (walk == begin) {
89
 
            Log("CPName_GetComponentGeneric: error: first char can't be NUL\n");
 
85
            Log("CPName_GetComponent: error: first char can't be NUL\n");
90
86
            return -1;
91
87
         }
92
88
 
98
94
 
99
95
         break;
100
96
      }
101
 
 
102
 
      /*
103
 
       * Make sure the input buffer does not contain any illegal
104
 
       * characters. In particular, we want to make sure that there
105
 
       * are no path separator characters in the name. Since the
106
 
       * cross-platform name format by definition does not use path
107
 
       * separators, this is an error condition, and is likely the
108
 
       * sign of an attack. See bug 27926. [bac]
109
 
       *
110
 
       * The test above ensures that *walk != NUL here, so we don't
111
 
       * need to test it again before calling strchr().
112
 
       */
113
 
      if (strchr(illegal, *walk) != NULL) {
114
 
         Log("CPName_GetComponentGeneric: error: Illegal char \"%c\" found in "
115
 
             "input\n", *walk);
116
 
         return -1;
117
 
      }
118
97
   }
119
98
 
120
99
   len = walk - begin;
121
100
 
122
 
   /* 
123
 
    * We're only interested in looking for dot/dotdot if the illegal character
124
 
    * string isn't empty. These characters are only relevant when the resulting
125
 
    * string is to be passed down to the filesystem. Some callers (such as the
126
 
    * HGFS server, when dealing with actual filenames) do care about this 
127
 
    * validation, but others (like DnD, hgFileCopy, and the HGFS server when
128
 
    * converting share names) just want to convert a CPName down to a 
129
 
    * nul-terminated string. 
130
 
    */
131
 
   if (strcmp(illegal, "") != 0 &&
132
 
       ((len == 1 && memcmp(begin, ".", 1) == 0) ||
133
 
        (len == 2 && memcmp(begin, "..", 2) == 0))) {
134
 
      Log("CPName_GetComponentGeneric: error: found dot/dotdot\n");
135
 
      return -1;
136
 
   }
137
 
 
138
101
   *next = myNext;
139
102
   return ((int) len);
140
103
}
143
106
/*
144
107
 *----------------------------------------------------------------------
145
108
 *
 
109
 * CPNameEscapeAndConvertFrom --
 
110
 *
 
111
 *    Converts a cross-platform name representation into a string for
 
112
 *    use in the local filesystem.
 
113
 *    Escapes illegal characters as a part of convertion.
 
114
 *    This is a cross-platform implementation and takes the path separator
 
115
 *    argument as an argument. The path separator is prepended before each
 
116
 *    additional path component, so this function never adds a trailing path
 
117
 *    separator.
 
118
 *
 
119
 * Results:
 
120
 *    0 on success.
 
121
 *    error < 0 on failure (the converted string did not fit in
 
122
 *    the buffer provided or the input was invalid).
 
123
 *
 
124
 * Side effects:
 
125
 *    None
 
126
 *
 
127
 *----------------------------------------------------------------------
 
128
 */
 
129
 
 
130
int
 
131
CPNameEscapeAndConvertFrom(char const **bufIn, // IN/OUT: Input to convert
 
132
                           size_t *inSize,     // IN/OUT: Size of input
 
133
                           size_t *outSize,    // IN/OUT: Size of output buffer
 
134
                           char **bufOut,      // IN/OUT: Output buffer
 
135
                           char pathSep)       // IN: Path separator character
 
136
{
 
137
   int result;
 
138
   size_t inputSize;
 
139
   inputSize = HgfsEscape_GetSize(*bufIn, *inSize);
 
140
   if (inputSize != 0) {
 
141
      char *savedBufOut = *bufOut;
 
142
      char const *savedOutConst = savedBufOut;
 
143
      size_t savedOutSize = *outSize;
 
144
      if (inputSize > *outSize) {
 
145
         Log("CPNameEscapeAndConvertFrom: error: not enough room for escaping\n");
 
146
         return -1;
 
147
      }
 
148
 
 
149
      /* Leaving space for the leading path separator, thus output to savedBufOut + 1. */
 
150
      *inSize = HgfsEscape_Do(*bufIn, *inSize, savedOutSize, savedBufOut + 1);
 
151
      result = CPNameConvertFrom(&savedOutConst, inSize, outSize, bufOut, pathSep);
 
152
      *bufIn += *inSize;
 
153
      *inSize = 0;
 
154
   } else {
 
155
      result = CPNameConvertFrom(bufIn, inSize, outSize, bufOut, pathSep);
 
156
   }
 
157
   return result;
 
158
}
 
159
 
 
160
 
 
161
/*
 
162
 *----------------------------------------------------------------------
 
163
 *
146
164
 * CPNameConvertFrom --
147
165
 *
148
166
 *    Converts a cross-platform name representation into a string for
174
192
   char const *inEnd;
175
193
   size_t myOutSize;
176
194
   char *out;
 
195
   Bool inPlaceConvertion = (*bufIn == *bufOut);
177
196
 
178
197
   ASSERT(bufIn);
179
198
   ASSERT(inSize);
181
200
   ASSERT(bufOut);
182
201
 
183
202
   in = *bufIn;
 
203
   if (inPlaceConvertion) {
 
204
      in++; // Skip place for the leading path separator.
 
205
   }
184
206
   inEnd = in + *inSize;
185
207
   myOutSize = *outSize;
186
208
   out = *bufOut;
196
218
         return len;
197
219
      }
198
220
 
 
221
      /* Bug 27926 - preventing escaping from shared folder. */
 
222
      if ((len == 1 && *in == '.') ||
 
223
          (len == 2 && in[0] == '.' && in[1] == '.')) {
 
224
         Log("CPNameConvertFrom: error: found dot/dotdot\n");
 
225
         return -1;
 
226
      }
 
227
 
199
228
      if (len == 0) {
200
229
         /* No more component */
201
230
         break;
209
238
      myOutSize = (size_t) newLen;
210
239
 
211
240
      *out++ = pathSep;
212
 
      memcpy(out, in, len);
 
241
      if (!inPlaceConvertion) {
 
242
         memcpy(out, in, len);
 
243
      }
213
244
      out += len;
214
245
 
215
246
      in = next;
308
339
                      size_t bufOutSize,  // IN:  Size of the output buffer
309
340
                      char *bufOut)       // OUT: Output buffer
310
341
{
311
 
   return CPNameConvertTo(nameIn, bufOutSize, bufOut, '/', NULL);
 
342
   return CPNameConvertTo(nameIn, bufOutSize, bufOut, '/');
312
343
}
313
344
 
314
345
 
339
370
                        size_t bufOutSize,  // IN:  Size of the output buffer
340
371
                        char *bufOut)       // OUT: Output buffer
341
372
{
342
 
   return CPNameConvertTo(nameIn, bufOutSize, bufOut, '\\', ":");
 
373
   return CPNameConvertTo(nameIn, bufOutSize, bufOut, '\\');
343
374
}
344
375
 
345
376
 
350
381
 *
351
382
 *    Makes a cross-platform name representation from the input string
352
383
 *    and writes it into the output buffer.
 
384
 *    HGFS convention is to echange names between guest and host in uescaped form.
 
385
 *    Both ends perform necessary name escaping according to its own rules
 
386
 *    to avoid presenitng invalid file names to OS. Thus the name needs to be unescaped
 
387
 *    as a part of conversion to host-independent format.
353
388
 *
354
389
 * Results:
355
390
 *    On success, returns the number of bytes used in the
366
401
CPNameConvertTo(char const *nameIn, // IN:  Buf to convert
367
402
                size_t bufOutSize,  // IN:  Size of the output buffer
368
403
                char *bufOut,       // OUT: Output buffer
369
 
                char pathSep,       // IN:  path separator to use
370
 
                char *ignores)      // IN:  chars to not transfer to output
 
404
                char pathSep)       // IN:  path separator to use
371
405
{
372
 
   char const *origOut = bufOut;
 
406
   char *origOut = bufOut;
373
407
   char const *endOut = bufOut + bufOutSize;
374
408
   size_t cpNameLength = 0;
375
409
 
381
415
      nameIn++;
382
416
   }
383
417
 
384
 
   /*
385
 
    * Copy the string to the output buf, converting all path separators into
386
 
    * '\0' and ignoring the specified characters.
387
 
    */
 
418
    /* Copy the string to the output buf, converting all path separators into '\0'. */
388
419
   for (; *nameIn != '\0' && bufOut < endOut; nameIn++) {
389
 
      if (ignores) {
390
 
         char *currIgnore = ignores;
391
 
         Bool ignore = FALSE;
392
 
 
393
 
         while (*currIgnore != '\0') {
394
 
            if (*nameIn == *currIgnore) {
395
 
               ignore = TRUE;
396
 
               break;
397
 
            }
398
 
            currIgnore++;
399
 
         }
400
 
 
401
 
         if (!ignore) {
402
 
            *bufOut = (*nameIn == pathSep) ? '\0' : *nameIn;
403
 
            bufOut++;
404
 
         }
405
 
      } else {
406
 
         *bufOut = (*nameIn == pathSep) ? '\0' : *nameIn;
407
 
         bufOut++;
408
 
      }
 
420
      *bufOut = (*nameIn == pathSep) ? '\0' : *nameIn;
 
421
      bufOut++;
409
422
   }
410
423
 
411
424
   /*
427
440
   while ((cpNameLength >= 1) && (origOut[cpNameLength - 1] == 0)) {
428
441
      cpNameLength--;
429
442
   }
 
443
   cpNameLength = HgfsEscape_Undo(origOut, cpNameLength);
430
444
 
431
445
   /* Return number of bytes used */
432
446
   return (int) cpNameLength;