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 .
25 #include <osl_Security_Const.h>
26 #include <osl/thread.h>
27 #include <rtl/process.h>
28 #include <rtl/strbuf.hxx>
33 /** print a UNI_CODE String.
35 inline void printUString( const ::rtl::OUString
& str
)
39 //t_print("#printUString_u# " );
40 aString
= ::rtl::OUStringToOString( str
, RTL_TEXTENCODING_ASCII_US
);
41 t_print("%s\n", aString
.getStr( ) );
44 // test code start here
46 namespace osl_Security
49 /** testing the method:
52 class ctors
: public CppUnit::TestFixture
61 CPPUNIT_ASSERT_MESSAGE( "#test comment#: create a security its handle should not be NULL.",
62 aSec
.getHandle( ) != NULL
);
65 CPPUNIT_TEST_SUITE( ctors
);
66 CPPUNIT_TEST( ctors_001
);
67 CPPUNIT_TEST_SUITE_END( );
70 /** testing the methods:
71 inline sal_Bool SAL_CALL logonUser(const ::rtl::OUString& strName,
72 const ::rtl::OUString& strPasswd);
73 inline sal_Bool SAL_CALL logonUser(const ::rtl::OUString & strName,
74 const ::rtl::OUString & strPasswd,
75 const ::rtl::OUString & strFileServer);
77 class logonUser
: public CppUnit::TestFixture
82 void logonUser_user_pwd( )
85 bRes
= aSec
.logonUser( aLogonUser
, aLogonPasswd
);
87 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd, passed in (UNX), failed in (W32).",
91 void logonUser_user_pwd_server( )
94 bRes
= aSec
.logonUser( aLogonUser
, aLogonPasswd
, aFileServer
);
96 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd and server name, failed in (UNX)(W32).",
100 CPPUNIT_TEST_SUITE( logonUser
);
101 if ( !aStringForward
.isEmpty() && aStringForward
.indexOf( (sal_Unicode
)' ' ) != -1 && ( aStringForward
.indexOf( ( sal_Unicode
) ' ' ) == aStringForward
.lastIndexOf( ( sal_Unicode
) ' ' ) ) )
102 /// if user name and passwd are forwarded
104 CPPUNIT_TEST( logonUser_user_pwd
);
106 if ( !aStringForward
.isEmpty() && aStringForward
.indexOf( (sal_Unicode
)' ' ) != -1 && ( aStringForward
.indexOf( ( sal_Unicode
) ' ' ) != aStringForward
.lastIndexOf( ( sal_Unicode
) ' ' ) ) )
107 /// if user name and passwd and file server are forwarded
109 CPPUNIT_TEST( logonUser_user_pwd_server
);
111 CPPUNIT_TEST_SUITE_END( );
112 }; // class logonUser
114 /** testing the method:
115 inline sal_Bool Security::getUserIdent( rtl::OUString& strIdent) const
117 class getUserIdent
: public CppUnit::TestFixture
122 void getUserIdent_001( )
124 ::osl::Security aSec
;
125 ::rtl::OUString strID
;
126 bRes
= aSec
.getUserIdent( strID
);
128 rtl::OStringBuffer aMessage
;
129 aMessage
.append("strUserID: ");
130 aMessage
.append(rtl::OUStringToOString(strUserID
, osl_getThreadTextEncoding()));
131 aMessage
.append(", strID: ");
132 aMessage
.append(rtl::OUStringToOString(strID
, osl_getThreadTextEncoding()));
133 aMessage
.append(", bRes: ");
134 aMessage
.append(bRes
);
136 CPPUNIT_ASSERT_MESSAGE( aMessage
.getStr(), strUserID
.equals(strID
) && bRes
);
139 CPPUNIT_TEST_SUITE( getUserIdent
);
140 CPPUNIT_TEST( getUserIdent_001
);
141 CPPUNIT_TEST_SUITE_END( );
142 }; // class getUserIdent
144 /** testing the method:
145 inline sal_Bool SAL_CALL getUserName( ::rtl::OUString& strName) const;
147 class getUserName
: public CppUnit::TestFixture
152 void getUserName_001( )
154 ::osl::Security aSec
;
156 ::rtl::OUString
strName( strUserName
), strGetName
;
158 ::rtl::OUString
strName( strUserName
), strGetName
;
160 bRes
= aSec
.getUserName( strGetName
);
163 if (!strName
.isEmpty())
165 nPos
= strGetName
.indexOf(strName
);
167 CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
168 ( nPos
>= 0 ) && bRes
);
171 CPPUNIT_TEST_SUITE( getUserName
);
172 CPPUNIT_TEST( getUserName_001
);
173 CPPUNIT_TEST_SUITE_END( );
174 }; // class getUserName
176 /** testing the method:
177 inline sal_Bool Security::getConfigDir( rtl::OUString& strDirectory ) const
179 class getConfigDir
: public CppUnit::TestFixture
184 void getConfigDir_001( )
186 ::osl::Security aSec
;
187 ::rtl::OUString strConfig
;
188 bRes
= aSec
.getConfigDir( strConfig
);
190 CPPUNIT_ASSERT_MESSAGE( "failed to find a ConfigDir!", bRes
);
193 CPPUNIT_TEST_SUITE( getConfigDir
);
194 CPPUNIT_TEST( getConfigDir_001
);
195 CPPUNIT_TEST_SUITE_END( );
196 }; // class getConfigDir
198 /** testing the method:
199 inline sal_Bool SAL_CALL isAdministrator() const;
201 class isAdministrator
: public CppUnit::TestFixture
206 void isAdministrator_001( )
208 ::osl::Security aSec
;
209 bRes
= aSec
.isAdministrator( );
211 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check if the user is administrator at beginning, compare here.",
215 CPPUNIT_TEST_SUITE( isAdministrator
);
216 CPPUNIT_TEST( isAdministrator_001
);
217 CPPUNIT_TEST_SUITE_END( );
218 }; // class isAdministrator
220 /** testing the method:
221 inline oslSecurity getHandle() const;
223 class getHandle
: public CppUnit::TestFixture
228 void getHandle_001( )
230 ::osl::Security aSec
;
231 bRes
= aSec
.isAdministrator( ) == bool(osl_isAdministrator( aSec
.getHandle( ) ));
233 CPPUNIT_ASSERT_MESSAGE( "#test comment#: use getHandle function to call C API.",
237 CPPUNIT_TEST_SUITE( getHandle
);
238 CPPUNIT_TEST( getHandle_001
);
239 CPPUNIT_TEST_SUITE_END( );
240 }; // class getHandle
242 class UserProfile
: public CppUnit::TestFixture
246 void loadUserProfile( )
248 ::osl::Security aSec
;
249 bool bValue
= osl_loadUserProfile(aSec
.getHandle());
251 CPPUNIT_ASSERT_MESSAGE( "empty function.", !bValue
);
254 void unloadUserProfile( )
256 ::osl::Security aSec
;
257 osl_unloadUserProfile(aSec
.getHandle());
258 CPPUNIT_ASSERT_MESSAGE( "empty function.", true );
261 CPPUNIT_TEST_SUITE( UserProfile
);
262 CPPUNIT_TEST( loadUserProfile
);
263 CPPUNIT_TEST( unloadUserProfile
);
264 CPPUNIT_TEST_SUITE_END( );
265 }; // class UserProfile
267 class loginUserOnFileServer
: public CppUnit::TestFixture
271 void loginUserOnFileServer_001( )
273 rtl::OUString suUserName
;
274 rtl::OUString suPassword
;
275 rtl::OUString suFileServer
;
276 ::osl::Security aSec
;
277 oslSecurity pSec
= aSec
.getHandle();
279 oslSecurityError erg
= osl_loginUserOnFileServer(suUserName
.pData
, suPassword
.pData
, suFileServer
.pData
, &pSec
);
281 CPPUNIT_ASSERT_MESSAGE( "empty function.", erg
== osl_Security_E_UserUnknown
);
284 CPPUNIT_TEST_SUITE( loginUserOnFileServer
);
285 CPPUNIT_TEST( loginUserOnFileServer_001
);
286 CPPUNIT_TEST_SUITE_END( );
287 }; // class loginUserOnFileServer
289 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::ctors
);
290 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::logonUser
);
291 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserIdent
);
292 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserName
);
293 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getConfigDir
);
294 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::isAdministrator
);
295 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getHandle
);
296 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::UserProfile
);
297 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::loginUserOnFileServer
);
299 } // namespace osl_Security
301 /* This defines an own TestPlugIn implementation with an own initialize()
302 method that will be called after loading the PlugIn
304 #include <cppunit/plugin/TestPlugInDefaultImpl.h>
306 class MyTestPlugInImpl
: public CPPUNIT_NS::TestPlugInDefaultImpl
309 MyTestPlugInImpl() {};
310 void initialize( CPPUNIT_NS::TestFactoryRegistry
*registry
,
311 const CPPUNIT_NS::PlugInParameters
¶meters
) SAL_OVERRIDE
;
314 void MyTestPlugInImpl::initialize( CPPUNIT_NS::TestFactoryRegistry
*,
315 const CPPUNIT_NS::PlugInParameters
& )
318 t_print("#Initializing ...\n" );
319 t_print("#\n#logonUser function need root/Administrator account to test.\n" );
320 t_print("#You can test by login with root/Administrator, and execute:\n" );
321 t_print("#testshl2 -forward \"username password\" ../../../wntmsci9/bin/Security.dll\n" );
322 t_print("# where username and password are forwarded account info.\n" );
323 t_print("#if no text forwarded, this function will be skipped.\n" );
325 /// get system information
327 /// some initialization work for UNIX OS
330 CPPUNIT_ASSERT_MESSAGE( "getpwuid: no password entry\n",( pw
= getpwuid( getuid() ) ) != NULL
);
333 strUserID
= OUString::number( getuid( ) );
336 strUserName
= ::rtl::OUString::createFromAscii( pw
->pw_name
);
338 /// get home directory;
339 char *pw_dir
= pw
->pw_dir
;
340 if( getenv( "FAKEROOTKEY" ) )
341 pw_dir
= getenv("HOME");
342 CPPUNIT_ASSERT_MESSAGE( "#Convert from system path to URL failed.",
343 ::osl::File::E_None
== ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( pw_dir
), strHomeDirectory
) );
345 /// get config directory;
346 strConfigDirectory
= strHomeDirectory
.copy(0);
348 /// is administrator;
354 /// some initialization work for Windows OS
356 /// Get the user name, computer name, user home directory.
357 LPTSTR lpszSystemInfo
; // pointer to system information string
358 DWORD cchBuff
= BUFSIZE
; // size of computer or user name
359 TCHAR tchBuffer
[BUFSIZE
]; // buffer for string
361 lpszSystemInfo
= tchBuffer
;
363 if( GetUserNameA(lpszSystemInfo
, &cchBuff
) )
364 strUserName
= ::rtl::OUString::createFromAscii( lpszSystemInfo
);
366 if( GetComputerName(lpszSystemInfo
, &cchBuff
) )
367 strComputerName
= ::rtl::OUString::createFromAscii( lpszSystemInfo
);
369 /// Get user home directory.
371 sal_Char PathA
[_MAX_PATH
];
372 ::rtl::OUString strHome
;
373 if (RegOpenKey(HKEY_CURRENT_USER
, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &hRegKey
) == ERROR_SUCCESS
)
375 LONG lRet
, lSize
= sizeof(PathA
);
378 lRet
= RegQueryValueEx(hRegKey
, "AppData", NULL
, &Type
, ( unsigned char * )PathA
, ( unsigned long * )&lSize
);
379 if ( ( lRet
== ERROR_SUCCESS
) && ( Type
== REG_SZ
) && ( _access( PathA
, 0 ) == 0 ) )
381 CPPUNIT_ASSERT_MESSAGE( "#Convert from system path to URL failed.",
382 ::osl::File::E_None
== ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( PathA
), strConfigDirectory
) );
385 lRet
= RegQueryValueEx(hRegKey
, "Personal", NULL
, &Type
, ( unsigned char * )PathA
, ( unsigned long * )&lSize
);
386 if ( ( lRet
== ERROR_SUCCESS
) && ( Type
== REG_SZ
) && ( _access( PathA
, 0 ) == 0 ) )
388 CPPUNIT_ASSERT_MESSAGE( "#Convert from system path to URL failed.",
389 ::osl::File::E_None
== ::osl::File::getFileURLFromSystemPath( ::rtl::OUString::createFromAscii( PathA
), strHomeDirectory
) );
392 RegCloseKey(hRegKey
);
395 /// Get user Security ID:
397 // Create buffers that may be large enough. If a buffer is too small, the count parameter will be set to the size needed.
398 const DWORD INITIAL_SIZE
= 32;
400 DWORD dwSidBufferSize
= INITIAL_SIZE
;
401 DWORD cchDomainName
= 0;
402 DWORD dwDomainBufferSize
= INITIAL_SIZE
;
403 WCHAR
* wszDomainName
= NULL
;
404 SID_NAME_USE eSidType
;
405 DWORD dwErrorCode
= 0;
407 LPCWSTR wszAccName
= ( LPWSTR
) strUserName
.getStr( );
409 // Create buffers for the SID and the domain name.
410 PSID pSid
= (PSID
) new BYTE
[dwSidBufferSize
];
411 CPPUNIT_ASSERT_MESSAGE("# creating SID buffer failed.\n", pSid
!= NULL
);
412 memset( pSid
, 0, dwSidBufferSize
);
414 wszDomainName
= new WCHAR
[dwDomainBufferSize
];
415 CPPUNIT_ASSERT_MESSAGE("# creating Domain name buffer failed.\n", wszDomainName
!= NULL
);
416 memset(wszDomainName
, 0, dwDomainBufferSize
*sizeof(WCHAR
));
418 // Obtain the SID for the account name passed.
421 // Set the count variables to the buffer sizes and retrieve the SID.
422 cbSid
= dwSidBufferSize
;
423 cchDomainName
= dwDomainBufferSize
;
424 if (LookupAccountNameW(
425 NULL
, // Computer name. NULL for the local computer
427 pSid
, // Pointer to the SID buffer. Use NULL to get the size needed,
428 &cbSid
, // Size of the SID buffer needed.
429 wszDomainName
, // wszDomainName,
434 if (IsValidSid( pSid
) == FALSE
)
435 wprintf(L
"# The SID for %s is invalid.\n", wszAccName
);
438 dwErrorCode
= GetLastError();
440 // Check if one of the buffers was too small.
441 if (dwErrorCode
== ERROR_INSUFFICIENT_BUFFER
)
443 if (cbSid
> dwSidBufferSize
)
445 // Reallocate memory for the SID buffer.
446 wprintf(L
"# The SID buffer was too small. It will be reallocated.\n");
448 pSid
= (PSID
) new BYTE
[cbSid
];
449 CPPUNIT_ASSERT_MESSAGE("# re-creating SID buffer failed.\n", pSid
!= NULL
);
450 memset( pSid
, 0, cbSid
);
451 dwSidBufferSize
= cbSid
;
453 if (cchDomainName
> dwDomainBufferSize
)
455 // Reallocate memory for the domain name buffer.
456 wprintf(L
"# The domain name buffer was too small. It will be reallocated.\n");
457 delete [] wszDomainName
;
458 wszDomainName
= new WCHAR
[cchDomainName
];
459 CPPUNIT_ASSERT_MESSAGE("# re-creating domain name buffer failed.\n", wszDomainName
!= NULL
);
460 memset(wszDomainName
, 0, cchDomainName
*sizeof(WCHAR
));
461 dwDomainBufferSize
= cchDomainName
;
466 wprintf(L
"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode
);
471 // now got SID successfully, only need to compare SID, so I copied the rest lines from source to convert SID to OUString.
472 PSID_IDENTIFIER_AUTHORITY psia
;
473 DWORD dwSubAuthorities
;
474 DWORD dwSidRev
=SID_REVISION
;
479 /* obtain SidIdentifierAuthority */
480 psia
=GetSidIdentifierAuthority(pSid
);
482 /* obtain sidsubauthority count */
483 dwSubAuthorities
=std::min((int) *GetSidSubAuthorityCount(pSid
), 5);
485 /* buffer length: S-SID_REVISION- + identifierauthority- + subauthorities- + NULL */
486 Ident
=(sal_Char
* )malloc(88*sizeof(sal_Char
));
488 /* prepare S-SID_REVISION- */
489 dwSidSize
=wsprintf(Ident
, TEXT("S-%lu-"), dwSidRev
);
491 /* prepare SidIdentifierAuthority */
492 if ((psia
->Value
[0] != 0) || (psia
->Value
[1] != 0))
494 dwSidSize
+=wsprintf(Ident
+ strlen(Ident
),
495 TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
496 (sal_uInt16
)psia
->Value
[0],
497 (sal_uInt16
)psia
->Value
[1],
498 (sal_uInt16
)psia
->Value
[2],
499 (sal_uInt16
)psia
->Value
[3],
500 (sal_uInt16
)psia
->Value
[4],
501 (sal_uInt16
)psia
->Value
[5]);
505 dwSidSize
+=wsprintf(Ident
+ strlen(Ident
),
507 (sal_uInt32
)(psia
->Value
[5] ) +
508 (sal_uInt32
)(psia
->Value
[4] << 8) +
509 (sal_uInt32
)(psia
->Value
[3] << 16) +
510 (sal_uInt32
)(psia
->Value
[2] << 24) );
513 /* loop through SidSubAuthorities */
514 for (dwCounter
=0; dwCounter
< dwSubAuthorities
; dwCounter
++)
516 dwSidSize
+=wsprintf(Ident
+ dwSidSize
, TEXT("-%lu"),
517 *GetSidSubAuthority(pSid
, dwCounter
) );
520 strUserID
= ::rtl::OUString::createFromAscii( Ident
);
523 delete [] reinterpret_cast<BYTE
*>(pSid
);
524 delete [] wszDomainName
;
526 /// check if logged in user is administrator:
529 SID_IDENTIFIER_AUTHORITY NtAuthority
= { SECURITY_NT_AUTHORITY
};
530 PSID AdministratorsGroup
;
531 b
= AllocateAndInitializeSid(
534 SECURITY_BUILTIN_DOMAIN_RID
,
535 DOMAIN_ALIAS_RID_ADMINS
,
537 &AdministratorsGroup
);
540 if (!CheckTokenMembership( NULL
, AdministratorsGroup
, &b
))
544 FreeSid(AdministratorsGroup
);
547 isAdmin
= ( sal_Bool
)b
;
551 /// print the information.
552 t_print("#\n#Retrieved system information is below:\n");
554 t_print("Computer Name: ");
555 if ( strComputerName
.isEmpty())
556 t_print("Not retrieved\n" );
558 printUString( strComputerName
);
560 t_print("Current User Name: ");
561 if ( strUserName
.isEmpty())
562 t_print("Not retrieved\n" );
564 printUString( strUserName
);
566 t_print("Current User Home Directory:");
567 if ( strHomeDirectory
.isEmpty())
568 t_print("Not retrieved\n" );
570 printUString( strHomeDirectory
);
572 t_print("Current Config Directory: ");
573 if ( strConfigDirectory
.isEmpty())
574 t_print("Not retrieved\n" );
576 printUString( strConfigDirectory
);
578 t_print("Current UserID: ");
579 if ( strUserID
.isEmpty())
580 t_print("Not retrieved\n" );
582 printUString( strUserID
);
584 t_print("Current User is: ");
586 t_print("NOT Administrator.\n" );
588 t_print("Administrator.\n" );
590 /// get and display forwarded text if available.
591 rtl::OUString args
[ 3 ];
593 sal_uInt32 n
= rtl_getAppCommandArgCount();
594 for (sal_uInt32 i
= 0; i
< n
; ++i
)
597 rtl_getAppCommandArg(i
, &arg
.pData
);
598 if( arg
.startsWith("-") )
602 SAL_WARN( "sal.osl", "Too many test arguments" );
605 args
[ argsCount
++ ] = arg
;
607 /// only forwarded two parameters, username and password.
610 aLogonUser
= args
[ 0 ];
611 t_print("\n#Forwarded username: ");
612 printUString( aLogonUser
);
614 aLogonPasswd
= args
[ 1 ];
615 t_print("#Forwarded password: ");
616 for (int i
= 0; i
< aLogonPasswd
.getLength(); ++i
)
620 else if( argsCount
== 3 )
621 /// forwarded three parameters, username, password and fileserver.
623 aLogonUser
= args
[ 0 ];
624 t_print("#Forwarded username: ");
625 printUString( aLogonUser
);
627 aLogonPasswd
= args
[ 1 ];
628 t_print("#Forwarded password: ");
629 for (int i
= 0; i
< aLogonPasswd
.getLength(); ++i
)
633 aFileServer
= args
[ 2 ];
634 t_print("#Forwarded FileServer: ");
635 printUString( aFileServer
);
637 t_print("#\n#Initialization Done.\n" );
641 /* Instantiate and register the own TestPlugIn and instantiate the default
643 (This is done by CPPUNIT_PLUGIN_IMPLEMENT() for TestPlugInDefaultImpl)
646 CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( MyTestPlugInImpl
);
647 CPPUNIT_PLUGIN_IMPLEMENT_MAIN();
649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */