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.8 2002/04/15 22:00:52 stevesk Exp $");
  35 
  36 #pragma ident   "%Z%%M% %I%     %E% SMI"
  37 
  38 #ifdef HAVE_CYGWIN
  39 
  40 #include <fcntl.h>
  41 #include <stdlib.h>
  42 #include <sys/utsname.h>
  43 #include <sys/vfs.h>
  44 #include <windows.h>
  45 #define is_winnt       (GetVersion() < 0x80000000)
  46 
  47 #define ntsec_on(c)     ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec"))
  48 #define ntea_on(c)      ((c) && strstr((c),"ntea") && !strstr((c),"nontea"))
  49 
  50 #if defined(open) && open == binary_open
  51 # undef open
  52 #endif
  53 #if defined(pipe) && open == binary_pipe
  54 # undef pipe
  55 #endif
  56 
  57 int binary_open(const char *filename, int flags, ...)
  58 {
  59         va_list ap;
  60         mode_t mode;
  61         
  62         va_start(ap, flags);
  63         mode = va_arg(ap, mode_t);
  64         va_end(ap);
  65         return open(filename, flags | O_BINARY, mode);
  66 }
  67 
  68 int binary_pipe(int fd[2])
  69 {
  70         int ret = pipe(fd);
  71 
  72         if (!ret) {
  73                 setmode (fd[0], O_BINARY);
  74                 setmode (fd[1], O_BINARY);
  75         }
  76         return ret;
  77 }
  78 
  79 int check_nt_auth(int pwd_authenticated, struct passwd *pw)
  80 {
  81         /*
  82         * The only authentication which is able to change the user
  83         * context on NT systems is the password authentication. So
  84         * we deny all requsts for changing the user context if another
  85         * authentication method is used.
  86         *
  87         * This doesn't apply to Cygwin versions >= 1.3.2 anymore which
  88         * uses the undocumented NtCreateToken() call to create a user
  89         * token if the process has the appropriate privileges and if
  90         * CYGWIN ntsec setting is on.
  91         */
  92         static int has_create_token = -1;
  93 
  94         if (pw == NULL)
  95                 return 0;
  96         if (is_winnt) {
  97                 if (has_create_token < 0) {
  98                         struct utsname uts;
  99                         int major_high = 0, major_low = 0, minor = 0;
 100                         char *cygwin = getenv("CYGWIN");
 101 
 102                         has_create_token = 0;
 103                         if (ntsec_on(cygwin) && !uname(&uts)) {
 104                                 sscanf(uts.release, "%d.%d.%d",
 105                                        &major_high, &major_low, &minor);
 106                                 if (major_high > 1 ||
 107                                     (major_high == 1 && (major_low > 3 ||
 108                                      (major_low == 3 && minor >= 2))))
 109                                         has_create_token = 1;
 110                         }
 111                 }
 112                 if (has_create_token < 1 &&
 113                     !pwd_authenticated && geteuid() != pw->pw_uid)
 114                         return 0;
 115         }
 116         return 1;
 117 }
 118 
 119 int check_ntsec(const char *filename)
 120 {
 121         char *cygwin;
 122         int allow_ntea = 0;
 123         int allow_ntsec = 0;
 124         struct statfs fsstat;
 125 
 126         /* Windows 95/98/ME don't support file system security at all. */
 127         if (!is_winnt)
 128                 return 0;
 129 
 130         /* Evaluate current CYGWIN settings. */
 131         cygwin = getenv("CYGWIN");
 132         allow_ntea = ntea_on(cygwin);
 133         allow_ntsec = ntsec_on(cygwin);
 134 
 135         /*
 136          * `ntea' is an emulation of POSIX attributes. It doesn't support
 137          * real file level security as ntsec on NTFS file systems does
 138          * but it supports FAT filesystems. `ntea' is minimum requirement
 139          * for security checks.
 140          */
 141         if (allow_ntea)
 142                 return 1;
 143 
 144         /*
 145          * Retrieve file system flags. In Cygwin, file system flags are
 146          * copied to f_type which has no meaning in Win32 itself.
 147          */
 148         if (statfs(filename, &fsstat))
 149                 return 1;
 150 
 151         /*
 152          * Only file systems supporting ACLs are able to set permissions.
 153          * `ntsec' is the setting in Cygwin which switches using of NTFS
 154          * ACLs to support POSIX permissions on files.
 155          */
 156         if (fsstat.f_type & FS_PERSISTENT_ACLS)
 157                 return allow_ntsec;
 158 
 159         return 0;
 160 }
 161 
 162 void register_9x_service(void)
 163 {
 164         HINSTANCE kerneldll;
 165         DWORD (*RegisterServiceProcess)(DWORD, DWORD);
 166 
 167         /* The service register mechanism in 9x/Me is pretty different from
 168          * NT/2K/XP.  In NT/2K/XP we're using a special service starter
 169          * application to register and control sshd as service.  This method
 170          * doesn't play nicely with 9x/Me.  For that reason we register here
 171          * as service when running under 9x/Me.  This function is only called
 172          * by the child sshd when it's going to daemonize.
 173          */
 174         if (is_winnt)
 175                 return;
 176         if (! (kerneldll = LoadLibrary("KERNEL32.DLL")))
 177                 return;
 178         if (! (RegisterServiceProcess = (DWORD (*)(DWORD, DWORD))
 179                           GetProcAddress(kerneldll, "RegisterServiceProcess")))
 180                 return;
 181         RegisterServiceProcess(0, 1);
 182 }
 183 
 184 #endif /* HAVE_CYGWIN */