android: Update app-specific/MIME type icons
[LibreOffice.git] / sal / qa / osl / security / osl_Security.cxx
blob34417cd146fd385fc5b09df265d2f6e40844d30a
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 #include <algorithm>
21 #ifdef _WIN32
22 #if !defined WIN32_LEAN_AND_MEAN
23 # define WIN32_LEAN_AND_MEAN
24 #endif
25 #include <windows.h>
26 #include <sddl.h>
27 #undef min
28 #endif
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>
36 using namespace osl;
37 using namespace rtl;
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:
54 Security()
56 class ctors : public CppUnit::TestFixture
58 public:
59 bool bRes, bRes1;
61 void ctors_001( )
63 ::osl::Security aSec;
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( );
72 }; // class ctors
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
83 public:
84 bool bRes;
86 void logonUser_user_pwd( )
88 ::osl::Security aSec;
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).",
92 bRes );
95 void logonUser_user_pwd_server( )
97 ::osl::Security aSec;
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).",
101 bRes );
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
123 public:
124 bool bRes, bRes1;
126 void getUserIdent_001( )
128 ::osl::Security aSec;
129 OUString strID;
130 bRes = aSec.getUserIdent( strID );
132 OString aMessage = "strUserID: " +
133 OUStringToOString(strUserID, osl_getThreadTextEncoding()) +
134 ", strID: " +
135 OUStringToOString(strID, osl_getThreadTextEncoding()) +
136 ", bRes: " +
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
153 public:
154 bool bRes, bRes1;
156 void getUserName_001( )
158 ::osl::Security aSec;
159 #ifdef _WIN32
160 OUString strName( strUserName ), strGetName;
161 #else
162 OUString strName( strUserName ), strGetName;
163 #endif
164 bRes = aSec.getUserName( strGetName );
166 sal_Int32 nPos = -1;
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.",
172 ( nPos >= 0 ) );
173 CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
174 bRes );
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
187 public:
188 bool bRes, bRes1;
190 void getConfigDir_001( )
192 ::osl::Security aSec;
193 OUString strConfig;
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
209 public:
210 bool bRes;
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.",
218 isAdmin, bRes );
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
231 public:
232 bool bRes;
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.",
240 bRes );
243 CPPUNIT_TEST_SUITE( getHandle );
244 CPPUNIT_TEST( getHandle_001 );
245 CPPUNIT_TEST_SUITE_END( );
246 }; // class getHandle
248 class UserProfile : public CppUnit::TestFixture
250 public:
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
275 public:
277 void loginUserOnFileServer_001( )
279 OUString suUserName;
280 OUString suPassword;
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 namespace {
314 class MyTestPlugInImpl: public CPPUNIT_NS::TestPlugInDefaultImpl
316 public:
317 MyTestPlugInImpl() {};
318 void initialize( CPPUNIT_NS::TestFactoryRegistry *registry,
319 const CPPUNIT_NS::PlugInParameters &parameters ) override;
324 void MyTestPlugInImpl::initialize( CPPUNIT_NS::TestFactoryRegistry *,
325 const CPPUNIT_NS::PlugInParameters & )
327 /// start message
328 t_print("#Initializing ...\n" );
329 t_print("#\n#logonUser function need root/Administrator account to test.\n" );
330 t_print("#You can test by login with root/Administrator, and execute:\n" );
331 t_print("#testshl2 -forward \"username password\" ../../../wntmsci9/bin/Security.dll\n" );
332 t_print("# where username and password are forwarded account info.\n" );
333 t_print("#if no text forwarded, this function will be skipped.\n" );
335 /// get system information
336 #if ( defined UNX )
337 /// some initialization work for UNIX OS
339 struct passwd* pw;
340 CPPUNIT_ASSERT_MESSAGE( "getpwuid: no password entry\n",( pw = getpwuid( getuid() ) ) != nullptr );
342 /// get user ID;
343 strUserID = OUString::number( getuid( ) );
345 /// get user Name;
346 strUserName = OUString::createFromAscii( pw->pw_name );
348 /// get home directory;
349 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
350 ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString::createFromAscii( pw->pw_dir ), strHomeDirectory ) );
352 /// get config directory;
353 strConfigDirectory = strHomeDirectory.copy(0);
355 /// is administrator;
356 if( !getuid( ) )
357 isAdmin = true;
359 #endif
360 #if defined(_WIN32)
361 /// some initialization work for Windows OS
363 /// Get the user name, computer name, user home directory.
364 LPWSTR lpszSystemInfo; // pointer to system information string
365 DWORD cchBuff = BUFSIZE; // size of computer or user name
366 WCHAR wchBuffer[BUFSIZE]; // buffer for string
368 lpszSystemInfo = wchBuffer;
369 if( GetUserNameW(lpszSystemInfo, &cchBuff) )
370 strUserName = o3tl::toU(lpszSystemInfo);
372 cchBuff = BUFSIZE;
373 if( GetComputerNameW(lpszSystemInfo, &cchBuff) )
374 strComputerName = o3tl::toU(lpszSystemInfo);
376 /// Get user home directory.
377 HKEY hRegKey;
378 if (RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &hRegKey) == ERROR_SUCCESS)
380 sal_Unicode PathW[_MAX_PATH];
381 LSTATUS lRet;
382 DWORD lSize = sizeof(PathW);
383 DWORD Type;
385 lRet = RegQueryValueExW(hRegKey, L"AppData", nullptr, &Type, reinterpret_cast<unsigned char *>(PathW), &lSize);
386 if ( ( lRet == ERROR_SUCCESS ) && ( Type == REG_SZ ) && ( _waccess( o3tl::toW(PathW), 0 ) == 0 ) )
388 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
389 ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString(PathW), strConfigDirectory ) );
392 lSize = sizeof(PathW);
393 lRet = RegQueryValueExW(hRegKey, L"Personal", nullptr, &Type, reinterpret_cast<unsigned char *>(PathW), &lSize);
394 if ( ( lRet == ERROR_SUCCESS ) && ( Type == REG_SZ ) && ( _waccess( o3tl::toW(PathW), 0 ) == 0 ) )
396 CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
397 ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString(PathW), strHomeDirectory ) );
400 RegCloseKey(hRegKey);
403 /// Get user Security ID:
405 // Create buffers that may be large enough. If a buffer is too small, the count parameter will be set to the size needed.
406 const DWORD INITIAL_SIZE = 32;
407 DWORD cbSid = 0;
408 DWORD dwSidBufferSize = INITIAL_SIZE;
409 DWORD cchDomainName = 0;
410 DWORD dwDomainBufferSize = INITIAL_SIZE;
411 WCHAR * wszDomainName = nullptr;
412 SID_NAME_USE eSidType;
413 DWORD dwErrorCode = 0;
415 OUString sLookupUserName = strUserName;
416 LPCWSTR wszAccName = o3tl::toW(sLookupUserName.getStr( ));
418 // Create buffers for the SID and the domain name.
419 PSID pSid = static_cast<PSID>(new BYTE[dwSidBufferSize]);
420 memset( pSid, 0, dwSidBufferSize);
422 wszDomainName = new WCHAR[dwDomainBufferSize];
423 memset(wszDomainName, 0, dwDomainBufferSize*sizeof(WCHAR));
425 // Obtain the SID for the account name passed.
426 for ( ; ; )
428 // Set the count variables to the buffer sizes and retrieve the SID.
429 cbSid = dwSidBufferSize;
430 cchDomainName = dwDomainBufferSize;
431 if (LookupAccountNameW(
432 nullptr, // Computer name. NULL for the local computer
433 wszAccName,
434 pSid, // Pointer to the SID buffer. Use NULL to get the size needed,
435 &cbSid, // Size of the SID buffer needed.
436 wszDomainName, // wszDomainName,
437 &cchDomainName,
438 &eSidType
441 if (eSidType == SID_NAME_USE::SidTypeDomain)
443 // LookupAccountNameW returned SID of a domain; likely the hostname is the same as
444 // username (case-insensitive): something like "JOHNSMITH\JohnSmith", so looking up
445 // for "JohnSmith" without domain returns domain itself. Try getting the SID of the
446 // user using fully qualified name (the case of user of another domain having name
447 // identical this hostname is not handled).
448 sLookupUserName = OUString::Concat(o3tl::toU(wszDomainName)) + u"\\" + strUserName;
449 wszAccName = o3tl::toW(sLookupUserName.getStr());
450 continue;
452 if (IsValidSid( pSid) == FALSE)
453 wprintf(L"# The SID for %s is invalid.\n", wszAccName);
454 break;
456 dwErrorCode = GetLastError();
458 // Check if one of the buffers was too small.
459 if (dwErrorCode == ERROR_INSUFFICIENT_BUFFER)
461 if (cbSid > dwSidBufferSize)
463 // Reallocate memory for the SID buffer.
464 wprintf(L"# The SID buffer was too small. It will be reallocated.\n");
465 delete[] static_cast<BYTE*>(pSid);
466 pSid = static_cast<PSID>(new BYTE[cbSid]);
467 memset( pSid, 0, cbSid);
468 dwSidBufferSize = cbSid;
470 if (cchDomainName > dwDomainBufferSize)
472 // Reallocate memory for the domain name buffer.
473 wprintf(L"# The domain name buffer was too small. It will be reallocated.\n");
474 delete [] wszDomainName;
475 wszDomainName = new WCHAR[cchDomainName];
476 memset(wszDomainName, 0, cchDomainName*sizeof(WCHAR));
477 dwDomainBufferSize = cchDomainName;
480 else
482 wprintf(L"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode);
483 break;
487 LPWSTR pSidStr = nullptr;
488 if (ConvertSidToStringSidW(pSid, &pSidStr))
490 strUserID = o3tl::toU(pSidStr);
491 LocalFree(pSidStr);
493 else
495 wprintf(L"# ConvertSidToStringSidW failed. GetLastError returned: %d\n", GetLastError());
498 delete [] static_cast<BYTE*>(pSid);
499 delete [] wszDomainName;
501 /// check if logged in user is administrator:
503 BOOL b;
504 SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
505 PSID AdministratorsGroup;
506 b = AllocateAndInitializeSid(
507 &NtAuthority,
509 SECURITY_BUILTIN_DOMAIN_RID,
510 DOMAIN_ALIAS_RID_ADMINS,
511 0, 0, 0, 0, 0, 0,
512 &AdministratorsGroup);
513 if(b)
515 if (!CheckTokenMembership( nullptr, AdministratorsGroup, &b))
517 b = FALSE;
519 FreeSid(AdministratorsGroup);
522 isAdmin = b;
524 #endif
526 /// print the information.
527 t_print("#\n#Retrieved system information is below:\n");
529 t_print("Computer Name: ");
530 if ( strComputerName.isEmpty())
531 t_print("Not retrieved\n" );
532 else
533 printUString( strComputerName );
535 t_print("Current User Name: ");
536 if ( strUserName.isEmpty())
537 t_print("Not retrieved\n" );
538 else
539 printUString( strUserName );
541 t_print("Current User Home Directory:");
542 if ( strHomeDirectory.isEmpty())
543 t_print("Not retrieved\n" );
544 else
545 printUString( strHomeDirectory );
547 t_print("Current Config Directory: ");
548 if ( strConfigDirectory.isEmpty())
549 t_print("Not retrieved\n" );
550 else
551 printUString( strConfigDirectory );
553 t_print("Current UserID: ");
554 if ( strUserID.isEmpty())
555 t_print("Not retrieved\n" );
556 else
557 printUString( strUserID );
559 t_print("Current User is: ");
560 if ( !isAdmin )
561 t_print("NOT Administrator.\n" );
562 else
563 t_print("Administrator.\n" );
565 /// get and display forwarded text if available.
566 OUString args[ 3 ];
567 int argsCount = 0;
568 sal_uInt32 n = rtl_getAppCommandArgCount();
569 for (sal_uInt32 i = 0; i < n; ++i)
571 OUString arg;
572 rtl_getAppCommandArg(i, &arg.pData);
573 if( arg.startsWith("-") )
574 continue;
575 if( argsCount >= 3 )
577 SAL_WARN( "sal.osl", "Too many test arguments" );
578 continue;
580 args[ argsCount++ ] = arg;
582 /// only forwarded two parameters, username and password.
583 if( argsCount == 2 )
585 aLogonUser = args[ 0 ];
586 t_print("\n#Forwarded username: ");
587 printUString( aLogonUser);
589 aLogonPasswd = args[ 1 ];
590 t_print("#Forwarded password: ");
591 for (int i = 0; i < aLogonPasswd.getLength(); ++i)
592 t_print("*");
593 t_print("\n" );
595 else if( argsCount == 3 )
596 /// forwarded three parameters, username, password and fileserver.
598 aLogonUser = args[ 0 ];
599 t_print("#Forwarded username: ");
600 printUString( aLogonUser);
602 aLogonPasswd = args[ 1 ];
603 t_print("#Forwarded password: ");
604 for (int i = 0; i < aLogonPasswd.getLength(); ++i)
605 t_print("*");
606 t_print("\n" );
608 aFileServer = args[ 2 ];
609 t_print("#Forwarded FileServer: ");
610 printUString( aFileServer );
612 t_print("#\n#Initialization Done.\n" );
616 /* Instantiate and register the own TestPlugIn and instantiate the default
617 main() function.
618 (This is done by CPPUNIT_PLUGIN_IMPLEMENT() for TestPlugInDefaultImpl)
621 CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( MyTestPlugInImpl );
622 CPPUNIT_PLUGIN_IMPLEMENT_MAIN();
624 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */