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