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 //------------------------------------------------------------------------
22 //------------------------------------------------------------------------
27 #include <osl_Security_Const.h>
28 #include <osl/thread.h>
29 #include <rtl/process.h>
30 #include <rtl/strbuf.hxx>
36 //------------------------------------------------------------------------
37 // helper functions and classes
38 //------------------------------------------------------------------------
40 /** print Boolean value.
42 inline void printBool( sal_Bool bOk
)
44 //t_print("#printBool# " );
45 ( sal_True
== bOk
) ? t_print("TRUE!\n" ): t_print("FALSE!\n" );
48 /** print a UNI_CODE String.
50 inline void printUString( const ::rtl::OUString
& str
)
54 //t_print("#printUString_u# " );
55 aString
= ::rtl::OUStringToOString( str
, RTL_TEXTENCODING_ASCII_US
);
56 t_print("%s\n", aString
.getStr( ) );
60 //------------------------------------------------------------------------
61 // test code start here
62 //------------------------------------------------------------------------
64 namespace osl_Security
67 /** testing the method:
70 class ctors
: public CppUnit::TestFixture
79 CPPUNIT_ASSERT_MESSAGE( "#test comment#: create a security its handle should not be NULL.",
80 aSec
.getHandle( ) != NULL
);
83 CPPUNIT_TEST_SUITE( ctors
);
84 CPPUNIT_TEST( ctors_001
);
85 CPPUNIT_TEST_SUITE_END( );
89 /** testing the methods:
90 inline sal_Bool SAL_CALL logonUser(const ::rtl::OUString& strName,
91 const ::rtl::OUString& strPasswd);
92 inline sal_Bool SAL_CALL logonUser(const ::rtl::OUString & strName,
93 const ::rtl::OUString & strPasswd,
94 const ::rtl::OUString & strFileServer);
96 class logonUser
: public CppUnit::TestFixture
101 void logonUser_user_pwd( )
103 ::osl::Security aSec
;
104 bRes
= aSec
.logonUser( aLogonUser
, aLogonPasswd
);
106 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd, passed in (UNX), failed in (W32).",
107 ( sal_True
== bRes
) );
110 void logonUser_user_pwd_server( )
112 ::osl::Security aSec
;
113 bRes
= aSec
.logonUser( aLogonUser
, aLogonPasswd
, aFileServer
);
115 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd and server name, failed in (UNX)(W32).",
116 ( sal_True
== bRes
) );
120 CPPUNIT_TEST_SUITE( logonUser
);
121 if ( !aStringForward
.isEmpty() && aStringForward
.indexOf( (sal_Unicode
)' ' ) != -1 && ( aStringForward
.indexOf( ( sal_Unicode
) ' ' ) == aStringForward
.lastIndexOf( ( sal_Unicode
) ' ' ) ) )
122 /// if user name and passwd are forwarded
124 CPPUNIT_TEST( logonUser_user_pwd
);
126 if ( !aStringForward
.isEmpty() && aStringForward
.indexOf( (sal_Unicode
)' ' ) != -1 && ( aStringForward
.indexOf( ( sal_Unicode
) ' ' ) != aStringForward
.lastIndexOf( ( sal_Unicode
) ' ' ) ) )
127 /// if user name and passwd and file server are forwarded
129 CPPUNIT_TEST( logonUser_user_pwd_server
);
131 CPPUNIT_TEST_SUITE_END( );
132 }; // class logonUser
135 /** testing the method:
136 inline sal_Bool Security::getUserIdent( rtl::OUString& strIdent) const
138 class getUserIdent
: public CppUnit::TestFixture
141 sal_Bool bRes
, bRes1
;
143 void getUserIdent_001( )
145 ::osl::Security aSec
;
146 ::rtl::OUString strID
;
147 bRes
= aSec
.getUserIdent( strID
);
149 rtl::OStringBuffer aMessage
;
150 aMessage
.append("strUserID: ");
151 aMessage
.append(rtl::OUStringToOString(strUserID
, osl_getThreadTextEncoding()));
152 aMessage
.append(", strID: ");
153 aMessage
.append(rtl::OUStringToOString(strID
, osl_getThreadTextEncoding()));
154 aMessage
.append(", bRes: ");
155 aMessage
.append(bRes
);
157 CPPUNIT_ASSERT_MESSAGE( aMessage
.getStr(), strUserID
.equals(strID
) && (bRes
== sal_True
));
160 CPPUNIT_TEST_SUITE( getUserIdent
);
161 CPPUNIT_TEST( getUserIdent_001
);
162 CPPUNIT_TEST_SUITE_END( );
163 }; // class getUserIdent
166 /** testing the method:
167 inline sal_Bool SAL_CALL getUserName( ::rtl::OUString& strName) const;
169 class getUserName
: public CppUnit::TestFixture
172 sal_Bool bRes
, bRes1
;
174 void getUserName_001( )
176 ::osl::Security aSec
;
178 ::rtl::OUString
strName( strUserName
), strGetName
;
180 ::rtl::OUString
strName( strUserName
), strGetName
;
182 bRes
= aSec
.getUserName( strGetName
);
185 if (!strName
.isEmpty())
187 nPos
= strGetName
.indexOf(strName
);
189 CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
190 ( nPos
>= 0 ) && ( sal_True
== bRes
) );
193 CPPUNIT_TEST_SUITE( getUserName
);
194 CPPUNIT_TEST( getUserName_001
);
195 CPPUNIT_TEST_SUITE_END( );
196 }; // class getUserName
199 /** testing the method:
200 inline sal_Bool Security::getConfigDir( rtl::OUString& strDirectory ) const
202 class getConfigDir
: public CppUnit::TestFixture
205 sal_Bool bRes
, bRes1
;
207 void getConfigDir_001( )
209 ::osl::Security aSec
;
210 ::rtl::OUString strConfig
;
211 bRes
= aSec
.getConfigDir( strConfig
);
213 CPPUNIT_ASSERT_MESSAGE( "failed to find a ConfigDir!",
214 ( sal_True
== bRes
));
217 CPPUNIT_TEST_SUITE( getConfigDir
);
218 CPPUNIT_TEST( getConfigDir_001
);
219 CPPUNIT_TEST_SUITE_END( );
220 }; // class getConfigDir
222 /** testing the method:
223 inline sal_Bool SAL_CALL isAdministrator() const;
225 class isAdministrator
: public CppUnit::TestFixture
230 void isAdministrator_001( )
232 ::osl::Security aSec
;
233 bRes
= aSec
.isAdministrator( );
235 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check if the user is administrator at beginning, compare here.",
239 CPPUNIT_TEST_SUITE( isAdministrator
);
240 CPPUNIT_TEST( isAdministrator_001
);
241 CPPUNIT_TEST_SUITE_END( );
242 }; // class isAdministrator
244 /** testing the method:
245 inline oslSecurity getHandle() const;
247 class getHandle
: public CppUnit::TestFixture
252 void getHandle_001( )
254 ::osl::Security aSec
;
255 bRes
= aSec
.isAdministrator( ) == osl_isAdministrator( aSec
.getHandle( ) );
257 CPPUNIT_ASSERT_MESSAGE( "#test comment#: use getHandle function to call C API.",
261 CPPUNIT_TEST_SUITE( getHandle
);
262 CPPUNIT_TEST( getHandle_001
);
263 CPPUNIT_TEST_SUITE_END( );
264 }; // class getHandle
267 class UserProfile
: public CppUnit::TestFixture
271 void loadUserProfile( )
273 ::osl::Security aSec
;
274 sal_Bool bValue
= osl_loadUserProfile(aSec
.getHandle());
276 CPPUNIT_ASSERT_MESSAGE( "empty function.", bValue
== sal_False
);
279 void unloadUserProfile( )
281 ::osl::Security aSec
;
282 osl_unloadUserProfile(aSec
.getHandle());
283 CPPUNIT_ASSERT_MESSAGE( "empty function.", sal_True
);
286 CPPUNIT_TEST_SUITE( UserProfile
);
287 CPPUNIT_TEST( loadUserProfile
);
288 CPPUNIT_TEST( unloadUserProfile
);
289 CPPUNIT_TEST_SUITE_END( );
290 }; // class UserProfile
292 class loginUserOnFileServer
: public CppUnit::TestFixture
296 void loginUserOnFileServer_001( )
298 rtl::OUString suUserName
;
299 rtl::OUString suPassword
;
300 rtl::OUString suFileServer
;
301 ::osl::Security aSec
;
302 oslSecurity pSec
= aSec
.getHandle();
304 oslSecurityError erg
= osl_loginUserOnFileServer(suUserName
.pData
, suPassword
.pData
, suFileServer
.pData
, &pSec
);
306 CPPUNIT_ASSERT_MESSAGE( "empty function.", erg
== osl_Security_E_UserUnknown
);
309 CPPUNIT_TEST_SUITE( loginUserOnFileServer
);
310 CPPUNIT_TEST( loginUserOnFileServer_001
);
311 CPPUNIT_TEST_SUITE_END( );
312 }; // class loginUserOnFileServer
314 // -----------------------------------------------------------------------------
315 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::ctors
);
316 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::logonUser
);
317 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserIdent
);
318 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserName
);
319 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getConfigDir
);
320 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::isAdministrator
);
321 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getHandle
);
322 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::UserProfile
);
323 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::loginUserOnFileServer
);
325 // -----------------------------------------------------------------------------
327 } // namespace osl_Security
330 /* This defines an own TestPlugIn implementation with an own initialize()
331 method that will be called after loading the PlugIn
333 #include <cppunit/plugin/TestPlugInDefaultImpl.h>
335 class MyTestPlugInImpl
: public CPPUNIT_NS::TestPlugInDefaultImpl
338 MyTestPlugInImpl() {};
339 void initialize( CPPUNIT_NS::TestFactoryRegistry
*registry
,
340 const CPPUNIT_NS::PlugInParameters
¶meters
);
344 void MyTestPlugInImpl::initialize( CPPUNIT_NS::TestFactoryRegistry
*,
345 const CPPUNIT_NS::PlugInParameters
& )
348 t_print("#Initializing ...\n" );
349 t_print("#\n#logonUser function need root/Administrator account to test.\n" );
350 t_print("#You can test by login with root/Administrator, and excute:\n" );
351 t_print("#testshl2 -forward \"username password\" ../../../wntmsci9/bin/Security.dll\n" );
352 t_print("# where username and password are forwarded account info.\n" );
353 t_print("#if no text forwarded, this function will be skipped.\n" );
355 /// get system information
357 /// some initialization work for UNIX OS
361 CPPUNIT_ASSERT_MESSAGE( "getpwuid: no password entry\n",( pw
= getpwuid( getuid() ) ) != NULL
);
364 strUserID
= OUString::number( getuid( ) );
367 strUserName
= ::rtl::OUString::createFromAscii( pw
->pw_name
);
369 /// get home directory;
370 char *pw_dir
= pw
->pw_dir
;
371 if( getenv( "FAKEROOTKEY" ) )
372 pw_dir
= getenv("HOME");
373 CPPUNIT_ASSERT_MESSAGE( "#Convert from system path to URL failed.",
374 ::osl::File::E_None
== ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( pw_dir
), strHomeDirectory
) );
376 /// get config directory;
377 strConfigDirectory
= strHomeDirectory
.copy(0);
379 /// is administrator;
385 /// some initialization work for Windows OS
388 /// Get the user name, computer name, user home directory.
389 LPTSTR lpszSystemInfo
; // pointer to system information string
390 DWORD cchBuff
= BUFSIZE
; // size of computer or user name
391 TCHAR tchBuffer
[BUFSIZE
]; // buffer for string
393 lpszSystemInfo
= tchBuffer
;
395 if( GetUserNameA(lpszSystemInfo
, &cchBuff
) )
396 strUserName
= ::rtl::OUString::createFromAscii( lpszSystemInfo
);
398 if( GetComputerName(lpszSystemInfo
, &cchBuff
) )
399 strComputerName
= ::rtl::OUString::createFromAscii( lpszSystemInfo
);
401 /// Get user home directory.
403 sal_Char PathA
[_MAX_PATH
];
404 ::rtl::OUString strHome
;
405 if (RegOpenKey(HKEY_CURRENT_USER
, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &hRegKey
) == ERROR_SUCCESS
)
407 LONG lRet
, lSize
= sizeof(PathA
);
410 lRet
= RegQueryValueEx(hRegKey
, "AppData", NULL
, &Type
, ( unsigned char * )PathA
, ( unsigned long * )&lSize
);
411 if ( ( lRet
== ERROR_SUCCESS
) && ( Type
== REG_SZ
) && ( _access( PathA
, 0 ) == 0 ) )
413 CPPUNIT_ASSERT_MESSAGE( "#Convert from system path to URL failed.",
414 ::osl::File::E_None
== ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( PathA
), strConfigDirectory
) );
417 lRet
= RegQueryValueEx(hRegKey
, "Personal", NULL
, &Type
, ( unsigned char * )PathA
, ( unsigned long * )&lSize
);
418 if ( ( lRet
== ERROR_SUCCESS
) && ( Type
== REG_SZ
) && ( _access( PathA
, 0 ) == 0 ) )
420 CPPUNIT_ASSERT_MESSAGE( "#Convert from system path to URL failed.",
421 ::osl::File::E_None
== ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( PathA
), strHomeDirectory
) );
424 RegCloseKey(hRegKey
);
428 /// Get user Security ID:
430 // Create buffers that may be large enough. If a buffer is too small, the count parameter will be set to the size needed.
431 const DWORD INITIAL_SIZE
= 32;
433 DWORD dwSidBufferSize
= INITIAL_SIZE
;
434 DWORD cchDomainName
= 0;
435 DWORD dwDomainBufferSize
= INITIAL_SIZE
;
436 WCHAR
* wszDomainName
= NULL
;
437 SID_NAME_USE eSidType
;
438 DWORD dwErrorCode
= 0;
440 LPCWSTR wszAccName
= ( LPWSTR
) strUserName
.getStr( );
442 // Create buffers for the SID and the domain name.
443 PSID pSid
= (PSID
) new BYTE
[dwSidBufferSize
];
444 CPPUNIT_ASSERT_MESSAGE("# creating SID buffer failed.\n", pSid
!= NULL
);
445 memset( pSid
, 0, dwSidBufferSize
);
447 wszDomainName
= new WCHAR
[dwDomainBufferSize
];
448 CPPUNIT_ASSERT_MESSAGE("# creating Domain name buffer failed.\n", wszDomainName
!= NULL
);
449 memset(wszDomainName
, 0, dwDomainBufferSize
*sizeof(WCHAR
));
451 // Obtain the SID for the account name passed.
454 // Set the count variables to the buffer sizes and retrieve the SID.
455 cbSid
= dwSidBufferSize
;
456 cchDomainName
= dwDomainBufferSize
;
457 if (LookupAccountNameW(
458 NULL
, // Computer name. NULL for the local computer
460 pSid
, // Pointer to the SID buffer. Use NULL to get the size needed,
461 &cbSid
, // Size of the SID buffer needed.
462 wszDomainName
, // wszDomainName,
467 if (IsValidSid( pSid
) == FALSE
)
468 wprintf(L
"# The SID for %s is invalid.\n", wszAccName
);
471 dwErrorCode
= GetLastError();
473 // Check if one of the buffers was too small.
474 if (dwErrorCode
== ERROR_INSUFFICIENT_BUFFER
)
476 if (cbSid
> dwSidBufferSize
)
478 // Reallocate memory for the SID buffer.
479 wprintf(L
"# The SID buffer was too small. It will be reallocated.\n");
481 pSid
= (PSID
) new BYTE
[cbSid
];
482 CPPUNIT_ASSERT_MESSAGE("# re-creating SID buffer failed.\n", pSid
!= NULL
);
483 memset( pSid
, 0, cbSid
);
484 dwSidBufferSize
= cbSid
;
486 if (cchDomainName
> dwDomainBufferSize
)
488 // Reallocate memory for the domain name buffer.
489 wprintf(L
"# The domain name buffer was too small. It will be reallocated.\n");
490 delete [] wszDomainName
;
491 wszDomainName
= new WCHAR
[cchDomainName
];
492 CPPUNIT_ASSERT_MESSAGE("# re-creating domain name buffer failed.\n", wszDomainName
!= NULL
);
493 memset(wszDomainName
, 0, cchDomainName
*sizeof(WCHAR
));
494 dwDomainBufferSize
= cchDomainName
;
499 wprintf(L
"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode
);
504 // now got SID successfully, only need to compare SID, so I copied the rest lines from source to convert SID to OUString.
505 PSID_IDENTIFIER_AUTHORITY psia
;
506 DWORD dwSubAuthorities
;
507 DWORD dwSidRev
=SID_REVISION
;
512 /* obtain SidIdentifierAuthority */
513 psia
=GetSidIdentifierAuthority(pSid
);
515 /* obtain sidsubauthority count */
516 dwSubAuthorities
=std::min((int) *GetSidSubAuthorityCount(pSid
), 5);
518 /* buffer length: S-SID_REVISION- + identifierauthority- + subauthorities- + NULL */
519 Ident
=(sal_Char
* )malloc(88*sizeof(sal_Char
));
521 /* prepare S-SID_REVISION- */
522 dwSidSize
=wsprintf(Ident
, TEXT("S-%lu-"), dwSidRev
);
524 /* prepare SidIdentifierAuthority */
525 if ((psia
->Value
[0] != 0) || (psia
->Value
[1] != 0))
527 dwSidSize
+=wsprintf(Ident
+ strlen(Ident
),
528 TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
529 (sal_uInt16
)psia
->Value
[0],
530 (sal_uInt16
)psia
->Value
[1],
531 (sal_uInt16
)psia
->Value
[2],
532 (sal_uInt16
)psia
->Value
[3],
533 (sal_uInt16
)psia
->Value
[4],
534 (sal_uInt16
)psia
->Value
[5]);
538 dwSidSize
+=wsprintf(Ident
+ strlen(Ident
),
540 (sal_uInt32
)(psia
->Value
[5] ) +
541 (sal_uInt32
)(psia
->Value
[4] << 8) +
542 (sal_uInt32
)(psia
->Value
[3] << 16) +
543 (sal_uInt32
)(psia
->Value
[2] << 24) );
546 /* loop through SidSubAuthorities */
547 for (dwCounter
=0; dwCounter
< dwSubAuthorities
; dwCounter
++)
549 dwSidSize
+=wsprintf(Ident
+ dwSidSize
, TEXT("-%lu"),
550 *GetSidSubAuthority(pSid
, dwCounter
) );
553 strUserID
= ::rtl::OUString::createFromAscii( Ident
);
556 delete [] reinterpret_cast<BYTE
*>(pSid
);
557 delete [] wszDomainName
;
560 /// check if logged in user is administrator:
563 SID_IDENTIFIER_AUTHORITY NtAuthority
= { SECURITY_NT_AUTHORITY
};
564 PSID AdministratorsGroup
;
565 b
= AllocateAndInitializeSid(
568 SECURITY_BUILTIN_DOMAIN_RID
,
569 DOMAIN_ALIAS_RID_ADMINS
,
571 &AdministratorsGroup
);
574 if (!CheckTokenMembership( NULL
, AdministratorsGroup
, &b
))
578 FreeSid(AdministratorsGroup
);
581 isAdmin
= ( sal_Bool
)b
;
585 /// print the information.
586 t_print("#\n#Retrived system information is below:\n");
588 t_print("Computer Name: ");
589 if ( strComputerName
.isEmpty())
590 t_print("Not retrived\n" );
592 printUString( strComputerName
);
594 t_print("Current User Name: ");
595 if ( strUserName
.isEmpty())
596 t_print("Not retrived\n" );
598 printUString( strUserName
);
600 t_print("Current User Home Directory:");
601 if ( strHomeDirectory
.isEmpty())
602 t_print("Not retrived\n" );
604 printUString( strHomeDirectory
);
606 t_print("Current Config Directory: ");
607 if ( strConfigDirectory
.isEmpty())
608 t_print("Not retrived\n" );
610 printUString( strConfigDirectory
);
612 t_print("Current UserID: ");
613 if ( strUserID
.isEmpty())
614 t_print("Not retrived\n" );
616 printUString( strUserID
);
618 t_print("Current User is: ");
619 if ( isAdmin
== sal_False
)
620 t_print("NOT Administrator.\n" );
622 t_print("Administrator.\n" );
624 /// get and display forwarded text if available.
625 rtl::OUString args
[ 3 ];
627 sal_uInt32 n
= rtl_getAppCommandArgCount();
628 for (sal_uInt32 i
= 0; i
< n
; ++i
)
631 rtl_getAppCommandArg(i
, &arg
.pData
);
632 if( !arg
.isEmpty() && arg
[ 0 ] == '-' )
636 SAL_WARN( "sal.osl", "Too many test arguments" );
639 args
[ argsCount
++ ] = arg
;
641 /// only forwarded two parameters, username and password.
644 aLogonUser
= args
[ 0 ];
645 t_print("\n#Forwarded username: ");
646 printUString( aLogonUser
);
648 aLogonPasswd
= args
[ 1 ];
649 t_print("#Forwarded password: ");
650 for (int i
= 0; i
< aLogonPasswd
.getLength(); ++i
)
654 else if( argsCount
== 3 )
655 /// forwarded three parameters, username, password and fileserver.
657 aLogonUser
= args
[ 0 ];
658 t_print("#Forwarded username: ");
659 printUString( aLogonUser
);
661 aLogonPasswd
= args
[ 1 ];
662 t_print("#Forwarded password: ");
663 for (int i
= 0; i
< aLogonPasswd
.getLength(); ++i
)
667 aFileServer
= args
[ 2 ];
668 t_print("#Forwarded FileServer: ");
669 printUString( aFileServer
);
671 t_print("#\n#Initialization Done.\n" );
675 /* Instantiate and register the own TestPlugIn and instantiate the default
677 (This is done by CPPUNIT_PLUGIN_IMPLEMENT() for TestPlugInDefaultImpl)
680 CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( MyTestPlugInImpl
);
681 CPPUNIT_PLUGIN_IMPLEMENT_MAIN();
684 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */