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