xref: /trunk/main/sal/osl/unx/security.c (revision 57fdf169)
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 
sysconf_SC_GETPW_R_SIZE_MAX(size_t * value)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 
growSecurityImpl(oslSecurityImpl * impl,size_t * bufSize)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 
deleteSecurityImpl(oslSecurityImpl * impl)110 static void deleteSecurityImpl(oslSecurityImpl * impl) {
111 	free(impl);
112 }
113 
osl_getCurrentSecurity()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
osl_PamConversation(int num_msg,const struct pam_message ** msgm,struct pam_response ** response,void * appdata_ptr)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 
osl_getPAM()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
osl_PamAuthentification(const sal_Char * name,const sal_Char * password)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
osl_noCrypt(const sal_Char * key,const sal_Char * salt)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
osl_getCrypt()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
osl_dynamicCrypt(const sal_Char * key,const sal_Char * salt)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
osl_equalPasswords(const sal_Char * pEncryptedPassword,const sal_Char * pPlainPassword)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 */
osl_loginUser(rtl_uString * ustrUserName,rtl_uString * ustrPassword,oslSecurity * pSecurity)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
osl_psz_loginUser(const sal_Char * pszUserName,const sal_Char * pszPasswd,oslSecurity * pSecurity)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 
osl_loginUserOnFileServer(rtl_uString * strUserName,rtl_uString * strPasswd,rtl_uString * strFileServer,oslSecurity * pSecurity)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 
osl_getUserIdent(oslSecurity Security,rtl_uString ** ustrIdent)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 
osl_psz_getUserIdent(oslSecurity Security,sal_Char * pszIdent,sal_uInt32 nMax)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 
osl_getUserName(oslSecurity Security,rtl_uString ** ustrName)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 
osl_psz_getUserName(oslSecurity Security,sal_Char * pszName,sal_uInt32 nMax)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 
osl_getHomeDir(oslSecurity Security,rtl_uString ** pustrDirectory)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 
osl_psz_getHomeDir(oslSecurity Security,sal_Char * pszDirectory,sal_uInt32 nMax)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 
osl_getConfigDir(oslSecurity Security,rtl_uString ** pustrDirectory)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 
osl_psz_getConfigDir(oslSecurity Security,sal_Char * pszDirectory,sal_uInt32 nMax)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"
osl_psz_getConfigDir(oslSecurity Security,sal_Char * pszDirectory,sal_uInt32 nMax)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 
osl_isAdministrator(oslSecurity Security)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 
osl_freeSecurityHandle(oslSecurity Security)842 void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
843 {
844 	deleteSecurityImpl(Security);
845 }
846 
847 
osl_loadUserProfile(oslSecurity Security)848 sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
849 {
850 	(void) Security; /* unused */
851 	return sal_False;
852 }
853 
osl_unloadUserProfile(oslSecurity Security)854 void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
855 {
856 	(void) Security; /* unused */
857 }
858