merged tag ooo/DEV300_m102
[LibreOffice.git] / sal / osl / unx / security.c
blobd08326e65ebe8af5dba730ab7c86ef1bc218af02
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #include <stddef.h>
30 /* Solaris 8 has no C99 stdint.h, and Solaris generally seems not to miss it for
31 SIZE_MAX: */
32 #if !defined __SUNPRO_C
33 #include <stdint.h>
34 #endif
36 #include "system.h"
38 #include <osl/security.h>
39 #include <osl/diagnose.h>
41 #include "osl/thread.h"
42 #include "osl/file.h"
44 #if defined LINUX || defined SOLARIS
45 #include <crypt.h>
46 #endif
48 #include "secimpl.h"
50 #ifndef NOPAM
51 #ifndef PAM_BINARY_MSG
52 #define PAM_BINARY_MSG 6
53 #endif
54 #endif
56 static oslSecurityError SAL_CALL
57 osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
58 oslSecurity* pSecurity);
59 sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax);
60 static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax);
61 static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
62 static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
64 static sal_Bool sysconf_SC_GETPW_R_SIZE_MAX(size_t * value) {
65 #if defined _SC_GETPW_R_SIZE_MAX
66 long m;
67 errno = 0;
68 m = sysconf(_SC_GETPW_R_SIZE_MAX);
69 if (m == -1) {
70 /* _SC_GETPW_R_SIZE_MAX has no limit; some platforms like certain
71 FreeBSD versions support sysconf(_SC_GETPW_R_SIZE_MAX) in a broken
72 way and always set EINVAL, so be resilient here: */
73 return sal_False;
74 } else {
75 OSL_ASSERT(m >= 0 && (unsigned long) m < SIZE_MAX);
76 *value = (size_t) m;
77 return sal_True;
79 #else
80 /* some platforms like Mac OS X 1.3 do not define _SC_GETPW_R_SIZE_MAX: */
81 return sal_False;
82 #endif
85 static oslSecurityImpl * growSecurityImpl(
86 oslSecurityImpl * impl, size_t * bufSize)
88 size_t n = 0;
89 oslSecurityImpl * p = NULL;
90 if (impl == NULL) {
91 if (!sysconf_SC_GETPW_R_SIZE_MAX(&n)) {
92 /* choose something sensible (the callers of growSecurityImpl will
93 detect it if the allocated buffer is too small: */
94 n = 1024;
96 } else if (*bufSize <= SIZE_MAX / 2) {
97 n = 2 * *bufSize;
99 if (n != 0) {
100 if (n <= SIZE_MAX - offsetof(oslSecurityImpl, m_buffer)) {
101 *bufSize = n;
102 n += offsetof(oslSecurityImpl, m_buffer);
103 } else {
104 *bufSize = SIZE_MAX - offsetof(oslSecurityImpl, m_buffer);
105 n = SIZE_MAX;
107 p = realloc(impl, n);
109 if (p == NULL) {
110 free(impl);
112 return p;
115 static void deleteSecurityImpl(oslSecurityImpl * impl) {
116 free(impl);
119 oslSecurity SAL_CALL osl_getCurrentSecurity()
121 size_t n = 0;
122 oslSecurityImpl * p = NULL;
123 for (;;) {
124 struct passwd * found;
125 p = growSecurityImpl(p, &n);
126 if (p == NULL) {
127 return NULL;
129 switch (getpwuid_r(getuid(), &p->m_pPasswd, p->m_buffer, n, &found)) {
130 case ERANGE:
131 break;
132 case 0:
133 if (found != NULL) {
134 return p;
136 /* fall through */
137 default:
138 deleteSecurityImpl(p);
139 return NULL;
145 #if defined LINUX && !defined NOPAM
149 * osl Routines for Pluggable Authentication Modules (PAM)
150 * tested with Linux-PAM 0.66 on Redhat-6.0 and
151 * Linux-PAM 0.64 on RedHat-5.2,
152 * XXX Will probably not run on PAM 0.59 or prior, since
153 * number of pam_response* responses has changed
157 #include <security/pam_appl.h>
159 typedef struct {
160 char* name;
161 char* password;
162 } sal_PamData;
164 typedef struct {
165 int (*pam_start)(const char *service_name, const char *user,
166 const struct pam_conv *pam_conversation,
167 pam_handle_t **pamh);
168 int (*pam_end) (pam_handle_t *pamh, int pam_status);
169 int (*pam_authenticate) (pam_handle_t *pamh, int flags);
170 int (*pam_acct_mgmt) (pam_handle_t *pamh, int flags);
171 } sal_PamModule;
174 * Implement a pam-conversation callback-routine,
175 * it just supply name and password instead of prompting the user.
176 * I guess that echo-off means 'ask for password' and echo-on means
177 * 'ask for user-name'. In fact I've never been asked anything else
178 * than the password
179 * XXX Please notice that if a pam-module does ask anything else, we
180 * are completely lost, and a pam-module is free to do so
181 * XXX
184 static int
185 osl_PamConversation (int num_msg, const struct pam_message **msgm,
186 struct pam_response **response, void *appdata_ptr)
188 int i;
189 sal_Bool error;
190 sal_PamData *pam_data;
191 struct pam_response *p_reply;
193 /* resource initialization */
194 pam_data = (sal_PamData*) appdata_ptr;
195 p_reply = (struct pam_response *) calloc( num_msg,
196 sizeof(struct pam_response));
197 if ( p_reply == NULL || pam_data == NULL )
199 if ( p_reply != NULL )
200 free ( p_reply );
201 *response = NULL;
202 return PAM_CONV_ERR;
205 /* pseudo dialog */
206 error = sal_False;
207 for ( i = 0; i < num_msg ; i++ )
209 switch ( msgm[ i ]->msg_style )
211 case PAM_PROMPT_ECHO_OFF:
212 p_reply[ i ].resp_retcode = 0;
213 p_reply[ i ].resp = strdup( pam_data->password );
214 break;
215 case PAM_PROMPT_ECHO_ON:
216 p_reply[ i ].resp_retcode = 0;
217 p_reply[ i ].resp = strdup( pam_data->name );
218 break;
219 case PAM_ERROR_MSG:
220 case PAM_TEXT_INFO:
221 case PAM_BINARY_PROMPT:
222 case PAM_BINARY_MSG:
223 p_reply[ i ].resp_retcode = 0;
224 p_reply[ i ].resp = NULL;
225 break;
226 default:
227 error = sal_True;
228 break;
232 /* free resources on error */
233 if ( error )
235 for ( i = 0; i < num_msg ; i++ )
236 if ( p_reply[ i ].resp )
238 memset ( p_reply[ i ].resp, 0,
239 strlen( p_reply[ i ].resp ) );
240 free ( p_reply[ i ].resp );
242 free ( p_reply );
244 *response = NULL;
245 return PAM_CONV_ERR;
248 /* well done */
249 *response = p_reply;
250 return PAM_SUCCESS;
253 #ifndef PAM_LINK
255 * avoid linking against libpam.so, since it is not available on all systems,
256 * instead load-on-call, returns structure which holds pointer to
257 * pam-functions,
258 * library is never closed in case of success
261 static sal_PamModule* osl_getPAM()
263 static sal_PamModule *pam_module = NULL;
264 static sal_Bool load_once = sal_False;
266 if ( !load_once )
268 /* get library-handle. cannot use osl-module, since
269 RTLD_GLOBAL is required for PAM-0.64 RH 5.2
270 (but not for PAM-0.66 RH 6.0) */
271 void *pam_hdl;
273 pam_hdl = dlopen( "libpam.so.0", RTLD_GLOBAL | RTLD_LAZY );
275 if ( pam_hdl != NULL )
276 pam_module = (sal_PamModule*)calloc( 1, sizeof(sal_PamModule) );
278 /* load functions */
279 if ( pam_module != NULL )
281 pam_module->pam_acct_mgmt = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_acct_mgmt" );
282 pam_module->pam_authenticate
283 = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_authenticate" );
284 pam_module->pam_end = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_end" );
285 pam_module->pam_start = (int (*)(const char *, const char *, const struct pam_conv *, pam_handle_t **)) dlsym ( pam_hdl, "pam_start" );
287 /* free resources, if not completely successful */
288 if ( (pam_module->pam_start == NULL)
289 || (pam_module->pam_end == NULL)
290 || (pam_module->pam_authenticate == NULL)
291 || (pam_module->pam_acct_mgmt == NULL) )
293 free( pam_module );
294 pam_module = NULL;
295 dlclose( pam_hdl );
299 /* never try again */
300 load_once = sal_True;
303 return pam_module;
305 #endif
308 * User Identification using PAM
311 static sal_Bool
312 osl_PamAuthentification( const sal_Char* name, const sal_Char* password )
314 sal_Bool success = sal_False;
316 #ifndef PAM_LINK
317 sal_PamModule* pam_module;
319 pam_module = osl_getPAM();
320 if ( pam_module != NULL )
322 #endif
323 pam_handle_t *pam_handle = NULL;
324 struct pam_conv pam_conversation;
325 sal_PamData pam_data;
327 int return_value;
329 pam_data.name = (char*) name;
330 pam_data.password = (char*) password;
332 pam_conversation.conv = osl_PamConversation;
333 pam_conversation.appdata_ptr = (void*)(&pam_data);
335 #ifndef PAM_LINK
336 return_value = pam_module->pam_start( "su", name,
337 &pam_conversation, &pam_handle);
338 #else
339 return_value = pam_start( "su", name,
340 &pam_conversation, &pam_handle);
341 #endif
342 if (return_value == PAM_SUCCESS )
343 #ifndef PAM_LINK
344 return_value = pam_module->pam_authenticate(pam_handle, 0);
345 #else
346 return_value = pam_authenticate(pam_handle, 0);
347 #endif
348 if (return_value == PAM_SUCCESS )
349 #ifndef PAM_LINK
350 return_value = pam_module->pam_acct_mgmt(pam_handle, 0);
351 pam_module->pam_end( pam_handle, return_value );
352 #else
353 return_value = pam_acct_mgmt(pam_handle, 0);
354 pam_end( pam_handle, return_value );
355 #endif
357 success = (sal_Bool)(return_value == PAM_SUCCESS);
358 #ifndef PAM_LINK
360 #endif
362 return success;
366 #ifndef CRYPT_LINK
367 /* dummy crypt, matches the interface of
368 crypt() but does not encrypt at all */
369 static const sal_Char* SAL_CALL
370 osl_noCrypt ( const sal_Char *key, const sal_Char *salt )
372 (void) salt; /* unused */
373 return key;
376 /* load-on-call crypt library and crypt symbol */
377 static void* SAL_CALL
378 osl_getCrypt()
380 static char* (*crypt_sym)(const char*, const char*) = NULL;
381 static sal_Bool load_once = sal_False;
383 if ( !load_once )
385 void * crypt_library;
387 crypt_library = dlopen( "libcrypt.so.1", RTLD_GLOBAL | RTLD_LAZY ); /* never closed */
388 if ( crypt_library != NULL )
389 crypt_sym = (char* (*)(const char *, const char *)) dlsym(crypt_library, "crypt" );
390 if ( crypt_sym == NULL ) /* no libcrypt or libcrypt without crypt */
391 crypt_sym = (char* (*)(const char *, const char *)) &osl_noCrypt;
393 load_once = sal_True;
396 return (void*)crypt_sym;
399 /* replacement for crypt function for password encryption, uses either
400 strong encryption of dlopen'ed libcrypt.so.1 or dummy implementation
401 with no encryption. Objective target is to avoid linking against
402 libcrypt (not available on caldera open linux 2.2 #63822#) */
403 static sal_Char* SAL_CALL
404 osl_dynamicCrypt ( const sal_Char *key, const sal_Char *salt )
406 char* (*dynamic_crypt)(char *, char *);
408 dynamic_crypt = (char * (*)(char *, char *)) osl_getCrypt();
410 return dynamic_crypt( (sal_Char*)key, (sal_Char*)salt );
412 #endif
415 * compare an encrypted and an unencrypted password for equality
416 * returns true if passwords are equal, false otherwise
417 * Note: uses crypt() and a mutex instead of crypt_r() since crypt_r needs
418 * more than 128KByte of external buffer for struct crypt_data
421 static sal_Bool SAL_CALL
422 osl_equalPasswords ( const sal_Char *pEncryptedPassword, const sal_Char *pPlainPassword )
424 static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
426 sal_Bool success;
427 sal_Char salt[3];
428 sal_Char *encrypted_plain;
430 salt[0] = pEncryptedPassword[0];
431 salt[1] = pEncryptedPassword[1];
432 salt[2] = '\0';
434 pthread_mutex_lock(&crypt_mutex);
436 #ifndef CRYPT_LINK
437 encrypted_plain = (sal_Char *)osl_dynamicCrypt( pPlainPassword, salt );
438 #else
439 encrypted_plain = (sal_Char *)crypt( pPlainPassword, salt );
440 #endif
441 success = (sal_Bool) (strcmp(pEncryptedPassword, encrypted_plain) == 0);
443 pthread_mutex_unlock(&crypt_mutex);
445 return success;
448 #endif /* defined LINUX && !defined NOPAM */
449 oslSecurityError SAL_CALL osl_loginUser(
450 rtl_uString *ustrUserName,
451 rtl_uString *ustrPassword,
452 oslSecurity *pSecurity
455 oslSecurityError Error;
456 rtl_String* strUserName=0;
457 rtl_String* strPassword=0;
458 sal_Char* pszUserName=0;
459 sal_Char* pszPassword=0;
461 if ( ustrUserName != 0 )
464 rtl_uString2String( &strUserName,
465 rtl_uString_getStr(ustrUserName),
466 rtl_uString_getLength(ustrUserName),
467 RTL_TEXTENCODING_UTF8,
468 OUSTRING_TO_OSTRING_CVTFLAGS );
469 pszUserName = rtl_string_getStr(strUserName);
473 if ( ustrPassword != 0 )
475 rtl_uString2String( &strPassword,
476 rtl_uString_getStr(ustrPassword),
477 rtl_uString_getLength(ustrPassword),
478 RTL_TEXTENCODING_UTF8,
479 OUSTRING_TO_OSTRING_CVTFLAGS );
480 pszPassword = rtl_string_getStr(strPassword);
484 Error=osl_psz_loginUser(pszUserName,pszPassword,pSecurity);
486 if ( strUserName != 0 )
488 rtl_string_release(strUserName);
491 if ( strPassword)
493 rtl_string_release(strPassword);
497 return Error;
501 static oslSecurityError SAL_CALL
502 osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
503 oslSecurity* pSecurity)
505 #if defined NETBSD || defined SCO || defined AIX || defined FREEBSD || \
506 defined MACOSX
508 return osl_Security_E_None;
510 #else
512 oslSecurityError nError = osl_Security_E_Unknown;
513 oslSecurityImpl * p = NULL;
514 if (pszUserName != NULL && pszPasswd != NULL && pSecurity != NULL) {
515 /* get nis or normal password, should succeed for any known user, but
516 perhaps the password is wrong (i.e. 'x') if shadow passwords are in
517 use or authentication must be done by PAM */
518 size_t n = 0;
519 int err = 0;
520 struct passwd * found = NULL;
521 for (;;) {
522 p = growSecurityImpl(p, &n);
523 if (p == NULL) {
524 break;
526 err = getpwnam_r(
527 pszUserName, &p->m_pPasswd, p->m_buffer, n, &found);
528 if (err != ERANGE) {
529 break;
532 if (p != NULL && err == 0) {
533 if (found == NULL) {
534 nError = osl_Security_E_UserUnknown;
535 } else {
536 #if defined LINUX && !defined NOPAM
537 /* only root is able to read the /etc/shadow passwd, a normal
538 user even can't read his own encrypted passwd */
539 if (osl_equalPasswords(p->m_pPasswd.pw_passwd, pszPasswd) ||
540 osl_PamAuthentification(pszUserName, pszPasswd))
542 nError = osl_Security_E_None;
543 } else {
544 char buffer[1024];
545 struct spwd result_buf;
546 struct spwd * pShadowPasswd;
547 buffer[0] = '\0';
548 if (getspnam_r(
549 pszUserName, &result_buf, buffer, sizeof buffer,
550 &pShadowPasswd) == 0 &&
551 pShadowPasswd != NULL)
553 nError =
554 osl_equalPasswords(
555 pShadowPasswd->sp_pwdp, pszPasswd)
556 ? osl_Security_E_None
557 : osl_Security_E_WrongPassword;
558 } else if (getuid() == 0) {
559 /* mfe: Try to verify the root-password via nis */
560 if (getspnam_r(
561 "root", &result_buf, buffer, sizeof buffer,
562 &pShadowPasswd) == 0 &&
563 pShadowPasswd != NULL &&
564 osl_equalPasswords(
565 pShadowPasswd->sp_pwdp, pszPasswd))
567 nError = osl_Security_E_None;
568 } else {
569 /* mfe: we can't get via nis (glibc2.0.x has bug in
570 getspnam_r) we try it with the normal getspnam */
571 static pthread_mutex_t pwmutex =
572 PTHREAD_MUTEX_INITIALIZER;
573 pthread_mutex_lock(&pwmutex);
574 pShadowPasswd = getspnam("root");
575 pthread_mutex_unlock(&pwmutex);
576 nError =
577 ((pShadowPasswd != NULL &&
578 osl_equalPasswords(
579 pShadowPasswd->sp_pwdp, pszPasswd)) ||
580 osl_PamAuthentification("root", pszPasswd))
581 ? osl_Security_E_None
582 : osl_Security_E_WrongPassword;
586 #else
587 char buffer[1024];
588 struct spwd spwdStruct;
589 buffer[0] = '\0';
590 #ifndef NEW_SHADOW_API
591 if (getspnam_r(pszUserName, &spwdStruct, buffer, sizeof buffer) != NULL)
592 #else
593 if (getspnam_r(pszUserName, &spwdStruct, buffer, sizeof buffer, NULL) == 0)
594 #endif
596 char salt[3];
597 char * cryptPasswd;
598 strncpy(salt, spwdStruct.sp_pwdp, 2);
599 salt[2] = '\0';
600 cryptPasswd = (char *) crypt(pszPasswd, salt);
601 if (strcmp(spwdStruct.sp_pwdp, cryptPasswd) == 0) {
602 nError = osl_Security_E_None;
603 } else if (getuid() == 0 &&
604 #ifndef NEW_SHADOW_API
605 (getspnam_r("root", &spwdStruct, buffer, sizeof buffer) != NULL))
606 #else
607 (getspnam_r("root", &spwdStruct, buffer, sizeof buffer, NULL) == 0))
608 #endif
610 /* if current process is running as root, allow to logon
611 as any other user */
612 strncpy(salt, spwdStruct.sp_pwdp, 2);
613 salt[2] = '\0';
614 cryptPasswd = (char *) crypt(pszPasswd, salt);
615 if (strcmp(spwdStruct.sp_pwdp, cryptPasswd) == 0) {
616 nError = osl_Security_E_None;
618 } else {
619 nError = osl_Security_E_WrongPassword;
622 #endif
626 if (nError == osl_Security_E_None) {
627 *pSecurity = p;
628 } else {
629 deleteSecurityImpl(p);
630 *pSecurity = NULL;
632 return nError;
634 #endif
637 oslSecurityError SAL_CALL osl_loginUserOnFileServer(
638 rtl_uString *strUserName,
639 rtl_uString *strPasswd,
640 rtl_uString *strFileServer,
641 oslSecurity *pSecurity
644 (void) strUserName; /* unused */
645 (void) strPasswd; /* unused */
646 (void) strFileServer; /* unused */
647 (void) pSecurity; /* unused */
648 return osl_Security_E_UserUnknown;
652 sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **ustrIdent)
654 sal_Bool bRet=sal_False;
655 sal_Char pszIdent[1024];
657 pszIdent[0] = '\0';
659 bRet = osl_psz_getUserIdent(Security,pszIdent,sizeof(pszIdent));
661 rtl_string2UString( ustrIdent, pszIdent, rtl_str_getLength( pszIdent ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
662 OSL_ASSERT(*ustrIdent != NULL);
664 return bRet;
668 sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax)
670 sal_Char buffer[32];
671 sal_Int32 nChr;
673 oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
675 if (pSecImpl == NULL)
676 return sal_False;
678 nChr = snprintf(buffer, sizeof(buffer), "%u", pSecImpl->m_pPasswd.pw_uid);
679 if ( nChr < 0 || SAL_INT_CAST(sal_uInt32, nChr) >= sizeof(buffer)
680 || SAL_INT_CAST(sal_uInt32, nChr) >= nMax )
681 return sal_False; /* leave *pszIdent unmodified in case of failure */
683 memcpy(pszIdent, buffer, nChr+1);
684 return sal_True;
687 sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **ustrName)
689 sal_Bool bRet=sal_False;
690 sal_Char pszName[1024];
692 pszName[0] = '\0';
694 bRet = osl_psz_getUserName(Security,pszName,sizeof(pszName));
696 rtl_string2UString( ustrName, pszName, rtl_str_getLength( pszName ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
697 OSL_ASSERT(*ustrName != NULL);
699 return bRet;
704 static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax)
706 oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
708 if (pSecImpl == NULL)
709 return sal_False;
711 strncpy(pszName, pSecImpl->m_pPasswd.pw_name, nMax);
713 return sal_True;
716 sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
718 sal_Bool bRet=sal_False;
719 sal_Char pszDirectory[PATH_MAX];
721 pszDirectory[0] = '\0';
723 bRet = osl_psz_getHomeDir(Security,pszDirectory,sizeof(pszDirectory));
725 if ( bRet == sal_True )
727 rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
728 OSL_ASSERT(*pustrDirectory != NULL);
729 osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
732 return bRet;
736 static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
738 oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
740 if (pSecImpl == NULL)
741 return sal_False;
743 /* if current user, check also environment for HOME */
744 if (getuid() == pSecImpl->m_pPasswd.pw_uid)
746 sal_Char *pStr = NULL;
747 #ifdef SOLARIS
748 char buffer[8192];
750 struct passwd pwd;
751 struct passwd *ppwd;
753 #ifdef _POSIX_PTHREAD_SEMANTICS
754 if ( 0 != getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &ppwd ) )
755 ppwd = NULL;
756 #else
757 ppwd = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer) );
758 #endif
760 if ( ppwd )
761 pStr = ppwd->pw_dir;
762 #else
763 pStr = getenv("HOME");
764 #endif
766 if ((pStr != NULL) && (strlen(pStr) > 0) &&
767 (access(pStr, 0) == 0))
768 strncpy(pszDirectory, pStr, nMax);
769 else
770 strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
772 else
773 strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
775 return sal_True;
778 sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
780 sal_Bool bRet = sal_False;
781 sal_Char pszDirectory[PATH_MAX];
783 pszDirectory[0] = '\0';
785 bRet = osl_psz_getConfigDir(Security,pszDirectory,sizeof(pszDirectory));
787 if ( bRet == sal_True )
789 rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
790 OSL_ASSERT(*pustrDirectory != NULL);
791 osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
794 return bRet;
797 #ifndef MACOSX
799 static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
801 sal_Char *pStr = getenv("XDG_CONFIG_HOME");
803 if ((pStr == NULL) || (strlen(pStr) == 0) ||
804 (access(pStr, 0) != 0))
805 return (osl_psz_getHomeDir(Security, pszDirectory, nMax));
807 strncpy(pszDirectory, pStr, nMax);
808 return sal_True;
811 #else
814 * FIXME: rewrite to use more flexible
815 * NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)
816 * as soon as we can bumb the baseline to Tiger (for NSApplicationSupportDirectory) and have
817 * support for Objective-C in the build environment
820 #define MACOSX_CONFIG_DIR "/Library/Application Support"
821 static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
823 if( osl_psz_getHomeDir(Security, pszDirectory, nMax - sizeof(MACOSX_CONFIG_DIR) + 1) )
825 strcat( pszDirectory, MACOSX_CONFIG_DIR );
826 return sal_True;
829 return sal_False;
832 #endif
834 sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
836 oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
838 if (pSecImpl == NULL)
839 return sal_False;
841 if (pSecImpl->m_pPasswd.pw_uid != 0)
842 return (sal_False);
844 return (sal_True);
847 void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
849 deleteSecurityImpl(Security);
853 sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
855 (void) Security; /* unused */
856 return sal_False;
859 void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
861 (void) Security; /* unused */