blob: 0fa5964bcb95c14ee0e4da0c93dc051bdfa9fc5e [file] [log] [blame] [raw]
/*
* cygwin_util.c
*
* Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Created: Sat Sep 02 12:17:00 2000 cv
*
* This file contains functions for forcing opened file descriptors to
* binary mode on Windows systems.
*/
#include "includes.h"
RCSID("$Id: bsd-cygwin_util.c,v 1.9 2002/11/09 15:59:29 mouring Exp $");
#ifdef HAVE_CYGWIN
#include <fcntl.h>
#include <stdlib.h>
#include <sys/utsname.h>
#include <sys/vfs.h>
#include <windows.h>
#define is_winnt (GetVersion() < 0x80000000)
#define ntsec_on(c) ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec"))
#define ntsec_off(c) ((c) && strstr((c),"nontsec"))
#define ntea_on(c) ((c) && strstr((c),"ntea") && !strstr((c),"nontea"))
#if defined(open) && open == binary_open
# undef open
#endif
#if defined(pipe) && open == binary_pipe
# undef pipe
#endif
int binary_open(const char *filename, int flags, ...)
{
va_list ap;
mode_t mode;
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
return open(filename, flags | O_BINARY, mode);
}
int binary_pipe(int fd[2])
{
int ret = pipe(fd);
if (!ret) {
setmode (fd[0], O_BINARY);
setmode (fd[1], O_BINARY);
}
return ret;
}
#define HAS_CREATE_TOKEN 1
#define HAS_NTSEC_BY_DEFAULT 2
static int has_capability(int what)
{
/* has_capability() basically calls uname() and checks if
specific capabilities of Cygwin can be evaluated from that.
This simplifies the calling functions which only have to ask
for a capability using has_capability() instead of having
to figure that out by themselves. */
static int inited;
static int has_create_token;
static int has_ntsec_by_default;
if (!inited) {
struct utsname uts;
char *c;
if (!uname(&uts)) {
int major_high = 0;
int major_low = 0;
int minor = 0;
int api_major_version = 0;
int api_minor_version = 0;
char *c;
sscanf(uts.release, "%d.%d.%d", &major_high,
&major_low, &minor);
c = strchr(uts.release, '(');
if (c)
sscanf(c + 1, "%d.%d", &api_major_version,
&api_minor_version);
if (major_high > 1 ||
(major_high == 1 && (major_low > 3 ||
(major_low == 3 && minor >= 2))))
has_create_token = 1;
if (api_major_version > 0 || api_minor_version >= 56)
has_ntsec_by_default = 1;
inited = 1;
}
}
switch (what) {
case HAS_CREATE_TOKEN:
return has_create_token;
case HAS_NTSEC_BY_DEFAULT:
return has_ntsec_by_default;
}
return 0;
}
int check_nt_auth(int pwd_authenticated, struct passwd *pw)
{
/*
* The only authentication which is able to change the user
* context on NT systems is the password authentication. So
* we deny all requsts for changing the user context if another
* authentication method is used.
*
* This doesn't apply to Cygwin versions >= 1.3.2 anymore which
* uses the undocumented NtCreateToken() call to create a user
* token if the process has the appropriate privileges and if
* CYGWIN ntsec setting is on.
*/
static int has_create_token = -1;
if (pw == NULL)
return 0;
if (is_winnt) {
if (has_create_token < 0) {
char *cygwin = getenv("CYGWIN");
has_create_token = 0;
if (has_capability(HAS_CREATE_TOKEN) &&
(ntsec_on(cygwin) ||
(has_capability(HAS_NTSEC_BY_DEFAULT) &&
!ntsec_off(cygwin))))
has_create_token = 1;
}
if (has_create_token < 1 &&
!pwd_authenticated && geteuid() != pw->pw_uid)
return 0;
}
return 1;
}
int check_ntsec(const char *filename)
{
char *cygwin;
int allow_ntea = 0;
int allow_ntsec = 0;
struct statfs fsstat;
/* Windows 95/98/ME don't support file system security at all. */
if (!is_winnt)
return 0;
/* Evaluate current CYGWIN settings. */
cygwin = getenv("CYGWIN");
allow_ntea = ntea_on(cygwin);
allow_ntsec = ntsec_on(cygwin) ||
(has_capability(HAS_NTSEC_BY_DEFAULT) &&
!ntsec_off(cygwin));
/*
* `ntea' is an emulation of POSIX attributes. It doesn't support
* real file level security as ntsec on NTFS file systems does
* but it supports FAT filesystems. `ntea' is minimum requirement
* for security checks.
*/
if (allow_ntea)
return 1;
/*
* Retrieve file system flags. In Cygwin, file system flags are
* copied to f_type which has no meaning in Win32 itself.
*/
if (statfs(filename, &fsstat))
return 1;
/*
* Only file systems supporting ACLs are able to set permissions.
* `ntsec' is the setting in Cygwin which switches using of NTFS
* ACLs to support POSIX permissions on files.
*/
if (fsstat.f_type & FS_PERSISTENT_ACLS)
return allow_ntsec;
return 0;
}
void register_9x_service(void)
{
HINSTANCE kerneldll;
DWORD (*RegisterServiceProcess)(DWORD, DWORD);
/* The service register mechanism in 9x/Me is pretty different from
* NT/2K/XP. In NT/2K/XP we're using a special service starter
* application to register and control sshd as service. This method
* doesn't play nicely with 9x/Me. For that reason we register here
* as service when running under 9x/Me. This function is only called
* by the child sshd when it's going to daemonize.
*/
if (is_winnt)
return;
if (! (kerneldll = LoadLibrary("KERNEL32.DLL")))
return;
if (! (RegisterServiceProcess = (DWORD (*)(DWORD, DWORD))
GetProcAddress(kerneldll, "RegisterServiceProcess")))
return;
RegisterServiceProcess(0, 1);
}
#endif /* HAVE_CYGWIN */