183d2307dSDag-Erling Smørgrav /* 2420bce64SDag-Erling Smørgrav * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com> 383d2307dSDag-Erling Smørgrav * 483d2307dSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 583d2307dSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 683d2307dSDag-Erling Smørgrav * are met: 783d2307dSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 883d2307dSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 983d2307dSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 1083d2307dSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 1183d2307dSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 1283d2307dSDag-Erling Smørgrav * 1383d2307dSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1483d2307dSDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1583d2307dSDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1683d2307dSDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1783d2307dSDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1883d2307dSDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1983d2307dSDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2083d2307dSDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2183d2307dSDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2283d2307dSDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2383d2307dSDag-Erling Smørgrav * 2483d2307dSDag-Erling Smørgrav * Created: Sat Sep 02 12:17:00 2000 cv 2583d2307dSDag-Erling Smørgrav * 2683d2307dSDag-Erling Smørgrav * This file contains functions for forcing opened file descriptors to 2783d2307dSDag-Erling Smørgrav * binary mode on Windows systems. 2883d2307dSDag-Erling Smørgrav */ 2983d2307dSDag-Erling Smørgrav 30420bce64SDag-Erling Smørgrav #define NO_BINARY_OPEN /* Avoid redefining open to binary_open for this file */ 3183d2307dSDag-Erling Smørgrav #include "includes.h" 3283d2307dSDag-Erling Smørgrav 3383d2307dSDag-Erling Smørgrav #ifdef HAVE_CYGWIN 3483d2307dSDag-Erling Smørgrav 35761efaa7SDag-Erling Smørgrav #include <sys/types.h> 36761efaa7SDag-Erling Smørgrav #include <fcntl.h> 37420bce64SDag-Erling Smørgrav #include <string.h> 38761efaa7SDag-Erling Smørgrav #include <unistd.h> 39190cef3dSDag-Erling Smørgrav #include <stdarg.h> 40*19261079SEd Maste #include <stdlib.h> 41*19261079SEd Maste #include <wchar.h> 42*19261079SEd Maste #include <wctype.h> 43761efaa7SDag-Erling Smørgrav 44761efaa7SDag-Erling Smørgrav #include "xmalloc.h" 45761efaa7SDag-Erling Smørgrav 46d95e11bfSDag-Erling Smørgrav int 47d95e11bfSDag-Erling Smørgrav binary_open(const char *filename, int flags, ...) 4883d2307dSDag-Erling Smørgrav { 4983d2307dSDag-Erling Smørgrav va_list ap; 5083d2307dSDag-Erling Smørgrav mode_t mode; 5183d2307dSDag-Erling Smørgrav 5283d2307dSDag-Erling Smørgrav va_start(ap, flags); 5383d2307dSDag-Erling Smørgrav mode = va_arg(ap, mode_t); 5483d2307dSDag-Erling Smørgrav va_end(ap); 55d95e11bfSDag-Erling Smørgrav return (open(filename, flags | O_BINARY, mode)); 5683d2307dSDag-Erling Smørgrav } 5783d2307dSDag-Erling Smørgrav 58d95e11bfSDag-Erling Smørgrav int 59d95e11bfSDag-Erling Smørgrav check_ntsec(const char *filename) 6083d2307dSDag-Erling Smørgrav { 61d4af9e69SDag-Erling Smørgrav return (pathconf(filename, _PC_POSIX_PERMISSIONS)); 6283d2307dSDag-Erling Smørgrav } 6383d2307dSDag-Erling Smørgrav 64a0ee8cc6SDag-Erling Smørgrav const char * 65a0ee8cc6SDag-Erling Smørgrav cygwin_ssh_privsep_user() 66a0ee8cc6SDag-Erling Smørgrav { 67a0ee8cc6SDag-Erling Smørgrav static char cyg_privsep_user[DNLEN + UNLEN + 2]; 68a0ee8cc6SDag-Erling Smørgrav 69a0ee8cc6SDag-Erling Smørgrav if (!cyg_privsep_user[0]) 70a0ee8cc6SDag-Erling Smørgrav { 71a0ee8cc6SDag-Erling Smørgrav #ifdef CW_CYGNAME_FROM_WINNAME 72a0ee8cc6SDag-Erling Smørgrav if (cygwin_internal (CW_CYGNAME_FROM_WINNAME, "sshd", cyg_privsep_user, 73a0ee8cc6SDag-Erling Smørgrav sizeof cyg_privsep_user) != 0) 74a0ee8cc6SDag-Erling Smørgrav #endif 75557f75e5SDag-Erling Smørgrav strlcpy(cyg_privsep_user, "sshd", sizeof(cyg_privsep_user)); 76a0ee8cc6SDag-Erling Smørgrav } 77a0ee8cc6SDag-Erling Smørgrav return cyg_privsep_user; 78a0ee8cc6SDag-Erling Smørgrav } 79a0ee8cc6SDag-Erling Smørgrav 805e8dbd04SDag-Erling Smørgrav #define NL(x) x, (sizeof (x) - 1) 815e8dbd04SDag-Erling Smørgrav #define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0])) 825e8dbd04SDag-Erling Smørgrav 835e8dbd04SDag-Erling Smørgrav static struct wenv { 845e8dbd04SDag-Erling Smørgrav const char *name; 855e8dbd04SDag-Erling Smørgrav size_t namelen; 865e8dbd04SDag-Erling Smørgrav } wenv_arr[] = { 875e8dbd04SDag-Erling Smørgrav { NL("ALLUSERSPROFILE=") }, 885e8dbd04SDag-Erling Smørgrav { NL("COMPUTERNAME=") }, 895e8dbd04SDag-Erling Smørgrav { NL("COMSPEC=") }, 904518870cSDag-Erling Smørgrav { NL("CYGWIN=") }, 915e8dbd04SDag-Erling Smørgrav { NL("OS=") }, 925e8dbd04SDag-Erling Smørgrav { NL("PATH=") }, 935e8dbd04SDag-Erling Smørgrav { NL("PATHEXT=") }, 94462c32cbSDag-Erling Smørgrav { NL("PROGRAMFILES=") }, 955e8dbd04SDag-Erling Smørgrav { NL("SYSTEMDRIVE=") }, 965e8dbd04SDag-Erling Smørgrav { NL("SYSTEMROOT=") }, 974518870cSDag-Erling Smørgrav { NL("WINDIR=") } 985e8dbd04SDag-Erling Smørgrav }; 995e8dbd04SDag-Erling Smørgrav 1005e8dbd04SDag-Erling Smørgrav char ** 1015e8dbd04SDag-Erling Smørgrav fetch_windows_environment(void) 1025e8dbd04SDag-Erling Smørgrav { 1035e8dbd04SDag-Erling Smørgrav char **e, **p; 104761efaa7SDag-Erling Smørgrav unsigned int i, idx = 0; 1055e8dbd04SDag-Erling Smørgrav 106761efaa7SDag-Erling Smørgrav p = xcalloc(WENV_SIZ + 1, sizeof(char *)); 1075e8dbd04SDag-Erling Smørgrav for (e = environ; *e != NULL; ++e) { 1085e8dbd04SDag-Erling Smørgrav for (i = 0; i < WENV_SIZ; ++i) { 1095e8dbd04SDag-Erling Smørgrav if (!strncmp(*e, wenv_arr[i].name, wenv_arr[i].namelen)) 1105e8dbd04SDag-Erling Smørgrav p[idx++] = *e; 1115e8dbd04SDag-Erling Smørgrav } 1125e8dbd04SDag-Erling Smørgrav } 1135e8dbd04SDag-Erling Smørgrav p[idx] = NULL; 1145e8dbd04SDag-Erling Smørgrav return p; 1155e8dbd04SDag-Erling Smørgrav } 1165e8dbd04SDag-Erling Smørgrav 1175e8dbd04SDag-Erling Smørgrav void 1185e8dbd04SDag-Erling Smørgrav free_windows_environment(char **p) 1195e8dbd04SDag-Erling Smørgrav { 120e4a9863fSDag-Erling Smørgrav free(p); 1215e8dbd04SDag-Erling Smørgrav } 1225e8dbd04SDag-Erling Smørgrav 123*19261079SEd Maste /* 124*19261079SEd Maste * Returns true if the given string matches the pattern (which may contain ? 125*19261079SEd Maste * and * as wildcards), and zero if it does not match. 126*19261079SEd Maste * 127*19261079SEd Maste * The Cygwin version of this function must be case-insensitive and take 128*19261079SEd Maste * Unicode characters into account. 129*19261079SEd Maste */ 130*19261079SEd Maste 131*19261079SEd Maste static int 132*19261079SEd Maste __match_pattern (const wchar_t *s, const wchar_t *pattern) 133*19261079SEd Maste { 134*19261079SEd Maste for (;;) { 135*19261079SEd Maste /* If at end of pattern, accept if also at end of string. */ 136*19261079SEd Maste if (!*pattern) 137*19261079SEd Maste return !*s; 138*19261079SEd Maste 139*19261079SEd Maste if (*pattern == '*') { 140*19261079SEd Maste /* Skip the asterisk. */ 141*19261079SEd Maste pattern++; 142*19261079SEd Maste 143*19261079SEd Maste /* If at end of pattern, accept immediately. */ 144*19261079SEd Maste if (!*pattern) 145*19261079SEd Maste return 1; 146*19261079SEd Maste 147*19261079SEd Maste /* If next character in pattern is known, optimize. */ 148*19261079SEd Maste if (*pattern != '?' && *pattern != '*') { 149*19261079SEd Maste /* 150*19261079SEd Maste * Look instances of the next character in 151*19261079SEd Maste * pattern, and try to match starting from 152*19261079SEd Maste * those. 153*19261079SEd Maste */ 154*19261079SEd Maste for (; *s; s++) 155*19261079SEd Maste if (*s == *pattern && 156*19261079SEd Maste __match_pattern(s + 1, pattern + 1)) 157*19261079SEd Maste return 1; 158*19261079SEd Maste /* Failed. */ 159*19261079SEd Maste return 0; 160*19261079SEd Maste } 161*19261079SEd Maste /* 162*19261079SEd Maste * Move ahead one character at a time and try to 163*19261079SEd Maste * match at each position. 164*19261079SEd Maste */ 165*19261079SEd Maste for (; *s; s++) 166*19261079SEd Maste if (__match_pattern(s, pattern)) 167*19261079SEd Maste return 1; 168*19261079SEd Maste /* Failed. */ 169*19261079SEd Maste return 0; 170*19261079SEd Maste } 171*19261079SEd Maste /* 172*19261079SEd Maste * There must be at least one more character in the string. 173*19261079SEd Maste * If we are at the end, fail. 174*19261079SEd Maste */ 175*19261079SEd Maste if (!*s) 176*19261079SEd Maste return 0; 177*19261079SEd Maste 178*19261079SEd Maste /* Check if the next character of the string is acceptable. */ 179*19261079SEd Maste if (*pattern != '?' && towlower(*pattern) != towlower(*s)) 180*19261079SEd Maste return 0; 181*19261079SEd Maste 182*19261079SEd Maste /* Move to the next character, both in string and in pattern. */ 183*19261079SEd Maste s++; 184*19261079SEd Maste pattern++; 185*19261079SEd Maste } 186*19261079SEd Maste /* NOTREACHED */ 187*19261079SEd Maste } 188*19261079SEd Maste 189*19261079SEd Maste static int 190*19261079SEd Maste _match_pattern(const char *s, const char *pattern) 191*19261079SEd Maste { 192*19261079SEd Maste wchar_t *ws; 193*19261079SEd Maste wchar_t *wpattern; 194*19261079SEd Maste size_t len; 195*19261079SEd Maste int ret; 196*19261079SEd Maste 197*19261079SEd Maste if ((len = mbstowcs(NULL, s, 0)) < 0) 198*19261079SEd Maste return 0; 199*19261079SEd Maste ws = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t)); 200*19261079SEd Maste mbstowcs(ws, s, len + 1); 201*19261079SEd Maste if ((len = mbstowcs(NULL, pattern, 0)) < 0) 202*19261079SEd Maste return 0; 203*19261079SEd Maste wpattern = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t)); 204*19261079SEd Maste mbstowcs(wpattern, pattern, len + 1); 205*19261079SEd Maste ret = __match_pattern (ws, wpattern); 206*19261079SEd Maste free(ws); 207*19261079SEd Maste free(wpattern); 208*19261079SEd Maste return ret; 209*19261079SEd Maste } 210*19261079SEd Maste 211*19261079SEd Maste /* 212*19261079SEd Maste * Tries to match the string against the 213*19261079SEd Maste * comma-separated sequence of subpatterns (each possibly preceded by ! to 214*19261079SEd Maste * indicate negation). Returns -1 if negation matches, 1 if there is 215*19261079SEd Maste * a positive match, 0 if there is no match at all. 216*19261079SEd Maste */ 217*19261079SEd Maste int 218*19261079SEd Maste cygwin_ug_match_pattern_list(const char *string, const char *pattern) 219*19261079SEd Maste { 220*19261079SEd Maste char sub[1024]; 221*19261079SEd Maste int negated; 222*19261079SEd Maste int got_positive; 223*19261079SEd Maste u_int i, subi, len = strlen(pattern); 224*19261079SEd Maste 225*19261079SEd Maste got_positive = 0; 226*19261079SEd Maste for (i = 0; i < len;) { 227*19261079SEd Maste /* Check if the subpattern is negated. */ 228*19261079SEd Maste if (pattern[i] == '!') { 229*19261079SEd Maste negated = 1; 230*19261079SEd Maste i++; 231*19261079SEd Maste } else 232*19261079SEd Maste negated = 0; 233*19261079SEd Maste 234*19261079SEd Maste /* 235*19261079SEd Maste * Extract the subpattern up to a comma or end. Convert the 236*19261079SEd Maste * subpattern to lowercase. 237*19261079SEd Maste */ 238*19261079SEd Maste for (subi = 0; 239*19261079SEd Maste i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; 240*19261079SEd Maste subi++, i++) 241*19261079SEd Maste sub[subi] = pattern[i]; 242*19261079SEd Maste /* If subpattern too long, return failure (no match). */ 243*19261079SEd Maste if (subi >= sizeof(sub) - 1) 244*19261079SEd Maste return 0; 245*19261079SEd Maste 246*19261079SEd Maste /* If the subpattern was terminated by a comma, then skip it. */ 247*19261079SEd Maste if (i < len && pattern[i] == ',') 248*19261079SEd Maste i++; 249*19261079SEd Maste 250*19261079SEd Maste /* Null-terminate the subpattern. */ 251*19261079SEd Maste sub[subi] = '\0'; 252*19261079SEd Maste 253*19261079SEd Maste /* Try to match the subpattern against the string. */ 254*19261079SEd Maste if (_match_pattern(string, sub)) { 255*19261079SEd Maste if (negated) 256*19261079SEd Maste return -1; /* Negative */ 257*19261079SEd Maste else 258*19261079SEd Maste got_positive = 1; /* Positive */ 259*19261079SEd Maste } 260*19261079SEd Maste } 261*19261079SEd Maste 262*19261079SEd Maste /* 263*19261079SEd Maste * Return success if got a positive match. If there was a negative 264*19261079SEd Maste * match, we have already returned -1 and never get here. 265*19261079SEd Maste */ 266*19261079SEd Maste return got_positive; 267*19261079SEd Maste } 268*19261079SEd Maste 26983d2307dSDag-Erling Smørgrav #endif /* HAVE_CYGWIN */ 270