1 /* 2 * cygwin_util.c 3 * 4 * Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * Created: Sat Sep 02 12:17:00 2000 cv 27 * 28 * This file contains functions for forcing opened file descriptors to 29 * binary mode on Windows systems. 30 */ 31 32 #include "includes.h" 33 34 RCSID("$Id: bsd-cygwin_util.c,v 1.9 2002/11/09 15:59:29 mouring Exp $"); 35 36 #ifdef HAVE_CYGWIN 37 38 #include <fcntl.h> 39 #include <stdlib.h> 40 #include <sys/utsname.h> 41 #include <sys/vfs.h> 42 #include <windows.h> 43 #define is_winnt (GetVersion() < 0x80000000) 44 45 #define ntsec_on(c) ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec")) 46 #define ntsec_off(c) ((c) && strstr((c),"nontsec")) 47 #define ntea_on(c) ((c) && strstr((c),"ntea") && !strstr((c),"nontea")) 48 49 #if defined(open) && open == binary_open 50 # undef open 51 #endif 52 #if defined(pipe) && open == binary_pipe 53 # undef pipe 54 #endif 55 56 int binary_open(const char *filename, int flags, ...) 57 { 58 va_list ap; 59 mode_t mode; 60 61 va_start(ap, flags); 62 mode = va_arg(ap, mode_t); 63 va_end(ap); 64 return open(filename, flags | O_BINARY, mode); 65 } 66 67 int binary_pipe(int fd[2]) 68 { 69 int ret = pipe(fd); 70 71 if (!ret) { 72 setmode (fd[0], O_BINARY); 73 setmode (fd[1], O_BINARY); 74 } 75 return ret; 76 } 77 78 #define HAS_CREATE_TOKEN 1 79 #define HAS_NTSEC_BY_DEFAULT 2 80 81 static int has_capability(int what) 82 { 83 /* has_capability() basically calls uname() and checks if 84 specific capabilities of Cygwin can be evaluated from that. 85 This simplifies the calling functions which only have to ask 86 for a capability using has_capability() instead of having 87 to figure that out by themselves. */ 88 static int inited; 89 static int has_create_token; 90 static int has_ntsec_by_default; 91 92 if (!inited) { 93 struct utsname uts; 94 char *c; 95 96 if (!uname(&uts)) { 97 int major_high = 0; 98 int major_low = 0; 99 int minor = 0; 100 int api_major_version = 0; 101 int api_minor_version = 0; 102 char *c; 103 104 sscanf(uts.release, "%d.%d.%d", &major_high, 105 &major_low, &minor); 106 c = strchr(uts.release, '('); 107 if (c) 108 sscanf(c + 1, "%d.%d", &api_major_version, 109 &api_minor_version); 110 if (major_high > 1 || 111 (major_high == 1 && (major_low > 3 || 112 (major_low == 3 && minor >= 2)))) 113 has_create_token = 1; 114 if (api_major_version > 0 || api_minor_version >= 56) 115 has_ntsec_by_default = 1; 116 inited = 1; 117 } 118 } 119 switch (what) { 120 case HAS_CREATE_TOKEN: 121 return has_create_token; 122 case HAS_NTSEC_BY_DEFAULT: 123 return has_ntsec_by_default; 124 } 125 return 0; 126 } 127 128 int check_nt_auth(int pwd_authenticated, struct passwd *pw) 129 { 130 /* 131 * The only authentication which is able to change the user 132 * context on NT systems is the password authentication. So 133 * we deny all requsts for changing the user context if another 134 * authentication method is used. 135 * 136 * This doesn't apply to Cygwin versions >= 1.3.2 anymore which 137 * uses the undocumented NtCreateToken() call to create a user 138 * token if the process has the appropriate privileges and if 139 * CYGWIN ntsec setting is on. 140 */ 141 static int has_create_token = -1; 142 143 if (pw == NULL) 144 return 0; 145 if (is_winnt) { 146 if (has_create_token < 0) { 147 char *cygwin = getenv("CYGWIN"); 148 149 has_create_token = 0; 150 if (has_capability(HAS_CREATE_TOKEN) && 151 (ntsec_on(cygwin) || 152 (has_capability(HAS_NTSEC_BY_DEFAULT) && 153 !ntsec_off(cygwin)))) 154 has_create_token = 1; 155 } 156 if (has_create_token < 1 && 157 !pwd_authenticated && geteuid() != pw->pw_uid) 158 return 0; 159 } 160 return 1; 161 } 162 163 int check_ntsec(const char *filename) 164 { 165 char *cygwin; 166 int allow_ntea = 0; 167 int allow_ntsec = 0; 168 struct statfs fsstat; 169 170 /* Windows 95/98/ME don't support file system security at all. */ 171 if (!is_winnt) 172 return 0; 173 174 /* Evaluate current CYGWIN settings. */ 175 cygwin = getenv("CYGWIN"); 176 allow_ntea = ntea_on(cygwin); 177 allow_ntsec = ntsec_on(cygwin) || 178 (has_capability(HAS_NTSEC_BY_DEFAULT) && 179 !ntsec_off(cygwin)); 180 181 /* 182 * `ntea' is an emulation of POSIX attributes. It doesn't support 183 * real file level security as ntsec on NTFS file systems does 184 * but it supports FAT filesystems. `ntea' is minimum requirement 185 * for security checks. 186 */ 187 if (allow_ntea) 188 return 1; 189 190 /* 191 * Retrieve file system flags. In Cygwin, file system flags are 192 * copied to f_type which has no meaning in Win32 itself. 193 */ 194 if (statfs(filename, &fsstat)) 195 return 1; 196 197 /* 198 * Only file systems supporting ACLs are able to set permissions. 199 * `ntsec' is the setting in Cygwin which switches using of NTFS 200 * ACLs to support POSIX permissions on files. 201 */ 202 if (fsstat.f_type & FS_PERSISTENT_ACLS) 203 return allow_ntsec; 204 205 return 0; 206 } 207 208 void register_9x_service(void) 209 { 210 HINSTANCE kerneldll; 211 DWORD (*RegisterServiceProcess)(DWORD, DWORD); 212 213 /* The service register mechanism in 9x/Me is pretty different from 214 * NT/2K/XP. In NT/2K/XP we're using a special service starter 215 * application to register and control sshd as service. This method 216 * doesn't play nicely with 9x/Me. For that reason we register here 217 * as service when running under 9x/Me. This function is only called 218 * by the child sshd when it's going to daemonize. 219 */ 220 if (is_winnt) 221 return; 222 if (! (kerneldll = LoadLibrary("KERNEL32.DLL"))) 223 return; 224 if (! (RegisterServiceProcess = (DWORD (*)(DWORD, DWORD)) 225 GetProcAddress(kerneldll, "RegisterServiceProcess"))) 226 return; 227 RegisterServiceProcess(0, 1); 228 } 229 230 #endif /* HAVE_CYGWIN */ 231