Windows 10 SDK build fixes
[heimdal.git] / lib / roken / getuserinfo.c
blob76cd78241be936b02128f4ceb92b99207b94602b
1 /*
2 * Copyright (c) 2017 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include <config.h>
35 #include "roken.h"
37 #ifdef WIN32
38 #include <Shlobj.h> // need to include definitions of constants
39 #define SECURITY_WIN32
40 #include <security.h>
41 #else
42 #include <sys/types.h>
43 #include <pwd.h>
44 #include <unistd.h>
45 #endif
47 /**
48 * Returns the user's SHELL.
50 ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
51 roken_get_shell(char *shell, size_t shellsz)
53 char *p;
55 #ifndef WIN32
56 char user[128];
57 const char *username = roken_get_username(user, sizeof(user));
58 size_t buflen = 2048;
60 if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0)
61 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
63 if (issuid())
64 return "/bin/sh";
66 p = secure_getenv("SHELL");
67 if (p != NULL && p[0] != '\0') {
68 if (strlcpy(shell, p, shellsz) < shellsz)
69 return shell;
70 errno = ERANGE;
71 return NULL;
74 #ifdef HAVE_GETPWNAM_R
76 struct passwd pwd;
77 struct passwd *pwdp;
78 char buf[buflen];
80 if (getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 &&
81 pwdp != NULL && pwdp->pw_shell != NULL) {
82 if (strlcpy(shell, pwdp->pw_shell, shellsz) < shellsz)
83 return shell;
84 errno = ERANGE;
85 return NULL;
88 #endif
89 errno = 0;
90 return "/bin/sh";
91 #else
92 /* Windows */
93 p = getenv("SHELL");
94 if (p != NULL && p[0] != '\0') {
95 if (strlcpy(shell, p, shellsz) < shellsz)
96 return shell;
97 errno = ERANGE;
98 return NULL;
100 errno = 0;
101 return NULL;
102 #endif
106 * Returns the home directory.
108 ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
109 roken_get_homedir(char *home, size_t homesz)
111 char *p;
113 #ifdef WIN32
114 if (homesz < MAX_PATH) {
115 errno = ERANGE;
116 return NULL;
119 if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL,
120 SHGFP_TYPE_CURRENT, home)))
121 return home;
123 if ((p = getenv("HOMEDRIVE")) != NULL && p[0] != '\0') {
124 if (strlcpy(home, p, homesz) >= homesz) {
125 errno = ERANGE;
126 return NULL;
128 if ((p = getenv("HOMEPATH")) != NULL) {
129 if (strlcat(home, p, homesz) < homesz)
130 return home;
131 errno = ERANGE;
132 return NULL;
134 return home;
136 /* Fallthru to return NULL */
137 #else
138 char user[128];
139 const char *username = roken_get_username(user, sizeof(user));
140 size_t buflen = 2048;
142 if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0)
143 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
145 if (issuid()) {
146 errno = 0;
147 return NULL;
150 p = secure_getenv("HOME");
151 if (p != NULL && p[0] != '\0') {
152 if (strlcpy(home, p, homesz) < homesz)
153 return home;
154 errno = ERANGE;
155 return NULL;
158 #ifdef HAVE_GETPWNAM_R
159 if (username) {
160 struct passwd pwd;
161 struct passwd *pwdp;
162 char buf[buflen];
164 if (getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 &&
165 pwdp != NULL && pwdp->pw_dir != NULL) {
166 if (strlcpy(home, pwdp->pw_dir, homesz) < homesz)
167 return home;
168 errno = ERANGE;
169 return NULL;
172 #endif
173 #endif
174 errno = 0;
175 return NULL;
179 * Returns the home directory on Unix, or the AppData directory on
180 * Windows.
182 ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
183 roken_get_appdatadir(char *appdata, size_t appdatasz)
185 #ifdef WIN32
186 char *p;
187 #endif
189 #ifndef WIN32
190 return roken_get_homedir(appdata, appdatasz);
191 #else
192 if (appdatasz < MAX_PATH) {
193 errno = ERANGE;
194 return NULL;
197 if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
198 SHGFP_TYPE_CURRENT, appdata)))
199 return appdata;
201 if ((p = getenv("APPDATA")) != NULL && p[0] != '\0') {
202 if (strlcpy(appdata, p, appdatasz) < appdatasz)
203 return appdata;
204 errno = ERANGE;
205 return NULL;
208 errno = 0;
209 return NULL;
210 #endif
214 * Return a bare username. This is used for, e.g., constructing default
215 * principal names.
217 * On POSIX systems, if the caller is not set-uid-like, then this will return
218 * the value of the USER or LOGNAME environment variables (in that order of
219 * preference), else the username found by looking up the effective UID.
221 ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
222 roken_get_username(char *user, size_t usersz)
224 char *p;
226 #ifdef WIN32
227 ULONG sz = usersz;
229 if (GetUserNameEx(NameSamCompatible, user, &sz)) {
231 * There's no EXTENDED_NAME_FORMAT for "bare username". We we
232 * have to parse one.
234 p = strchr(user, '\\');
235 if (p != NULL) {
236 p++;
237 memmove(user, p, strlen(p) + 1);
239 return user;
240 } else {
241 DWORD err = GetLastError();
242 if (err == ERROR_MORE_DATA) {
243 errno = ERANGE;
244 return NULL;
246 /* %USERNAME% is generally bare */
247 p = getenv("USERNAME");
248 if (p != NULL && p[0] != '\0') {
249 if (strchr(p, '\\') != NULL)
250 p = strchr(p, '\\') + 1;
251 if (strlcpy(user, p, usersz) < usersz)
252 return user;
253 errno = ERANGE;
254 return NULL;
257 #else
258 size_t buflen = 2048;
260 p = secure_getenv("USER");
261 if (p == NULL || p[0] == '\0')
262 p = secure_getenv("LOGNAME");
263 if (p != NULL && p[0] != '\0') {
264 if (strlcpy(user, p, usersz) < usersz)
265 return user;
266 errno = ERANGE;
267 return NULL;
270 #ifdef HAVE_GETPWUID_R
271 if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0)
272 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
275 struct passwd pwd;
276 struct passwd *pwdp;
277 char buf[buflen];
279 if (getpwuid_r(getuid(), &pwd, buf, buflen, &pwdp) == 0 &&
280 pwdp != NULL && pwdp->pw_name != NULL) {
281 if (strlcpy(user, pwdp->pw_name, usersz) < usersz)
282 return user;
283 errno = ERANGE;
284 return NULL;
287 #endif
288 #endif
289 errno = 0;
290 return NULL;
294 * Return a bare username. This is used for, e.g., constructing default
295 * principal names.
297 * On POSIX systems this returns the name recorded in the system as currently
298 * logged in on the current terminal.
300 ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
301 roken_get_loginname(char *user, size_t usersz)
303 #ifdef WIN32
304 return roken_get_username(user, usersz);
305 #else
306 #ifdef HAVE_GETLOGIN_R
307 if ((errno = getlogin_r(user, usersz)) == 0)
308 return user;
309 if (errno != ENOENT)
310 return NULL;
311 #else
312 #ifdef HAVE_GETLOGIN
313 if ((p = getlogin()) != NULL && p[0] != '\0') {
314 if (strlcpy(user, p, usersz) < usersz)
315 return user;
316 errno = ERANGE;
317 return NULL;
319 if (errno != ENOENT)
320 return NULL;
321 #endif
322 #endif
323 errno = 0;
324 return NULL;
325 #endif