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 .
22 #if !defined WIN32_LEAN_AND_MEAN
23 # define WIN32_LEAN_AND_MEAN
29 #include "osl_Security_Const.h"
30 #include <osl/thread.h>
31 #include <rtl/process.h>
32 #include <rtl/strbuf.hxx>
33 #include <sal/log.hxx>
34 #include <o3tl/char16_t2wchar_t.hxx>
39 /** print a UNICODE String.
41 static void printUString( const OUString
& str
)
43 //t_print("#printUString_u# " );
44 OString aString
= OUStringToOString( str
, RTL_TEXTENCODING_ASCII_US
);
45 t_print("%s\n", aString
.getStr( ) );
48 // test code start here
50 namespace osl_Security
53 /** testing the method:
56 class ctors
: public CppUnit::TestFixture
65 CPPUNIT_ASSERT_MESSAGE( "#test comment#: create a security its handle should not be NULL.",
66 aSec
.getHandle( ) != nullptr );
69 CPPUNIT_TEST_SUITE( ctors
);
70 CPPUNIT_TEST( ctors_001
);
71 CPPUNIT_TEST_SUITE_END( );
74 /** testing the methods:
75 inline sal_Bool SAL_CALL logonUser(const OUString& strName,
76 const OUString& strPasswd);
77 inline sal_Bool SAL_CALL logonUser(const OUString & strName,
78 const OUString & strPasswd,
79 const OUString & strFileServer);
81 class logonUser
: public CppUnit::TestFixture
86 void logonUser_user_pwd( )
89 bRes
= aSec
.logonUser( aLogonUser
, aLogonPasswd
);
91 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd, passed in (UNX), failed in (W32).",
95 void logonUser_user_pwd_server( )
98 bRes
= aSec
.logonUser( aLogonUser
, aLogonPasswd
, aFileServer
);
100 CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd and server name, failed in (UNX)(W32).",
104 CPPUNIT_TEST_SUITE( logonUser
);
105 if ( !aStringForward
.isEmpty() && aStringForward
.indexOf( ' ' ) != -1 && ( aStringForward
.indexOf( ' ' ) == aStringForward
.lastIndexOf( ' ' ) ) )
106 /// if user name and passwd are forwarded
108 CPPUNIT_TEST( logonUser_user_pwd
);
110 if ( !aStringForward
.isEmpty() && aStringForward
.indexOf( ' ' ) != -1 && ( aStringForward
.indexOf( ' ' ) != aStringForward
.lastIndexOf( ' ' ) ) )
111 /// if user name and passwd and file server are forwarded
113 CPPUNIT_TEST( logonUser_user_pwd_server
);
115 CPPUNIT_TEST_SUITE_END( );
116 }; // class logonUser
118 /** testing the method:
119 inline sal_Bool Security::getUserIdent( OUString& strIdent) const
121 class getUserIdent
: public CppUnit::TestFixture
126 void getUserIdent_001( )
128 ::osl::Security aSec
;
130 bRes
= aSec
.getUserIdent( strID
);
132 OString aMessage
= "strUserID: " +
133 OUStringToOString(strUserID
, osl_getThreadTextEncoding()) +
135 OUStringToOString(strID
, osl_getThreadTextEncoding()) +
137 OString::boolean(bRes
);
139 CPPUNIT_ASSERT_EQUAL_MESSAGE( aMessage
.getStr(), strUserID
, strID
);
140 CPPUNIT_ASSERT_MESSAGE( aMessage
.getStr(), bRes
);
143 CPPUNIT_TEST_SUITE( getUserIdent
);
144 CPPUNIT_TEST( getUserIdent_001
);
145 CPPUNIT_TEST_SUITE_END( );
146 }; // class getUserIdent
148 /** testing the method:
149 inline sal_Bool SAL_CALL getUserName( OUString& strName) const;
151 class getUserName
: public CppUnit::TestFixture
156 void getUserName_001( )
158 ::osl::Security aSec
;
160 OUString
strName( strUserName
), strGetName
;
162 OUString
strName( strUserName
), strGetName
;
164 bRes
= aSec
.getUserName( strGetName
);
167 if (!strName
.isEmpty())
169 nPos
= strGetName
.indexOf(strName
);
171 CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
173 CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
177 CPPUNIT_TEST_SUITE( getUserName
);
178 CPPUNIT_TEST( getUserName_001
);
179 CPPUNIT_TEST_SUITE_END( );
180 }; // class getUserName
182 /** testing the method:
183 inline sal_Bool Security::getConfigDir( OUString& strDirectory ) const
185 class getConfigDir
: public CppUnit::TestFixture
190 void getConfigDir_001( )
192 ::osl::Security aSec
;
194 bRes
= aSec
.getConfigDir( strConfig
);
196 CPPUNIT_ASSERT_MESSAGE( "failed to find a ConfigDir!", bRes
);
199 CPPUNIT_TEST_SUITE( getConfigDir
);
200 CPPUNIT_TEST( getConfigDir_001
);
201 CPPUNIT_TEST_SUITE_END( );
202 }; // class getConfigDir
204 /** testing the method:
205 inline sal_Bool SAL_CALL isAdministrator() const;
207 class isAdministrator
: public CppUnit::TestFixture
212 void isAdministrator_001( )
214 ::osl::Security aSec
;
215 bRes
= aSec
.isAdministrator( );
217 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#test comment#: check if the user is administrator at beginning, compare here.",
221 CPPUNIT_TEST_SUITE( isAdministrator
);
222 CPPUNIT_TEST( isAdministrator_001
);
223 CPPUNIT_TEST_SUITE_END( );
224 }; // class isAdministrator
226 /** testing the method:
227 inline oslSecurity getHandle() const;
229 class getHandle
: public CppUnit::TestFixture
234 void getHandle_001( )
236 ::osl::Security aSec
;
237 bRes
= aSec
.isAdministrator( ) == bool(osl_isAdministrator( aSec
.getHandle( ) ));
239 CPPUNIT_ASSERT_MESSAGE( "#test comment#: use getHandle function to call C API.",
243 CPPUNIT_TEST_SUITE( getHandle
);
244 CPPUNIT_TEST( getHandle_001
);
245 CPPUNIT_TEST_SUITE_END( );
246 }; // class getHandle
248 class UserProfile
: public CppUnit::TestFixture
252 void loadUserProfile( )
254 ::osl::Security aSec
;
255 bool bValue
= osl_loadUserProfile(aSec
.getHandle());
257 CPPUNIT_ASSERT_MESSAGE( "empty function.", !bValue
);
260 void unloadUserProfile( )
262 ::osl::Security aSec
;
263 osl_unloadUserProfile(aSec
.getHandle());
264 CPPUNIT_ASSERT_MESSAGE( "empty function.", true );
267 CPPUNIT_TEST_SUITE( UserProfile
);
268 CPPUNIT_TEST( loadUserProfile
);
269 CPPUNIT_TEST( unloadUserProfile
);
270 CPPUNIT_TEST_SUITE_END( );
271 }; // class UserProfile
273 class loginUserOnFileServer
: public CppUnit::TestFixture
277 void loginUserOnFileServer_001( )
281 OUString suFileServer
;
282 ::osl::Security aSec
;
283 oslSecurity pSec
= aSec
.getHandle();
285 oslSecurityError erg
= osl_loginUserOnFileServer(suUserName
.pData
, suPassword
.pData
, suFileServer
.pData
, &pSec
);
287 CPPUNIT_ASSERT_EQUAL_MESSAGE( "empty function.", osl_Security_E_UserUnknown
, erg
);
290 CPPUNIT_TEST_SUITE( loginUserOnFileServer
);
291 CPPUNIT_TEST( loginUserOnFileServer_001
);
292 CPPUNIT_TEST_SUITE_END( );
293 }; // class loginUserOnFileServer
295 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::ctors
);
296 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::logonUser
);
297 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserIdent
);
298 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserName
);
299 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getConfigDir
);
300 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::isAdministrator
);
301 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getHandle
);
302 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::UserProfile
);
303 CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::loginUserOnFileServer
);
305 } // namespace osl_Security
307 /* This defines an own TestPlugIn implementation with an own initialize()
308 method that will be called after loading the PlugIn
310 #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
;
320 void MyTestPlugInImpl::initialize( CPPUNIT_NS::TestFactoryRegistry
*,
321 const CPPUNIT_NS::PlugInParameters
& )
324 t_print("#Initializing ...\n" );
325 t_print("#\n#logonUser function need root/Administrator account to test.\n" );
326 t_print("#You can test by login with root/Administrator, and execute:\n" );
327 t_print("#testshl2 -forward \"username password\" ../../../wntmsci9/bin/Security.dll\n" );
328 t_print("# where username and password are forwarded account info.\n" );
329 t_print("#if no text forwarded, this function will be skipped.\n" );
331 /// get system information
333 /// some initialization work for UNIX OS
336 CPPUNIT_ASSERT_MESSAGE( "getpwuid: no password entry\n",( pw
= getpwuid( getuid() ) ) != nullptr );
339 strUserID
= OUString::number( getuid( ) );
342 strUserName
= OUString::createFromAscii( pw
->pw_name
);
344 /// get home directory;
345 char *pw_dir
= pw
->pw_dir
;
346 if( getenv( "FAKEROOTKEY" ) )
347 pw_dir
= getenv("HOME");
348 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
349 ::osl::File::E_None
, ::osl::File::getFileURLFromSystemPath( OUString::createFromAscii( pw_dir
), strHomeDirectory
) );
351 /// get config directory;
352 strConfigDirectory
= strHomeDirectory
.copy(0);
354 /// is administrator;
360 /// some initialization work for Windows OS
362 /// Get the user name, computer name, user home directory.
363 LPWSTR lpszSystemInfo
; // pointer to system information string
364 DWORD cchBuff
= BUFSIZE
; // size of computer or user name
365 WCHAR wchBuffer
[BUFSIZE
]; // buffer for string
367 lpszSystemInfo
= wchBuffer
;
368 if( GetUserNameW(lpszSystemInfo
, &cchBuff
) )
369 strUserName
= o3tl::toU(lpszSystemInfo
);
372 if( GetComputerNameW(lpszSystemInfo
, &cchBuff
) )
373 strComputerName
= o3tl::toU(lpszSystemInfo
);
375 /// Get user home directory.
377 if (RegOpenKeyW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &hRegKey
) == ERROR_SUCCESS
)
379 sal_Unicode PathW
[_MAX_PATH
];
381 DWORD lSize
= sizeof(PathW
);
384 lRet
= RegQueryValueExW(hRegKey
, L
"AppData", nullptr, &Type
, reinterpret_cast<unsigned char *>(PathW
), &lSize
);
385 if ( ( lRet
== ERROR_SUCCESS
) && ( Type
== REG_SZ
) && ( _waccess( o3tl::toW(PathW
), 0 ) == 0 ) )
387 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
388 ::osl::File::E_None
, ::osl::File::getFileURLFromSystemPath( PathW
, strConfigDirectory
) );
391 lSize
= sizeof(PathW
);
392 lRet
= RegQueryValueExW(hRegKey
, L
"Personal", nullptr, &Type
, reinterpret_cast<unsigned char *>(PathW
), &lSize
);
393 if ( ( lRet
== ERROR_SUCCESS
) && ( Type
== REG_SZ
) && ( _waccess( o3tl::toW(PathW
), 0 ) == 0 ) )
395 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
396 ::osl::File::E_None
, ::osl::File::getFileURLFromSystemPath( PathW
, strHomeDirectory
) );
399 RegCloseKey(hRegKey
);
402 /// Get user Security ID:
404 // Create buffers that may be large enough. If a buffer is too small, the count parameter will be set to the size needed.
405 const DWORD INITIAL_SIZE
= 32;
407 DWORD dwSidBufferSize
= INITIAL_SIZE
;
408 DWORD cchDomainName
= 0;
409 DWORD dwDomainBufferSize
= INITIAL_SIZE
;
410 WCHAR
* wszDomainName
= nullptr;
411 SID_NAME_USE eSidType
;
412 DWORD dwErrorCode
= 0;
414 LPCWSTR wszAccName
= o3tl::toW(strUserName
.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 (IsValidSid( pSid
) == FALSE
)
440 wprintf(L
"# The SID for %s is invalid.\n", wszAccName
);
443 dwErrorCode
= GetLastError();
445 // Check if one of the buffers was too small.
446 if (dwErrorCode
== ERROR_INSUFFICIENT_BUFFER
)
448 if (cbSid
> dwSidBufferSize
)
450 // Reallocate memory for the SID buffer.
451 wprintf(L
"# The SID buffer was too small. It will be reallocated.\n");
452 delete[] static_cast<BYTE
*>(pSid
);
453 pSid
= static_cast<PSID
>(new BYTE
[cbSid
]);
454 memset( pSid
, 0, cbSid
);
455 dwSidBufferSize
= cbSid
;
457 if (cchDomainName
> dwDomainBufferSize
)
459 // Reallocate memory for the domain name buffer.
460 wprintf(L
"# The domain name buffer was too small. It will be reallocated.\n");
461 delete [] wszDomainName
;
462 wszDomainName
= new WCHAR
[cchDomainName
];
463 memset(wszDomainName
, 0, cchDomainName
*sizeof(WCHAR
));
464 dwDomainBufferSize
= cchDomainName
;
469 wprintf(L
"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode
);
474 LPWSTR pSidStr
= nullptr;
475 if (ConvertSidToStringSidW(pSid
, &pSidStr
))
477 strUserID
= o3tl::toU(pSidStr
);
482 wprintf(L
"# ConvertSidToStringSidW failed. GetLastError returned: %d\n", GetLastError());
485 delete [] static_cast<BYTE
*>(pSid
);
486 delete [] wszDomainName
;
488 /// check if logged in user is administrator:
491 SID_IDENTIFIER_AUTHORITY NtAuthority
= { SECURITY_NT_AUTHORITY
};
492 PSID AdministratorsGroup
;
493 b
= AllocateAndInitializeSid(
496 SECURITY_BUILTIN_DOMAIN_RID
,
497 DOMAIN_ALIAS_RID_ADMINS
,
499 &AdministratorsGroup
);
502 if (!CheckTokenMembership( nullptr, AdministratorsGroup
, &b
))
506 FreeSid(AdministratorsGroup
);
513 /// print the information.
514 t_print("#\n#Retrieved system information is below:\n");
516 t_print("Computer Name: ");
517 if ( strComputerName
.isEmpty())
518 t_print("Not retrieved\n" );
520 printUString( strComputerName
);
522 t_print("Current User Name: ");
523 if ( strUserName
.isEmpty())
524 t_print("Not retrieved\n" );
526 printUString( strUserName
);
528 t_print("Current User Home Directory:");
529 if ( strHomeDirectory
.isEmpty())
530 t_print("Not retrieved\n" );
532 printUString( strHomeDirectory
);
534 t_print("Current Config Directory: ");
535 if ( strConfigDirectory
.isEmpty())
536 t_print("Not retrieved\n" );
538 printUString( strConfigDirectory
);
540 t_print("Current UserID: ");
541 if ( strUserID
.isEmpty())
542 t_print("Not retrieved\n" );
544 printUString( strUserID
);
546 t_print("Current User is: ");
548 t_print("NOT Administrator.\n" );
550 t_print("Administrator.\n" );
552 /// get and display forwarded text if available.
555 sal_uInt32 n
= rtl_getAppCommandArgCount();
556 for (sal_uInt32 i
= 0; i
< n
; ++i
)
559 rtl_getAppCommandArg(i
, &arg
.pData
);
560 if( arg
.startsWith("-") )
564 SAL_WARN( "sal.osl", "Too many test arguments" );
567 args
[ argsCount
++ ] = arg
;
569 /// only forwarded two parameters, username and password.
572 aLogonUser
= args
[ 0 ];
573 t_print("\n#Forwarded username: ");
574 printUString( aLogonUser
);
576 aLogonPasswd
= args
[ 1 ];
577 t_print("#Forwarded password: ");
578 for (int i
= 0; i
< aLogonPasswd
.getLength(); ++i
)
582 else if( argsCount
== 3 )
583 /// forwarded three parameters, username, password and fileserver.
585 aLogonUser
= args
[ 0 ];
586 t_print("#Forwarded username: ");
587 printUString( aLogonUser
);
589 aLogonPasswd
= args
[ 1 ];
590 t_print("#Forwarded password: ");
591 for (int i
= 0; i
< aLogonPasswd
.getLength(); ++i
)
595 aFileServer
= args
[ 2 ];
596 t_print("#Forwarded FileServer: ");
597 printUString( aFileServer
);
599 t_print("#\n#Initialization Done.\n" );
603 /* Instantiate and register the own TestPlugIn and instantiate the default
605 (This is done by CPPUNIT_PLUGIN_IMPLEMENT() for TestPlugInDefaultImpl)
608 CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( MyTestPlugInImpl
);
609 CPPUNIT_PLUGIN_IMPLEMENT_MAIN();
611 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */