LCOV - code coverage report
Current view: top level - sal/osl/unx - security.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 114 166 68.7 %
Date: 2014-11-03 Functions: 17 19 89.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <sal/config.h>
      21             : 
      22             : #include <cstddef>
      23             : #include <limits>
      24             : 
      25             : #ifdef IOS
      26             : #include <premac.h>
      27             : #import <Foundation/Foundation.h>
      28             : #include <postmac.h>
      29             : #endif
      30             : 
      31             : #include "system.h"
      32             : 
      33             : #include <osl/security.h>
      34             : #include <osl/diagnose.h>
      35             : #include <rtl/bootstrap.h>
      36             : #include <sal/log.hxx>
      37             : 
      38             : #include "osl/thread.h"
      39             : #include "osl/file.h"
      40             : 
      41             : #if defined LINUX || defined SOLARIS
      42             : #include <crypt.h>
      43             : #endif
      44             : 
      45             : #include "secimpl.h"
      46             : 
      47             : #ifdef ANDROID
      48             : #define getpwuid_r(uid, pwd, buf, buflen, result) (*(result) = getpwuid(uid), (*(result) ? (memcpy (buf, *(result), sizeof (struct passwd)), 0) : errno))
      49             : #endif
      50             : 
      51             : static oslSecurityError SAL_CALL
      52             : osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
      53             :                   oslSecurity* pSecurity);
      54             : static bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32  nMax);
      55             : static bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
      56             : static bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
      57             : 
      58        3429 : static bool sysconf_SC_GETPW_R_SIZE_MAX(std::size_t * value) {
      59             : #if defined _SC_GETPW_R_SIZE_MAX
      60             :     long m;
      61        3429 :     errno = 0;
      62        3429 :     m = sysconf(_SC_GETPW_R_SIZE_MAX);
      63        3429 :     if (m == -1) {
      64             :         /* _SC_GETPW_R_SIZE_MAX has no limit; some platforms like certain
      65             :            FreeBSD versions support sysconf(_SC_GETPW_R_SIZE_MAX) in a broken
      66             :            way and always set EINVAL, so be resilient here: */
      67           0 :         return false;
      68             :     } else {
      69             :         SAL_WARN_IF( m < 0 || (unsigned long) m >= std::numeric_limits<std::size_t>::max(), "sal.osl", 
      70             :                 "m < 0 || (unsigned long) m >= std::numeric_limits<std::size_t>::max()");
      71        3429 :         *value = (std::size_t) m;
      72        3429 :         return true;
      73             :     }
      74             : #else
      75             :     /* some platforms like Mac OS X 1.3 do not define _SC_GETPW_R_SIZE_MAX: */
      76             :     return false;
      77             : #endif
      78             : }
      79             : 
      80        3429 : static oslSecurityImpl * growSecurityImpl(
      81             :     oslSecurityImpl * impl, std::size_t * bufSize)
      82             : {
      83        3429 :     std::size_t n = 0;
      84        3429 :     oslSecurityImpl * p = NULL;
      85        3429 :     if (impl == NULL) {
      86        3429 :         if (!sysconf_SC_GETPW_R_SIZE_MAX(&n)) {
      87             :             /* choose something sensible (the callers of growSecurityImpl will
      88             :                detect it if the allocated buffer is too small: */
      89           0 :             n = 1024;
      90             :         }
      91           0 :     } else if (*bufSize <= std::numeric_limits<std::size_t>::max() / 2) {
      92           0 :         n = 2 * *bufSize;
      93             :     }
      94        3429 :     if (n != 0) {
      95        6858 :         if (n <= std::numeric_limits<std::size_t>::max()
      96        3429 :             - offsetof(oslSecurityImpl, m_buffer))
      97             :         {
      98        3429 :             *bufSize = n;
      99        3429 :             n += offsetof(oslSecurityImpl, m_buffer);
     100             :         } else {
     101           0 :             *bufSize = std::numeric_limits<std::size_t>::max()
     102           0 :                 - offsetof(oslSecurityImpl, m_buffer);
     103           0 :             n = std::numeric_limits<std::size_t>::max();
     104             :         }
     105        3429 :         p = static_cast<oslSecurityImpl *>(realloc(impl, n));
     106        3429 :         memset (p, 0, n);
     107             :     }
     108        3429 :     if (p == NULL) {
     109           0 :         free(impl);
     110             :     }
     111        3429 :     return p;
     112             : }
     113             : 
     114        3429 : static void deleteSecurityImpl(oslSecurityImpl * impl) {
     115        3429 :     free(impl);
     116        3429 : }
     117             : 
     118        3429 : oslSecurity SAL_CALL osl_getCurrentSecurity()
     119             : {
     120        3429 :     std::size_t n = 0;
     121        3429 :     oslSecurityImpl * p = NULL;
     122             :     for (;;) {
     123             :         struct passwd * found;
     124        3429 :         p = growSecurityImpl(p, &n);
     125        3429 :         if (p == NULL) {
     126        3429 :             return NULL;
     127             :         }
     128        3429 :         switch (getpwuid_r(getuid(), &p->m_pPasswd, p->m_buffer, n, &found)) {
     129             :         case ERANGE:
     130           0 :             break;
     131             :         case 0:
     132        3429 :             if (found != NULL) {
     133        3429 :                 return p;
     134             :             }
     135             :             /* fall through */
     136             :         default:
     137           0 :             deleteSecurityImpl(p);
     138           0 :             return NULL;
     139             :         }
     140           0 :     }
     141             : }
     142             : 
     143           0 : oslSecurityError SAL_CALL osl_loginUser(
     144             :     rtl_uString *ustrUserName,
     145             :     rtl_uString *ustrPassword,
     146             :     oslSecurity *pSecurity
     147             :     )
     148             : {
     149             :     oslSecurityError Error;
     150           0 :     rtl_String* strUserName=0;
     151           0 :     rtl_String* strPassword=0;
     152           0 :     sal_Char* pszUserName=0;
     153           0 :     sal_Char* pszPassword=0;
     154             : 
     155           0 :     if ( ustrUserName != 0 )
     156             :     {
     157             :         rtl_uString2String( &strUserName,
     158           0 :                             rtl_uString_getStr(ustrUserName),
     159             :                             rtl_uString_getLength(ustrUserName),
     160             :                             RTL_TEXTENCODING_UTF8,
     161           0 :                             OUSTRING_TO_OSTRING_CVTFLAGS );
     162           0 :         pszUserName = rtl_string_getStr(strUserName);
     163             :     }
     164             : 
     165           0 :     if ( ustrPassword != 0 )
     166             :     {
     167             :         rtl_uString2String( &strPassword,
     168           0 :                             rtl_uString_getStr(ustrPassword),
     169             :                             rtl_uString_getLength(ustrPassword),
     170             :                             RTL_TEXTENCODING_UTF8,
     171           0 :                             OUSTRING_TO_OSTRING_CVTFLAGS );
     172           0 :         pszPassword = rtl_string_getStr(strPassword);
     173             :     }
     174             : 
     175           0 :     Error=osl_psz_loginUser(pszUserName,pszPassword,pSecurity);
     176             : 
     177           0 :     if ( strUserName != 0 )
     178             :     {
     179           0 :         rtl_string_release(strUserName);
     180             :     }
     181             : 
     182           0 :     if ( strPassword)
     183             :     {
     184           0 :         rtl_string_release(strPassword);
     185             :     }
     186             : 
     187           0 :     return Error;
     188             : }
     189             : 
     190             : static oslSecurityError SAL_CALL
     191           0 : osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
     192             :                oslSecurity* pSecurity)
     193             : {
     194             :     (void)pszUserName;
     195             :     (void)pszPasswd;
     196             :     (void)pSecurity;
     197             : 
     198           0 :     return osl_Security_E_None;
     199             : }
     200             : 
     201           2 : oslSecurityError SAL_CALL osl_loginUserOnFileServer(
     202             :     rtl_uString *strUserName,
     203             :     rtl_uString *strPasswd,
     204             :     rtl_uString *strFileServer,
     205             :     oslSecurity *pSecurity
     206             :     )
     207             : {
     208             :     (void) strUserName; /* unused */
     209             :     (void) strPasswd; /* unused */
     210             :     (void) strFileServer; /* unused */
     211             :     (void) pSecurity; /* unused */
     212           2 :     return osl_Security_E_UserUnknown;
     213             : }
     214             : 
     215           2 : sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **ustrIdent)
     216             : {
     217           2 :     bool     bRet = false;
     218             :     sal_Char pszIdent[1024];
     219             : 
     220           2 :     pszIdent[0] = '\0';
     221             : 
     222           2 :     bRet = osl_psz_getUserIdent(Security,pszIdent,sizeof(pszIdent));
     223             : 
     224           2 :     rtl_string2UString( ustrIdent, pszIdent, rtl_str_getLength( pszIdent ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
     225             :     SAL_WARN_IF(*ustrIdent == NULL, "sal.osl", "*ustrIdent == NULL");
     226             : 
     227           2 :     return bRet;
     228             : }
     229             : 
     230         482 : sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax)
     231             : {
     232             :     sal_Char  buffer[32];
     233             :     sal_Int32 nChr;
     234             : 
     235         482 :     oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
     236             : 
     237         482 :     if (pSecImpl == NULL)
     238           0 :         return sal_False;
     239             : 
     240         482 :     nChr = snprintf(buffer, sizeof(buffer), "%u", pSecImpl->m_pPasswd.pw_uid);
     241         964 :     if ( nChr < 0 || sal::static_int_cast<sal_uInt32>(nChr) >= sizeof(buffer)
     242         964 :          || sal::static_int_cast<sal_uInt32>(nChr) >= nMax )
     243           0 :         return sal_False; /* leave *pszIdent unmodified in case of failure */
     244             : 
     245         482 :     memcpy(pszIdent, buffer, nChr+1);
     246         482 :     return sal_True;
     247             : }
     248             : 
     249         558 : sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **ustrName)
     250             : {
     251         558 :     bool     bRet = false;
     252             :     sal_Char pszName[1024];
     253             : 
     254         558 :     pszName[0] = '\0';
     255             : 
     256         558 :     bRet = osl_psz_getUserName(Security,pszName,sizeof(pszName));
     257             : 
     258         558 :     rtl_string2UString( ustrName, pszName, rtl_str_getLength( pszName ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
     259             :     SAL_WARN_IF(*ustrName == NULL, "sal.osl", "ustrName == NULL");
     260             : 
     261         558 :     return bRet;
     262             : }
     263             : 
     264         558 : static bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32  nMax)
     265             : {
     266         558 :     oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
     267             : 
     268         558 :     if (pSecImpl == NULL || pSecImpl->m_pPasswd.pw_name == NULL)
     269           0 :         return false;
     270             : 
     271         558 :     strncpy(pszName, pSecImpl->m_pPasswd.pw_name, nMax);
     272             : 
     273         558 :     return true;
     274             : }
     275             : 
     276        2293 : sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
     277             : {
     278        2293 :     bool     bRet = false;
     279             :     sal_Char pszDirectory[PATH_MAX];
     280             : 
     281        2293 :     pszDirectory[0] = '\0';
     282             : 
     283        2293 :     bRet = osl_psz_getHomeDir(Security,pszDirectory,sizeof(pszDirectory));
     284             : 
     285        2293 :     if ( bRet )
     286             :     {
     287        2293 :         rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
     288             :         SAL_WARN_IF(*pustrDirectory == NULL, "sal.osl", "*pustrDirectory == NULL");
     289        2293 :         osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
     290             :     }
     291             : 
     292        2293 :     return bRet;
     293             : }
     294             : 
     295        2359 : static bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
     296             : {
     297        2359 :     oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
     298             : 
     299        2359 :     if (pSecImpl == NULL)
     300           0 :         return false;
     301             : 
     302             : #ifdef ANDROID
     303             : {
     304             :     sal_Bool bRet = sal_False;
     305             :     rtl_uString *pName = 0, *pValue = 0;
     306             : 
     307             :     rtl_uString_newFromAscii(&pName, "HOME");
     308             : 
     309             :     if (rtl_bootstrap_get(pName, &pValue, NULL))
     310             :     {
     311             :         rtl_String *pStrValue = 0;
     312             :         if (pValue && pValue->length > 0)
     313             :         {
     314             :             rtl_uString2String(&pStrValue, pValue->buffer,
     315             :                                pValue->length, RTL_TEXTENCODING_UTF8,
     316             :                                OUSTRING_TO_OSTRING_CVTFLAGS);
     317             :             if (pStrValue && pStrValue->length > 0)
     318             :             {
     319             :                 sal_Int32 nCopy = (sal_Int32)(nMax-1) < pStrValue->length ? (sal_Int32)(nMax-1) : pStrValue->length ;
     320             :                 strncpy (pszDirectory, pStrValue->buffer, nCopy);
     321             :                 pszDirectory[nCopy] = '\0';
     322             :                 bRet = (std::size_t)pStrValue->length < nMax;
     323             :             }
     324             :             rtl_string_release(pStrValue);
     325             :         }
     326             :         rtl_uString_release(pName);
     327             :     }
     328             :     if (bRet)
     329             :         return bRet;
     330             : }
     331             : #endif
     332             : 
     333             : #ifdef IOS
     334             :     {
     335             :         // Let's pretend the app-specific "Documents" directory is the home directory for now
     336             :         NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
     337             :         NSString *userDirectory = [paths objectAtIndex:0];
     338             :         if ([userDirectory length] < nMax)
     339             :         {
     340             :             strcpy(pszDirectory, [userDirectory UTF8String]);
     341             :             return sal_True;
     342             :         }
     343             :     }
     344             : #endif
     345             : 
     346             :     /* if current user, check also environment for HOME */
     347        2359 :     if (getuid() == pSecImpl->m_pPasswd.pw_uid)
     348             :     {
     349        2359 :         sal_Char *pStr = NULL;
     350             : #ifdef SOLARIS
     351             :         char    buffer[8192];
     352             : 
     353             :         struct passwd pwd;
     354             :         struct passwd *ppwd;
     355             : 
     356             : #ifdef _POSIX_PTHREAD_SEMANTICS
     357             :         if ( 0 != getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &ppwd ) )
     358             :             ppwd = NULL;
     359             : #else
     360             :         ppwd = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer) );
     361             : #endif
     362             : 
     363             :         if ( ppwd )
     364             :             pStr = ppwd->pw_dir;
     365             : #else
     366        2359 :         pStr = getenv("HOME");
     367             : #endif
     368             : 
     369        2359 :         if (pStr != NULL && strlen(pStr) > 0 && access(pStr, 0) == 0)
     370        2359 :             strncpy(pszDirectory, pStr, nMax);
     371           0 :         else if (pSecImpl->m_pPasswd.pw_dir != NULL)
     372           0 :             strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
     373             :         else
     374           0 :             return false;
     375             :     }
     376           0 :     else if (pSecImpl->m_pPasswd.pw_dir != NULL)
     377           0 :         strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
     378             :     else
     379           0 :         return false;
     380             : 
     381        2359 :     return true;
     382             : }
     383             : 
     384          66 : sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
     385             : {
     386          66 :     bool     bRet = false;
     387             :     sal_Char pszDirectory[PATH_MAX];
     388             : 
     389          66 :     pszDirectory[0] = '\0';
     390             : 
     391          66 :     bRet = osl_psz_getConfigDir(Security,pszDirectory,sizeof(pszDirectory));
     392             : 
     393          66 :     if ( bRet )
     394             :     {
     395          66 :         rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
     396             :         SAL_WARN_IF(*pustrDirectory == NULL, "sal.osl", "*pustrDirectory == NULL");
     397          66 :         osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
     398             :     }
     399             : 
     400          66 :     return bRet;
     401             : }
     402             : 
     403             : #if !defined(MACOSX) && !defined(IOS)
     404             : 
     405             : #define DOT_CONFIG "/.config"
     406             : 
     407          66 : static bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
     408             : {
     409          66 :     sal_Char *pStr = getenv("XDG_CONFIG_HOME");
     410             : 
     411          66 :     if (pStr == NULL || strlen(pStr) == 0 || access(pStr, 0) != 0)
     412             :     {
     413          66 :         std::size_t n = 0;
     414             : 
     415             :         // a default equal to $HOME/.config should be used.
     416          66 :         if (!osl_psz_getHomeDir(Security, pszDirectory, nMax))
     417           0 :             return false;
     418          66 :         n = strlen(pszDirectory);
     419          66 :         if (n + sizeof(DOT_CONFIG) < nMax)
     420             :         {
     421          66 :             strncpy(pszDirectory+n, DOT_CONFIG, sizeof(DOT_CONFIG));
     422             : 
     423             :             // try to create dir if not present
     424          66 :             bool dirOK = true;
     425          66 :             if (mkdir(pszDirectory, S_IRWXU) != 0)
     426             :             {
     427          66 :                 int e = errno;
     428          66 :                 if (e != EEXIST)
     429             :                 {
     430             :                     SAL_WARN(
     431             :                         "sal.osl",
     432             :                         "mkdir(" << pszDirectory << "): errno=" << e);
     433           0 :                     dirOK = false;
     434             :                 }
     435             :             }
     436          66 :             if (dirOK)
     437             :             {
     438             :                 // check file type and permissions
     439             :                 struct stat st;
     440          66 :                 if (stat(pszDirectory, &st) != 0)
     441             :                 {
     442             :                     SAL_INFO("sal.osl","Could not stat $HOME/.config");
     443           0 :                     dirOK = false;
     444             :                 }
     445             :                 else
     446             :                 {
     447          66 :                     if (!S_ISDIR(st.st_mode))
     448             :                     {
     449             :                         SAL_INFO("sal.osl", "$HOME/.config is not a directory");
     450           0 :                         dirOK = false;
     451             :                     }
     452          66 :                     if (!(st.st_mode & S_IRUSR && st.st_mode & S_IWUSR && st.st_mode & S_IXUSR))
     453             :                     {
     454             :                         SAL_INFO("sal.osl", "$HOME/.config has bad permissions");
     455           0 :                         dirOK = false;
     456             :                     }
     457             :                 }
     458             :             }
     459             : 
     460             :             // resort to HOME
     461          66 :             if (!dirOK)
     462           0 :                 pszDirectory[n] = '\0';
     463             :         }
     464             :     }
     465             :     else
     466           0 :         strncpy(pszDirectory, pStr, nMax);
     467             : 
     468          66 :     return true;
     469             : }
     470             : 
     471             : #undef DOT_CONFIG
     472             : 
     473             : #else
     474             : 
     475             : /*
     476             :  * FIXME: rewrite to use more flexible
     477             :  * NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)
     478             :  * as soon as we can bumb the baseline to Tiger (for NSApplicationSupportDirectory) and have
     479             :  * support for Objective-C in the build environment
     480             :  */
     481             : 
     482             : #define MACOSX_CONFIG_DIR "/Library/Application Support" /* Used on iOS, too */
     483             : static bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
     484             : {
     485             :     if( osl_psz_getHomeDir(Security, pszDirectory, nMax - sizeof(MACOSX_CONFIG_DIR) + 1) )
     486             :     {
     487             :         strcat( pszDirectory, MACOSX_CONFIG_DIR );
     488             :         return true;
     489             :     }
     490             : 
     491             :     return false;
     492             : }
     493             : 
     494             : #endif
     495             : 
     496           6 : sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
     497             : {
     498           6 :     oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
     499             : 
     500           6 :     if (pSecImpl == NULL)
     501           0 :         return sal_False;
     502             : 
     503           6 :     if (pSecImpl->m_pPasswd.pw_uid != 0)
     504           0 :         return sal_False;
     505             : 
     506           6 :     return sal_True;
     507             : }
     508             : 
     509        3429 : void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
     510             : {
     511        3429 :     deleteSecurityImpl(static_cast<oslSecurityImpl *>(Security));
     512        3429 : }
     513             : 
     514           2 : sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
     515             : {
     516             :     (void) Security; /* unused */
     517           2 :     return sal_False;
     518             : }
     519             : 
     520           2 : void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
     521             : {
     522             :     (void) Security; /* unused */
     523           2 : }
     524             : 
     525             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10