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 .
21 #if !defined WIN32_LEAN_AND_MEAN
22 # define WIN32_LEAN_AND_MEAN
28 #include "osl_Security_Const.h"
29 #include <osl/thread.h>
30 #include <rtl/process.h>
31 #include <sal/log.hxx>
32 #include <o3tl/char16_t2wchar_t.hxx>
37 /** print a UNICODE String.
39 static void printUString( const OUString
& str
)
41 //t_print("#printUString_u# " );
42 OString aString
= OUStringToOString( str
, RTL_TEXTENCODING_ASCII_US
);
43 t_print("%s\n", aString
.getStr( ) );
46 // test code start here
48 namespace osl_Security
51 /** testing the method:
54 class ctors
: public CppUnit::TestFixture
63 CPPUNIT_ASSERT_MESSAGE( "#test comment#: create a security its handle should not be NULL.",
64 aSec
.getHandle( ) != nullptr );
67 CPPUNIT_TEST_SUITE( ctors
);
68 CPPUNIT_TEST( ctors_001
);
69 CPPUNIT_TEST_SUITE_END( );
72 /** testing the methods:
73 inline sal_Bool SAL_CALL logonUser(const OUString& strName,
74 const OUString& strPasswd);
75 inline sal_Bool SAL_CALL logonUser(const OUString & strName,
76 const OUString & strPasswd,
77 const OUString & strFileServer);
79 class logonUser
: public CppUnit::TestFixture
84 void logonUser_user_pwd( )
87 bRes
= aSec
.logonUser( aLogonUser
, aLogonPasswd
);
89 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd, passed in (UNX), failed in (W32).",
93 void logonUser_user_pwd_server( )
96 bRes
= aSec
.logonUser( aLogonUser
, aLogonPasswd
, aFileServer
);
98 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd and server name, failed in (UNX)(W32).",
102 CPPUNIT_TEST_SUITE( logonUser
);
103 if ( !aStringForward
.isEmpty() && aStringForward
.indexOf( ' ' ) != -1 && ( aStringForward
.indexOf( ' ' ) == aStringForward
.lastIndexOf( ' ' ) ) )
104 /// if user name and passwd are forwarded
106 CPPUNIT_TEST( logonUser_user_pwd
);
108 if ( !aStringForward
.isEmpty() && aStringForward
.indexOf( ' ' ) != -1 && ( aStringForward
.indexOf( ' ' ) != aStringForward
.lastIndexOf( ' ' ) ) )
109 /// if user name and passwd and file server are forwarded
111 CPPUNIT_TEST( logonUser_user_pwd_server
);
113 CPPUNIT_TEST_SUITE_END( );
114 }; // class logonUser
116 /** testing the method:
117 inline sal_Bool Security::getUserIdent( OUString& strIdent) const
119 class getUserIdent
: public CppUnit::TestFixture
124 void getUserIdent_001( )
126 ::osl::Security aSec
;
128 bRes
= aSec
.getUserIdent( strID
);
130 OString aMessage
= "strUserID: " +
131 OUStringToOString(strUserID
, osl_getThreadTextEncoding()) +
133 OUStringToOString(strID
, osl_getThreadTextEncoding()) +
135 OString::boolean(bRes
);
137 CPPUNIT_ASSERT_EQUAL_MESSAGE( aMessage
.getStr(), strUserID
, strID
);
138 CPPUNIT_ASSERT_MESSAGE( aMessage
.getStr(), bRes
);
141 CPPUNIT_TEST_SUITE( getUserIdent
);
142 CPPUNIT_TEST( getUserIdent_001
);
143 CPPUNIT_TEST_SUITE_END( );
144 }; // class getUserIdent
146 /** testing the method:
147 inline sal_Bool SAL_CALL getUserName( OUString& strName) const;
149 class getUserName
: public CppUnit::TestFixture
154 void getUserName_001( )
156 ::osl::Security aSec
;
158 OUString
strName( strUserName
), strGetName
;
160 OUString
strName( strUserName
), strGetName
;
162 bRes
= aSec
.getUserName( strGetName
);
165 if (!strName
.isEmpty())
167 nPos
= strGetName
.indexOf(strName
);
169 CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
171 CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
175 CPPUNIT_TEST_SUITE( getUserName
);
176 CPPUNIT_TEST( getUserName_001
);
177 CPPUNIT_TEST_SUITE_END( );
178 }; // class getUserName
180 /** testing the method:
181 inline sal_Bool Security::getConfigDir( OUString& strDirectory ) const
183 class getConfigDir
: public CppUnit::TestFixture
188 void getConfigDir_001( )
190 ::osl::Security aSec
;
192 bRes
= aSec
.getConfigDir( strConfig
);
194 CPPUNIT_ASSERT_MESSAGE( "failed to find a ConfigDir!", bRes
);
197 CPPUNIT_TEST_SUITE( getConfigDir
);
198 CPPUNIT_TEST( getConfigDir_001
);
199 CPPUNIT_TEST_SUITE_END( );
200 }; // class getConfigDir
202 /** testing the method:
203 inline sal_Bool SAL_CALL isAdministrator() const;
205 class isAdministrator
: public CppUnit::TestFixture
210 void isAdministrator_001( )
212 ::osl::Security aSec
;
213 bRes
= aSec
.isAdministrator( );
215 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#test comment#: check if the user is administrator at beginning, compare here.",
219 CPPUNIT_TEST_SUITE( isAdministrator
);
220 CPPUNIT_TEST( isAdministrator_001
);
221 CPPUNIT_TEST_SUITE_END( );
222 }; // class isAdministrator
224 /** testing the method:
225 inline oslSecurity getHandle() const;
227 class getHandle
: public CppUnit::TestFixture
232 void getHandle_001( )
234 ::osl::Security aSec
;
235 bRes
= aSec
.isAdministrator( ) == bool(osl_isAdministrator( aSec
.getHandle( ) ));
237 CPPUNIT_ASSERT_MESSAGE( "#test comment#: use getHandle function to call C API.",
241 CPPUNIT_TEST_SUITE( getHandle
);
242 CPPUNIT_TEST( getHandle_001
);
243 CPPUNIT_TEST_SUITE_END( );
244 }; // class getHandle
246 class UserProfile
: public CppUnit::TestFixture
250 void loadUserProfile( )
252 ::osl::Security aSec
;
253 bool bValue
= osl_loadUserProfile(aSec
.getHandle());
255 CPPUNIT_ASSERT_MESSAGE( "empty function.", !bValue
);
258 void unloadUserProfile( )
260 ::osl::Security aSec
;
261 osl_unloadUserProfile(aSec
.getHandle());
262 CPPUNIT_ASSERT_MESSAGE( "empty function.", true );
265 CPPUNIT_TEST_SUITE( UserProfile
);
266 CPPUNIT_TEST( loadUserProfile
);
267 CPPUNIT_TEST( unloadUserProfile
);
268 CPPUNIT_TEST_SUITE_END( );
269 }; // class UserProfile
271 class loginUserOnFileServer
: public CppUnit::TestFixture
275 void loginUserOnFileServer_001( )
279 OUString suFileServer
;
280 ::osl::Security aSec
;
281 oslSecurity pSec
= aSec
.getHandle();
283 oslSecurityError erg
= osl_loginUserOnFileServer(suUserName
.pData
, suPassword
.pData
, suFileServer
.pData
, &pSec
);
285 CPPUNIT_ASSERT_EQUAL_MESSAGE( "empty function.", osl_Security_E_UserUnknown
, erg
);
288 CPPUNIT_TEST_SUITE( loginUserOnFileServer
);
289 CPPUNIT_TEST( loginUserOnFileServer_001
);
290 CPPUNIT_TEST_SUITE_END( );
291 }; // class loginUserOnFileServer
293 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::ctors
);
294 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::logonUser
);
295 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserIdent
);
296 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserName
);
297 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getConfigDir
);
298 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::isAdministrator
);
299 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getHandle
);
300 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::UserProfile
);
301 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::loginUserOnFileServer
);
303 } // namespace osl_Security
305 /* This defines an own TestPlugIn implementation with an own initialize()
306 method that will be called after loading the PlugIn
308 #include <cppunit/plugin/TestPlugInDefaultImpl.h>
312 class MyTestPlugInImpl
: public CPPUNIT_NS::TestPlugInDefaultImpl
315 MyTestPlugInImpl() {};
316 void initialize( CPPUNIT_NS::TestFactoryRegistry
*registry
,
317 const CPPUNIT_NS::PlugInParameters
¶meters
) override
;
322 void MyTestPlugInImpl::initialize( CPPUNIT_NS::TestFactoryRegistry
*,
323 const CPPUNIT_NS::PlugInParameters
& )
326 t_print("#Initializing ...\n" );
327 t_print("#\n#logonUser function need root/Administrator account to test.\n" );
328 t_print("#You can test by login with root/Administrator, and execute:\n" );
329 t_print("#testshl2 -forward \"username password\" ../../../wntmsci9/bin/Security.dll\n" );
330 t_print("# where username and password are forwarded account info.\n" );
331 t_print("#if no text forwarded, this function will be skipped.\n" );
333 /// get system information
335 /// some initialization work for UNIX OS
338 CPPUNIT_ASSERT_MESSAGE( "getpwuid: no password entry\n",( pw
= getpwuid( getuid() ) ) != nullptr );
341 strUserID
= OUString::number( getuid( ) );
344 strUserName
= OUString::createFromAscii( pw
->pw_name
);
346 /// get home directory;
347 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
348 ::osl::File::E_None
, ::osl::File::getFileURLFromSystemPath( OUString::createFromAscii( pw
->pw_dir
), strHomeDirectory
) );
350 /// get config directory;
351 strConfigDirectory
= strHomeDirectory
.copy(0);
353 /// is administrator;
359 /// some initialization work for Windows OS
361 /// Get the user name, computer name, user home directory.
362 LPWSTR lpszSystemInfo
; // pointer to system information string
363 DWORD cchBuff
= BUFSIZE
; // size of computer or user name
364 WCHAR wchBuffer
[BUFSIZE
]; // buffer for string
366 lpszSystemInfo
= wchBuffer
;
367 if( GetUserNameW(lpszSystemInfo
, &cchBuff
) )
368 strUserName
= o3tl::toU(lpszSystemInfo
);
371 if( GetComputerNameW(lpszSystemInfo
, &cchBuff
) )
372 strComputerName
= o3tl::toU(lpszSystemInfo
);
374 /// Get user home directory.
376 if (RegOpenKeyW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &hRegKey
) == ERROR_SUCCESS
)
378 sal_Unicode PathW
[_MAX_PATH
];
380 DWORD lSize
= sizeof(PathW
);
383 lRet
= RegQueryValueExW(hRegKey
, L
"AppData", nullptr, &Type
, reinterpret_cast<unsigned char *>(PathW
), &lSize
);
384 if ( ( lRet
== ERROR_SUCCESS
) && ( Type
== REG_SZ
) && ( _waccess( o3tl::toW(PathW
), 0 ) == 0 ) )
386 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
387 ::osl::File::E_None
, ::osl::File::getFileURLFromSystemPath( OUString(PathW
), strConfigDirectory
) );
390 lSize
= sizeof(PathW
);
391 lRet
= RegQueryValueExW(hRegKey
, L
"Personal", nullptr, &Type
, reinterpret_cast<unsigned char *>(PathW
), &lSize
);
392 if ( ( lRet
== ERROR_SUCCESS
) && ( Type
== REG_SZ
) && ( _waccess( o3tl::toW(PathW
), 0 ) == 0 ) )
394 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
395 ::osl::File::E_None
, ::osl::File::getFileURLFromSystemPath( OUString(PathW
), strHomeDirectory
) );
398 RegCloseKey(hRegKey
);
401 /// Get user Security ID:
403 // Create buffers that may be large enough. If a buffer is too small, the count parameter will be set to the size needed.
404 const DWORD INITIAL_SIZE
= 32;
406 DWORD dwSidBufferSize
= INITIAL_SIZE
;
407 DWORD cchDomainName
= 0;
408 DWORD dwDomainBufferSize
= INITIAL_SIZE
;
409 WCHAR
* wszDomainName
= nullptr;
410 SID_NAME_USE eSidType
;
411 DWORD dwErrorCode
= 0;
413 OUString sLookupUserName
= strUserName
;
414 LPCWSTR wszAccName
= o3tl::toW(sLookupUserName
.getStr( ));
416 // Create buffers for the SID and the domain name.
417 PSID pSid
= static_cast<PSID
>(new BYTE
[dwSidBufferSize
]);
418 memset( pSid
, 0, dwSidBufferSize
);
420 wszDomainName
= new WCHAR
[dwDomainBufferSize
];
421 memset(wszDomainName
, 0, dwDomainBufferSize
*sizeof(WCHAR
));
423 // Obtain the SID for the account name passed.
426 // Set the count variables to the buffer sizes and retrieve the SID.
427 cbSid
= dwSidBufferSize
;
428 cchDomainName
= dwDomainBufferSize
;
429 if (LookupAccountNameW(
430 nullptr, // Computer name. NULL for the local computer
432 pSid
, // Pointer to the SID buffer. Use NULL to get the size needed,
433 &cbSid
, // Size of the SID buffer needed.
434 wszDomainName
, // wszDomainName,
439 if (eSidType
== SID_NAME_USE::SidTypeDomain
)
441 // LookupAccountNameW returned SID of a domain; likely the hostname is the same as
442 // username (case-insensitive): something like "JOHNSMITH\JohnSmith", so looking up
443 // for "JohnSmith" without domain returns domain itself. Try getting the SID of the
444 // user using fully qualified name (the case of user of another domain having name
445 // identical this hostname is not handled).
446 sLookupUserName
= OUString::Concat(o3tl::toU(wszDomainName
)) + u
"\\" + strUserName
;
447 wszAccName
= o3tl::toW(sLookupUserName
.getStr());
450 if (IsValidSid( pSid
) == FALSE
)
451 wprintf(L
"# The SID for %s is invalid.\n", wszAccName
);
454 dwErrorCode
= GetLastError();
456 // Check if one of the buffers was too small.
457 if (dwErrorCode
== ERROR_INSUFFICIENT_BUFFER
)
459 if (cbSid
> dwSidBufferSize
)
461 // Reallocate memory for the SID buffer.
462 wprintf(L
"# The SID buffer was too small. It will be reallocated.\n");
463 delete[] static_cast<BYTE
*>(pSid
);
464 pSid
= static_cast<PSID
>(new BYTE
[cbSid
]);
465 memset( pSid
, 0, cbSid
);
466 dwSidBufferSize
= cbSid
;
468 if (cchDomainName
> dwDomainBufferSize
)
470 // Reallocate memory for the domain name buffer.
471 wprintf(L
"# The domain name buffer was too small. It will be reallocated.\n");
472 delete [] wszDomainName
;
473 wszDomainName
= new WCHAR
[cchDomainName
];
474 memset(wszDomainName
, 0, cchDomainName
*sizeof(WCHAR
));
475 dwDomainBufferSize
= cchDomainName
;
480 wprintf(L
"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode
);
485 LPWSTR pSidStr
= nullptr;
486 if (ConvertSidToStringSidW(pSid
, &pSidStr
))
488 strUserID
= o3tl::toU(pSidStr
);
493 wprintf(L
"# ConvertSidToStringSidW failed. GetLastError returned: %d\n", GetLastError());
496 delete [] static_cast<BYTE
*>(pSid
);
497 delete [] wszDomainName
;
499 /// check if logged in user is administrator:
502 SID_IDENTIFIER_AUTHORITY NtAuthority
= { SECURITY_NT_AUTHORITY
};
503 PSID AdministratorsGroup
;
504 b
= AllocateAndInitializeSid(
507 SECURITY_BUILTIN_DOMAIN_RID
,
508 DOMAIN_ALIAS_RID_ADMINS
,
510 &AdministratorsGroup
);
513 if (!CheckTokenMembership( nullptr, AdministratorsGroup
, &b
))
517 FreeSid(AdministratorsGroup
);
524 /// print the information.
525 t_print("#\n#Retrieved system information is below:\n");
527 t_print("Computer Name: ");
528 if ( strComputerName
.isEmpty())
529 t_print("Not retrieved\n" );
531 printUString( strComputerName
);
533 t_print("Current User Name: ");
534 if ( strUserName
.isEmpty())
535 t_print("Not retrieved\n" );
537 printUString( strUserName
);
539 t_print("Current User Home Directory:");
540 if ( strHomeDirectory
.isEmpty())
541 t_print("Not retrieved\n" );
543 printUString( strHomeDirectory
);
545 t_print("Current Config Directory: ");
546 if ( strConfigDirectory
.isEmpty())
547 t_print("Not retrieved\n" );
549 printUString( strConfigDirectory
);
551 t_print("Current UserID: ");
552 if ( strUserID
.isEmpty())
553 t_print("Not retrieved\n" );
555 printUString( strUserID
);
557 t_print("Current User is: ");
559 t_print("NOT Administrator.\n" );
561 t_print("Administrator.\n" );
563 /// get and display forwarded text if available.
566 sal_uInt32 n
= rtl_getAppCommandArgCount();
567 for (sal_uInt32 i
= 0; i
< n
; ++i
)
570 rtl_getAppCommandArg(i
, &arg
.pData
);
571 if( arg
.startsWith("-") )
575 SAL_WARN( "sal.osl", "Too many test arguments" );
578 args
[ argsCount
++ ] = arg
;
580 /// only forwarded two parameters, username and password.
583 aLogonUser
= args
[ 0 ];
584 t_print("\n#Forwarded username: ");
585 printUString( aLogonUser
);
587 aLogonPasswd
= args
[ 1 ];
588 t_print("#Forwarded password: ");
589 for (int i
= 0; i
< aLogonPasswd
.getLength(); ++i
)
593 else if( argsCount
== 3 )
594 /// forwarded three parameters, username, password and fileserver.
596 aLogonUser
= args
[ 0 ];
597 t_print("#Forwarded username: ");
598 printUString( aLogonUser
);
600 aLogonPasswd
= args
[ 1 ];
601 t_print("#Forwarded password: ");
602 for (int i
= 0; i
< aLogonPasswd
.getLength(); ++i
)
606 aFileServer
= args
[ 2 ];
607 t_print("#Forwarded FileServer: ");
608 printUString( aFileServer
);
610 t_print("#\n#Initialization Done.\n" );
614 /* Instantiate and register the own TestPlugIn and instantiate the default
616 (This is done by CPPUNIT_PLUGIN_IMPLEMENT() for TestPlugInDefaultImpl)
619 CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( MyTestPlugInImpl
);
620 CPPUNIT_PLUGIN_IMPLEMENT_MAIN();
622 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */