Fix GNU C++ version check
[LibreOffice.git] / sal / qa / osl / security / osl_Security.cxx
blob3c0764014b67cb11f36ee33733646922c7016441
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 #ifdef _WIN32
21 #if !defined WIN32_LEAN_AND_MEAN
22 # define WIN32_LEAN_AND_MEAN
23 #endif
24 #include <windows.h>
25 #include <sddl.h>
26 #undef min
27 #endif
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>
34 using namespace osl;
35 using namespace rtl;
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:
52 Security()
54 class ctors : public CppUnit::TestFixture
56 public:
57 bool bRes, bRes1;
59 void ctors_001( )
61 ::osl::Security aSec;
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( );
70 }; // class ctors
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
81 public:
82 bool bRes;
84 void logonUser_user_pwd( )
86 ::osl::Security aSec;
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).",
90 bRes );
93 void logonUser_user_pwd_server( )
95 ::osl::Security aSec;
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).",
99 bRes );
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
121 public:
122 bool bRes, bRes1;
124 void getUserIdent_001( )
126 ::osl::Security aSec;
127 OUString strID;
128 bRes = aSec.getUserIdent( strID );
130 OString aMessage = "strUserID: " +
131 OUStringToOString(strUserID, osl_getThreadTextEncoding()) +
132 ", strID: " +
133 OUStringToOString(strID, osl_getThreadTextEncoding()) +
134 ", bRes: " +
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
151 public:
152 bool bRes, bRes1;
154 void getUserName_001( )
156 ::osl::Security aSec;
157 #ifdef _WIN32
158 OUString strName( strUserName ), strGetName;
159 #else
160 OUString strName( strUserName ), strGetName;
161 #endif
162 bRes = aSec.getUserName( strGetName );
164 sal_Int32 nPos = -1;
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.",
170 ( nPos >= 0 ) );
171 CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
172 bRes );
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
185 public:
186 bool bRes, bRes1;
188 void getConfigDir_001( )
190 ::osl::Security aSec;
191 OUString strConfig;
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
207 public:
208 bool bRes;
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.",
216 isAdmin, bRes );
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
229 public:
230 bool bRes;
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.",
238 bRes );
241 CPPUNIT_TEST_SUITE( getHandle );
242 CPPUNIT_TEST( getHandle_001 );
243 CPPUNIT_TEST_SUITE_END( );
244 }; // class getHandle
246 class UserProfile : public CppUnit::TestFixture
248 public:
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
273 public:
275 void loginUserOnFileServer_001( )
277 OUString suUserName;
278 OUString suPassword;
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>
310 namespace {
312 class MyTestPlugInImpl: public CPPUNIT_NS::TestPlugInDefaultImpl
314 public:
315 MyTestPlugInImpl() {};
316 void initialize( CPPUNIT_NS::TestFactoryRegistry *registry,
317 const CPPUNIT_NS::PlugInParameters &parameters ) override;
322 void MyTestPlugInImpl::initialize( CPPUNIT_NS::TestFactoryRegistry *,
323 const CPPUNIT_NS::PlugInParameters & )
325 /// start message
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
334 #if ( defined UNX )
335 /// some initialization work for UNIX OS
337 struct passwd* pw;
338 CPPUNIT_ASSERT_MESSAGE( "getpwuid: no password entry\n",( pw = getpwuid( getuid() ) ) != nullptr );
340 /// get user ID;
341 strUserID = OUString::number( getuid( ) );
343 /// get user Name;
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;
354 if( !getuid( ) )
355 isAdmin = true;
357 #endif
358 #if defined(_WIN32)
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);
370 cchBuff = BUFSIZE;
371 if( GetComputerNameW(lpszSystemInfo, &cchBuff) )
372 strComputerName = o3tl::toU(lpszSystemInfo);
374 /// Get user home directory.
375 HKEY hRegKey;
376 if (RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &hRegKey) == ERROR_SUCCESS)
378 sal_Unicode PathW[_MAX_PATH];
379 LSTATUS lRet;
380 DWORD lSize = sizeof(PathW);
381 DWORD Type;
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;
405 DWORD cbSid = 0;
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.
424 for ( ; ; )
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
431 wszAccName,
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,
435 &cchDomainName,
436 &eSidType
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());
448 continue;
450 if (IsValidSid( pSid) == FALSE)
451 wprintf(L"# The SID for %s is invalid.\n", wszAccName);
452 break;
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;
478 else
480 wprintf(L"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode);
481 break;
485 LPWSTR pSidStr = nullptr;
486 if (ConvertSidToStringSidW(pSid, &pSidStr))
488 strUserID = o3tl::toU(pSidStr);
489 LocalFree(pSidStr);
491 else
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:
501 BOOL b;
502 SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
503 PSID AdministratorsGroup;
504 b = AllocateAndInitializeSid(
505 &NtAuthority,
507 SECURITY_BUILTIN_DOMAIN_RID,
508 DOMAIN_ALIAS_RID_ADMINS,
509 0, 0, 0, 0, 0, 0,
510 &AdministratorsGroup);
511 if(b)
513 if (!CheckTokenMembership( nullptr, AdministratorsGroup, &b))
515 b = FALSE;
517 FreeSid(AdministratorsGroup);
520 isAdmin = b;
522 #endif
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" );
530 else
531 printUString( strComputerName );
533 t_print("Current User Name: ");
534 if ( strUserName.isEmpty())
535 t_print("Not retrieved\n" );
536 else
537 printUString( strUserName );
539 t_print("Current User Home Directory:");
540 if ( strHomeDirectory.isEmpty())
541 t_print("Not retrieved\n" );
542 else
543 printUString( strHomeDirectory );
545 t_print("Current Config Directory: ");
546 if ( strConfigDirectory.isEmpty())
547 t_print("Not retrieved\n" );
548 else
549 printUString( strConfigDirectory );
551 t_print("Current UserID: ");
552 if ( strUserID.isEmpty())
553 t_print("Not retrieved\n" );
554 else
555 printUString( strUserID );
557 t_print("Current User is: ");
558 if ( !isAdmin )
559 t_print("NOT Administrator.\n" );
560 else
561 t_print("Administrator.\n" );
563 /// get and display forwarded text if available.
564 OUString args[ 3 ];
565 int argsCount = 0;
566 sal_uInt32 n = rtl_getAppCommandArgCount();
567 for (sal_uInt32 i = 0; i < n; ++i)
569 OUString arg;
570 rtl_getAppCommandArg(i, &arg.pData);
571 if( arg.startsWith("-") )
572 continue;
573 if( argsCount >= 3 )
575 SAL_WARN( "sal.osl", "Too many test arguments" );
576 continue;
578 args[ argsCount++ ] = arg;
580 /// only forwarded two parameters, username and password.
581 if( argsCount == 2 )
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)
590 t_print("*");
591 t_print("\n" );
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)
603 t_print("*");
604 t_print("\n" );
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
615 main() function.
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: */