diff options
Diffstat (limited to 'sal/osl/unx/security.c')
-rw-r--r-- | sal/osl/unx/security.c | 862 |
1 files changed, 862 insertions, 0 deletions
diff --git a/sal/osl/unx/security.c b/sal/osl/unx/security.c new file mode 100644 index 000000000000..d08326e65ebe --- /dev/null +++ b/sal/osl/unx/security.c @@ -0,0 +1,862 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <stddef.h> + +/* Solaris 8 has no C99 stdint.h, and Solaris generally seems not to miss it for + SIZE_MAX: */ +#if !defined __SUNPRO_C +#include <stdint.h> +#endif + +#include "system.h" + +#include <osl/security.h> +#include <osl/diagnose.h> + +#include "osl/thread.h" +#include "osl/file.h" + +#if defined LINUX || defined SOLARIS +#include <crypt.h> +#endif + +#include "secimpl.h" + +#ifndef NOPAM +#ifndef PAM_BINARY_MSG +#define PAM_BINARY_MSG 6 +#endif +#endif + +static oslSecurityError SAL_CALL +osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd, + oslSecurity* pSecurity); +sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax); +static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax); +static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax); +static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax); + +static sal_Bool sysconf_SC_GETPW_R_SIZE_MAX(size_t * value) { +#if defined _SC_GETPW_R_SIZE_MAX + long m; + errno = 0; + m = sysconf(_SC_GETPW_R_SIZE_MAX); + if (m == -1) { + /* _SC_GETPW_R_SIZE_MAX has no limit; some platforms like certain + FreeBSD versions support sysconf(_SC_GETPW_R_SIZE_MAX) in a broken + way and always set EINVAL, so be resilient here: */ + return sal_False; + } else { + OSL_ASSERT(m >= 0 && (unsigned long) m < SIZE_MAX); + *value = (size_t) m; + return sal_True; + } +#else + /* some platforms like Mac OS X 1.3 do not define _SC_GETPW_R_SIZE_MAX: */ + return sal_False; +#endif +} + +static oslSecurityImpl * growSecurityImpl( + oslSecurityImpl * impl, size_t * bufSize) +{ + size_t n = 0; + oslSecurityImpl * p = NULL; + if (impl == NULL) { + if (!sysconf_SC_GETPW_R_SIZE_MAX(&n)) { + /* choose something sensible (the callers of growSecurityImpl will + detect it if the allocated buffer is too small: */ + n = 1024; + } + } else if (*bufSize <= SIZE_MAX / 2) { + n = 2 * *bufSize; + } + if (n != 0) { + if (n <= SIZE_MAX - offsetof(oslSecurityImpl, m_buffer)) { + *bufSize = n; + n += offsetof(oslSecurityImpl, m_buffer); + } else { + *bufSize = SIZE_MAX - offsetof(oslSecurityImpl, m_buffer); + n = SIZE_MAX; + } + p = realloc(impl, n); + } + if (p == NULL) { + free(impl); + } + return p; +} + +static void deleteSecurityImpl(oslSecurityImpl * impl) { + free(impl); +} + +oslSecurity SAL_CALL osl_getCurrentSecurity() +{ + size_t n = 0; + oslSecurityImpl * p = NULL; + for (;;) { + struct passwd * found; + p = growSecurityImpl(p, &n); + if (p == NULL) { + return NULL; + } + switch (getpwuid_r(getuid(), &p->m_pPasswd, p->m_buffer, n, &found)) { + case ERANGE: + break; + case 0: + if (found != NULL) { + return p; + } + /* fall through */ + default: + deleteSecurityImpl(p); + return NULL; + } + } +} + + +#if defined LINUX && !defined NOPAM + +/* + * + * osl Routines for Pluggable Authentication Modules (PAM) + * tested with Linux-PAM 0.66 on Redhat-6.0 and + * Linux-PAM 0.64 on RedHat-5.2, + * XXX Will probably not run on PAM 0.59 or prior, since + * number of pam_response* responses has changed + * + */ + +#include <security/pam_appl.h> + +typedef struct { + char* name; + char* password; +} sal_PamData; + +typedef struct { + int (*pam_start)(const char *service_name, const char *user, + const struct pam_conv *pam_conversation, + pam_handle_t **pamh); + int (*pam_end) (pam_handle_t *pamh, int pam_status); + int (*pam_authenticate) (pam_handle_t *pamh, int flags); + int (*pam_acct_mgmt) (pam_handle_t *pamh, int flags); +} sal_PamModule; + +/* + * Implement a pam-conversation callback-routine, + * it just supply name and password instead of prompting the user. + * I guess that echo-off means 'ask for password' and echo-on means + * 'ask for user-name'. In fact I've never been asked anything else + * than the password + * XXX Please notice that if a pam-module does ask anything else, we + * are completely lost, and a pam-module is free to do so + * XXX + */ + +static int +osl_PamConversation (int num_msg, const struct pam_message **msgm, + struct pam_response **response, void *appdata_ptr) +{ + int i; + sal_Bool error; + sal_PamData *pam_data; + struct pam_response *p_reply; + + /* resource initialization */ + pam_data = (sal_PamData*) appdata_ptr; + p_reply = (struct pam_response *) calloc( num_msg, + sizeof(struct pam_response)); + if ( p_reply == NULL || pam_data == NULL ) + { + if ( p_reply != NULL ) + free ( p_reply ); + *response = NULL; + return PAM_CONV_ERR; + } + + /* pseudo dialog */ + error = sal_False; + for ( i = 0; i < num_msg ; i++ ) + { + switch ( msgm[ i ]->msg_style ) + { + case PAM_PROMPT_ECHO_OFF: + p_reply[ i ].resp_retcode = 0; + p_reply[ i ].resp = strdup( pam_data->password ); + break; + case PAM_PROMPT_ECHO_ON: + p_reply[ i ].resp_retcode = 0; + p_reply[ i ].resp = strdup( pam_data->name ); + break; + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: + case PAM_BINARY_PROMPT: + case PAM_BINARY_MSG: + p_reply[ i ].resp_retcode = 0; + p_reply[ i ].resp = NULL; + break; + default: + error = sal_True; + break; + } + } + + /* free resources on error */ + if ( error ) + { + for ( i = 0; i < num_msg ; i++ ) + if ( p_reply[ i ].resp ) + { + memset ( p_reply[ i ].resp, 0, + strlen( p_reply[ i ].resp ) ); + free ( p_reply[ i ].resp ); + } + free ( p_reply ); + + *response = NULL; + return PAM_CONV_ERR; + } + + /* well done */ + *response = p_reply; + return PAM_SUCCESS; +} + +#ifndef PAM_LINK +/* + * avoid linking against libpam.so, since it is not available on all systems, + * instead load-on-call, returns structure which holds pointer to + * pam-functions, + * library is never closed in case of success + */ + +static sal_PamModule* osl_getPAM() +{ + static sal_PamModule *pam_module = NULL; + static sal_Bool load_once = sal_False; + + if ( !load_once ) + { + /* get library-handle. cannot use osl-module, since + RTLD_GLOBAL is required for PAM-0.64 RH 5.2 + (but not for PAM-0.66 RH 6.0) */ + void *pam_hdl; + + pam_hdl = dlopen( "libpam.so.0", RTLD_GLOBAL | RTLD_LAZY ); + + if ( pam_hdl != NULL ) + pam_module = (sal_PamModule*)calloc( 1, sizeof(sal_PamModule) ); + + /* load functions */ + if ( pam_module != NULL ) + { + pam_module->pam_acct_mgmt = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_acct_mgmt" ); + pam_module->pam_authenticate + = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_authenticate" ); + pam_module->pam_end = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_end" ); + pam_module->pam_start = (int (*)(const char *, const char *, const struct pam_conv *, pam_handle_t **)) dlsym ( pam_hdl, "pam_start" ); + + /* free resources, if not completely successful */ + if ( (pam_module->pam_start == NULL) + || (pam_module->pam_end == NULL) + || (pam_module->pam_authenticate == NULL) + || (pam_module->pam_acct_mgmt == NULL) ) + { + free( pam_module ); + pam_module = NULL; + dlclose( pam_hdl ); + } + } + + /* never try again */ + load_once = sal_True; + } + + return pam_module; +} +#endif + +/* + * User Identification using PAM + */ + +static sal_Bool +osl_PamAuthentification( const sal_Char* name, const sal_Char* password ) +{ + sal_Bool success = sal_False; + +#ifndef PAM_LINK + sal_PamModule* pam_module; + + pam_module = osl_getPAM(); + if ( pam_module != NULL ) + { +#endif + pam_handle_t *pam_handle = NULL; + struct pam_conv pam_conversation; + sal_PamData pam_data; + + int return_value; + + pam_data.name = (char*) name; + pam_data.password = (char*) password; + + pam_conversation.conv = osl_PamConversation; + pam_conversation.appdata_ptr = (void*)(&pam_data); + +#ifndef PAM_LINK + return_value = pam_module->pam_start( "su", name, + &pam_conversation, &pam_handle); +#else + return_value = pam_start( "su", name, + &pam_conversation, &pam_handle); +#endif + if (return_value == PAM_SUCCESS ) +#ifndef PAM_LINK + return_value = pam_module->pam_authenticate(pam_handle, 0); +#else + return_value = pam_authenticate(pam_handle, 0); +#endif + if (return_value == PAM_SUCCESS ) +#ifndef PAM_LINK + return_value = pam_module->pam_acct_mgmt(pam_handle, 0); + pam_module->pam_end( pam_handle, return_value ); +#else + return_value = pam_acct_mgmt(pam_handle, 0); + pam_end( pam_handle, return_value ); +#endif + + success = (sal_Bool)(return_value == PAM_SUCCESS); +#ifndef PAM_LINK + } +#endif + + return success; +} + + +#ifndef CRYPT_LINK +/* dummy crypt, matches the interface of + crypt() but does not encrypt at all */ +static const sal_Char* SAL_CALL +osl_noCrypt ( const sal_Char *key, const sal_Char *salt ) +{ + (void) salt; /* unused */ + return key; +} + +/* load-on-call crypt library and crypt symbol */ +static void* SAL_CALL +osl_getCrypt() +{ + static char* (*crypt_sym)(const char*, const char*) = NULL; + static sal_Bool load_once = sal_False; + + if ( !load_once ) + { + void * crypt_library; + + crypt_library = dlopen( "libcrypt.so.1", RTLD_GLOBAL | RTLD_LAZY ); /* never closed */ + if ( crypt_library != NULL ) + crypt_sym = (char* (*)(const char *, const char *)) dlsym(crypt_library, "crypt" ); + if ( crypt_sym == NULL ) /* no libcrypt or libcrypt without crypt */ + crypt_sym = (char* (*)(const char *, const char *)) &osl_noCrypt; + + load_once = sal_True; + } + + return (void*)crypt_sym; +} + +/* replacement for crypt function for password encryption, uses either + strong encryption of dlopen'ed libcrypt.so.1 or dummy implementation + with no encryption. Objective target is to avoid linking against + libcrypt (not available on caldera open linux 2.2 #63822#) */ +static sal_Char* SAL_CALL +osl_dynamicCrypt ( const sal_Char *key, const sal_Char *salt ) +{ + char* (*dynamic_crypt)(char *, char *); + + dynamic_crypt = (char * (*)(char *, char *)) osl_getCrypt(); + + return dynamic_crypt( (sal_Char*)key, (sal_Char*)salt ); +} +#endif + +/* + * compare an encrypted and an unencrypted password for equality + * returns true if passwords are equal, false otherwise + * Note: uses crypt() and a mutex instead of crypt_r() since crypt_r needs + * more than 128KByte of external buffer for struct crypt_data + */ + +static sal_Bool SAL_CALL +osl_equalPasswords ( const sal_Char *pEncryptedPassword, const sal_Char *pPlainPassword ) +{ + static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER; + + sal_Bool success; + sal_Char salt[3]; + sal_Char *encrypted_plain; + + salt[0] = pEncryptedPassword[0]; + salt[1] = pEncryptedPassword[1]; + salt[2] = '\0'; + + pthread_mutex_lock(&crypt_mutex); + +#ifndef CRYPT_LINK + encrypted_plain = (sal_Char *)osl_dynamicCrypt( pPlainPassword, salt ); +#else + encrypted_plain = (sal_Char *)crypt( pPlainPassword, salt ); +#endif + success = (sal_Bool) (strcmp(pEncryptedPassword, encrypted_plain) == 0); + + pthread_mutex_unlock(&crypt_mutex); + + return success; +} + +#endif /* defined LINUX && !defined NOPAM */ +oslSecurityError SAL_CALL osl_loginUser( + rtl_uString *ustrUserName, + rtl_uString *ustrPassword, + oslSecurity *pSecurity + ) +{ + oslSecurityError Error; + rtl_String* strUserName=0; + rtl_String* strPassword=0; + sal_Char* pszUserName=0; + sal_Char* pszPassword=0; + + if ( ustrUserName != 0 ) + { + + rtl_uString2String( &strUserName, + rtl_uString_getStr(ustrUserName), + rtl_uString_getLength(ustrUserName), + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszUserName = rtl_string_getStr(strUserName); + } + + + if ( ustrPassword != 0 ) + { + rtl_uString2String( &strPassword, + rtl_uString_getStr(ustrPassword), + rtl_uString_getLength(ustrPassword), + RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszPassword = rtl_string_getStr(strPassword); + } + + + Error=osl_psz_loginUser(pszUserName,pszPassword,pSecurity); + + if ( strUserName != 0 ) + { + rtl_string_release(strUserName); + } + + if ( strPassword) + { + rtl_string_release(strPassword); + } + + + return Error; +} + + +static oslSecurityError SAL_CALL +osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd, + oslSecurity* pSecurity) +{ +#if defined NETBSD || defined SCO || defined AIX || defined FREEBSD || \ + defined MACOSX + + return osl_Security_E_None; + +#else + + oslSecurityError nError = osl_Security_E_Unknown; + oslSecurityImpl * p = NULL; + if (pszUserName != NULL && pszPasswd != NULL && pSecurity != NULL) { + /* get nis or normal password, should succeed for any known user, but + perhaps the password is wrong (i.e. 'x') if shadow passwords are in + use or authentication must be done by PAM */ + size_t n = 0; + int err = 0; + struct passwd * found = NULL; + for (;;) { + p = growSecurityImpl(p, &n); + if (p == NULL) { + break; + } + err = getpwnam_r( + pszUserName, &p->m_pPasswd, p->m_buffer, n, &found); + if (err != ERANGE) { + break; + } + } + if (p != NULL && err == 0) { + if (found == NULL) { + nError = osl_Security_E_UserUnknown; + } else { +#if defined LINUX && !defined NOPAM + /* only root is able to read the /etc/shadow passwd, a normal + user even can't read his own encrypted passwd */ + if (osl_equalPasswords(p->m_pPasswd.pw_passwd, pszPasswd) || + osl_PamAuthentification(pszUserName, pszPasswd)) + { + nError = osl_Security_E_None; + } else { + char buffer[1024]; + struct spwd result_buf; + struct spwd * pShadowPasswd; + buffer[0] = '\0'; + if (getspnam_r( + pszUserName, &result_buf, buffer, sizeof buffer, + &pShadowPasswd) == 0 && + pShadowPasswd != NULL) + { + nError = + osl_equalPasswords( + pShadowPasswd->sp_pwdp, pszPasswd) + ? osl_Security_E_None + : osl_Security_E_WrongPassword; + } else if (getuid() == 0) { + /* mfe: Try to verify the root-password via nis */ + if (getspnam_r( + "root", &result_buf, buffer, sizeof buffer, + &pShadowPasswd) == 0 && + pShadowPasswd != NULL && + osl_equalPasswords( + pShadowPasswd->sp_pwdp, pszPasswd)) + { + nError = osl_Security_E_None; + } else { + /* mfe: we can't get via nis (glibc2.0.x has bug in + getspnam_r) we try it with the normal getspnam */ + static pthread_mutex_t pwmutex = + PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&pwmutex); + pShadowPasswd = getspnam("root"); + pthread_mutex_unlock(&pwmutex); + nError = + ((pShadowPasswd != NULL && + osl_equalPasswords( + pShadowPasswd->sp_pwdp, pszPasswd)) || + osl_PamAuthentification("root", pszPasswd)) + ? osl_Security_E_None + : osl_Security_E_WrongPassword; + } + } + } +#else + char buffer[1024]; + struct spwd spwdStruct; + buffer[0] = '\0'; +#ifndef NEW_SHADOW_API + if (getspnam_r(pszUserName, &spwdStruct, buffer, sizeof buffer) != NULL) +#else + if (getspnam_r(pszUserName, &spwdStruct, buffer, sizeof buffer, NULL) == 0) +#endif + { + char salt[3]; + char * cryptPasswd; + strncpy(salt, spwdStruct.sp_pwdp, 2); + salt[2] = '\0'; + cryptPasswd = (char *) crypt(pszPasswd, salt); + if (strcmp(spwdStruct.sp_pwdp, cryptPasswd) == 0) { + nError = osl_Security_E_None; + } else if (getuid() == 0 && +#ifndef NEW_SHADOW_API + (getspnam_r("root", &spwdStruct, buffer, sizeof buffer) != NULL)) +#else + (getspnam_r("root", &spwdStruct, buffer, sizeof buffer, NULL) == 0)) +#endif + { + /* if current process is running as root, allow to logon + as any other user */ + strncpy(salt, spwdStruct.sp_pwdp, 2); + salt[2] = '\0'; + cryptPasswd = (char *) crypt(pszPasswd, salt); + if (strcmp(spwdStruct.sp_pwdp, cryptPasswd) == 0) { + nError = osl_Security_E_None; + } + } else { + nError = osl_Security_E_WrongPassword; + } + } +#endif + } + } + } + if (nError == osl_Security_E_None) { + *pSecurity = p; + } else { + deleteSecurityImpl(p); + *pSecurity = NULL; + } + return nError; + +#endif +} + +oslSecurityError SAL_CALL osl_loginUserOnFileServer( + rtl_uString *strUserName, + rtl_uString *strPasswd, + rtl_uString *strFileServer, + oslSecurity *pSecurity + ) +{ + (void) strUserName; /* unused */ + (void) strPasswd; /* unused */ + (void) strFileServer; /* unused */ + (void) pSecurity; /* unused */ + return osl_Security_E_UserUnknown; +} + + +sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **ustrIdent) +{ + sal_Bool bRet=sal_False; + sal_Char pszIdent[1024]; + + pszIdent[0] = '\0'; + + bRet = osl_psz_getUserIdent(Security,pszIdent,sizeof(pszIdent)); + + rtl_string2UString( ustrIdent, pszIdent, rtl_str_getLength( pszIdent ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*ustrIdent != NULL); + + return bRet; +} + + +sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax) +{ + sal_Char buffer[32]; + sal_Int32 nChr; + + oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security; + + if (pSecImpl == NULL) + return sal_False; + + nChr = snprintf(buffer, sizeof(buffer), "%u", pSecImpl->m_pPasswd.pw_uid); + if ( nChr < 0 || SAL_INT_CAST(sal_uInt32, nChr) >= sizeof(buffer) + || SAL_INT_CAST(sal_uInt32, nChr) >= nMax ) + return sal_False; /* leave *pszIdent unmodified in case of failure */ + + memcpy(pszIdent, buffer, nChr+1); + return sal_True; +} + +sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **ustrName) +{ + sal_Bool bRet=sal_False; + sal_Char pszName[1024]; + + pszName[0] = '\0'; + + bRet = osl_psz_getUserName(Security,pszName,sizeof(pszName)); + + rtl_string2UString( ustrName, pszName, rtl_str_getLength( pszName ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*ustrName != NULL); + + return bRet; +} + + + +static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax) +{ + oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security; + + if (pSecImpl == NULL) + return sal_False; + + strncpy(pszName, pSecImpl->m_pPasswd.pw_name, nMax); + + return sal_True; +} + +sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory) +{ + sal_Bool bRet=sal_False; + sal_Char pszDirectory[PATH_MAX]; + + pszDirectory[0] = '\0'; + + bRet = osl_psz_getHomeDir(Security,pszDirectory,sizeof(pszDirectory)); + + if ( bRet == sal_True ) + { + rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*pustrDirectory != NULL); + osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory ); + } + + return bRet; +} + + +static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax) +{ + oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security; + + if (pSecImpl == NULL) + return sal_False; + + /* if current user, check also environment for HOME */ + if (getuid() == pSecImpl->m_pPasswd.pw_uid) + { + sal_Char *pStr = NULL; +#ifdef SOLARIS + char buffer[8192]; + + struct passwd pwd; + struct passwd *ppwd; + +#ifdef _POSIX_PTHREAD_SEMANTICS + if ( 0 != getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &ppwd ) ) + ppwd = NULL; +#else + ppwd = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer) ); +#endif + + if ( ppwd ) + pStr = ppwd->pw_dir; +#else + pStr = getenv("HOME"); +#endif + + if ((pStr != NULL) && (strlen(pStr) > 0) && + (access(pStr, 0) == 0)) + strncpy(pszDirectory, pStr, nMax); + else + strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax); + } + else + strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax); + + return sal_True; +} + +sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory) +{ + sal_Bool bRet = sal_False; + sal_Char pszDirectory[PATH_MAX]; + + pszDirectory[0] = '\0'; + + bRet = osl_psz_getConfigDir(Security,pszDirectory,sizeof(pszDirectory)); + + if ( bRet == sal_True ) + { + rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + OSL_ASSERT(*pustrDirectory != NULL); + osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory ); + } + + return bRet; +} + +#ifndef MACOSX + +static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax) +{ + sal_Char *pStr = getenv("XDG_CONFIG_HOME"); + + if ((pStr == NULL) || (strlen(pStr) == 0) || + (access(pStr, 0) != 0)) + return (osl_psz_getHomeDir(Security, pszDirectory, nMax)); + + strncpy(pszDirectory, pStr, nMax); + return sal_True; +} + +#else + +/* + * FIXME: rewrite to use more flexible + * NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) + * as soon as we can bumb the baseline to Tiger (for NSApplicationSupportDirectory) and have + * support for Objective-C in the build environment + */ + +#define MACOSX_CONFIG_DIR "/Library/Application Support" +static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax) +{ + if( osl_psz_getHomeDir(Security, pszDirectory, nMax - sizeof(MACOSX_CONFIG_DIR) + 1) ) + { + strcat( pszDirectory, MACOSX_CONFIG_DIR ); + return sal_True; + } + + return sal_False; +} + +#endif + +sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security) +{ + oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security; + + if (pSecImpl == NULL) + return sal_False; + + if (pSecImpl->m_pPasswd.pw_uid != 0) + return (sal_False); + + return (sal_True); +} + +void SAL_CALL osl_freeSecurityHandle(oslSecurity Security) +{ + deleteSecurityImpl(Security); +} + + +sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security) +{ + (void) Security; /* unused */ + return sal_False; +} + +void SAL_CALL osl_unloadUserProfile(oslSecurity Security) +{ + (void) Security; /* unused */ +} |