183d2307dSDag-Erling Smørgrav /* 283d2307dSDag-Erling Smørgrav * Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.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 3083d2307dSDag-Erling Smørgrav #include "includes.h" 3183d2307dSDag-Erling Smørgrav 325e8dbd04SDag-Erling Smørgrav RCSID("$Id: bsd-cygwin_util.c,v 1.13 2004/08/30 10:42:08 dtucker Exp $"); 3383d2307dSDag-Erling Smørgrav 3483d2307dSDag-Erling Smørgrav #ifdef HAVE_CYGWIN 3583d2307dSDag-Erling Smørgrav 3683d2307dSDag-Erling Smørgrav #include <fcntl.h> 3783d2307dSDag-Erling Smørgrav #include <stdlib.h> 3883d2307dSDag-Erling Smørgrav #include <sys/utsname.h> 3983d2307dSDag-Erling Smørgrav #include <sys/vfs.h> 4083d2307dSDag-Erling Smørgrav #include <windows.h> 415e8dbd04SDag-Erling Smørgrav #include "xmalloc.h" 4283d2307dSDag-Erling Smørgrav #define is_winnt (GetVersion() < 0x80000000) 4383d2307dSDag-Erling Smørgrav 4483d2307dSDag-Erling Smørgrav #define ntsec_on(c) ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec")) 45d0c8c0bcSDag-Erling Smørgrav #define ntsec_off(c) ((c) && strstr((c),"nontsec")) 4683d2307dSDag-Erling Smørgrav #define ntea_on(c) ((c) && strstr((c),"ntea") && !strstr((c),"nontea")) 4783d2307dSDag-Erling Smørgrav 4883d2307dSDag-Erling Smørgrav #if defined(open) && open == binary_open 4983d2307dSDag-Erling Smørgrav # undef open 5083d2307dSDag-Erling Smørgrav #endif 5183d2307dSDag-Erling Smørgrav #if defined(pipe) && open == binary_pipe 5283d2307dSDag-Erling Smørgrav # undef pipe 5383d2307dSDag-Erling Smørgrav #endif 5483d2307dSDag-Erling Smørgrav 55d95e11bfSDag-Erling Smørgrav int 56d95e11bfSDag-Erling Smørgrav binary_open(const char *filename, int flags, ...) 5783d2307dSDag-Erling Smørgrav { 5883d2307dSDag-Erling Smørgrav va_list ap; 5983d2307dSDag-Erling Smørgrav mode_t mode; 6083d2307dSDag-Erling Smørgrav 6183d2307dSDag-Erling Smørgrav va_start(ap, flags); 6283d2307dSDag-Erling Smørgrav mode = va_arg(ap, mode_t); 6383d2307dSDag-Erling Smørgrav va_end(ap); 64d95e11bfSDag-Erling Smørgrav return (open(filename, flags | O_BINARY, mode)); 6583d2307dSDag-Erling Smørgrav } 6683d2307dSDag-Erling Smørgrav 67d95e11bfSDag-Erling Smørgrav int 68d95e11bfSDag-Erling Smørgrav binary_pipe(int fd[2]) 6983d2307dSDag-Erling Smørgrav { 7083d2307dSDag-Erling Smørgrav int ret = pipe(fd); 7183d2307dSDag-Erling Smørgrav 7283d2307dSDag-Erling Smørgrav if (!ret) { 7383d2307dSDag-Erling Smørgrav setmode(fd[0], O_BINARY); 7483d2307dSDag-Erling Smørgrav setmode(fd[1], O_BINARY); 7583d2307dSDag-Erling Smørgrav } 76d95e11bfSDag-Erling Smørgrav return (ret); 7783d2307dSDag-Erling Smørgrav } 7883d2307dSDag-Erling Smørgrav 79d0c8c0bcSDag-Erling Smørgrav #define HAS_CREATE_TOKEN 1 80d0c8c0bcSDag-Erling Smørgrav #define HAS_NTSEC_BY_DEFAULT 2 8152028650SDag-Erling Smørgrav #define HAS_CREATE_TOKEN_WO_NTSEC 3 82d0c8c0bcSDag-Erling Smørgrav 83d95e11bfSDag-Erling Smørgrav static int 84d95e11bfSDag-Erling Smørgrav has_capability(int what) 85d0c8c0bcSDag-Erling Smørgrav { 86d0c8c0bcSDag-Erling Smørgrav static int inited; 87d0c8c0bcSDag-Erling Smørgrav static int has_create_token; 88d0c8c0bcSDag-Erling Smørgrav static int has_ntsec_by_default; 8952028650SDag-Erling Smørgrav static int has_create_token_wo_ntsec; 90d0c8c0bcSDag-Erling Smørgrav 91d95e11bfSDag-Erling Smørgrav /* 92d95e11bfSDag-Erling Smørgrav * has_capability() basically calls uname() and checks if 93d95e11bfSDag-Erling Smørgrav * specific capabilities of Cygwin can be evaluated from that. 94d95e11bfSDag-Erling Smørgrav * This simplifies the calling functions which only have to ask 95d95e11bfSDag-Erling Smørgrav * for a capability using has_capability() instead of having 96d95e11bfSDag-Erling Smørgrav * to figure that out by themselves. 97d95e11bfSDag-Erling Smørgrav */ 98d0c8c0bcSDag-Erling Smørgrav if (!inited) { 99d0c8c0bcSDag-Erling Smørgrav struct utsname uts; 100d0c8c0bcSDag-Erling Smørgrav 101d0c8c0bcSDag-Erling Smørgrav if (!uname(&uts)) { 102d95e11bfSDag-Erling Smørgrav int major_high = 0, major_low = 0, minor = 0; 103d95e11bfSDag-Erling Smørgrav int api_major_version = 0, api_minor_version = 0; 104d0c8c0bcSDag-Erling Smørgrav char *c; 105d0c8c0bcSDag-Erling Smørgrav 106d0c8c0bcSDag-Erling Smørgrav sscanf(uts.release, "%d.%d.%d", &major_high, 107d0c8c0bcSDag-Erling Smørgrav &major_low, &minor); 108d95e11bfSDag-Erling Smørgrav if ((c = strchr(uts.release, '(')) != NULL) { 109d0c8c0bcSDag-Erling Smørgrav sscanf(c + 1, "%d.%d", &api_major_version, 110d0c8c0bcSDag-Erling Smørgrav &api_minor_version); 111d95e11bfSDag-Erling Smørgrav } 112d0c8c0bcSDag-Erling Smørgrav if (major_high > 1 || 113d0c8c0bcSDag-Erling Smørgrav (major_high == 1 && (major_low > 3 || 114d0c8c0bcSDag-Erling Smørgrav (major_low == 3 && minor >= 2)))) 115d0c8c0bcSDag-Erling Smørgrav has_create_token = 1; 116d0c8c0bcSDag-Erling Smørgrav if (api_major_version > 0 || api_minor_version >= 56) 117d0c8c0bcSDag-Erling Smørgrav has_ntsec_by_default = 1; 11852028650SDag-Erling Smørgrav if (major_high > 1 || 11952028650SDag-Erling Smørgrav (major_high == 1 && major_low >= 5)) 12052028650SDag-Erling Smørgrav has_create_token_wo_ntsec = 1; 121d0c8c0bcSDag-Erling Smørgrav inited = 1; 122d0c8c0bcSDag-Erling Smørgrav } 123d0c8c0bcSDag-Erling Smørgrav } 124d0c8c0bcSDag-Erling Smørgrav switch (what) { 125d0c8c0bcSDag-Erling Smørgrav case HAS_CREATE_TOKEN: 126d95e11bfSDag-Erling Smørgrav return (has_create_token); 127d0c8c0bcSDag-Erling Smørgrav case HAS_NTSEC_BY_DEFAULT: 128d95e11bfSDag-Erling Smørgrav return (has_ntsec_by_default); 12952028650SDag-Erling Smørgrav case HAS_CREATE_TOKEN_WO_NTSEC: 13052028650SDag-Erling Smørgrav return (has_create_token_wo_ntsec); 131d0c8c0bcSDag-Erling Smørgrav } 132d95e11bfSDag-Erling Smørgrav return (0); 133d0c8c0bcSDag-Erling Smørgrav } 134d0c8c0bcSDag-Erling Smørgrav 135d95e11bfSDag-Erling Smørgrav int 136d95e11bfSDag-Erling Smørgrav check_nt_auth(int pwd_authenticated, struct passwd *pw) 13783d2307dSDag-Erling Smørgrav { 13883d2307dSDag-Erling Smørgrav /* 13983d2307dSDag-Erling Smørgrav * The only authentication which is able to change the user 14083d2307dSDag-Erling Smørgrav * context on NT systems is the password authentication. So 14183d2307dSDag-Erling Smørgrav * we deny all requsts for changing the user context if another 14283d2307dSDag-Erling Smørgrav * authentication method is used. 14383d2307dSDag-Erling Smørgrav * 14483d2307dSDag-Erling Smørgrav * This doesn't apply to Cygwin versions >= 1.3.2 anymore which 14583d2307dSDag-Erling Smørgrav * uses the undocumented NtCreateToken() call to create a user 14683d2307dSDag-Erling Smørgrav * token if the process has the appropriate privileges and if 14783d2307dSDag-Erling Smørgrav * CYGWIN ntsec setting is on. 14883d2307dSDag-Erling Smørgrav */ 14983d2307dSDag-Erling Smørgrav static int has_create_token = -1; 15083d2307dSDag-Erling Smørgrav 15183d2307dSDag-Erling Smørgrav if (pw == NULL) 15283d2307dSDag-Erling Smørgrav return 0; 15383d2307dSDag-Erling Smørgrav if (is_winnt) { 15483d2307dSDag-Erling Smørgrav if (has_create_token < 0) { 15583d2307dSDag-Erling Smørgrav char *cygwin = getenv("CYGWIN"); 15683d2307dSDag-Erling Smørgrav 15783d2307dSDag-Erling Smørgrav has_create_token = 0; 158d0c8c0bcSDag-Erling Smørgrav if (has_capability(HAS_CREATE_TOKEN) && 159d0c8c0bcSDag-Erling Smørgrav (ntsec_on(cygwin) || 160d0c8c0bcSDag-Erling Smørgrav (has_capability(HAS_NTSEC_BY_DEFAULT) && 16152028650SDag-Erling Smørgrav !ntsec_off(cygwin)) || 16252028650SDag-Erling Smørgrav has_capability(HAS_CREATE_TOKEN_WO_NTSEC))) 16383d2307dSDag-Erling Smørgrav has_create_token = 1; 16483d2307dSDag-Erling Smørgrav } 16583d2307dSDag-Erling Smørgrav if (has_create_token < 1 && 16683d2307dSDag-Erling Smørgrav !pwd_authenticated && geteuid() != pw->pw_uid) 167d95e11bfSDag-Erling Smørgrav return (0); 16883d2307dSDag-Erling Smørgrav } 169d95e11bfSDag-Erling Smørgrav return (1); 17083d2307dSDag-Erling Smørgrav } 17183d2307dSDag-Erling Smørgrav 172d95e11bfSDag-Erling Smørgrav int 173d95e11bfSDag-Erling Smørgrav check_ntsec(const char *filename) 17483d2307dSDag-Erling Smørgrav { 17583d2307dSDag-Erling Smørgrav char *cygwin; 176d95e11bfSDag-Erling Smørgrav int allow_ntea = 0, allow_ntsec = 0; 17783d2307dSDag-Erling Smørgrav struct statfs fsstat; 17883d2307dSDag-Erling Smørgrav 17983d2307dSDag-Erling Smørgrav /* Windows 95/98/ME don't support file system security at all. */ 18083d2307dSDag-Erling Smørgrav if (!is_winnt) 181d95e11bfSDag-Erling Smørgrav return (0); 18283d2307dSDag-Erling Smørgrav 18383d2307dSDag-Erling Smørgrav /* Evaluate current CYGWIN settings. */ 18483d2307dSDag-Erling Smørgrav cygwin = getenv("CYGWIN"); 18583d2307dSDag-Erling Smørgrav allow_ntea = ntea_on(cygwin); 186d0c8c0bcSDag-Erling Smørgrav allow_ntsec = ntsec_on(cygwin) || 187d95e11bfSDag-Erling Smørgrav (has_capability(HAS_NTSEC_BY_DEFAULT) && !ntsec_off(cygwin)); 18883d2307dSDag-Erling Smørgrav 18983d2307dSDag-Erling Smørgrav /* 19083d2307dSDag-Erling Smørgrav * `ntea' is an emulation of POSIX attributes. It doesn't support 19183d2307dSDag-Erling Smørgrav * real file level security as ntsec on NTFS file systems does 19283d2307dSDag-Erling Smørgrav * but it supports FAT filesystems. `ntea' is minimum requirement 19383d2307dSDag-Erling Smørgrav * for security checks. 19483d2307dSDag-Erling Smørgrav */ 19583d2307dSDag-Erling Smørgrav if (allow_ntea) 196d95e11bfSDag-Erling Smørgrav return (1); 19783d2307dSDag-Erling Smørgrav 19883d2307dSDag-Erling Smørgrav /* 19983d2307dSDag-Erling Smørgrav * Retrieve file system flags. In Cygwin, file system flags are 20083d2307dSDag-Erling Smørgrav * copied to f_type which has no meaning in Win32 itself. 20183d2307dSDag-Erling Smørgrav */ 20283d2307dSDag-Erling Smørgrav if (statfs(filename, &fsstat)) 203d95e11bfSDag-Erling Smørgrav return (1); 20483d2307dSDag-Erling Smørgrav 20583d2307dSDag-Erling Smørgrav /* 20683d2307dSDag-Erling Smørgrav * Only file systems supporting ACLs are able to set permissions. 20783d2307dSDag-Erling Smørgrav * `ntsec' is the setting in Cygwin which switches using of NTFS 20883d2307dSDag-Erling Smørgrav * ACLs to support POSIX permissions on files. 20983d2307dSDag-Erling Smørgrav */ 21083d2307dSDag-Erling Smørgrav if (fsstat.f_type & FS_PERSISTENT_ACLS) 211d95e11bfSDag-Erling Smørgrav return (allow_ntsec); 21283d2307dSDag-Erling Smørgrav 213d95e11bfSDag-Erling Smørgrav return (0); 21483d2307dSDag-Erling Smørgrav } 21583d2307dSDag-Erling Smørgrav 216d95e11bfSDag-Erling Smørgrav void 217d95e11bfSDag-Erling Smørgrav register_9x_service(void) 21883d2307dSDag-Erling Smørgrav { 21983d2307dSDag-Erling Smørgrav HINSTANCE kerneldll; 22083d2307dSDag-Erling Smørgrav DWORD (*RegisterServiceProcess)(DWORD, DWORD); 22183d2307dSDag-Erling Smørgrav 22283d2307dSDag-Erling Smørgrav /* The service register mechanism in 9x/Me is pretty different from 22383d2307dSDag-Erling Smørgrav * NT/2K/XP. In NT/2K/XP we're using a special service starter 22483d2307dSDag-Erling Smørgrav * application to register and control sshd as service. This method 22583d2307dSDag-Erling Smørgrav * doesn't play nicely with 9x/Me. For that reason we register here 22683d2307dSDag-Erling Smørgrav * as service when running under 9x/Me. This function is only called 22783d2307dSDag-Erling Smørgrav * by the child sshd when it's going to daemonize. 22883d2307dSDag-Erling Smørgrav */ 22983d2307dSDag-Erling Smørgrav if (is_winnt) 23083d2307dSDag-Erling Smørgrav return; 23183d2307dSDag-Erling Smørgrav if (!(kerneldll = LoadLibrary("KERNEL32.DLL"))) 23283d2307dSDag-Erling Smørgrav return; 23383d2307dSDag-Erling Smørgrav if (!(RegisterServiceProcess = (DWORD (*)(DWORD, DWORD)) 23483d2307dSDag-Erling Smørgrav GetProcAddress(kerneldll, "RegisterServiceProcess"))) 23583d2307dSDag-Erling Smørgrav return; 23683d2307dSDag-Erling Smørgrav RegisterServiceProcess(0, 1); 23783d2307dSDag-Erling Smørgrav } 23883d2307dSDag-Erling Smørgrav 2395e8dbd04SDag-Erling Smørgrav #define NL(x) x, (sizeof (x) - 1) 2405e8dbd04SDag-Erling Smørgrav #define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0])) 2415e8dbd04SDag-Erling Smørgrav 2425e8dbd04SDag-Erling Smørgrav static struct wenv { 2435e8dbd04SDag-Erling Smørgrav const char *name; 2445e8dbd04SDag-Erling Smørgrav size_t namelen; 2455e8dbd04SDag-Erling Smørgrav } wenv_arr[] = { 2465e8dbd04SDag-Erling Smørgrav { NL("ALLUSERSPROFILE=") }, 2475e8dbd04SDag-Erling Smørgrav { NL("COMMONPROGRAMFILES=") }, 2485e8dbd04SDag-Erling Smørgrav { NL("COMPUTERNAME=") }, 2495e8dbd04SDag-Erling Smørgrav { NL("COMSPEC=") }, 2505e8dbd04SDag-Erling Smørgrav { NL("NUMBER_OF_PROCESSORS=") }, 2515e8dbd04SDag-Erling Smørgrav { NL("OS=") }, 2525e8dbd04SDag-Erling Smørgrav { NL("PATH=") }, 2535e8dbd04SDag-Erling Smørgrav { NL("PATHEXT=") }, 2545e8dbd04SDag-Erling Smørgrav { NL("PROCESSOR_ARCHITECTURE=") }, 2555e8dbd04SDag-Erling Smørgrav { NL("PROCESSOR_IDENTIFIER=") }, 2565e8dbd04SDag-Erling Smørgrav { NL("PROCESSOR_LEVEL=") }, 2575e8dbd04SDag-Erling Smørgrav { NL("PROCESSOR_REVISION=") }, 2585e8dbd04SDag-Erling Smørgrav { NL("PROGRAMFILES=") }, 2595e8dbd04SDag-Erling Smørgrav { NL("SYSTEMDRIVE=") }, 2605e8dbd04SDag-Erling Smørgrav { NL("SYSTEMROOT=") }, 2615e8dbd04SDag-Erling Smørgrav { NL("TMP=") }, 2625e8dbd04SDag-Erling Smørgrav { NL("TEMP=") }, 2635e8dbd04SDag-Erling Smørgrav { NL("WINDIR=") }, 2645e8dbd04SDag-Erling Smørgrav }; 2655e8dbd04SDag-Erling Smørgrav 2665e8dbd04SDag-Erling Smørgrav char ** 2675e8dbd04SDag-Erling Smørgrav fetch_windows_environment(void) 2685e8dbd04SDag-Erling Smørgrav { 2695e8dbd04SDag-Erling Smørgrav char **e, **p; 2705e8dbd04SDag-Erling Smørgrav int i, idx = 0; 2715e8dbd04SDag-Erling Smørgrav 2725e8dbd04SDag-Erling Smørgrav p = xmalloc(WENV_SIZ * sizeof(char *)); 2735e8dbd04SDag-Erling Smørgrav for (e = environ; *e != NULL; ++e) { 2745e8dbd04SDag-Erling Smørgrav for (i = 0; i < WENV_SIZ; ++i) { 2755e8dbd04SDag-Erling Smørgrav if (!strncmp(*e, wenv_arr[i].name, wenv_arr[i].namelen)) 2765e8dbd04SDag-Erling Smørgrav p[idx++] = *e; 2775e8dbd04SDag-Erling Smørgrav } 2785e8dbd04SDag-Erling Smørgrav } 2795e8dbd04SDag-Erling Smørgrav p[idx] = NULL; 2805e8dbd04SDag-Erling Smørgrav return p; 2815e8dbd04SDag-Erling Smørgrav } 2825e8dbd04SDag-Erling Smørgrav 2835e8dbd04SDag-Erling Smørgrav void 2845e8dbd04SDag-Erling Smørgrav free_windows_environment(char **p) 2855e8dbd04SDag-Erling Smørgrav { 2865e8dbd04SDag-Erling Smørgrav xfree(p); 2875e8dbd04SDag-Erling Smørgrav } 2885e8dbd04SDag-Erling Smørgrav 28983d2307dSDag-Erling Smørgrav #endif /* HAVE_CYGWIN */ 290