1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_stoc.hxx" 30 31 #include <hash_map> 32 33 #include <osl/diagnose.h> 34 #include <osl/file.h> 35 #include <rtl/byteseq.hxx> 36 #include <rtl/string.hxx> 37 #include <rtl/ustrbuf.hxx> 38 39 #include <cppuhelper/access_control.hxx> 40 #include <cppuhelper/compbase2.hxx> 41 #include <cppuhelper/implementationentry.hxx> 42 43 #include <com/sun/star/lang/XServiceInfo.hpp> 44 #include <com/sun/star/security/XAccessController.hpp> 45 #include <com/sun/star/security/XPolicy.hpp> 46 #include <com/sun/star/security/AllPermission.hpp> 47 #include <com/sun/star/security/RuntimePermission.hpp> 48 #include <com/sun/star/io/FilePermission.hpp> 49 #include <com/sun/star/connection/SocketPermission.hpp> 50 51 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 52 #define SERVICE_NAME "com.sun.star.security.Policy" 53 #define IMPL_NAME "com.sun.star.security.comp.stoc.FilePolicy" 54 55 56 using namespace ::osl; 57 using namespace ::rtl; 58 using namespace ::cppu; 59 using namespace ::com::sun::star; 60 using namespace ::com::sun::star::uno; 61 62 extern ::rtl_StandardModuleCount g_moduleCount; 63 64 namespace stoc_sec 65 { 66 // static stuff initialized when loading lib 67 static OUString s_implName = OUSTR(IMPL_NAME); 68 static OUString s_serviceName = OUSTR(SERVICE_NAME); 69 70 static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 ); 71 //################################################################################################## 72 73 //-------------------------------------------------------------------------------------------------- 74 static inline void dispose( Reference< XInterface > const & x ) 75 SAL_THROW( (RuntimeException) ) 76 { 77 Reference< lang::XComponent > xComp( x, UNO_QUERY ); 78 if (xComp.is()) 79 { 80 xComp->dispose(); 81 } 82 } 83 84 //################################################################################################## 85 86 struct MutexHolder 87 { 88 Mutex m_mutex; 89 }; 90 typedef WeakComponentImplHelper2< security::XPolicy, lang::XServiceInfo > t_helper; 91 92 //================================================================================================== 93 class FilePolicy 94 : public MutexHolder 95 , public t_helper 96 { 97 Reference< XComponentContext > m_xComponentContext; 98 AccessControl m_ac; 99 100 Sequence< Any > m_defaultPermissions; 101 typedef std::hash_map< OUString, Sequence< Any >, OUStringHash > t_permissions; 102 t_permissions m_userPermissions; 103 bool m_init; 104 105 protected: 106 virtual void SAL_CALL disposing(); 107 108 public: 109 FilePolicy( Reference< XComponentContext > const & xComponentContext ) 110 SAL_THROW( () ); 111 virtual ~FilePolicy() 112 SAL_THROW( () ); 113 114 // XPolicy impl 115 virtual Sequence< Any > SAL_CALL getPermissions( 116 OUString const & userId ) 117 throw (RuntimeException); 118 virtual Sequence< Any > SAL_CALL getDefaultPermissions() 119 throw (RuntimeException); 120 virtual void SAL_CALL refresh() 121 throw (RuntimeException); 122 123 // XServiceInfo impl 124 virtual OUString SAL_CALL getImplementationName() 125 throw (RuntimeException); 126 virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) 127 throw (RuntimeException); 128 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() 129 throw (RuntimeException); 130 }; 131 //__________________________________________________________________________________________________ 132 FilePolicy::FilePolicy( Reference< XComponentContext > const & xComponentContext ) 133 SAL_THROW( () ) 134 : t_helper( m_mutex ) 135 , m_xComponentContext( xComponentContext ) 136 , m_ac( xComponentContext ) 137 , m_init( false ) 138 { 139 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 140 } 141 //__________________________________________________________________________________________________ 142 FilePolicy::~FilePolicy() 143 SAL_THROW( () ) 144 { 145 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 146 } 147 //__________________________________________________________________________________________________ 148 void FilePolicy::disposing() 149 { 150 m_userPermissions.clear(); 151 m_defaultPermissions = Sequence< Any >(); 152 m_xComponentContext.clear(); 153 } 154 155 //__________________________________________________________________________________________________ 156 Sequence< Any > FilePolicy::getPermissions( 157 OUString const & userId ) 158 throw (RuntimeException) 159 { 160 if (! m_init) 161 { 162 refresh(); 163 m_init = true; 164 } 165 166 MutexGuard guard( m_mutex ); 167 t_permissions::iterator iFind( m_userPermissions.find( userId ) ); 168 if (m_userPermissions.end() == iFind) 169 { 170 return Sequence< Any >(); 171 } 172 else 173 { 174 return iFind->second; 175 } 176 } 177 //__________________________________________________________________________________________________ 178 Sequence< Any > FilePolicy::getDefaultPermissions() 179 throw (RuntimeException) 180 { 181 if (! m_init) 182 { 183 refresh(); 184 m_init = true; 185 } 186 187 MutexGuard guard( m_mutex ); 188 return m_defaultPermissions; 189 } 190 191 //================================================================================================== 192 class PolicyReader 193 { 194 OUString m_fileName; 195 oslFileHandle m_file; 196 197 sal_Int32 m_linepos; 198 ByteSequence m_line; 199 sal_Int32 m_pos; 200 sal_Unicode m_back; 201 202 sal_Unicode get() 203 SAL_THROW( (RuntimeException) ); 204 inline void back( sal_Unicode c ) SAL_THROW( () ) 205 { m_back = c; } 206 207 inline bool isWhiteSpace( sal_Unicode c ) SAL_THROW( () ) 208 { return (' ' == c || '\t' == c || '\n' == c || '\r' == c); } 209 void skipWhiteSpace() 210 SAL_THROW( (RuntimeException) ); 211 212 inline bool isCharToken( sal_Unicode c ) SAL_THROW( () ) 213 { return (';' == c || ',' == c || '{' == c || '}' == c); } 214 215 public: 216 PolicyReader( OUString const & file, AccessControl & ac ) 217 SAL_THROW( (RuntimeException) ); 218 ~PolicyReader() 219 SAL_THROW( () ); 220 221 void error( OUString const & msg ) 222 SAL_THROW( (RuntimeException) ); 223 224 OUString getToken() 225 SAL_THROW( (RuntimeException) ); 226 OUString assureToken() 227 SAL_THROW( (RuntimeException) ); 228 OUString getQuotedToken() 229 SAL_THROW( (RuntimeException) ); 230 OUString assureQuotedToken() 231 SAL_THROW( (RuntimeException) ); 232 void assureToken( sal_Unicode token ) 233 SAL_THROW( (RuntimeException) ); 234 }; 235 //__________________________________________________________________________________________________ 236 void PolicyReader::assureToken( sal_Unicode token ) 237 SAL_THROW( (RuntimeException) ) 238 { 239 skipWhiteSpace(); 240 sal_Unicode c = get(); 241 if (c == token) 242 return; 243 OUStringBuffer buf( 16 ); 244 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("expected >") ); 245 buf.append( c ); 246 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("<!") ); 247 error( buf.makeStringAndClear() ); 248 } 249 //__________________________________________________________________________________________________ 250 OUString PolicyReader::assureQuotedToken() 251 SAL_THROW( (RuntimeException) ) 252 { 253 OUString token( getQuotedToken() ); 254 if (! token.getLength()) 255 error( OUSTR("unexpected end of file!") ); 256 return token; 257 } 258 //__________________________________________________________________________________________________ 259 OUString PolicyReader::getQuotedToken() 260 SAL_THROW( (RuntimeException) ) 261 { 262 skipWhiteSpace(); 263 OUStringBuffer buf( 32 ); 264 sal_Unicode c = get(); 265 if ('\"' != c) 266 error( OUSTR("expected quoting >\"< character!") ); 267 c = get(); 268 while ('\0' != c && '\"' != c) 269 { 270 buf.append( c ); 271 c = get(); 272 } 273 return buf.makeStringAndClear(); 274 } 275 //__________________________________________________________________________________________________ 276 OUString PolicyReader::assureToken() 277 SAL_THROW( (RuntimeException) ) 278 { 279 OUString token( getToken() ); 280 if (! token.getLength()) 281 error( OUSTR("unexpected end of file!") ); 282 return token; 283 } 284 //__________________________________________________________________________________________________ 285 OUString PolicyReader::getToken() 286 SAL_THROW( (RuntimeException) ) 287 { 288 skipWhiteSpace(); 289 sal_Unicode c = get(); 290 if (isCharToken( c )) 291 return OUString( &c, 1 ); 292 OUStringBuffer buf( 32 ); 293 while ('\0' != c && !isCharToken( c ) && !isWhiteSpace( c )) 294 { 295 buf.append( c ); 296 c = get(); 297 } 298 back( c ); 299 return buf.makeStringAndClear(); 300 } 301 //__________________________________________________________________________________________________ 302 void PolicyReader::skipWhiteSpace() 303 SAL_THROW( (RuntimeException) ) 304 { 305 sal_Unicode c; 306 do 307 { 308 c = get(); 309 } 310 while (isWhiteSpace( c )); // seeking next non-whitespace char 311 312 if ('/' == c) // C/C++ like comment 313 { 314 c = get(); 315 if ('/' == c) // C++ like comment 316 { 317 do 318 { 319 c = get(); 320 } 321 while ('\n' != c && '\0' != c); // seek eol/eof 322 skipWhiteSpace(); // cont skip on next line 323 } 324 else if ('*' == c) // C like comment 325 { 326 bool fini = true; 327 do 328 { 329 c = get(); 330 if ('*' == c) 331 { 332 c = get(); 333 fini = ('/' == c || '\0' == c); 334 } 335 else 336 { 337 fini = ('\0' == c); 338 } 339 } 340 while (! fini); 341 skipWhiteSpace(); // cont skip on next line 342 } 343 else 344 { 345 error( OUSTR("expected C/C++ like comment!") ); 346 } 347 } 348 else if ('#' == c) // script like comment 349 { 350 do 351 { 352 c = get(); 353 } 354 while ('\n' != c && '\0' != c); // seek eol/eof 355 skipWhiteSpace(); // cont skip on next line 356 } 357 358 else // is token char 359 { 360 back( c ); 361 } 362 } 363 //__________________________________________________________________________________________________ 364 sal_Unicode PolicyReader::get() 365 SAL_THROW( (RuntimeException) ) 366 { 367 if ('\0' != m_back) // one char push back possible 368 { 369 sal_Unicode c = m_back; 370 m_back = '\0'; 371 return c; 372 } 373 else if (m_pos == m_line.getLength()) // provide newline as whitespace 374 { 375 ++m_pos; 376 return '\n'; 377 } 378 else if (m_pos > m_line.getLength()) // read new line 379 { 380 sal_Bool eof; 381 oslFileError rc = ::osl_isEndOfFile( m_file, &eof ); 382 if (osl_File_E_None != rc) 383 error( OUSTR("checking eof failed!") ); 384 if (eof) 385 return '\0'; 386 387 rc = ::osl_readLine( m_file, reinterpret_cast< sal_Sequence ** >( &m_line ) ); 388 if (osl_File_E_None != rc) 389 error( OUSTR("read line failed!") ); 390 ++m_linepos; 391 if (! m_line.getLength()) // empty line read 392 { 393 m_pos = 1; // read new line next time 394 return '\n'; 395 } 396 m_pos = 0; 397 } 398 return (m_line.getConstArray()[ m_pos++ ]); 399 } 400 //__________________________________________________________________________________________________ 401 void PolicyReader::error( OUString const & msg ) 402 SAL_THROW( (RuntimeException) ) 403 { 404 OUStringBuffer buf( 32 ); 405 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("error processing file \"") ); 406 buf.append( m_fileName ); 407 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" [line ") ); 408 buf.append( m_linepos ); 409 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", column ") ); 410 buf.append( m_pos ); 411 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); 412 buf.append( msg ); 413 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() ); 414 } 415 //__________________________________________________________________________________________________ 416 PolicyReader::PolicyReader( OUString const & fileName, AccessControl & ac ) 417 SAL_THROW( (RuntimeException) ) 418 : m_fileName( fileName ) 419 , m_linepos( 0 ) 420 , m_pos( 1 ) // force readline 421 , m_back( '\0' ) 422 { 423 ac.checkFilePermission( m_fileName, OUSTR("read") ); 424 if (osl_File_E_None != ::osl_openFile( m_fileName.pData, &m_file, osl_File_OpenFlag_Read )) 425 { 426 OUStringBuffer buf( 32 ); 427 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot open file \"") ); 428 buf.append( m_fileName ); 429 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") ); 430 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() ); 431 } 432 } 433 //__________________________________________________________________________________________________ 434 PolicyReader::~PolicyReader() 435 SAL_THROW( () ) 436 { 437 if ( ::osl_closeFile( m_file ) != osl_File_E_None ) { 438 OSL_ASSERT( false ); 439 } 440 } 441 442 static OUString s_grant = OUSTR("grant"); 443 static OUString s_user = OUSTR("user"); 444 static OUString s_permission = OUSTR("permission"); 445 static OUString s_openBrace = OUSTR("{"); 446 static OUString s_closingBrace = OUSTR("}"); 447 448 static OUString s_filePermission = OUSTR("com.sun.star.io.FilePermission"); 449 static OUString s_socketPermission = OUSTR("com.sun.star.connection.SocketPermission"); 450 static OUString s_runtimePermission = OUSTR("com.sun.star.security.RuntimePermission"); 451 static OUString s_allPermission = OUSTR("com.sun.star.security.AllPermission"); 452 453 //__________________________________________________________________________________________________ 454 void FilePolicy::refresh() 455 throw (RuntimeException) 456 { 457 // read out file 458 OUString fileName; 459 m_xComponentContext->getValueByName( 460 OUSTR("/implementations/" IMPL_NAME "/file-name") ) >>= fileName; 461 if (! fileName.getLength()) 462 { 463 throw RuntimeException( 464 OUSTR("name of policy file unknown!"), 465 (OWeakObject *)this ); 466 } 467 468 PolicyReader reader( fileName, m_ac ); 469 470 // fill these two 471 Sequence< Any > defaultPermissions; 472 t_permissions userPermissions; 473 474 OUString token( reader.getToken() ); 475 while (token.getLength()) 476 { 477 if (! token.equals( s_grant )) 478 reader.error( OUSTR("expected >grant< token!") ); 479 OUString userId; 480 token = reader.assureToken(); 481 if (token.equals( s_user )) // next token is user-id 482 { 483 userId = reader.assureQuotedToken(); 484 token = reader.assureToken(); 485 } 486 if (! token.equals( s_openBrace )) 487 reader.error( OUSTR("expected opening brace >{<!") ); 488 token = reader.assureToken(); 489 // permissions list 490 while (! token.equals( s_closingBrace )) 491 { 492 if (! token.equals( s_permission )) 493 reader.error( OUSTR("expected >permission< or closing brace >}<!") ); 494 495 token = reader.assureToken(); // permission type 496 Any perm; 497 if (token.equals( s_filePermission )) // FilePermission 498 { 499 OUString url( reader.assureQuotedToken() ); 500 reader.assureToken( ',' ); 501 OUString actions( reader.assureQuotedToken() ); 502 perm <<= io::FilePermission( url, actions ); 503 } 504 else if (token.equals( s_socketPermission )) // SocketPermission 505 { 506 OUString host( reader.assureQuotedToken() ); 507 reader.assureToken( ',' ); 508 OUString actions( reader.assureQuotedToken() ); 509 perm <<= connection::SocketPermission( host, actions ); 510 } 511 else if (token.equals( s_runtimePermission )) // RuntimePermission 512 { 513 OUString name( reader.assureQuotedToken() ); 514 perm <<= security::RuntimePermission( name ); 515 } 516 else if (token.equals( s_allPermission )) // AllPermission 517 { 518 perm <<= security::AllPermission(); 519 } 520 else 521 { 522 reader.error( OUSTR("expected permission type!") ); 523 } 524 525 reader.assureToken( ';' ); 526 527 // insert 528 if (userId.getLength()) 529 { 530 Sequence< Any > perms( userPermissions[ userId ] ); 531 sal_Int32 len = perms.getLength(); 532 perms.realloc( len +1 ); 533 perms[ len ] = perm; 534 userPermissions[ userId ] = perms; 535 } 536 else 537 { 538 sal_Int32 len = defaultPermissions.getLength(); 539 defaultPermissions.realloc( len +1 ); 540 defaultPermissions[ len ] = perm; 541 } 542 543 token = reader.assureToken(); // next permissions token 544 } 545 546 reader.assureToken( ';' ); // semi 547 token = reader.getToken(); // next grant token 548 } 549 550 // assign new ones 551 MutexGuard guard( m_mutex ); 552 m_defaultPermissions = defaultPermissions; 553 m_userPermissions = userPermissions; 554 } 555 556 //__________________________________________________________________________________________________ 557 OUString FilePolicy::getImplementationName() 558 throw (RuntimeException) 559 { 560 return s_implName; 561 } 562 //__________________________________________________________________________________________________ 563 sal_Bool FilePolicy::supportsService( OUString const & serviceName ) 564 throw (RuntimeException) 565 { 566 OUString const * pNames = s_serviceNames.getConstArray(); 567 for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; ) 568 { 569 if (serviceName.equals( pNames[ nPos ] )) 570 { 571 return sal_True; 572 } 573 } 574 return sal_False; 575 } 576 //__________________________________________________________________________________________________ 577 Sequence< OUString > FilePolicy::getSupportedServiceNames() 578 throw (RuntimeException) 579 { 580 return s_serviceNames; 581 } 582 } 583 //################################################################################################## 584 namespace stoc_bootstrap 585 { 586 //-------------------------------------------------------------------------------------------------- 587 Reference< XInterface > SAL_CALL filepolicy_create( 588 Reference< XComponentContext > const & xComponentContext ) 589 SAL_THROW( (Exception) ) 590 { 591 return (OWeakObject *)new stoc_sec::FilePolicy( xComponentContext ); 592 } 593 //-------------------------------------------------------------------------------------------------- 594 Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () ) 595 { 596 return stoc_sec::s_serviceNames; 597 } 598 //-------------------------------------------------------------------------------------------------- 599 OUString filepolicy_getImplementationName() SAL_THROW( () ) 600 { 601 return stoc_sec::s_implName; 602 } 603 } 604