xref: /trunk/main/sal/osl/unx/security.c (revision c938ccda3ac505248a9f1ba389738d0de385daba)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <stddef.h>
25 
26 /* Solaris 8 has no C99 stdint.h, and Solaris generally seems not to miss it for
27    SIZE_MAX: */
28 #if !defined __SUNPRO_C
29 #include <stdint.h>
30 #endif
31 
32 #include "system.h"
33 
34 #include <osl/security.h>
35 #include <osl/diagnose.h>
36 
37 #include "osl/thread.h"
38 #include "osl/file.h"
39 
40 #if defined LINUX || defined SOLARIS
41 #include <crypt.h>
42 #endif
43 
44 #include "secimpl.h"
45 
46 #ifndef NOPAM
47 #ifndef PAM_BINARY_MSG
48 #define PAM_BINARY_MSG 6
49 #endif
50 #endif
51 
52 static oslSecurityError SAL_CALL
53 osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd, oslSecurity* pSecurity);
54 sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax);
55 static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax);
56 static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
57 static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
58 
59 static sal_Bool sysconf_SC_GETPW_R_SIZE_MAX(size_t * value) {
60 #if defined _SC_GETPW_R_SIZE_MAX
61     long m;
62     errno = 0;
63     m = sysconf(_SC_GETPW_R_SIZE_MAX);
64     if (m == -1) {
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: */
68         return sal_False;
69     } else {
70         OSL_ASSERT(m >= 0 && (unsigned long) m < SIZE_MAX);
71         *value = (size_t) m;
72         return sal_True;
73     }
74 #else
75     /* some platforms like Mac OS X 1.3 do not define _SC_GETPW_R_SIZE_MAX: */
76     return sal_False;
77 #endif
78 }
79 
80 static oslSecurityImpl * growSecurityImpl(
81     oslSecurityImpl * impl, size_t * bufSize)
82 {
83     size_t n = 0;
84     oslSecurityImpl * p = NULL;
85     if (impl == NULL) {
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: */
89             n = 1024;
90         }
91     } else if (*bufSize <= SIZE_MAX / 2) {
92         n = 2 * *bufSize;
93     }
94     if (n != 0) {
95         if (n <= SIZE_MAX - offsetof(oslSecurityImpl, m_buffer)) {
96             *bufSize = n;
97             n += offsetof(oslSecurityImpl, m_buffer);
98         } else {
99             *bufSize = SIZE_MAX - offsetof(oslSecurityImpl, m_buffer);
100             n = SIZE_MAX;
101         }
102         p = realloc(impl, n);
103     }
104     if (p == NULL) {
105         free(impl);
106     }
107     return p;
108 }
109 
110 static void deleteSecurityImpl(oslSecurityImpl * impl) {
111     free(impl);
112 }
113 
114 oslSecurity SAL_CALL osl_getCurrentSecurity()
115 {
116     size_t n = 0;
117     oslSecurityImpl * p = NULL;
118     for (;;) {
119         struct passwd * found;
120         p = growSecurityImpl(p, &n);
121         if (p == NULL) {
122             return NULL;
123         }
124         switch (getpwuid_r(getuid(), &p->m_pPasswd, p->m_buffer, n, &found)) {
125         case ERANGE:
126             break;
127         case 0:
128             if (found != NULL) {
129                 return p;
130             }
131             /* fall through */
132         default:
133             deleteSecurityImpl(p);
134             return NULL;
135         }
136     }
137 }
138 
139 
140 #if defined LINUX && !defined NOPAM
141 
142 /*
143  *
144  * osl Routines for Pluggable Authentication Modules (PAM)
145  * tested with Linux-PAM 0.66 on Redhat-6.0 and
146  * Linux-PAM 0.64 on RedHat-5.2,
147  * XXX Will probably not run on PAM 0.59 or prior, since
148  * number of pam_response* responses has changed
149  *
150  */
151 
152 #include <security/pam_appl.h>
153 
154 typedef struct {
155     char* name;
156     char* password;
157 } sal_PamData;
158 
159 typedef struct {
160     int (*pam_start)(const char *service_name, const char *user,
161                      const struct pam_conv *pam_conversation,
162                      pam_handle_t **pamh);
163     int (*pam_end)          (pam_handle_t *pamh, int pam_status);
164     int (*pam_authenticate) (pam_handle_t *pamh, int flags);
165     int (*pam_acct_mgmt)    (pam_handle_t *pamh, int flags);
166 } sal_PamModule;
167 
168 /*
169  * Implement a pam-conversation callback-routine,
170  * it just supply name and password instead of prompting the user.
171  * I guess that echo-off means 'ask for password' and echo-on means
172  * 'ask for user-name'. In fact I've never been asked anything else
173  * than the password
174  * XXX Please notice that if a pam-module does ask anything else, we
175  *     are completely lost, and a pam-module is free to do so
176  * XXX
177  */
178 
179 static int
180 osl_PamConversation (int num_msg, const struct pam_message **msgm,
181                      struct pam_response **response, void *appdata_ptr)
182 {
183     int         i;
184     sal_Bool    error;
185     sal_PamData         *pam_data;
186     struct pam_response *p_reply;
187 
188     /* resource initialization */
189     pam_data = (sal_PamData*) appdata_ptr;
190     p_reply  = (struct pam_response *) calloc( num_msg,
191                                                sizeof(struct pam_response));
192     if ( p_reply == NULL || pam_data == NULL )
193     {
194         if ( p_reply != NULL )
195             free ( p_reply );
196         *response = NULL;
197         return PAM_CONV_ERR;
198     }
199 
200     /* pseudo dialog */
201     error = sal_False;
202     for ( i = 0; i < num_msg ; i++ )
203     {
204         switch ( msgm[ i ]->msg_style )
205         {
206             case PAM_PROMPT_ECHO_OFF:
207                 p_reply[ i ].resp_retcode   = 0;
208                 p_reply[ i ].resp           = strdup( pam_data->password );
209                 break;
210             case PAM_PROMPT_ECHO_ON:
211                 p_reply[ i ].resp_retcode   = 0;
212                 p_reply[ i ].resp           = strdup( pam_data->name );
213                 break;
214             case PAM_ERROR_MSG:
215             case PAM_TEXT_INFO:
216             case PAM_BINARY_PROMPT:
217             case PAM_BINARY_MSG:
218                 p_reply[ i ].resp_retcode   = 0;
219                 p_reply[ i ].resp           = NULL;
220                 break;
221             default:
222                 error = sal_True;
223                 break;
224         }
225     }
226 
227     /* free resources on error */
228     if ( error )
229     {
230         for ( i = 0; i < num_msg ; i++ )
231             if ( p_reply[ i ].resp )
232             {
233                 memset ( p_reply[ i ].resp, 0,
234                          strlen( p_reply[ i ].resp ) );
235                 free   ( p_reply[ i ].resp );
236             }
237         free ( p_reply );
238 
239         *response = NULL;
240         return PAM_CONV_ERR;
241     }
242 
243     /* well done */
244     *response = p_reply;
245     return PAM_SUCCESS;
246 }
247 
248 #ifndef PAM_LINK
249 /*
250  * avoid linking against libpam.so, since it is not available on all systems,
251  * instead load-on-call, returns structure which holds pointer to
252  * pam-functions,
253  * library is never closed in case of success
254  */
255 
256 static sal_PamModule* osl_getPAM()
257 {
258     static sal_PamModule *pam_module = NULL;
259     static sal_Bool load_once = sal_False;
260 
261     if ( !load_once )
262     {
263         /* get library-handle. cannot use osl-module, since
264            RTLD_GLOBAL is required for PAM-0.64 RH 5.2
265            (but not for PAM-0.66 RH 6.0) */
266         void *pam_hdl;
267 
268         pam_hdl = dlopen( "libpam.so.0", RTLD_GLOBAL | RTLD_LAZY );
269 
270         if ( pam_hdl != NULL )
271             pam_module = (sal_PamModule*)calloc( 1, sizeof(sal_PamModule) );
272 
273         /* load functions */
274         if ( pam_module != NULL )
275         {
276             pam_module->pam_acct_mgmt = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_acct_mgmt" );
277             pam_module->pam_authenticate
278                                       = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_authenticate" );
279             pam_module->pam_end       = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_end" );
280             pam_module->pam_start     = (int (*)(const char *, const char *, const struct pam_conv *, pam_handle_t **)) dlsym ( pam_hdl, "pam_start" );
281 
282             /* free resources, if not completely successful */
283             if (   (pam_module->pam_start        == NULL)
284                 || (pam_module->pam_end          == NULL)
285                 || (pam_module->pam_authenticate == NULL)
286                 || (pam_module->pam_acct_mgmt    == NULL) )
287             {
288                 free( pam_module );
289                 pam_module = NULL;
290                 dlclose( pam_hdl );
291             }
292         }
293 
294         /* never try again */
295         load_once = sal_True;
296     }
297 
298     return pam_module;
299 }
300 #endif
301 
302 /*
303  * User Identification using PAM
304  */
305 
306 static sal_Bool
307 osl_PamAuthentification( const sal_Char* name, const sal_Char* password )
308 {
309     sal_Bool success = sal_False;
310 
311 #ifndef PAM_LINK
312     sal_PamModule* pam_module;
313 
314     pam_module = osl_getPAM();
315     if ( pam_module != NULL )
316     {
317 #endif
318         pam_handle_t   *pam_handle = NULL;
319         struct pam_conv pam_conversation;
320         sal_PamData     pam_data;
321 
322         int             return_value;
323 
324         pam_data.name    = (char*) name;
325         pam_data.password = (char*) password;
326 
327         pam_conversation.conv        = osl_PamConversation;
328         pam_conversation.appdata_ptr = (void*)(&pam_data);
329 
330 #ifndef PAM_LINK
331         return_value = pam_module->pam_start( "su", name,
332             &pam_conversation, &pam_handle);
333 #else
334         return_value = pam_start( "su", name,
335             &pam_conversation, &pam_handle);
336 #endif
337         if (return_value == PAM_SUCCESS )
338 #ifndef PAM_LINK
339             return_value = pam_module->pam_authenticate(pam_handle, 0);
340 #else
341             return_value = pam_authenticate(pam_handle, 0);
342 #endif
343         if (return_value == PAM_SUCCESS )
344 #ifndef PAM_LINK
345             return_value = pam_module->pam_acct_mgmt(pam_handle, 0);
346         pam_module->pam_end( pam_handle, return_value );
347 #else
348             return_value = pam_acct_mgmt(pam_handle, 0);
349         pam_end( pam_handle, return_value );
350 #endif
351 
352         success = (sal_Bool)(return_value == PAM_SUCCESS);
353 #ifndef PAM_LINK
354     }
355 #endif
356 
357     return success;
358 }
359 
360 
361 #ifndef CRYPT_LINK
362 /* dummy crypt, matches the interface of
363    crypt() but does not encrypt at all */
364 static const sal_Char* SAL_CALL
365 osl_noCrypt ( const sal_Char *key, const sal_Char *salt )
366 {
367     (void) salt; /* unused */
368     return key;
369 }
370 
371 /* load-on-call crypt library and crypt symbol */
372 static void* SAL_CALL
373 osl_getCrypt()
374 {
375     static char* (*crypt_sym)(const char*, const char*) = NULL;
376     static sal_Bool load_once = sal_False;
377 
378     if ( !load_once )
379     {
380         void * crypt_library;
381 
382         crypt_library = dlopen( "libcrypt.so.1", RTLD_GLOBAL | RTLD_LAZY ); /* never closed */
383         if ( crypt_library != NULL )
384             crypt_sym = (char* (*)(const char *, const char *)) dlsym(crypt_library, "crypt" );
385         if ( crypt_sym == NULL ) /* no libcrypt or libcrypt without crypt */
386             crypt_sym = (char* (*)(const char *, const char *)) &osl_noCrypt;
387 
388         load_once = sal_True;
389     }
390 
391     return (void*)crypt_sym;
392 }
393 
394 /* replacement for crypt function for password encryption, uses either
395    strong encryption of dlopen'ed libcrypt.so.1 or dummy implementation
396    with no encryption. Objective target is to avoid linking against
397    libcrypt (not available on caldera open linux 2.2 #63822#) */
398 static sal_Char* SAL_CALL
399 osl_dynamicCrypt ( const sal_Char *key, const sal_Char *salt )
400 {
401     char* (*dynamic_crypt)(char *, char *);
402 
403     dynamic_crypt = (char * (*)(char *, char *)) osl_getCrypt();
404 
405     return dynamic_crypt( (sal_Char*)key, (sal_Char*)salt );
406 }
407 #endif
408 
409 /*
410  * compare an encrypted and an unencrypted password for equality
411  * returns true if passwords are equal, false otherwise
412  * Note: uses crypt() and a mutex instead of crypt_r() since crypt_r needs
413  * more than 128KByte of external buffer for struct crypt_data
414  */
415 
416 static sal_Bool SAL_CALL
417 osl_equalPasswords ( const sal_Char *pEncryptedPassword, const sal_Char *pPlainPassword )
418 {
419     static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
420 
421     sal_Bool  success;
422     sal_Char  salt[3];
423     sal_Char *encrypted_plain;
424 
425     salt[0] = pEncryptedPassword[0];
426     salt[1] = pEncryptedPassword[1];
427     salt[2] = '\0';
428 
429     pthread_mutex_lock(&crypt_mutex);
430 
431 #ifndef CRYPT_LINK
432     encrypted_plain = (sal_Char *)osl_dynamicCrypt( pPlainPassword, salt );
433 #else
434     encrypted_plain = (sal_Char *)crypt( pPlainPassword, salt );
435 #endif
436     success = (sal_Bool) (strcmp(pEncryptedPassword, encrypted_plain) == 0);
437 
438     pthread_mutex_unlock(&crypt_mutex);
439 
440     return success;
441 }
442 
443 #endif /* defined LINUX && !defined NOPAM */
444 oslSecurityError SAL_CALL osl_loginUser(
445     rtl_uString *ustrUserName,
446     rtl_uString *ustrPassword,
447     oslSecurity *pSecurity
448     )
449 {
450     oslSecurityError Error;
451     rtl_String* strUserName=NULL;
452     rtl_String* strPassword=NULL;
453     sal_Char* pszUserName=NULL;
454     sal_Char* pszPassword=NULL;
455 
456     if ( ustrUserName != NULL )
457     {
458 
459         rtl_uString2String( &strUserName,
460                             rtl_uString_getStr(ustrUserName),
461                             rtl_uString_getLength(ustrUserName),
462                             RTL_TEXTENCODING_UTF8,
463                             OUSTRING_TO_OSTRING_CVTFLAGS );
464         pszUserName = rtl_string_getStr(strUserName);
465     }
466 
467 
468     if ( ustrPassword != NULL )
469     {
470         rtl_uString2String( &strPassword,
471                             rtl_uString_getStr(ustrPassword),
472                             rtl_uString_getLength(ustrPassword),
473                             RTL_TEXTENCODING_UTF8,
474                             OUSTRING_TO_OSTRING_CVTFLAGS );
475         pszPassword = rtl_string_getStr(strPassword);
476     }
477 
478 
479     Error=osl_psz_loginUser(pszUserName,pszPassword,pSecurity);
480 
481     if ( strUserName != NULL )
482     {
483         rtl_string_release(strUserName);
484     }
485 
486     if ( strPassword)
487     {
488         rtl_string_release(strPassword);
489     }
490 
491 
492     return Error;
493 }
494 
495 
496 static oslSecurityError SAL_CALL
497 osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
498                oslSecurity* pSecurity)
499 {
500 #if defined NETBSD || defined SCO || defined AIX || defined FREEBSD || \
501     defined MACOSX
502 
503     return osl_Security_E_None;
504 
505 #else
506 
507     oslSecurityError nError = osl_Security_E_Unknown;
508     oslSecurityImpl * p = NULL;
509     if (pszUserName != NULL && pszPasswd != NULL && pSecurity != NULL) {
510         /* get nis or normal password, should succeed for any known user, but
511            perhaps the password is wrong (i.e. 'x') if shadow passwords are in
512            use or authentication must be done by PAM */
513         size_t n = 0;
514         int err = 0;
515         struct passwd * found = NULL;
516         for (;;) {
517             p = growSecurityImpl(p, &n);
518             if (p == NULL) {
519                 break;
520             }
521             err = getpwnam_r(
522                 pszUserName, &p->m_pPasswd, p->m_buffer, n, &found);
523             if (err != ERANGE) {
524                 break;
525             }
526         }
527         if (p != NULL && err == 0) {
528             if (found == NULL) {
529                 nError = osl_Security_E_UserUnknown;
530             } else {
531 #if defined LINUX && !defined NOPAM
532                 /* only root is able to read the /etc/shadow passwd, a normal
533                    user even can't read his own encrypted passwd */
534                 if (osl_equalPasswords(p->m_pPasswd.pw_passwd, pszPasswd) ||
535                     osl_PamAuthentification(pszUserName, pszPasswd))
536                 {
537                     nError = osl_Security_E_None;
538                 } else {
539                     char buffer[1024];
540                     struct spwd result_buf;
541                     struct spwd * pShadowPasswd;
542                     buffer[0] = '\0';
543                     if (getspnam_r(
544                             pszUserName, &result_buf, buffer, sizeof buffer,
545                             &pShadowPasswd) == 0 &&
546                         pShadowPasswd != NULL)
547                     {
548                         nError =
549                             osl_equalPasswords(
550                                 pShadowPasswd->sp_pwdp, pszPasswd)
551                             ? osl_Security_E_None
552                             : osl_Security_E_WrongPassword;
553                     } else if (getuid() == 0) {
554                         /* mfe: Try to verify the root-password via nis */
555                         if (getspnam_r(
556                                 "root", &result_buf, buffer, sizeof buffer,
557                                 &pShadowPasswd) == 0 &&
558                             pShadowPasswd != NULL &&
559                             osl_equalPasswords(
560                                 pShadowPasswd->sp_pwdp, pszPasswd))
561                         {
562                             nError = osl_Security_E_None;
563                         } else {
564                             /* mfe: we can't get via nis (glibc2.0.x has bug in
565                                getspnam_r) we try it with the normal getspnam */
566                             static pthread_mutex_t pwmutex =
567                                 PTHREAD_MUTEX_INITIALIZER;
568                             pthread_mutex_lock(&pwmutex);
569                             pShadowPasswd = getspnam("root");
570                             pthread_mutex_unlock(&pwmutex);
571                             nError =
572                                 ((pShadowPasswd != NULL &&
573                                   osl_equalPasswords(
574                                       pShadowPasswd->sp_pwdp, pszPasswd)) ||
575                                  osl_PamAuthentification("root", pszPasswd))
576                                 ? osl_Security_E_None
577                                 : osl_Security_E_WrongPassword;
578                         }
579                     }
580                 }
581 #else
582                 char buffer[1024];
583                 struct spwd spwdStruct;
584                 buffer[0] = '\0';
585 #ifdef OLD_SHADOW_API
586                 if (getspnam_r(pszUserName, &spwdStruct, buffer, sizeof buffer) != NULL)
587 #else
588                 if (getspnam_r(pszUserName, &spwdStruct, buffer, sizeof buffer, NULL) == 0)
589 #endif
590                 {
591                     char salt[3];
592                     char * cryptPasswd;
593                     strncpy(salt, spwdStruct.sp_pwdp, 2);
594                     salt[2] = '\0';
595                     cryptPasswd = (char *) crypt(pszPasswd, salt);
596                     if (strcmp(spwdStruct.sp_pwdp, cryptPasswd) == 0) {
597                         nError = osl_Security_E_None;
598                     } else if (getuid() == 0 &&
599 #ifdef OLD_SHADOW_API
600                               (getspnam_r("root", &spwdStruct, buffer, sizeof buffer) != NULL))
601 #else
602                               (getspnam_r("root", &spwdStruct, buffer, sizeof buffer, NULL) == 0))
603 #endif
604                     {
605                         /* if current process is running as root, allow to logon
606                            as any other user */
607                         strncpy(salt, spwdStruct.sp_pwdp, 2);
608                         salt[2] = '\0';
609                         cryptPasswd = (char *) crypt(pszPasswd, salt);
610                         if (strcmp(spwdStruct.sp_pwdp, cryptPasswd) == 0) {
611                             nError = osl_Security_E_None;
612                         }
613                     } else {
614                         nError = osl_Security_E_WrongPassword;
615                     }
616                 }
617 #endif
618             }
619         }
620     }
621     if (nError == osl_Security_E_None) {
622         *pSecurity = p;
623     } else {
624         deleteSecurityImpl(p);
625         *pSecurity = NULL;
626     }
627     return nError;
628 
629 #endif
630 }
631 
632 oslSecurityError SAL_CALL osl_loginUserOnFileServer(
633     rtl_uString *strUserName,
634     rtl_uString *strPasswd,
635     rtl_uString *strFileServer,
636     oslSecurity *pSecurity
637     )
638 {
639     (void) strUserName; /* unused */
640     (void) strPasswd; /* unused */
641     (void) strFileServer; /* unused */
642     (void) pSecurity; /* unused */
643     return osl_Security_E_UserUnknown;
644 }
645 
646 
647 sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **ustrIdent)
648 {
649     sal_Bool bRet=sal_False;
650     sal_Char pszIdent[1024];
651 
652     pszIdent[0] = '\0';
653 
654     bRet = osl_psz_getUserIdent(Security,pszIdent,sizeof(pszIdent));
655 
656     rtl_string2UString( ustrIdent, pszIdent, rtl_str_getLength( pszIdent ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
657     OSL_ASSERT(*ustrIdent != NULL);
658 
659     return bRet;
660 }
661 
662 
663 sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax)
664 {
665     sal_Char  buffer[32];
666     sal_Int32 nChr;
667 
668     oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
669 
670     if (pSecImpl == NULL)
671         return sal_False;
672 
673     nChr = snprintf(buffer, sizeof(buffer), "%u", pSecImpl->m_pPasswd.pw_uid);
674     if ( nChr < 0 || SAL_INT_CAST(sal_uInt32, nChr) >= sizeof(buffer)
675          || SAL_INT_CAST(sal_uInt32, nChr) >= nMax )
676         return sal_False; /* leave *pszIdent unmodified in case of failure */
677 
678     memcpy(pszIdent, buffer, nChr+1);
679     return sal_True;
680 }
681 
682 sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **ustrName)
683 {
684     sal_Bool bRet=sal_False;
685     sal_Char pszName[1024];
686 
687     pszName[0] = '\0';
688 
689     bRet = osl_psz_getUserName(Security,pszName,sizeof(pszName));
690 
691     rtl_string2UString( ustrName, pszName, rtl_str_getLength( pszName ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
692     OSL_ASSERT(*ustrName != NULL);
693 
694     return bRet;
695 }
696 
697 
698 
699 static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax)
700 {
701     oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
702 
703     if (pSecImpl == NULL)
704         return sal_False;
705 
706     strncpy(pszName, pSecImpl->m_pPasswd.pw_name, nMax);
707 
708     return sal_True;
709 }
710 
711 sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
712 {
713     sal_Bool bRet=sal_False;
714     sal_Char pszDirectory[PATH_MAX];
715 
716     pszDirectory[0] = '\0';
717 
718     bRet = osl_psz_getHomeDir(Security,pszDirectory,sizeof(pszDirectory));
719 
720     if ( bRet == sal_True )
721     {
722         rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
723         OSL_ASSERT(*pustrDirectory != NULL);
724         osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
725     }
726 
727     return bRet;
728 }
729 
730 
731 static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
732 {
733     oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
734 
735     if (pSecImpl == NULL)
736         return sal_False;
737 
738     /* if current user, check also environment for HOME */
739     if (getuid() == pSecImpl->m_pPasswd.pw_uid)
740     {
741         sal_Char *pStr = NULL;
742 #ifdef SOLARIS
743         char buffer[8192];
744 
745         struct passwd pwd;
746         struct passwd *ppwd;
747 
748 #ifdef _POSIX_PTHREAD_SEMANTICS
749         if ( 0 != getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &ppwd ) )
750             ppwd = NULL;
751 #else
752         ppwd = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer) );
753 #endif
754 
755         if ( ppwd )
756             pStr = ppwd->pw_dir;
757 #else
758         pStr = getenv("HOME");
759 #endif
760 
761         if ((pStr != NULL) && (strlen(pStr) > 0) &&
762             (access(pStr, 0) == 0))
763             strncpy(pszDirectory, pStr, nMax);
764         else
765             strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
766     }
767     else
768         strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
769 
770     return sal_True;
771 }
772 
773 sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
774 {
775     sal_Bool bRet = sal_False;
776     sal_Char pszDirectory[PATH_MAX];
777 
778     pszDirectory[0] = '\0';
779 
780     bRet = osl_psz_getConfigDir(Security,pszDirectory,sizeof(pszDirectory));
781 
782     if ( bRet == sal_True )
783     {
784         rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
785         OSL_ASSERT(*pustrDirectory != NULL);
786         osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
787     }
788 
789     return bRet;
790 }
791 
792 #ifndef MACOSX
793 
794 static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
795 {
796     sal_Char *pStr = getenv("XDG_CONFIG_HOME");
797 
798     if ((pStr == NULL) || (strlen(pStr) == 0) ||
799         (access(pStr, 0) != 0))
800         return (osl_psz_getHomeDir(Security, pszDirectory, nMax));
801 
802     strncpy(pszDirectory, pStr, nMax);
803     return sal_True;
804 }
805 
806 #else
807 
808 /*
809  * FIXME: rewrite to use more flexible
810  * NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)
811  * as soon as we can bumb the baseline to Tiger (for NSApplicationSupportDirectory) and have
812  * support for Objective-C in the build environment
813  */
814 
815 #define MACOSX_CONFIG_DIR "/Library/Application Support"
816 static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
817 {
818     if( osl_psz_getHomeDir(Security, pszDirectory, nMax - sizeof(MACOSX_CONFIG_DIR) + 1) )
819     {
820         strcat( pszDirectory, MACOSX_CONFIG_DIR );
821         return sal_True;
822     }
823 
824     return sal_False;
825 }
826 
827 #endif
828 
829 sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
830 {
831     oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
832 
833     if (pSecImpl == NULL)
834         return sal_False;
835 
836     if (pSecImpl->m_pPasswd.pw_uid != 0)
837         return (sal_False);
838 
839     return (sal_True);
840 }
841 
842 void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
843 {
844     deleteSecurityImpl(Security);
845 }
846 
847 
848 sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
849 {
850     (void) Security; /* unused */
851     return sal_False;
852 }
853 
854 void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
855 {
856     (void) Security; /* unused */
857 }
858