Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <stddef.h>
30 : :
31 : : /* Solaris 8 has no C99 stdint.h, and Solaris generally seems not to miss it for
32 : : SIZE_MAX: */
33 : : #if !defined __SUNPRO_C
34 : : #include <stdint.h>
35 : : #endif
36 : :
37 : : #include "system.h"
38 : :
39 : : #include <osl/security.h>
40 : : #include <osl/diagnose.h>
41 : : #include <rtl/bootstrap.h>
42 : :
43 : : #include "osl/thread.h"
44 : : #include "osl/file.h"
45 : :
46 : : #if defined LINUX || defined SOLARIS
47 : : #include <crypt.h>
48 : : #endif
49 : :
50 : : #include "secimpl.h"
51 : :
52 : : #ifdef ANDROID
53 : : #define getpwuid_r(uid, pwd, buf, buflen, result) (*(result) = getpwuid(uid), (*(result) ? (memcpy (buf, *(result), sizeof (struct passwd)), 0) : errno))
54 : : #endif
55 : :
56 : :
57 : : static oslSecurityError SAL_CALL
58 : : osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
59 : : oslSecurity* pSecurity);
60 : : sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax);
61 : : static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax);
62 : : static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
63 : : static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
64 : :
65 : 5323 : static sal_Bool sysconf_SC_GETPW_R_SIZE_MAX(size_t * value) {
66 : : #if defined _SC_GETPW_R_SIZE_MAX
67 : : long m;
68 : 5323 : errno = 0;
69 : 5323 : m = sysconf(_SC_GETPW_R_SIZE_MAX);
70 [ - + ]: 5323 : if (m == -1) {
71 : : /* _SC_GETPW_R_SIZE_MAX has no limit; some platforms like certain
72 : : FreeBSD versions support sysconf(_SC_GETPW_R_SIZE_MAX) in a broken
73 : : way and always set EINVAL, so be resilient here: */
74 : 0 : return sal_False;
75 : : } else {
76 : : OSL_ASSERT(m >= 0 && (unsigned long) m < SIZE_MAX);
77 : 5323 : *value = (size_t) m;
78 : 5323 : return sal_True;
79 : : }
80 : : #else
81 : : /* some platforms like Mac OS X 1.3 do not define _SC_GETPW_R_SIZE_MAX: */
82 : : return sal_False;
83 : : #endif
84 : : }
85 : :
86 : 5323 : static oslSecurityImpl * growSecurityImpl(
87 : : oslSecurityImpl * impl, size_t * bufSize)
88 : : {
89 : 5323 : size_t n = 0;
90 : 5323 : oslSecurityImpl * p = NULL;
91 [ + - ]: 5323 : if (impl == NULL) {
92 [ - + ]: 5323 : if (!sysconf_SC_GETPW_R_SIZE_MAX(&n)) {
93 : : /* choose something sensible (the callers of growSecurityImpl will
94 : : detect it if the allocated buffer is too small: */
95 : 0 : n = 1024;
96 : : }
97 [ # # ]: 0 : } else if (*bufSize <= SIZE_MAX / 2) {
98 : 0 : n = 2 * *bufSize;
99 : : }
100 [ + - ]: 5323 : if (n != 0) {
101 [ + - ]: 5323 : if (n <= SIZE_MAX - offsetof(oslSecurityImpl, m_buffer)) {
102 : 5323 : *bufSize = n;
103 : 5323 : n += offsetof(oslSecurityImpl, m_buffer);
104 : : } else {
105 : 0 : *bufSize = SIZE_MAX - offsetof(oslSecurityImpl, m_buffer);
106 : 0 : n = SIZE_MAX;
107 : : }
108 : 5323 : p = realloc(impl, n);
109 : 5323 : memset (p, 0, n);
110 : : }
111 [ - + ]: 5323 : if (p == NULL) {
112 : 0 : free(impl);
113 : : }
114 : 5323 : return p;
115 : : }
116 : :
117 : 5308 : static void deleteSecurityImpl(oslSecurityImpl * impl) {
118 : 5308 : free(impl);
119 : 5308 : }
120 : :
121 : 5323 : oslSecurity SAL_CALL osl_getCurrentSecurity()
122 : : {
123 : 5323 : size_t n = 0;
124 : 5323 : oslSecurityImpl * p = NULL;
125 : : for (;;) {
126 : : struct passwd * found;
127 : 5323 : p = growSecurityImpl(p, &n);
128 [ - + ]: 5323 : if (p == NULL) {
129 : 0 : return NULL;
130 : : }
131 [ - + - ]: 5323 : switch (getpwuid_r(getuid(), &p->m_pPasswd, p->m_buffer, n, &found)) {
132 : : case ERANGE:
133 : 0 : break;
134 : : case 0:
135 [ + - ]: 5323 : if (found != NULL) {
136 : 5323 : return p;
137 : : }
138 : : /* fall through */
139 : : default:
140 : 0 : deleteSecurityImpl(p);
141 : 0 : return NULL;
142 : : }
143 : 5323 : }
144 : : }
145 : :
146 : 0 : oslSecurityError SAL_CALL osl_loginUser(
147 : : rtl_uString *ustrUserName,
148 : : rtl_uString *ustrPassword,
149 : : oslSecurity *pSecurity
150 : : )
151 : : {
152 : : oslSecurityError Error;
153 : 0 : rtl_String* strUserName=0;
154 : 0 : rtl_String* strPassword=0;
155 : 0 : sal_Char* pszUserName=0;
156 : 0 : sal_Char* pszPassword=0;
157 : :
158 [ # # ]: 0 : if ( ustrUserName != 0 )
159 : : {
160 : 0 : rtl_uString2String( &strUserName,
161 : 0 : rtl_uString_getStr(ustrUserName),
162 : : rtl_uString_getLength(ustrUserName),
163 : : RTL_TEXTENCODING_UTF8,
164 : : OUSTRING_TO_OSTRING_CVTFLAGS );
165 : 0 : pszUserName = rtl_string_getStr(strUserName);
166 : : }
167 : :
168 : :
169 [ # # ]: 0 : if ( ustrPassword != 0 )
170 : : {
171 : 0 : rtl_uString2String( &strPassword,
172 : 0 : rtl_uString_getStr(ustrPassword),
173 : : rtl_uString_getLength(ustrPassword),
174 : : RTL_TEXTENCODING_UTF8,
175 : : OUSTRING_TO_OSTRING_CVTFLAGS );
176 : 0 : pszPassword = rtl_string_getStr(strPassword);
177 : : }
178 : :
179 : :
180 : 0 : Error=osl_psz_loginUser(pszUserName,pszPassword,pSecurity);
181 : :
182 [ # # ]: 0 : if ( strUserName != 0 )
183 : : {
184 : 0 : rtl_string_release(strUserName);
185 : : }
186 : :
187 [ # # ]: 0 : if ( strPassword)
188 : : {
189 : 0 : rtl_string_release(strPassword);
190 : : }
191 : :
192 : :
193 : 0 : return Error;
194 : : }
195 : :
196 : :
197 : : static oslSecurityError SAL_CALL
198 : 0 : osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
199 : : oslSecurity* pSecurity)
200 : : {
201 : : (void)pszUserName;
202 : : (void)pszPasswd;
203 : : (void)pSecurity;
204 : :
205 : 0 : return osl_Security_E_None;
206 : : }
207 : :
208 : 5 : oslSecurityError SAL_CALL osl_loginUserOnFileServer(
209 : : rtl_uString *strUserName,
210 : : rtl_uString *strPasswd,
211 : : rtl_uString *strFileServer,
212 : : oslSecurity *pSecurity
213 : : )
214 : : {
215 : : (void) strUserName; /* unused */
216 : : (void) strPasswd; /* unused */
217 : : (void) strFileServer; /* unused */
218 : : (void) pSecurity; /* unused */
219 : 5 : return osl_Security_E_UserUnknown;
220 : : }
221 : :
222 : :
223 : 163 : sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **ustrIdent)
224 : : {
225 : 163 : sal_Bool bRet=sal_False;
226 : : sal_Char pszIdent[1024];
227 : :
228 : 163 : pszIdent[0] = '\0';
229 : :
230 : 163 : bRet = osl_psz_getUserIdent(Security,pszIdent,sizeof(pszIdent));
231 : :
232 : 163 : rtl_string2UString( ustrIdent, pszIdent, rtl_str_getLength( pszIdent ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
233 : : OSL_ASSERT(*ustrIdent != NULL);
234 : :
235 : 163 : return bRet;
236 : : }
237 : :
238 : :
239 : 1359 : sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax)
240 : : {
241 : : sal_Char buffer[32];
242 : : sal_Int32 nChr;
243 : :
244 : 1359 : oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
245 : :
246 [ - + ]: 1359 : if (pSecImpl == NULL)
247 : 0 : return sal_False;
248 : :
249 : 1359 : nChr = snprintf(buffer, sizeof(buffer), "%u", pSecImpl->m_pPasswd.pw_uid);
250 [ + - ][ + - ]: 1359 : if ( nChr < 0 || SAL_INT_CAST(sal_uInt32, nChr) >= sizeof(buffer)
251 [ - + ]: 1359 : || SAL_INT_CAST(sal_uInt32, nChr) >= nMax )
252 : 0 : return sal_False; /* leave *pszIdent unmodified in case of failure */
253 : :
254 : 1359 : memcpy(pszIdent, buffer, nChr+1);
255 : 1359 : return sal_True;
256 : : }
257 : :
258 : 357 : sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **ustrName)
259 : : {
260 : 357 : sal_Bool bRet=sal_False;
261 : : sal_Char pszName[1024];
262 : :
263 : 357 : pszName[0] = '\0';
264 : :
265 : 357 : bRet = osl_psz_getUserName(Security,pszName,sizeof(pszName));
266 : :
267 : 357 : rtl_string2UString( ustrName, pszName, rtl_str_getLength( pszName ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
268 : : OSL_ASSERT(*ustrName != NULL);
269 : :
270 : 357 : return bRet;
271 : : }
272 : :
273 : :
274 : :
275 : 357 : static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax)
276 : : {
277 : 357 : oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
278 : :
279 [ + - ][ - + ]: 357 : if (pSecImpl == NULL || pSecImpl->m_pPasswd.pw_name == NULL)
280 : 0 : return sal_False;
281 : :
282 : 357 : strncpy(pszName, pSecImpl->m_pPasswd.pw_name, nMax);
283 : :
284 : 357 : return sal_True;
285 : : }
286 : :
287 : 3403 : sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
288 : : {
289 : 3403 : sal_Bool bRet=sal_False;
290 : : sal_Char pszDirectory[PATH_MAX];
291 : :
292 : 3403 : pszDirectory[0] = '\0';
293 : :
294 : 3403 : bRet = osl_psz_getHomeDir(Security,pszDirectory,sizeof(pszDirectory));
295 : :
296 [ + - ]: 3403 : if ( bRet == sal_True )
297 : : {
298 : 3403 : rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
299 : : OSL_ASSERT(*pustrDirectory != NULL);
300 : 3403 : osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
301 : : }
302 : :
303 : 3403 : return bRet;
304 : : }
305 : :
306 : 3718 : static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
307 : : {
308 : 3718 : oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
309 : :
310 [ - + ]: 3718 : if (pSecImpl == NULL)
311 : 0 : return sal_False;
312 : :
313 : : #ifdef ANDROID
314 : : {
315 : : sal_Bool bRet = sal_False;
316 : : rtl_uString *pName = 0, *pValue = 0;
317 : :
318 : : rtl_uString_newFromAscii(&pName, "HOME");
319 : :
320 : : if (rtl_bootstrap_get(pName, &pValue, NULL))
321 : : {
322 : : rtl_String *pStrValue = 0;
323 : : if (pValue && pValue->length > 0)
324 : : {
325 : : rtl_uString2String(&pStrValue, pValue->buffer,
326 : : pValue->length, RTL_TEXTENCODING_UTF8,
327 : : OUSTRING_TO_OSTRING_CVTFLAGS);
328 : : if (pStrValue && pStrValue->length > 0)
329 : : {
330 : : sal_Int32 nCopy = SAL_MIN ((sal_Int32)(nMax-1), pStrValue->length);
331 : : strncpy (pszDirectory, pStrValue->buffer, nCopy);
332 : : pszDirectory[nCopy] = '\0';
333 : : bRet = (size_t)pStrValue->length < nMax;
334 : : }
335 : : rtl_string_release(pStrValue);
336 : : }
337 : : rtl_uString_release(pName);
338 : : }
339 : : if (bRet)
340 : : return bRet;
341 : : }
342 : : #endif
343 : :
344 : : /* if current user, check also environment for HOME */
345 [ + - ]: 3718 : if (getuid() == pSecImpl->m_pPasswd.pw_uid)
346 : : {
347 : 3718 : sal_Char *pStr = NULL;
348 : : #ifdef SOLARIS
349 : : char buffer[8192];
350 : :
351 : : struct passwd pwd;
352 : : struct passwd *ppwd;
353 : :
354 : : #ifdef _POSIX_PTHREAD_SEMANTICS
355 : : if ( 0 != getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &ppwd ) )
356 : : ppwd = NULL;
357 : : #else
358 : : ppwd = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer) );
359 : : #endif
360 : :
361 : : if ( ppwd )
362 : : pStr = ppwd->pw_dir;
363 : : #else
364 : 3718 : pStr = getenv("HOME");
365 : : #endif
366 : :
367 [ + - ][ + - ]: 3718 : if (pStr != NULL && strlen(pStr) > 0 && access(pStr, 0) == 0)
[ + - ]
368 : 3718 : strncpy(pszDirectory, pStr, nMax);
369 [ # # ]: 0 : else if (pSecImpl->m_pPasswd.pw_dir != NULL)
370 : 0 : strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
371 : : else
372 : 3718 : return sal_False;
373 : : }
374 [ # # ]: 0 : else if (pSecImpl->m_pPasswd.pw_dir != NULL)
375 : 0 : strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
376 : : else
377 : 0 : return sal_False;
378 : :
379 : 3718 : return sal_True;
380 : : }
381 : :
382 : 315 : sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
383 : : {
384 : 315 : sal_Bool bRet = sal_False;
385 : : sal_Char pszDirectory[PATH_MAX];
386 : :
387 : 315 : pszDirectory[0] = '\0';
388 : :
389 : 315 : bRet = osl_psz_getConfigDir(Security,pszDirectory,sizeof(pszDirectory));
390 : :
391 [ + - ]: 315 : if ( bRet == sal_True )
392 : : {
393 : 315 : rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
394 : : OSL_ASSERT(*pustrDirectory != NULL);
395 : 315 : osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
396 : : }
397 : :
398 : 315 : return bRet;
399 : : }
400 : :
401 : : #ifndef MACOSX
402 : :
403 : : #define DOT_CONFIG "/.config"
404 : :
405 : 315 : static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
406 : : {
407 : 315 : sal_Char *pStr = getenv("XDG_CONFIG_HOME");
408 : :
409 [ # # ][ # # ]: 315 : if (pStr == NULL || strlen(pStr) == 0 || access(pStr, 0) != 0)
[ - + ]
410 : 315 : {
411 : 315 : size_t n = 0;
412 : : // a default equal to $HOME/.config should be used.
413 [ - + ]: 315 : if (!osl_psz_getHomeDir(Security, pszDirectory, nMax))
414 : 0 : return sal_False;
415 : 315 : n = strlen(pszDirectory);
416 [ + - ]: 315 : if (n + sizeof(DOT_CONFIG) < nMax)
417 : : {
418 : 315 : strncpy(pszDirectory+n, DOT_CONFIG, sizeof(DOT_CONFIG));
419 [ - + ]: 315 : if (access(pszDirectory, 0) != 0)
420 : : {
421 : : // resort to HOME
422 : 0 : pszDirectory[n] = '\0';
423 : : }
424 : : }
425 : : }
426 : : else
427 : 0 : strncpy(pszDirectory, pStr, nMax);
428 : :
429 : 315 : return sal_True;
430 : : }
431 : :
432 : : #undef DOT_CONFIG
433 : :
434 : : #else
435 : :
436 : : /*
437 : : * FIXME: rewrite to use more flexible
438 : : * NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)
439 : : * as soon as we can bumb the baseline to Tiger (for NSApplicationSupportDirectory) and have
440 : : * support for Objective-C in the build environment
441 : : */
442 : :
443 : : #define MACOSX_CONFIG_DIR "/Library/Application Support"
444 : : static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
445 : : {
446 : : if( osl_psz_getHomeDir(Security, pszDirectory, nMax - sizeof(MACOSX_CONFIG_DIR) + 1) )
447 : : {
448 : : strcat( pszDirectory, MACOSX_CONFIG_DIR );
449 : : return sal_True;
450 : : }
451 : :
452 : : return sal_False;
453 : : }
454 : :
455 : : #endif
456 : :
457 : 15 : sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
458 : : {
459 : 15 : oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
460 : :
461 [ - + ]: 15 : if (pSecImpl == NULL)
462 : 0 : return sal_False;
463 : :
464 [ - + ]: 15 : if (pSecImpl->m_pPasswd.pw_uid != 0)
465 : 0 : return sal_False;
466 : :
467 : 15 : return sal_True;
468 : : }
469 : :
470 : 5308 : void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
471 : : {
472 : 5308 : deleteSecurityImpl(Security);
473 : 5308 : }
474 : :
475 : :
476 : 5 : sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
477 : : {
478 : : (void) Security; /* unused */
479 : 5 : return sal_False;
480 : : }
481 : :
482 : 5 : void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
483 : : {
484 : : (void) Security; /* unused */
485 : 5 : }
486 : :
487 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|