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 32d95e11bfSDag-Erling Smørgrav RCSID("$Id: bsd-cygwin_util.c,v 1.11 2003/08/07 06:23:43 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> 4183d2307dSDag-Erling Smørgrav #define is_winnt (GetVersion() < 0x80000000) 4283d2307dSDag-Erling Smørgrav 4383d2307dSDag-Erling Smørgrav #define ntsec_on(c) ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec")) 44d0c8c0bcSDag-Erling Smørgrav #define ntsec_off(c) ((c) && strstr((c),"nontsec")) 4583d2307dSDag-Erling Smørgrav #define ntea_on(c) ((c) && strstr((c),"ntea") && !strstr((c),"nontea")) 4683d2307dSDag-Erling Smørgrav 4783d2307dSDag-Erling Smørgrav #if defined(open) && open == binary_open 4883d2307dSDag-Erling Smørgrav # undef open 4983d2307dSDag-Erling Smørgrav #endif 5083d2307dSDag-Erling Smørgrav #if defined(pipe) && open == binary_pipe 5183d2307dSDag-Erling Smørgrav # undef pipe 5283d2307dSDag-Erling Smørgrav #endif 5383d2307dSDag-Erling Smørgrav 54d95e11bfSDag-Erling Smørgrav int 55d95e11bfSDag-Erling Smørgrav binary_open(const char *filename, int flags, ...) 5683d2307dSDag-Erling Smørgrav { 5783d2307dSDag-Erling Smørgrav va_list ap; 5883d2307dSDag-Erling Smørgrav mode_t mode; 5983d2307dSDag-Erling Smørgrav 6083d2307dSDag-Erling Smørgrav va_start(ap, flags); 6183d2307dSDag-Erling Smørgrav mode = va_arg(ap, mode_t); 6283d2307dSDag-Erling Smørgrav va_end(ap); 63d95e11bfSDag-Erling Smørgrav return (open(filename, flags | O_BINARY, mode)); 6483d2307dSDag-Erling Smørgrav } 6583d2307dSDag-Erling Smørgrav 66d95e11bfSDag-Erling Smørgrav int 67d95e11bfSDag-Erling Smørgrav binary_pipe(int fd[2]) 6883d2307dSDag-Erling Smørgrav { 6983d2307dSDag-Erling Smørgrav int ret = pipe(fd); 7083d2307dSDag-Erling Smørgrav 7183d2307dSDag-Erling Smørgrav if (!ret) { 7283d2307dSDag-Erling Smørgrav setmode(fd[0], O_BINARY); 7383d2307dSDag-Erling Smørgrav setmode(fd[1], O_BINARY); 7483d2307dSDag-Erling Smørgrav } 75d95e11bfSDag-Erling Smørgrav return (ret); 7683d2307dSDag-Erling Smørgrav } 7783d2307dSDag-Erling Smørgrav 78d0c8c0bcSDag-Erling Smørgrav #define HAS_CREATE_TOKEN 1 79d0c8c0bcSDag-Erling Smørgrav #define HAS_NTSEC_BY_DEFAULT 2 80d0c8c0bcSDag-Erling Smørgrav 81d95e11bfSDag-Erling Smørgrav static int 82d95e11bfSDag-Erling Smørgrav has_capability(int what) 83d0c8c0bcSDag-Erling Smørgrav { 84d0c8c0bcSDag-Erling Smørgrav static int inited; 85d0c8c0bcSDag-Erling Smørgrav static int has_create_token; 86d0c8c0bcSDag-Erling Smørgrav static int has_ntsec_by_default; 87d0c8c0bcSDag-Erling Smørgrav 88d95e11bfSDag-Erling Smørgrav /* 89d95e11bfSDag-Erling Smørgrav * has_capability() basically calls uname() and checks if 90d95e11bfSDag-Erling Smørgrav * specific capabilities of Cygwin can be evaluated from that. 91d95e11bfSDag-Erling Smørgrav * This simplifies the calling functions which only have to ask 92d95e11bfSDag-Erling Smørgrav * for a capability using has_capability() instead of having 93d95e11bfSDag-Erling Smørgrav * to figure that out by themselves. 94d95e11bfSDag-Erling Smørgrav */ 95d0c8c0bcSDag-Erling Smørgrav if (!inited) { 96d0c8c0bcSDag-Erling Smørgrav struct utsname uts; 97d0c8c0bcSDag-Erling Smørgrav char *c; 98d0c8c0bcSDag-Erling Smørgrav 99d0c8c0bcSDag-Erling Smørgrav if (!uname(&uts)) { 100d95e11bfSDag-Erling Smørgrav int major_high = 0, major_low = 0, minor = 0; 101d95e11bfSDag-Erling Smørgrav int api_major_version = 0, api_minor_version = 0; 102d0c8c0bcSDag-Erling Smørgrav char *c; 103d0c8c0bcSDag-Erling Smørgrav 104d0c8c0bcSDag-Erling Smørgrav sscanf(uts.release, "%d.%d.%d", &major_high, 105d0c8c0bcSDag-Erling Smørgrav &major_low, &minor); 106d95e11bfSDag-Erling Smørgrav if ((c = strchr(uts.release, '(')) != NULL) { 107d0c8c0bcSDag-Erling Smørgrav sscanf(c + 1, "%d.%d", &api_major_version, 108d0c8c0bcSDag-Erling Smørgrav &api_minor_version); 109d95e11bfSDag-Erling Smørgrav } 110d0c8c0bcSDag-Erling Smørgrav if (major_high > 1 || 111d0c8c0bcSDag-Erling Smørgrav (major_high == 1 && (major_low > 3 || 112d0c8c0bcSDag-Erling Smørgrav (major_low == 3 && minor >= 2)))) 113d0c8c0bcSDag-Erling Smørgrav has_create_token = 1; 114d0c8c0bcSDag-Erling Smørgrav if (api_major_version > 0 || api_minor_version >= 56) 115d0c8c0bcSDag-Erling Smørgrav has_ntsec_by_default = 1; 116d0c8c0bcSDag-Erling Smørgrav inited = 1; 117d0c8c0bcSDag-Erling Smørgrav } 118d0c8c0bcSDag-Erling Smørgrav } 119d0c8c0bcSDag-Erling Smørgrav switch (what) { 120d0c8c0bcSDag-Erling Smørgrav case HAS_CREATE_TOKEN: 121d95e11bfSDag-Erling Smørgrav return (has_create_token); 122d0c8c0bcSDag-Erling Smørgrav case HAS_NTSEC_BY_DEFAULT: 123d95e11bfSDag-Erling Smørgrav return (has_ntsec_by_default); 124d0c8c0bcSDag-Erling Smørgrav } 125d95e11bfSDag-Erling Smørgrav return (0); 126d0c8c0bcSDag-Erling Smørgrav } 127d0c8c0bcSDag-Erling Smørgrav 128d95e11bfSDag-Erling Smørgrav int 129d95e11bfSDag-Erling Smørgrav check_nt_auth(int pwd_authenticated, struct passwd *pw) 13083d2307dSDag-Erling Smørgrav { 13183d2307dSDag-Erling Smørgrav /* 13283d2307dSDag-Erling Smørgrav * The only authentication which is able to change the user 13383d2307dSDag-Erling Smørgrav * context on NT systems is the password authentication. So 13483d2307dSDag-Erling Smørgrav * we deny all requsts for changing the user context if another 13583d2307dSDag-Erling Smørgrav * authentication method is used. 13683d2307dSDag-Erling Smørgrav * 13783d2307dSDag-Erling Smørgrav * This doesn't apply to Cygwin versions >= 1.3.2 anymore which 13883d2307dSDag-Erling Smørgrav * uses the undocumented NtCreateToken() call to create a user 13983d2307dSDag-Erling Smørgrav * token if the process has the appropriate privileges and if 14083d2307dSDag-Erling Smørgrav * CYGWIN ntsec setting is on. 14183d2307dSDag-Erling Smørgrav */ 14283d2307dSDag-Erling Smørgrav static int has_create_token = -1; 14383d2307dSDag-Erling Smørgrav 14483d2307dSDag-Erling Smørgrav if (pw == NULL) 14583d2307dSDag-Erling Smørgrav return 0; 14683d2307dSDag-Erling Smørgrav if (is_winnt) { 14783d2307dSDag-Erling Smørgrav if (has_create_token < 0) { 14883d2307dSDag-Erling Smørgrav char *cygwin = getenv("CYGWIN"); 14983d2307dSDag-Erling Smørgrav 15083d2307dSDag-Erling Smørgrav has_create_token = 0; 151d0c8c0bcSDag-Erling Smørgrav if (has_capability(HAS_CREATE_TOKEN) && 152d0c8c0bcSDag-Erling Smørgrav (ntsec_on(cygwin) || 153d0c8c0bcSDag-Erling Smørgrav (has_capability(HAS_NTSEC_BY_DEFAULT) && 154d0c8c0bcSDag-Erling Smørgrav !ntsec_off(cygwin)))) 15583d2307dSDag-Erling Smørgrav has_create_token = 1; 15683d2307dSDag-Erling Smørgrav } 15783d2307dSDag-Erling Smørgrav if (has_create_token < 1 && 15883d2307dSDag-Erling Smørgrav !pwd_authenticated && geteuid() != pw->pw_uid) 159d95e11bfSDag-Erling Smørgrav return (0); 16083d2307dSDag-Erling Smørgrav } 161d95e11bfSDag-Erling Smørgrav return (1); 16283d2307dSDag-Erling Smørgrav } 16383d2307dSDag-Erling Smørgrav 164d95e11bfSDag-Erling Smørgrav int 165d95e11bfSDag-Erling Smørgrav check_ntsec(const char *filename) 16683d2307dSDag-Erling Smørgrav { 16783d2307dSDag-Erling Smørgrav char *cygwin; 168d95e11bfSDag-Erling Smørgrav int allow_ntea = 0, allow_ntsec = 0; 16983d2307dSDag-Erling Smørgrav struct statfs fsstat; 17083d2307dSDag-Erling Smørgrav 17183d2307dSDag-Erling Smørgrav /* Windows 95/98/ME don't support file system security at all. */ 17283d2307dSDag-Erling Smørgrav if (!is_winnt) 173d95e11bfSDag-Erling Smørgrav return (0); 17483d2307dSDag-Erling Smørgrav 17583d2307dSDag-Erling Smørgrav /* Evaluate current CYGWIN settings. */ 17683d2307dSDag-Erling Smørgrav cygwin = getenv("CYGWIN"); 17783d2307dSDag-Erling Smørgrav allow_ntea = ntea_on(cygwin); 178d0c8c0bcSDag-Erling Smørgrav allow_ntsec = ntsec_on(cygwin) || 179d95e11bfSDag-Erling Smørgrav (has_capability(HAS_NTSEC_BY_DEFAULT) && !ntsec_off(cygwin)); 18083d2307dSDag-Erling Smørgrav 18183d2307dSDag-Erling Smørgrav /* 18283d2307dSDag-Erling Smørgrav * `ntea' is an emulation of POSIX attributes. It doesn't support 18383d2307dSDag-Erling Smørgrav * real file level security as ntsec on NTFS file systems does 18483d2307dSDag-Erling Smørgrav * but it supports FAT filesystems. `ntea' is minimum requirement 18583d2307dSDag-Erling Smørgrav * for security checks. 18683d2307dSDag-Erling Smørgrav */ 18783d2307dSDag-Erling Smørgrav if (allow_ntea) 188d95e11bfSDag-Erling Smørgrav return (1); 18983d2307dSDag-Erling Smørgrav 19083d2307dSDag-Erling Smørgrav /* 19183d2307dSDag-Erling Smørgrav * Retrieve file system flags. In Cygwin, file system flags are 19283d2307dSDag-Erling Smørgrav * copied to f_type which has no meaning in Win32 itself. 19383d2307dSDag-Erling Smørgrav */ 19483d2307dSDag-Erling Smørgrav if (statfs(filename, &fsstat)) 195d95e11bfSDag-Erling Smørgrav return (1); 19683d2307dSDag-Erling Smørgrav 19783d2307dSDag-Erling Smørgrav /* 19883d2307dSDag-Erling Smørgrav * Only file systems supporting ACLs are able to set permissions. 19983d2307dSDag-Erling Smørgrav * `ntsec' is the setting in Cygwin which switches using of NTFS 20083d2307dSDag-Erling Smørgrav * ACLs to support POSIX permissions on files. 20183d2307dSDag-Erling Smørgrav */ 20283d2307dSDag-Erling Smørgrav if (fsstat.f_type & FS_PERSISTENT_ACLS) 203d95e11bfSDag-Erling Smørgrav return (allow_ntsec); 20483d2307dSDag-Erling Smørgrav 205d95e11bfSDag-Erling Smørgrav return (0); 20683d2307dSDag-Erling Smørgrav } 20783d2307dSDag-Erling Smørgrav 208d95e11bfSDag-Erling Smørgrav void 209d95e11bfSDag-Erling Smørgrav register_9x_service(void) 21083d2307dSDag-Erling Smørgrav { 21183d2307dSDag-Erling Smørgrav HINSTANCE kerneldll; 21283d2307dSDag-Erling Smørgrav DWORD (*RegisterServiceProcess)(DWORD, DWORD); 21383d2307dSDag-Erling Smørgrav 21483d2307dSDag-Erling Smørgrav /* The service register mechanism in 9x/Me is pretty different from 21583d2307dSDag-Erling Smørgrav * NT/2K/XP. In NT/2K/XP we're using a special service starter 21683d2307dSDag-Erling Smørgrav * application to register and control sshd as service. This method 21783d2307dSDag-Erling Smørgrav * doesn't play nicely with 9x/Me. For that reason we register here 21883d2307dSDag-Erling Smørgrav * as service when running under 9x/Me. This function is only called 21983d2307dSDag-Erling Smørgrav * by the child sshd when it's going to daemonize. 22083d2307dSDag-Erling Smørgrav */ 22183d2307dSDag-Erling Smørgrav if (is_winnt) 22283d2307dSDag-Erling Smørgrav return; 22383d2307dSDag-Erling Smørgrav if (!(kerneldll = LoadLibrary("KERNEL32.DLL"))) 22483d2307dSDag-Erling Smørgrav return; 22583d2307dSDag-Erling Smørgrav if (!(RegisterServiceProcess = (DWORD (*)(DWORD, DWORD)) 22683d2307dSDag-Erling Smørgrav GetProcAddress(kerneldll, "RegisterServiceProcess"))) 22783d2307dSDag-Erling Smørgrav return; 22883d2307dSDag-Erling Smørgrav RegisterServiceProcess(0, 1); 22983d2307dSDag-Erling Smørgrav } 23083d2307dSDag-Erling Smørgrav 23183d2307dSDag-Erling Smørgrav #endif /* HAVE_CYGWIN */ 232