1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
27 #import <Foundation/Foundation.h>
33 #include <osl/security.h>
34 #include <rtl/bootstrap.h>
35 #include <sal/log.hxx>
37 #include <osl/thread.h>
40 #if defined LINUX || defined __sun
46 #include <FindDirectory.h>
49 #include "secimpl.hxx"
52 #define getpwuid_r(uid, pwd, buf, buflen, result) (*(result) = getpwuid(uid), (*(result) ? (memcpy (buf, *(result), sizeof (struct passwd)), 0) : errno))
55 static bool osl_psz_getUserName(oslSecurity Security
, sal_Char
* pszName
, sal_uInt32 nMax
);
56 static bool osl_psz_getHomeDir(oslSecurity Security
, sal_Char
* pszDirectory
, sal_uInt32 nMax
);
57 static bool osl_psz_getConfigDir(oslSecurity Security
, sal_Char
* pszDirectory
, sal_uInt32 nMax
);
59 static bool sysconf_SC_GETPW_R_SIZE_MAX(std::size_t * value
) {
60 #if defined _SC_GETPW_R_SIZE_MAX
63 m
= sysconf(_SC_GETPW_R_SIZE_MAX
);
65 /* _SC_GETPW_R_SIZE_MAX has no limit; some platforms like certain
66 FreeBSD versions support sysconf(_SC_GETPW_R_SIZE_MAX) in a broken
67 way and always set EINVAL, so be resilient here: */
70 SAL_WARN_IF( m
< 0 || static_cast<unsigned long>(m
) >= std::numeric_limits
<std::size_t>::max(), "sal.osl",
71 "m < 0 || (unsigned long) m >= std::numeric_limits<std::size_t>::max()");
72 *value
= static_cast<std::size_t>(m
);
75 /* some platforms like Mac OS X 1.3 do not define _SC_GETPW_R_SIZE_MAX: */
80 static oslSecurityImpl
* growSecurityImpl(
81 oslSecurityImpl
* impl
, std::size_t * bufSize
)
84 oslSecurityImpl
* p
= nullptr;
85 if (impl
== nullptr) {
86 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: */
91 } else if (*bufSize
<= std::numeric_limits
<std::size_t>::max() / 2) {
95 if (n
<= std::numeric_limits
<std::size_t>::max()
96 - offsetof(oslSecurityImpl
, m_buffer
))
99 n
+= offsetof(oslSecurityImpl
, m_buffer
);
101 *bufSize
= std::numeric_limits
<std::size_t>::max()
102 - offsetof(oslSecurityImpl
, m_buffer
);
103 n
= std::numeric_limits
<std::size_t>::max();
105 p
= static_cast<oslSecurityImpl
*>(realloc(impl
, n
));
114 static void deleteSecurityImpl(oslSecurityImpl
* impl
) {
118 oslSecurity SAL_CALL
osl_getCurrentSecurity()
121 oslSecurityImpl
* p
= nullptr;
123 struct passwd
* found
;
124 p
= growSecurityImpl(p
, &n
);
128 #if defined(IOS) && defined(X86_64)
129 // getpwuid_r() does not work in the iOS simulator
131 char * buffer
= p
->m_buffer
;
133 strcpy(buffer
, "mobile");
134 p
->m_pPasswd
.pw_name
= buffer
;
135 buffer
+= strlen(buffer
) + 1;
137 p
->m_pPasswd
.pw_passwd
= buffer
;
138 buffer
+= strlen(buffer
) + 1;
139 p
->m_pPasswd
.pw_uid
= geteuid();
140 p
->m_pPasswd
.pw_gid
= getegid();
141 p
->m_pPasswd
.pw_change
= 0;
143 p
->m_pPasswd
.pw_class
= buffer
;
144 buffer
+= strlen(buffer
) + 1;
145 strcpy(buffer
, "Mobile User");
146 p
->m_pPasswd
.pw_gecos
= buffer
;
147 buffer
+= strlen(buffer
) + 1;
148 strcpy(buffer
, "/var/mobile"); // ???
149 p
->m_pPasswd
.pw_dir
= buffer
;
150 buffer
+= strlen(buffer
) + 1;
152 p
->m_pPasswd
.pw_shell
= buffer
;
153 buffer
+= strlen(buffer
) + 1;
154 p
->m_pPasswd
.pw_expire
= 0;
157 switch (getpwuid_r(getuid(), &p
->m_pPasswd
, p
->m_buffer
, n
, &found
)) {
161 if (found
!= nullptr) {
166 deleteSecurityImpl(p
);
173 oslSecurityError SAL_CALL
osl_loginUser(
174 SAL_UNUSED_PARAMETER rtl_uString
*,
175 SAL_UNUSED_PARAMETER rtl_uString
*,
176 SAL_UNUSED_PARAMETER oslSecurity
*
179 return osl_Security_E_None
;
182 oslSecurityError SAL_CALL
osl_loginUserOnFileServer(
183 SAL_UNUSED_PARAMETER rtl_uString
*,
184 SAL_UNUSED_PARAMETER rtl_uString
*,
185 SAL_UNUSED_PARAMETER rtl_uString
*,
186 SAL_UNUSED_PARAMETER oslSecurity
*
189 return osl_Security_E_UserUnknown
;
192 sal_Bool SAL_CALL
osl_getUserIdent(oslSecurity Security
, rtl_uString
**ustrIdent
)
195 sal_Char pszIdent
[1024];
199 bRet
= osl_psz_getUserIdent(Security
,pszIdent
,sizeof(pszIdent
));
201 rtl_string2UString( ustrIdent
, pszIdent
, rtl_str_getLength( pszIdent
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
202 SAL_WARN_IF(*ustrIdent
== nullptr, "sal.osl", "*ustrIdent == NULL");
207 bool osl_psz_getUserIdent(oslSecurity Security
, sal_Char
*pszIdent
, sal_uInt32 nMax
)
212 oslSecurityImpl
*pSecImpl
= static_cast<oslSecurityImpl
*>(Security
);
214 if (pSecImpl
== nullptr)
217 nChr
= snprintf(buffer
, sizeof(buffer
), "%u", pSecImpl
->m_pPasswd
.pw_uid
);
218 if ( nChr
< 0 || sal::static_int_cast
<sal_uInt32
>(nChr
) >= sizeof(buffer
)
219 || sal::static_int_cast
<sal_uInt32
>(nChr
) >= nMax
)
220 return false; /* leave *pszIdent unmodified in case of failure */
222 memcpy(pszIdent
, buffer
, nChr
+1);
226 sal_Bool SAL_CALL
osl_getUserName(oslSecurity Security
, rtl_uString
**ustrName
)
229 sal_Char pszName
[1024];
233 bRet
= osl_psz_getUserName(Security
,pszName
,sizeof(pszName
));
235 rtl_string2UString( ustrName
, pszName
, rtl_str_getLength( pszName
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
236 SAL_WARN_IF(*ustrName
== nullptr, "sal.osl", "ustrName == NULL");
241 sal_Bool SAL_CALL
osl_getShortUserName(oslSecurity Security
, rtl_uString
**ustrName
)
243 return osl_getUserName(Security
, ustrName
); // No domain name on unix
246 static bool osl_psz_getUserName(oslSecurity Security
, sal_Char
* pszName
, sal_uInt32 nMax
)
248 oslSecurityImpl
*pSecImpl
= static_cast<oslSecurityImpl
*>(Security
);
250 if (pSecImpl
== nullptr || pSecImpl
->m_pPasswd
.pw_name
== nullptr)
253 strncpy(pszName
, pSecImpl
->m_pPasswd
.pw_name
, nMax
);
258 sal_Bool SAL_CALL
osl_getHomeDir(oslSecurity Security
, rtl_uString
**pustrDirectory
)
261 sal_Char pszDirectory
[PATH_MAX
];
263 pszDirectory
[0] = '\0';
265 bRet
= osl_psz_getHomeDir(Security
,pszDirectory
,sizeof(pszDirectory
));
269 rtl_string2UString( pustrDirectory
, pszDirectory
, rtl_str_getLength( pszDirectory
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
270 SAL_WARN_IF(*pustrDirectory
== nullptr, "sal.osl", "*pustrDirectory == NULL");
271 osl_getFileURLFromSystemPath( *pustrDirectory
, pustrDirectory
);
277 static bool osl_psz_getHomeDir(oslSecurity Security
, sal_Char
* pszDirectory
, sal_uInt32 nMax
)
279 oslSecurityImpl
*pSecImpl
= static_cast<oslSecurityImpl
*>(Security
);
281 if (pSecImpl
== nullptr)
285 dev_t volume
= dev_for_path("/boot");
286 sal_Char homeDir
[B_PATH_NAME_LENGTH
+ B_FILE_NAME_LENGTH
];
287 status_t result
= find_directory(B_USER_DIRECTORY
, volume
, false, homeDir
,
289 if (result
== B_OK
&& strlen(homeDir
) < nMax
) {
290 strcpy(pszDirectory
, homeDir
);
298 sal_Bool bRet
= sal_False
;
299 rtl_uString
*pName
= 0, *pValue
= 0;
301 rtl_uString_newFromAscii(&pName
, "HOME");
303 if (rtl_bootstrap_get(pName
, &pValue
, NULL
))
305 rtl_String
*pStrValue
= 0;
306 if (pValue
&& pValue
->length
> 0)
308 rtl_uString2String(&pStrValue
, pValue
->buffer
,
309 pValue
->length
, RTL_TEXTENCODING_UTF8
,
310 OUSTRING_TO_OSTRING_CVTFLAGS
);
311 if (pStrValue
&& pStrValue
->length
> 0)
313 sal_Int32 nCopy
= (sal_Int32
)std::min
<sal_uInt32
>(nMax
-1, pStrValue
->length
) ;
314 strncpy (pszDirectory
, pStrValue
->buffer
, nCopy
);
315 pszDirectory
[nCopy
] = '\0';
316 bRet
= (std::size_t)pStrValue
->length
< nMax
;
318 rtl_string_release(pStrValue
);
320 rtl_uString_release(pName
);
329 // Let's pretend the app-specific "Documents" directory is the home directory for now
330 NSArray
*paths
= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory
, NSUserDomainMask
, YES
);
331 NSString
*userDirectory
= [paths objectAtIndex
:0];
332 if ([userDirectory length
] < nMax
)
334 strcpy(pszDirectory
, [userDirectory UTF8String
]);
340 /* if current user, check also environment for HOME */
341 if (getuid() == pSecImpl
->m_pPasswd
.pw_uid
)
343 sal_Char
*pStr
= nullptr;
350 #ifdef _POSIX_PTHREAD_SEMANTICS
351 if ( 0 != getpwuid_r(getuid(), &pwd
, buffer
, sizeof(buffer
), &ppwd
) )
354 ppwd
= getpwuid_r(getuid(), &pwd
, buffer
, sizeof(buffer
) );
360 pStr
= getenv("HOME");
363 if (pStr
!= nullptr && strlen(pStr
) > 0 && access(pStr
, 0) == 0)
364 strncpy(pszDirectory
, pStr
, nMax
);
365 else if (pSecImpl
->m_pPasswd
.pw_dir
!= nullptr)
366 strncpy(pszDirectory
, pSecImpl
->m_pPasswd
.pw_dir
, nMax
);
370 else if (pSecImpl
->m_pPasswd
.pw_dir
!= nullptr)
371 strncpy(pszDirectory
, pSecImpl
->m_pPasswd
.pw_dir
, nMax
);
378 sal_Bool SAL_CALL
osl_getConfigDir(oslSecurity Security
, rtl_uString
**pustrDirectory
)
381 sal_Char pszDirectory
[PATH_MAX
];
383 pszDirectory
[0] = '\0';
385 bRet
= osl_psz_getConfigDir(Security
,pszDirectory
,sizeof(pszDirectory
));
389 rtl_string2UString( pustrDirectory
, pszDirectory
, rtl_str_getLength( pszDirectory
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
390 SAL_WARN_IF(*pustrDirectory
== nullptr, "sal.osl", "*pustrDirectory == NULL");
391 osl_getFileURLFromSystemPath( *pustrDirectory
, pustrDirectory
);
399 static bool osl_psz_getConfigDir(oslSecurity Security
, sal_Char
* pszDirectory
, sal_uInt32 nMax
)
402 dev_t volume
= dev_for_path("/boot");
403 sal_Char configDir
[B_PATH_NAME_LENGTH
+ B_FILE_NAME_LENGTH
];
404 status_t result
= find_directory(B_USER_SETTINGS_DIRECTORY
, volume
, false,
405 configDir
, sizeof(configDir
));
406 if (result
== B_OK
&& strlen(configDir
) < nMax
) {
407 strcpy(pszDirectory
, configDir
);
413 #elif !defined(MACOSX) && !defined(IOS)
415 #define DOT_CONFIG "/.config"
417 static bool osl_psz_getConfigDir(oslSecurity Security
, sal_Char
* pszDirectory
, sal_uInt32 nMax
)
419 sal_Char
*pStr
= getenv("XDG_CONFIG_HOME");
421 if (pStr
== nullptr || strlen(pStr
) == 0 || access(pStr
, 0) != 0)
425 // a default equal to $HOME/.config should be used.
426 if (!osl_psz_getHomeDir(Security
, pszDirectory
, nMax
))
428 n
= strlen(pszDirectory
);
429 if (n
+ sizeof(DOT_CONFIG
) < nMax
)
431 strcpy(pszDirectory
+n
, DOT_CONFIG
); // safe
433 // try to create dir if not present
435 if (mkdir(pszDirectory
, S_IRWXU
) != 0)
442 "mkdir(" << pszDirectory
<< "): errno=" << e
);
448 // check file type and permissions
450 if (stat(pszDirectory
, &st
) != 0)
452 SAL_INFO("sal.osl","Could not stat $HOME/.config");
457 if (!S_ISDIR(st
.st_mode
))
459 SAL_INFO("sal.osl", "$HOME/.config is not a directory");
462 if (!(st
.st_mode
& S_IRUSR
&& st
.st_mode
& S_IWUSR
&& st
.st_mode
& S_IXUSR
))
464 SAL_INFO("sal.osl", "$HOME/.config has bad permissions");
472 pszDirectory
[n
] = '\0';
476 strncpy(pszDirectory
, pStr
, nMax
);
486 * FIXME: rewrite to use more flexible
487 * NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)
488 * as soon as we can bump the baseline to Tiger (for NSApplicationSupportDirectory) and have
489 * support for Objective-C in the build environment
492 #define MACOSX_CONFIG_DIR "/Library/Application Support" /* Used on iOS, too */
493 static bool osl_psz_getConfigDir(oslSecurity Security
, sal_Char
* pszDirectory
, sal_uInt32 nMax
)
495 if( osl_psz_getHomeDir(Security
, pszDirectory
, nMax
- sizeof(MACOSX_CONFIG_DIR
) + 1) )
497 strcat( pszDirectory
, MACOSX_CONFIG_DIR
);
506 sal_Bool SAL_CALL
osl_isAdministrator(oslSecurity Security
)
508 oslSecurityImpl
*pSecImpl
= static_cast<oslSecurityImpl
*>(Security
);
510 if (pSecImpl
== nullptr)
513 if (pSecImpl
->m_pPasswd
.pw_uid
!= 0)
519 void SAL_CALL
osl_freeSecurityHandle(oslSecurity Security
)
521 deleteSecurityImpl(static_cast<oslSecurityImpl
*>(Security
));
524 sal_Bool SAL_CALL
osl_loadUserProfile(SAL_UNUSED_PARAMETER oslSecurity
)
529 void SAL_CALL
osl_unloadUserProfile(SAL_UNUSED_PARAMETER oslSecurity
) {}
531 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */