bsd-cygwin_util.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com>
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  14. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  15. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  16. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  17. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  20. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. *
  24. * Created: Sat Sep 02 12:17:00 2000 cv
  25. *
  26. * This file contains functions for forcing opened file descriptors to
  27. * binary mode on Windows systems.
  28. */
  29. #define NO_BINARY_OPEN /* Avoid redefining open to binary_open for this file */
  30. #include "includes.h"
  31. #ifdef HAVE_CYGWIN
  32. #include <sys/types.h>
  33. #include <fcntl.h>
  34. #include <string.h>
  35. #include <unistd.h>
  36. #include <stdarg.h>
  37. #include <stdlib.h>
  38. #include <wchar.h>
  39. #include <wctype.h>
  40. #include "xmalloc.h"
  41. int
  42. binary_open(const char *filename, int flags, ...)
  43. {
  44. va_list ap;
  45. mode_t mode;
  46. va_start(ap, flags);
  47. mode = va_arg(ap, mode_t);
  48. va_end(ap);
  49. return (open(filename, flags | O_BINARY, mode));
  50. }
  51. int
  52. check_ntsec(const char *filename)
  53. {
  54. return (pathconf(filename, _PC_POSIX_PERMISSIONS));
  55. }
  56. const char *
  57. cygwin_ssh_privsep_user()
  58. {
  59. static char cyg_privsep_user[DNLEN + UNLEN + 2];
  60. if (!cyg_privsep_user[0])
  61. {
  62. #ifdef CW_CYGNAME_FROM_WINNAME
  63. if (cygwin_internal (CW_CYGNAME_FROM_WINNAME, "sshd", cyg_privsep_user,
  64. sizeof cyg_privsep_user) != 0)
  65. #endif
  66. strlcpy(cyg_privsep_user, "sshd", sizeof(cyg_privsep_user));
  67. }
  68. return cyg_privsep_user;
  69. }
  70. #define NL(x) x, (sizeof (x) - 1)
  71. #define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0]))
  72. static struct wenv {
  73. const char *name;
  74. size_t namelen;
  75. } wenv_arr[] = {
  76. { NL("ALLUSERSPROFILE=") },
  77. { NL("COMPUTERNAME=") },
  78. { NL("COMSPEC=") },
  79. { NL("CYGWIN=") },
  80. { NL("OS=") },
  81. { NL("PATH=") },
  82. { NL("PATHEXT=") },
  83. { NL("PROGRAMFILES=") },
  84. { NL("SYSTEMDRIVE=") },
  85. { NL("SYSTEMROOT=") },
  86. { NL("WINDIR=") }
  87. };
  88. char **
  89. fetch_windows_environment(void)
  90. {
  91. char **e, **p;
  92. unsigned int i, idx = 0;
  93. p = xcalloc(WENV_SIZ + 1, sizeof(char *));
  94. for (e = environ; *e != NULL; ++e) {
  95. for (i = 0; i < WENV_SIZ; ++i) {
  96. if (!strncmp(*e, wenv_arr[i].name, wenv_arr[i].namelen))
  97. p[idx++] = *e;
  98. }
  99. }
  100. p[idx] = NULL;
  101. return p;
  102. }
  103. void
  104. free_windows_environment(char **p)
  105. {
  106. free(p);
  107. }
  108. /*
  109. * Returns true if the given string matches the pattern (which may contain ?
  110. * and * as wildcards), and zero if it does not match.
  111. *
  112. * The Cygwin version of this function must be case-insensitive and take
  113. * Unicode characters into account.
  114. */
  115. static int
  116. __match_pattern (const wchar_t *s, const wchar_t *pattern)
  117. {
  118. for (;;) {
  119. /* If at end of pattern, accept if also at end of string. */
  120. if (!*pattern)
  121. return !*s;
  122. if (*pattern == '*') {
  123. /* Skip the asterisk. */
  124. pattern++;
  125. /* If at end of pattern, accept immediately. */
  126. if (!*pattern)
  127. return 1;
  128. /* If next character in pattern is known, optimize. */
  129. if (*pattern != '?' && *pattern != '*') {
  130. /*
  131. * Look instances of the next character in
  132. * pattern, and try to match starting from
  133. * those.
  134. */
  135. for (; *s; s++)
  136. if (*s == *pattern &&
  137. __match_pattern(s + 1, pattern + 1))
  138. return 1;
  139. /* Failed. */
  140. return 0;
  141. }
  142. /*
  143. * Move ahead one character at a time and try to
  144. * match at each position.
  145. */
  146. for (; *s; s++)
  147. if (__match_pattern(s, pattern))
  148. return 1;
  149. /* Failed. */
  150. return 0;
  151. }
  152. /*
  153. * There must be at least one more character in the string.
  154. * If we are at the end, fail.
  155. */
  156. if (!*s)
  157. return 0;
  158. /* Check if the next character of the string is acceptable. */
  159. if (*pattern != '?' && towlower(*pattern) != towlower(*s))
  160. return 0;
  161. /* Move to the next character, both in string and in pattern. */
  162. s++;
  163. pattern++;
  164. }
  165. /* NOTREACHED */
  166. }
  167. static int
  168. _match_pattern(const char *s, const char *pattern)
  169. {
  170. wchar_t *ws;
  171. wchar_t *wpattern;
  172. size_t len;
  173. int ret;
  174. if ((len = mbstowcs(NULL, s, 0)) < 0)
  175. return 0;
  176. ws = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t));
  177. mbstowcs(ws, s, len + 1);
  178. if ((len = mbstowcs(NULL, pattern, 0)) < 0)
  179. return 0;
  180. wpattern = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t));
  181. mbstowcs(wpattern, pattern, len + 1);
  182. ret = __match_pattern (ws, wpattern);
  183. free(ws);
  184. free(wpattern);
  185. return ret;
  186. }
  187. /*
  188. * Tries to match the string against the
  189. * comma-separated sequence of subpatterns (each possibly preceded by ! to
  190. * indicate negation). Returns -1 if negation matches, 1 if there is
  191. * a positive match, 0 if there is no match at all.
  192. */
  193. int
  194. cygwin_ug_match_pattern_list(const char *string, const char *pattern)
  195. {
  196. char sub[1024];
  197. int negated;
  198. int got_positive;
  199. u_int i, subi, len = strlen(pattern);
  200. got_positive = 0;
  201. for (i = 0; i < len;) {
  202. /* Check if the subpattern is negated. */
  203. if (pattern[i] == '!') {
  204. negated = 1;
  205. i++;
  206. } else
  207. negated = 0;
  208. /*
  209. * Extract the subpattern up to a comma or end. Convert the
  210. * subpattern to lowercase.
  211. */
  212. for (subi = 0;
  213. i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
  214. subi++, i++)
  215. sub[subi] = pattern[i];
  216. /* If subpattern too long, return failure (no match). */
  217. if (subi >= sizeof(sub) - 1)
  218. return 0;
  219. /* If the subpattern was terminated by a comma, then skip it. */
  220. if (i < len && pattern[i] == ',')
  221. i++;
  222. /* Null-terminate the subpattern. */
  223. sub[subi] = '\0';
  224. /* Try to match the subpattern against the string. */
  225. if (_match_pattern(string, sub)) {
  226. if (negated)
  227. return -1; /* Negative */
  228. else
  229. got_positive = 1; /* Positive */
  230. }
  231. }
  232. /*
  233. * Return success if got a positive match. If there was a negative
  234. * match, we have already returned -1 and never get here.
  235. */
  236. return got_positive;
  237. }
  238. #endif /* HAVE_CYGWIN */