summaryrefslogtreecommitdiffstats
path: root/sal/qa/osl/security/osl_Security.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/qa/osl/security/osl_Security.cxx')
-rw-r--r--sal/qa/osl/security/osl_Security.cxx624
1 files changed, 624 insertions, 0 deletions
diff --git a/sal/qa/osl/security/osl_Security.cxx b/sal/qa/osl/security/osl_Security.cxx
new file mode 100644
index 000000000..34417cd14
--- /dev/null
+++ b/sal/qa/osl/security/osl_Security.cxx
@@ -0,0 +1,624 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <algorithm>
+#ifdef _WIN32
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <sddl.h>
+#undef min
+#endif
+#include "osl_Security_Const.h"
+#include <osl/thread.h>
+#include <rtl/process.h>
+#include <rtl/strbuf.hxx>
+#include <sal/log.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+
+using namespace osl;
+using namespace rtl;
+
+/** print a UNICODE String.
+*/
+static void printUString( const OUString & str )
+{
+ //t_print("#printUString_u# " );
+ OString aString = OUStringToOString( str, RTL_TEXTENCODING_ASCII_US );
+ t_print("%s\n", aString.getStr( ) );
+}
+
+// test code start here
+
+namespace osl_Security
+{
+
+ /** testing the method:
+ Security()
+ */
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void ctors_001( )
+ {
+ ::osl::Security aSec;
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: create a security its handle should not be NULL.",
+ aSec.getHandle( ) != nullptr );
+ }
+
+ CPPUNIT_TEST_SUITE( ctors );
+ CPPUNIT_TEST( ctors_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class ctors
+
+ /** testing the methods:
+ inline sal_Bool SAL_CALL logonUser(const OUString& strName,
+ const OUString& strPasswd);
+ inline sal_Bool SAL_CALL logonUser(const OUString & strName,
+ const OUString & strPasswd,
+ const OUString & strFileServer);
+ */
+ class logonUser : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes;
+
+ void logonUser_user_pwd( )
+ {
+ ::osl::Security aSec;
+ bRes = aSec.logonUser( aLogonUser, aLogonPasswd );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd, passed in (UNX), failed in (W32).",
+ bRes );
+ }
+
+ void logonUser_user_pwd_server( )
+ {
+ ::osl::Security aSec;
+ bRes = aSec.logonUser( aLogonUser, aLogonPasswd, aFileServer );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd and server name, failed in (UNX)(W32).",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( logonUser );
+ if ( !aStringForward.isEmpty() && aStringForward.indexOf( ' ' ) != -1 && ( aStringForward.indexOf( ' ' ) == aStringForward.lastIndexOf( ' ' ) ) )
+ /// if user name and passwd are forwarded
+ {
+ CPPUNIT_TEST( logonUser_user_pwd );
+ }
+ if ( !aStringForward.isEmpty() && aStringForward.indexOf( ' ' ) != -1 && ( aStringForward.indexOf( ' ' ) != aStringForward.lastIndexOf( ' ' ) ) )
+ /// if user name and passwd and file server are forwarded
+ {
+ CPPUNIT_TEST( logonUser_user_pwd_server );
+ }
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class logonUser
+
+ /** testing the method:
+ inline sal_Bool Security::getUserIdent( OUString& strIdent) const
+ */
+ class getUserIdent : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getUserIdent_001( )
+ {
+ ::osl::Security aSec;
+ OUString strID;
+ bRes = aSec.getUserIdent( strID );
+
+ OString aMessage = "strUserID: " +
+ OUStringToOString(strUserID, osl_getThreadTextEncoding()) +
+ ", strID: " +
+ OUStringToOString(strID, osl_getThreadTextEncoding()) +
+ ", bRes: " +
+ OString::boolean(bRes);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( aMessage.getStr(), strUserID, strID );
+ CPPUNIT_ASSERT_MESSAGE( aMessage.getStr(), bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getUserIdent );
+ CPPUNIT_TEST( getUserIdent_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getUserIdent
+
+ /** testing the method:
+ inline sal_Bool SAL_CALL getUserName( OUString& strName) const;
+ */
+ class getUserName : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getUserName_001( )
+ {
+ ::osl::Security aSec;
+#ifdef _WIN32
+ OUString strName( strUserName ), strGetName;
+#else
+ OUString strName( strUserName ), strGetName;
+#endif
+ bRes = aSec.getUserName( strGetName );
+
+ sal_Int32 nPos = -1;
+ if (!strName.isEmpty())
+ {
+ nPos = strGetName.indexOf(strName);
+ }
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
+ ( nPos >= 0 ) );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getUserName );
+ CPPUNIT_TEST( getUserName_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getUserName
+
+ /** testing the method:
+ inline sal_Bool Security::getConfigDir( OUString& strDirectory ) const
+ */
+ class getConfigDir : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getConfigDir_001( )
+ {
+ ::osl::Security aSec;
+ OUString strConfig;
+ bRes = aSec.getConfigDir( strConfig );
+
+ CPPUNIT_ASSERT_MESSAGE( "failed to find a ConfigDir!", bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getConfigDir );
+ CPPUNIT_TEST( getConfigDir_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getConfigDir
+
+ /** testing the method:
+ inline sal_Bool SAL_CALL isAdministrator() const;
+ */
+ class isAdministrator : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes;
+
+ void isAdministrator_001( )
+ {
+ ::osl::Security aSec;
+ bRes = aSec.isAdministrator( );
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#test comment#: check if the user is administrator at beginning, compare here.",
+ isAdmin, bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( isAdministrator );
+ CPPUNIT_TEST( isAdministrator_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class isAdministrator
+
+ /** testing the method:
+ inline oslSecurity getHandle() const;
+ */
+ class getHandle : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes;
+
+ void getHandle_001( )
+ {
+ ::osl::Security aSec;
+ bRes = aSec.isAdministrator( ) == bool(osl_isAdministrator( aSec.getHandle( ) ));
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: use getHandle function to call C API.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getHandle );
+ CPPUNIT_TEST( getHandle_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getHandle
+
+ class UserProfile : public CppUnit::TestFixture
+ {
+ public:
+
+ void loadUserProfile( )
+ {
+ ::osl::Security aSec;
+ bool bValue = osl_loadUserProfile(aSec.getHandle());
+
+ CPPUNIT_ASSERT_MESSAGE( "empty function.", !bValue );
+ }
+
+ void unloadUserProfile( )
+ {
+ ::osl::Security aSec;
+ osl_unloadUserProfile(aSec.getHandle());
+ CPPUNIT_ASSERT_MESSAGE( "empty function.", true );
+ }
+
+ CPPUNIT_TEST_SUITE( UserProfile );
+ CPPUNIT_TEST( loadUserProfile );
+ CPPUNIT_TEST( unloadUserProfile );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class UserProfile
+
+ class loginUserOnFileServer : public CppUnit::TestFixture
+ {
+ public:
+
+ void loginUserOnFileServer_001( )
+ {
+ OUString suUserName;
+ OUString suPassword;
+ OUString suFileServer;
+ ::osl::Security aSec;
+ oslSecurity pSec = aSec.getHandle();
+
+ oslSecurityError erg = osl_loginUserOnFileServer(suUserName.pData, suPassword.pData, suFileServer.pData, &pSec);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "empty function.", osl_Security_E_UserUnknown, erg );
+ }
+
+ CPPUNIT_TEST_SUITE( loginUserOnFileServer );
+ CPPUNIT_TEST( loginUserOnFileServer_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class loginUserOnFileServer
+
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::ctors);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::logonUser);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserIdent);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserName);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getConfigDir);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::isAdministrator);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getHandle);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::UserProfile);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::loginUserOnFileServer);
+
+} // namespace osl_Security
+
+/* This defines an own TestPlugIn implementation with an own initialize()
+ method that will be called after loading the PlugIn
+ */
+#include <cppunit/plugin/TestPlugInDefaultImpl.h>
+
+namespace {
+
+class MyTestPlugInImpl: public CPPUNIT_NS::TestPlugInDefaultImpl
+{
+ public:
+ MyTestPlugInImpl() {};
+ void initialize( CPPUNIT_NS::TestFactoryRegistry *registry,
+ const CPPUNIT_NS::PlugInParameters &parameters ) override;
+};
+
+}
+
+void MyTestPlugInImpl::initialize( CPPUNIT_NS::TestFactoryRegistry *,
+ const CPPUNIT_NS::PlugInParameters & )
+{
+ /// start message
+ t_print("#Initializing ...\n" );
+ t_print("#\n#logonUser function need root/Administrator account to test.\n" );
+ t_print("#You can test by login with root/Administrator, and execute:\n" );
+ t_print("#testshl2 -forward \"username password\" ../../../wntmsci9/bin/Security.dll\n" );
+ t_print("# where username and password are forwarded account info.\n" );
+ t_print("#if no text forwarded, this function will be skipped.\n" );
+
+ /// get system information
+#if ( defined UNX )
+ /// some initialization work for UNIX OS
+
+ struct passwd* pw;
+ CPPUNIT_ASSERT_MESSAGE( "getpwuid: no password entry\n",( pw = getpwuid( getuid() ) ) != nullptr );
+
+ /// get user ID;
+ strUserID = OUString::number( getuid( ) );
+
+ /// get user Name;
+ strUserName = OUString::createFromAscii( pw->pw_name );
+
+ /// get home directory;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
+ ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString::createFromAscii( pw->pw_dir ), strHomeDirectory ) );
+
+ /// get config directory;
+ strConfigDirectory = strHomeDirectory.copy(0);
+
+ /// is administrator;
+ if( !getuid( ) )
+ isAdmin = true;
+
+#endif
+#if defined(_WIN32)
+ /// some initialization work for Windows OS
+
+ /// Get the user name, computer name, user home directory.
+ LPWSTR lpszSystemInfo; // pointer to system information string
+ DWORD cchBuff = BUFSIZE; // size of computer or user name
+ WCHAR wchBuffer[BUFSIZE]; // buffer for string
+
+ lpszSystemInfo = wchBuffer;
+ if( GetUserNameW(lpszSystemInfo, &cchBuff) )
+ strUserName = o3tl::toU(lpszSystemInfo);
+
+ cchBuff = BUFSIZE;
+ if( GetComputerNameW(lpszSystemInfo, &cchBuff) )
+ strComputerName = o3tl::toU(lpszSystemInfo);
+
+ /// Get user home directory.
+ HKEY hRegKey;
+ if (RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &hRegKey) == ERROR_SUCCESS)
+ {
+ sal_Unicode PathW[_MAX_PATH];
+ LSTATUS lRet;
+ DWORD lSize = sizeof(PathW);
+ DWORD Type;
+
+ lRet = RegQueryValueExW(hRegKey, L"AppData", nullptr, &Type, reinterpret_cast<unsigned char *>(PathW), &lSize);
+ if ( ( lRet == ERROR_SUCCESS ) && ( Type == REG_SZ ) && ( _waccess( o3tl::toW(PathW), 0 ) == 0 ) )
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
+ ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString(PathW), strConfigDirectory ) );
+ }
+
+ lSize = sizeof(PathW);
+ lRet = RegQueryValueExW(hRegKey, L"Personal", nullptr, &Type, reinterpret_cast<unsigned char *>(PathW), &lSize);
+ if ( ( lRet == ERROR_SUCCESS ) && ( Type == REG_SZ ) && ( _waccess( o3tl::toW(PathW), 0 ) == 0 ) )
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
+ ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString(PathW), strHomeDirectory ) );
+ }
+
+ RegCloseKey(hRegKey);
+ }
+
+ /// Get user Security ID:
+
+ // Create buffers that may be large enough. If a buffer is too small, the count parameter will be set to the size needed.
+ const DWORD INITIAL_SIZE = 32;
+ DWORD cbSid = 0;
+ DWORD dwSidBufferSize = INITIAL_SIZE;
+ DWORD cchDomainName = 0;
+ DWORD dwDomainBufferSize = INITIAL_SIZE;
+ WCHAR * wszDomainName = nullptr;
+ SID_NAME_USE eSidType;
+ DWORD dwErrorCode = 0;
+
+ OUString sLookupUserName = strUserName;
+ LPCWSTR wszAccName = o3tl::toW(sLookupUserName.getStr( ));
+
+ // Create buffers for the SID and the domain name.
+ PSID pSid = static_cast<PSID>(new BYTE[dwSidBufferSize]);
+ memset( pSid, 0, dwSidBufferSize);
+
+ wszDomainName = new WCHAR[dwDomainBufferSize];
+ memset(wszDomainName, 0, dwDomainBufferSize*sizeof(WCHAR));
+
+ // Obtain the SID for the account name passed.
+ for ( ; ; )
+ {
+ // Set the count variables to the buffer sizes and retrieve the SID.
+ cbSid = dwSidBufferSize;
+ cchDomainName = dwDomainBufferSize;
+ if (LookupAccountNameW(
+ nullptr, // Computer name. NULL for the local computer
+ wszAccName,
+ pSid, // Pointer to the SID buffer. Use NULL to get the size needed,
+ &cbSid, // Size of the SID buffer needed.
+ wszDomainName, // wszDomainName,
+ &cchDomainName,
+ &eSidType
+ ))
+ {
+ if (eSidType == SID_NAME_USE::SidTypeDomain)
+ {
+ // LookupAccountNameW returned SID of a domain; likely the hostname is the same as
+ // username (case-insensitive): something like "JOHNSMITH\JohnSmith", so looking up
+ // for "JohnSmith" without domain returns domain itself. Try getting the SID of the
+ // user using fully qualified name (the case of user of another domain having name
+ // identical this hostname is not handled).
+ sLookupUserName = OUString::Concat(o3tl::toU(wszDomainName)) + u"\\" + strUserName;
+ wszAccName = o3tl::toW(sLookupUserName.getStr());
+ continue;
+ }
+ if (IsValidSid( pSid) == FALSE)
+ wprintf(L"# The SID for %s is invalid.\n", wszAccName);
+ break;
+ }
+ dwErrorCode = GetLastError();
+
+ // Check if one of the buffers was too small.
+ if (dwErrorCode == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if (cbSid > dwSidBufferSize)
+ {
+ // Reallocate memory for the SID buffer.
+ wprintf(L"# The SID buffer was too small. It will be reallocated.\n");
+ delete[] static_cast<BYTE*>(pSid);
+ pSid = static_cast<PSID>(new BYTE[cbSid]);
+ memset( pSid, 0, cbSid);
+ dwSidBufferSize = cbSid;
+ }
+ if (cchDomainName > dwDomainBufferSize)
+ {
+ // Reallocate memory for the domain name buffer.
+ wprintf(L"# The domain name buffer was too small. It will be reallocated.\n");
+ delete [] wszDomainName;
+ wszDomainName = new WCHAR[cchDomainName];
+ memset(wszDomainName, 0, cchDomainName*sizeof(WCHAR));
+ dwDomainBufferSize = cchDomainName;
+ }
+ }
+ else
+ {
+ wprintf(L"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode);
+ break;
+ }
+ }
+
+ LPWSTR pSidStr = nullptr;
+ if (ConvertSidToStringSidW(pSid, &pSidStr))
+ {
+ strUserID = o3tl::toU(pSidStr);
+ LocalFree(pSidStr);
+ }
+ else
+ {
+ wprintf(L"# ConvertSidToStringSidW failed. GetLastError returned: %d\n", GetLastError());
+ }
+
+ delete [] static_cast<BYTE*>(pSid);
+ delete [] wszDomainName;
+
+ /// check if logged in user is administrator:
+
+ BOOL b;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
+ PSID AdministratorsGroup;
+ b = AllocateAndInitializeSid(
+ &NtAuthority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &AdministratorsGroup);
+ if(b)
+ {
+ if (!CheckTokenMembership( nullptr, AdministratorsGroup, &b))
+ {
+ b = FALSE;
+ }
+ FreeSid(AdministratorsGroup);
+ }
+
+ isAdmin = b;
+
+#endif
+
+ /// print the information.
+ t_print("#\n#Retrieved system information is below:\n");
+
+ t_print("Computer Name: ");
+ if ( strComputerName.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strComputerName );
+
+ t_print("Current User Name: ");
+ if ( strUserName.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strUserName );
+
+ t_print("Current User Home Directory:");
+ if ( strHomeDirectory.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strHomeDirectory );
+
+ t_print("Current Config Directory: ");
+ if ( strConfigDirectory.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strConfigDirectory );
+
+ t_print("Current UserID: ");
+ if ( strUserID.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strUserID );
+
+ t_print("Current User is: ");
+ if ( !isAdmin )
+ t_print("NOT Administrator.\n" );
+ else
+ t_print("Administrator.\n" );
+
+ /// get and display forwarded text if available.
+ OUString args[ 3 ];
+ int argsCount = 0;
+ sal_uInt32 n = rtl_getAppCommandArgCount();
+ for (sal_uInt32 i = 0; i < n; ++i)
+ {
+ OUString arg;
+ rtl_getAppCommandArg(i, &arg.pData);
+ if( arg.startsWith("-") )
+ continue;
+ if( argsCount >= 3 )
+ {
+ SAL_WARN( "sal.osl", "Too many test arguments" );
+ continue;
+ }
+ args[ argsCount++ ] = arg;
+ }
+ /// only forwarded two parameters, username and password.
+ if( argsCount == 2 )
+ {
+ aLogonUser = args[ 0 ];
+ t_print("\n#Forwarded username: ");
+ printUString( aLogonUser);
+
+ aLogonPasswd = args[ 1 ];
+ t_print("#Forwarded password: ");
+ for (int i = 0; i < aLogonPasswd.getLength(); ++i)
+ t_print("*");
+ t_print("\n" );
+ }
+ else if( argsCount == 3 )
+ /// forwarded three parameters, username, password and fileserver.
+ {
+ aLogonUser = args[ 0 ];
+ t_print("#Forwarded username: ");
+ printUString( aLogonUser);
+
+ aLogonPasswd = args[ 1 ];
+ t_print("#Forwarded password: ");
+ for (int i = 0; i < aLogonPasswd.getLength(); ++i)
+ t_print("*");
+ t_print("\n" );
+
+ aFileServer = args[ 2 ];
+ t_print("#Forwarded FileServer: ");
+ printUString( aFileServer );
+ }
+ t_print("#\n#Initialization Done.\n" );
+
+}
+
+/* Instantiate and register the own TestPlugIn and instantiate the default
+ main() function.
+ (This is done by CPPUNIT_PLUGIN_IMPLEMENT() for TestPlugInDefaultImpl)
+ */
+
+CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( MyTestPlugInImpl );
+CPPUNIT_PLUGIN_IMPLEMENT_MAIN();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */