xref: /freebsd/crypto/openssh/openbsd-compat/bsd-cygwin_util.c (revision d4af9e693f15f5155095f38c7650b24fe74ae351)
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 
3283d2307dSDag-Erling Smørgrav #ifdef HAVE_CYGWIN
3383d2307dSDag-Erling Smørgrav 
3483d2307dSDag-Erling Smørgrav #if defined(open) && open == binary_open
3583d2307dSDag-Erling Smørgrav # undef open
3683d2307dSDag-Erling Smørgrav #endif
3783d2307dSDag-Erling Smørgrav #if defined(pipe) && open == binary_pipe
3883d2307dSDag-Erling Smørgrav # undef pipe
3983d2307dSDag-Erling Smørgrav #endif
4083d2307dSDag-Erling Smørgrav 
41761efaa7SDag-Erling Smørgrav #include <sys/types.h>
42761efaa7SDag-Erling Smørgrav #include <sys/stat.h>
43761efaa7SDag-Erling Smørgrav #include <sys/utsname.h>
44761efaa7SDag-Erling Smørgrav #include <sys/vfs.h>
45761efaa7SDag-Erling Smørgrav 
46761efaa7SDag-Erling Smørgrav #include <fcntl.h>
47761efaa7SDag-Erling Smørgrav #include <stdlib.h>
48761efaa7SDag-Erling Smørgrav #include <unistd.h>
49761efaa7SDag-Erling Smørgrav #include <windows.h>
50761efaa7SDag-Erling Smørgrav 
51761efaa7SDag-Erling Smørgrav #include "xmalloc.h"
52761efaa7SDag-Erling Smørgrav #define is_winnt       (GetVersion() < 0x80000000)
53761efaa7SDag-Erling Smørgrav 
54761efaa7SDag-Erling Smørgrav #define ntsec_on(c)	((c) && strstr((c),"ntsec") && !strstr((c),"nontsec"))
55761efaa7SDag-Erling Smørgrav #define ntsec_off(c)	((c) && strstr((c),"nontsec"))
56761efaa7SDag-Erling Smørgrav #define ntea_on(c)	((c) && strstr((c),"ntea") && !strstr((c),"nontea"))
57761efaa7SDag-Erling Smørgrav 
58d95e11bfSDag-Erling Smørgrav int
59d95e11bfSDag-Erling Smørgrav binary_open(const char *filename, int flags, ...)
6083d2307dSDag-Erling Smørgrav {
6183d2307dSDag-Erling Smørgrav 	va_list ap;
6283d2307dSDag-Erling Smørgrav 	mode_t mode;
6383d2307dSDag-Erling Smørgrav 
6483d2307dSDag-Erling Smørgrav 	va_start(ap, flags);
6583d2307dSDag-Erling Smørgrav 	mode = va_arg(ap, mode_t);
6683d2307dSDag-Erling Smørgrav 	va_end(ap);
67d95e11bfSDag-Erling Smørgrav 	return (open(filename, flags | O_BINARY, mode));
6883d2307dSDag-Erling Smørgrav }
6983d2307dSDag-Erling Smørgrav 
70d95e11bfSDag-Erling Smørgrav int
71d95e11bfSDag-Erling Smørgrav binary_pipe(int fd[2])
7283d2307dSDag-Erling Smørgrav {
7383d2307dSDag-Erling Smørgrav 	int ret = pipe(fd);
7483d2307dSDag-Erling Smørgrav 
7583d2307dSDag-Erling Smørgrav 	if (!ret) {
7683d2307dSDag-Erling Smørgrav 		setmode(fd[0], O_BINARY);
7783d2307dSDag-Erling Smørgrav 		setmode(fd[1], O_BINARY);
7883d2307dSDag-Erling Smørgrav 	}
79d95e11bfSDag-Erling Smørgrav 	return (ret);
8083d2307dSDag-Erling Smørgrav }
8183d2307dSDag-Erling Smørgrav 
82d0c8c0bcSDag-Erling Smørgrav #define HAS_CREATE_TOKEN 1
83d0c8c0bcSDag-Erling Smørgrav #define HAS_NTSEC_BY_DEFAULT 2
8452028650SDag-Erling Smørgrav #define HAS_CREATE_TOKEN_WO_NTSEC 3
85d0c8c0bcSDag-Erling Smørgrav 
86d95e11bfSDag-Erling Smørgrav static int
87d95e11bfSDag-Erling Smørgrav has_capability(int what)
88d0c8c0bcSDag-Erling Smørgrav {
89d0c8c0bcSDag-Erling Smørgrav 	static int inited;
90d0c8c0bcSDag-Erling Smørgrav 	static int has_create_token;
91d0c8c0bcSDag-Erling Smørgrav 	static int has_ntsec_by_default;
9252028650SDag-Erling Smørgrav 	static int has_create_token_wo_ntsec;
93d0c8c0bcSDag-Erling Smørgrav 
94d95e11bfSDag-Erling Smørgrav 	/*
95d95e11bfSDag-Erling Smørgrav 	 * has_capability() basically calls uname() and checks if
96d95e11bfSDag-Erling Smørgrav 	 * specific capabilities of Cygwin can be evaluated from that.
97d95e11bfSDag-Erling Smørgrav 	 * This simplifies the calling functions which only have to ask
98d95e11bfSDag-Erling Smørgrav 	 * for a capability using has_capability() instead of having
99d95e11bfSDag-Erling Smørgrav 	 * to figure that out by themselves.
100d95e11bfSDag-Erling Smørgrav 	 */
101d0c8c0bcSDag-Erling Smørgrav 	if (!inited) {
102d0c8c0bcSDag-Erling Smørgrav 		struct utsname uts;
103d0c8c0bcSDag-Erling Smørgrav 
104d0c8c0bcSDag-Erling Smørgrav 		if (!uname(&uts)) {
105d95e11bfSDag-Erling Smørgrav 			int major_high = 0, major_low = 0, minor = 0;
106d95e11bfSDag-Erling Smørgrav 			int api_major_version = 0, api_minor_version = 0;
107d0c8c0bcSDag-Erling Smørgrav 			char *c;
108d0c8c0bcSDag-Erling Smørgrav 
109d0c8c0bcSDag-Erling Smørgrav 			sscanf(uts.release, "%d.%d.%d", &major_high,
110d0c8c0bcSDag-Erling Smørgrav 			    &major_low, &minor);
111d95e11bfSDag-Erling Smørgrav 			if ((c = strchr(uts.release, '(')) != NULL) {
112d0c8c0bcSDag-Erling Smørgrav 				sscanf(c + 1, "%d.%d", &api_major_version,
113d0c8c0bcSDag-Erling Smørgrav 				    &api_minor_version);
114d95e11bfSDag-Erling Smørgrav 			}
115d0c8c0bcSDag-Erling Smørgrav 			if (major_high > 1 ||
116d0c8c0bcSDag-Erling Smørgrav 			    (major_high == 1 && (major_low > 3 ||
117d0c8c0bcSDag-Erling Smørgrav 			    (major_low == 3 && minor >= 2))))
118d0c8c0bcSDag-Erling Smørgrav 				has_create_token = 1;
119d0c8c0bcSDag-Erling Smørgrav 			if (api_major_version > 0 || api_minor_version >= 56)
120d0c8c0bcSDag-Erling Smørgrav 				has_ntsec_by_default = 1;
12152028650SDag-Erling Smørgrav 			if (major_high > 1 ||
12252028650SDag-Erling Smørgrav 			    (major_high == 1 && major_low >= 5))
12352028650SDag-Erling Smørgrav 				has_create_token_wo_ntsec = 1;
124d0c8c0bcSDag-Erling Smørgrav 			inited = 1;
125d0c8c0bcSDag-Erling Smørgrav 		}
126d0c8c0bcSDag-Erling Smørgrav 	}
127d0c8c0bcSDag-Erling Smørgrav 	switch (what) {
128d0c8c0bcSDag-Erling Smørgrav 	case HAS_CREATE_TOKEN:
129d95e11bfSDag-Erling Smørgrav 		return (has_create_token);
130d0c8c0bcSDag-Erling Smørgrav 	case HAS_NTSEC_BY_DEFAULT:
131d95e11bfSDag-Erling Smørgrav 		return (has_ntsec_by_default);
13252028650SDag-Erling Smørgrav 	case HAS_CREATE_TOKEN_WO_NTSEC:
13352028650SDag-Erling Smørgrav 		return (has_create_token_wo_ntsec);
134d0c8c0bcSDag-Erling Smørgrav 	}
135d95e11bfSDag-Erling Smørgrav 	return (0);
136d0c8c0bcSDag-Erling Smørgrav }
137d0c8c0bcSDag-Erling Smørgrav 
138d95e11bfSDag-Erling Smørgrav int
139d95e11bfSDag-Erling Smørgrav check_nt_auth(int pwd_authenticated, struct passwd *pw)
14083d2307dSDag-Erling Smørgrav {
14183d2307dSDag-Erling Smørgrav 	/*
14283d2307dSDag-Erling Smørgrav 	* The only authentication which is able to change the user
14383d2307dSDag-Erling Smørgrav 	* context on NT systems is the password authentication. So
14483d2307dSDag-Erling Smørgrav 	* we deny all requsts for changing the user context if another
14583d2307dSDag-Erling Smørgrav 	* authentication method is used.
14683d2307dSDag-Erling Smørgrav 	*
14783d2307dSDag-Erling Smørgrav 	* This doesn't apply to Cygwin versions >= 1.3.2 anymore which
14883d2307dSDag-Erling Smørgrav 	* uses the undocumented NtCreateToken() call to create a user
14983d2307dSDag-Erling Smørgrav 	* token if the process has the appropriate privileges and if
15083d2307dSDag-Erling Smørgrav 	* CYGWIN ntsec setting is on.
15183d2307dSDag-Erling Smørgrav 	*/
15283d2307dSDag-Erling Smørgrav 	static int has_create_token = -1;
15383d2307dSDag-Erling Smørgrav 
15483d2307dSDag-Erling Smørgrav 	if (pw == NULL)
15583d2307dSDag-Erling Smørgrav 		return 0;
15683d2307dSDag-Erling Smørgrav 	if (is_winnt) {
15783d2307dSDag-Erling Smørgrav 		if (has_create_token < 0) {
15883d2307dSDag-Erling Smørgrav 			char *cygwin = getenv("CYGWIN");
15983d2307dSDag-Erling Smørgrav 
16083d2307dSDag-Erling Smørgrav 			has_create_token = 0;
161d0c8c0bcSDag-Erling Smørgrav 			if (has_capability(HAS_CREATE_TOKEN) &&
162d0c8c0bcSDag-Erling Smørgrav 			    (ntsec_on(cygwin) ||
163d0c8c0bcSDag-Erling Smørgrav 			    (has_capability(HAS_NTSEC_BY_DEFAULT) &&
16452028650SDag-Erling Smørgrav 			     !ntsec_off(cygwin)) ||
16552028650SDag-Erling Smørgrav 			     has_capability(HAS_CREATE_TOKEN_WO_NTSEC)))
16683d2307dSDag-Erling Smørgrav 				has_create_token = 1;
16783d2307dSDag-Erling Smørgrav 		}
16883d2307dSDag-Erling Smørgrav 		if (has_create_token < 1 &&
16983d2307dSDag-Erling Smørgrav 		    !pwd_authenticated && geteuid() != pw->pw_uid)
170d95e11bfSDag-Erling Smørgrav 			return (0);
17183d2307dSDag-Erling Smørgrav 	}
172d95e11bfSDag-Erling Smørgrav 	return (1);
17383d2307dSDag-Erling Smørgrav }
17483d2307dSDag-Erling Smørgrav 
175d95e11bfSDag-Erling Smørgrav int
176d95e11bfSDag-Erling Smørgrav check_ntsec(const char *filename)
17783d2307dSDag-Erling Smørgrav {
178d4af9e69SDag-Erling Smørgrav 	return (pathconf(filename, _PC_POSIX_PERMISSIONS));
17983d2307dSDag-Erling Smørgrav }
18083d2307dSDag-Erling Smørgrav 
181d95e11bfSDag-Erling Smørgrav void
182d95e11bfSDag-Erling Smørgrav register_9x_service(void)
18383d2307dSDag-Erling Smørgrav {
18483d2307dSDag-Erling Smørgrav         HINSTANCE kerneldll;
18583d2307dSDag-Erling Smørgrav         DWORD (*RegisterServiceProcess)(DWORD, DWORD);
18683d2307dSDag-Erling Smørgrav 
18783d2307dSDag-Erling Smørgrav 	/* The service register mechanism in 9x/Me is pretty different from
18883d2307dSDag-Erling Smørgrav 	 * NT/2K/XP.  In NT/2K/XP we're using a special service starter
18983d2307dSDag-Erling Smørgrav 	 * application to register and control sshd as service.  This method
19083d2307dSDag-Erling Smørgrav 	 * doesn't play nicely with 9x/Me.  For that reason we register here
19183d2307dSDag-Erling Smørgrav 	 * as service when running under 9x/Me.  This function is only called
19283d2307dSDag-Erling Smørgrav 	 * by the child sshd when it's going to daemonize.
19383d2307dSDag-Erling Smørgrav 	 */
19483d2307dSDag-Erling Smørgrav 	if (is_winnt)
19583d2307dSDag-Erling Smørgrav 		return;
19683d2307dSDag-Erling Smørgrav 	if (!(kerneldll = LoadLibrary("KERNEL32.DLL")))
19783d2307dSDag-Erling Smørgrav 		return;
19883d2307dSDag-Erling Smørgrav 	if (!(RegisterServiceProcess = (DWORD (*)(DWORD, DWORD))
19983d2307dSDag-Erling Smørgrav 		GetProcAddress(kerneldll, "RegisterServiceProcess")))
20083d2307dSDag-Erling Smørgrav 		return;
20183d2307dSDag-Erling Smørgrav 	RegisterServiceProcess(0, 1);
20283d2307dSDag-Erling Smørgrav }
20383d2307dSDag-Erling Smørgrav 
2045e8dbd04SDag-Erling Smørgrav #define NL(x) x, (sizeof (x) - 1)
2055e8dbd04SDag-Erling Smørgrav #define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0]))
2065e8dbd04SDag-Erling Smørgrav 
2075e8dbd04SDag-Erling Smørgrav static struct wenv {
2085e8dbd04SDag-Erling Smørgrav 	const char *name;
2095e8dbd04SDag-Erling Smørgrav 	size_t namelen;
2105e8dbd04SDag-Erling Smørgrav } wenv_arr[] = {
2115e8dbd04SDag-Erling Smørgrav 	{ NL("ALLUSERSPROFILE=") },
2125e8dbd04SDag-Erling Smørgrav 	{ NL("COMMONPROGRAMFILES=") },
2135e8dbd04SDag-Erling Smørgrav 	{ NL("COMPUTERNAME=") },
2145e8dbd04SDag-Erling Smørgrav 	{ NL("COMSPEC=") },
2154518870cSDag-Erling Smørgrav 	{ NL("CYGWIN=") },
2165e8dbd04SDag-Erling Smørgrav 	{ NL("NUMBER_OF_PROCESSORS=") },
2175e8dbd04SDag-Erling Smørgrav 	{ NL("OS=") },
2185e8dbd04SDag-Erling Smørgrav 	{ NL("PATH=") },
2195e8dbd04SDag-Erling Smørgrav 	{ NL("PATHEXT=") },
2205e8dbd04SDag-Erling Smørgrav 	{ NL("PROCESSOR_ARCHITECTURE=") },
2215e8dbd04SDag-Erling Smørgrav 	{ NL("PROCESSOR_IDENTIFIER=") },
2225e8dbd04SDag-Erling Smørgrav 	{ NL("PROCESSOR_LEVEL=") },
2235e8dbd04SDag-Erling Smørgrav 	{ NL("PROCESSOR_REVISION=") },
2245e8dbd04SDag-Erling Smørgrav 	{ NL("PROGRAMFILES=") },
2255e8dbd04SDag-Erling Smørgrav 	{ NL("SYSTEMDRIVE=") },
2265e8dbd04SDag-Erling Smørgrav 	{ NL("SYSTEMROOT=") },
2275e8dbd04SDag-Erling Smørgrav 	{ NL("TMP=") },
2285e8dbd04SDag-Erling Smørgrav 	{ NL("TEMP=") },
2294518870cSDag-Erling Smørgrav 	{ NL("WINDIR=") }
2305e8dbd04SDag-Erling Smørgrav };
2315e8dbd04SDag-Erling Smørgrav 
2325e8dbd04SDag-Erling Smørgrav char **
2335e8dbd04SDag-Erling Smørgrav fetch_windows_environment(void)
2345e8dbd04SDag-Erling Smørgrav {
2355e8dbd04SDag-Erling Smørgrav 	char **e, **p;
236761efaa7SDag-Erling Smørgrav 	unsigned int i, idx = 0;
2375e8dbd04SDag-Erling Smørgrav 
238761efaa7SDag-Erling Smørgrav 	p = xcalloc(WENV_SIZ + 1, sizeof(char *));
2395e8dbd04SDag-Erling Smørgrav 	for (e = environ; *e != NULL; ++e) {
2405e8dbd04SDag-Erling Smørgrav 		for (i = 0; i < WENV_SIZ; ++i) {
2415e8dbd04SDag-Erling Smørgrav 			if (!strncmp(*e, wenv_arr[i].name, wenv_arr[i].namelen))
2425e8dbd04SDag-Erling Smørgrav 				p[idx++] = *e;
2435e8dbd04SDag-Erling Smørgrav 		}
2445e8dbd04SDag-Erling Smørgrav 	}
2455e8dbd04SDag-Erling Smørgrav 	p[idx] = NULL;
2465e8dbd04SDag-Erling Smørgrav 	return p;
2475e8dbd04SDag-Erling Smørgrav }
2485e8dbd04SDag-Erling Smørgrav 
2495e8dbd04SDag-Erling Smørgrav void
2505e8dbd04SDag-Erling Smørgrav free_windows_environment(char **p)
2515e8dbd04SDag-Erling Smørgrav {
2525e8dbd04SDag-Erling Smørgrav 	xfree(p);
2535e8dbd04SDag-Erling Smørgrav }
2545e8dbd04SDag-Erling Smørgrav 
25583d2307dSDag-Erling Smørgrav #endif /* HAVE_CYGWIN */
256