1 /*
   2  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @bug 6866804 7006126
  26  * @summary Unit test for java.nio.file.Files
  27  * @library ..
  28  * @build CheckPermissions
  29  * @run main/othervm CheckPermissions
  30  */
  31 
  32 import java.nio.ByteBuffer;
  33 import java.nio.file.*;
  34 import static java.nio.file.Files.*;
  35 import static java.nio.file.StandardOpenOption.*;
  36 import java.nio.file.attribute.*;
  37 import java.nio.channels.SeekableByteChannel;
  38 import java.security.Permission;
  39 import java.io.*;
  40 import java.util.*;
  41 
  42 /**
  43  * Checks each method that accesses the file system does the right permission
  44  * check when there is a security manager set.
  45  */
  46 
  47 public class CheckPermissions {
  48 
  49     static class Checks {
  50         private List<Permission> permissionsChecked = new ArrayList<>();
  51         private Set<String>  propertiesChecked = new HashSet<>();
  52         private List<String> readsChecked   = new ArrayList<>();
  53         private List<String> writesChecked  = new ArrayList<>();
  54         private List<String> deletesChecked = new ArrayList<>();
  55         private List<String> execsChecked   = new ArrayList<>();
  56 
  57         List<Permission> permissionsChecked()  { return permissionsChecked; }
  58         Set<String> propertiesChecked()        { return propertiesChecked; }
  59         List<String> readsChecked()            { return readsChecked; }
  60         List<String> writesChecked()           { return writesChecked; }
  61         List<String> deletesChecked()          { return deletesChecked; }
  62         List<String> execsChecked()            { return execsChecked; }
  63     }
  64 
  65     static ThreadLocal<Checks> myChecks =
  66         new ThreadLocal<Checks>() {
  67             @Override protected Checks initialValue() {
  68                 return null;
  69             }
  70         };
  71 
  72     static void prepare() {
  73         myChecks.set(new Checks());
  74     }
  75 
  76     static void assertCheckPermission(Class<? extends Permission> type,
  77                                       String name)
  78     {
  79         for (Permission perm: myChecks.get().permissionsChecked()) {
  80             if (type.isInstance(perm) && perm.getName().equals(name))
  81                 return;
  82         }
  83         throw new RuntimeException(type.getName() + "(\"" + name + "\") not checked");
  84     }
  85 
  86     static void assertCheckPropertyAccess(String key) {
  87         if (!myChecks.get().propertiesChecked().contains(key))
  88             throw new RuntimeException("Property " + key + " not checked");
  89     }
  90 
  91     static void assertChecked(Path file, List<String> list) {
  92         String s = file.toString();
  93         for (String f: list) {
  94             if (f.endsWith(s))
  95                 return;
  96         }
  97         throw new RuntimeException("Access not checked");
  98     }
  99 
 100     static void assertCheckRead(Path file) {
 101         assertChecked(file, myChecks.get().readsChecked());
 102     }
 103 
 104     static void assertCheckWrite(Path file) {
 105         assertChecked(file, myChecks.get().writesChecked());
 106     }
 107 
 108     static void assertCheckWriteToDirectory(Path dir) {
 109         String s = dir.toString();
 110         List<String> list = myChecks.get().writesChecked();
 111         for (String f: list) {
 112             if (f.startsWith(s)) {
 113                 return;
 114             }
 115         }
 116         throw new RuntimeException("Access not checked");
 117     }
 118 
 119     static void assertCheckDelete(Path file) {
 120         assertChecked(file, myChecks.get().deletesChecked());
 121     }
 122 
 123     static void assertCheckExec(Path file) {
 124         assertChecked(file, myChecks.get().execsChecked());
 125     }
 126 
 127     static class LoggingSecurityManager extends SecurityManager {
 128         static void install() {
 129             System.setSecurityManager(new LoggingSecurityManager());
 130         }
 131 
 132         @Override
 133         public void checkPermission(Permission perm) {
 134             Checks checks = myChecks.get();
 135             if (checks != null)
 136                 checks.permissionsChecked().add(perm);
 137         }
 138 
 139         @Override
 140         public void checkPropertyAccess(String key) {
 141             Checks checks = myChecks.get();
 142             if (checks != null)
 143                 checks.propertiesChecked().add(key);
 144         }
 145 
 146         @Override
 147         public void checkRead(String file) {
 148             Checks checks = myChecks.get();
 149             if (checks != null)
 150                 checks.readsChecked().add(file);
 151         }
 152 
 153         @Override
 154         public void checkWrite(String file) {
 155             Checks checks = myChecks.get();
 156             if (checks != null)
 157                 checks.writesChecked().add(file);
 158         }
 159 
 160         @Override
 161         public void checkDelete(String file) {
 162             Checks checks = myChecks.get();
 163             if (checks != null)
 164                 checks.deletesChecked().add(file);
 165         }
 166 
 167         @Override
 168         public void checkExec(String file) {
 169             Checks checks = myChecks.get();
 170             if (checks != null)
 171                 checks.execsChecked().add(file);
 172         }
 173     }
 174 
 175     static void testBasicFileAttributeView(BasicFileAttributeView view, Path file)
 176         throws IOException
 177     {
 178         prepare();
 179         view.readAttributes();
 180         assertCheckRead(file);
 181 
 182         prepare();
 183         FileTime now = FileTime.fromMillis(System.currentTimeMillis());
 184         view.setTimes(null, now, now);
 185         assertCheckWrite(file);
 186     }
 187 
 188     static void testPosixFileAttributeView(PosixFileAttributeView view, Path file)
 189         throws IOException
 190     {
 191         prepare();
 192         PosixFileAttributes attrs = view.readAttributes();
 193         assertCheckRead(file);
 194         assertCheckPermission(RuntimePermission.class, "accessUserInformation");
 195 
 196         prepare();
 197         view.setPermissions(attrs.permissions());
 198         assertCheckWrite(file);
 199         assertCheckPermission(RuntimePermission.class, "accessUserInformation");
 200 
 201         prepare();
 202         view.setOwner(attrs.owner());
 203         assertCheckWrite(file);
 204         assertCheckPermission(RuntimePermission.class, "accessUserInformation");
 205 
 206         prepare();
 207         view.setOwner(attrs.owner());
 208         assertCheckWrite(file);
 209         assertCheckPermission(RuntimePermission.class, "accessUserInformation");
 210     }
 211 
 212     public static void main(String[] args) throws IOException {
 213         final Path testdir = Paths.get(System.getProperty("test.dir", ".")).toAbsolutePath();
 214         final Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
 215 
 216         Path file = createFile(testdir.resolve("file1234"));
 217         try {
 218             LoggingSecurityManager.install();
 219 
 220             // -- check access --
 221 
 222             prepare();
 223             exists(file);
 224             assertCheckRead(file);
 225 
 226             prepare();
 227             isReadable(file);
 228             assertCheckRead(file);
 229 
 230             prepare();
 231             isWritable(file);
 232             assertCheckWrite(file);
 233 
 234             prepare();
 235             isExecutable(file);
 236             assertCheckExec(file);
 237 
 238             // -- copy --
 239 
 240             Path target = testdir.resolve("target1234");
 241             prepare();
 242             copy(file, target);
 243             try {
 244                 assertCheckRead(file);
 245                 assertCheckWrite(target);
 246             } finally {
 247                 delete(target);
 248             }
 249 
 250             if (TestUtil.supportsLinks(testdir)) {
 251                 Path link = testdir.resolve("link1234");
 252                 createSymbolicLink(link, file);
 253                 try {
 254                     prepare();
 255                     copy(link, target, LinkOption.NOFOLLOW_LINKS);
 256                     try {
 257                         assertCheckRead(link);
 258                         assertCheckWrite(target);
 259                         assertCheckPermission(LinkPermission.class, "symbolic");
 260                     } finally {
 261                         delete(target);
 262                     }
 263                 } finally {
 264                     delete(link);
 265                 }
 266             }
 267 
 268             // -- createDirectory --
 269 
 270             Path subdir = testdir.resolve("subdir1234");
 271             prepare();
 272             createDirectory(subdir);
 273             try {
 274                 assertCheckWrite(subdir);
 275             } finally {
 276                 delete(subdir);
 277             }
 278 
 279             // -- createFile --
 280 
 281             Path fileToCreate = testdir.resolve("file7890");
 282             prepare();
 283             createFile(fileToCreate);
 284             try {
 285                 assertCheckWrite(fileToCreate);
 286             } finally {
 287                 delete(fileToCreate);
 288             }
 289 
 290             // -- createSymbolicLink --
 291 
 292             if (TestUtil.supportsLinks(testdir)) {
 293                 prepare();
 294                 Path link = testdir.resolve("link1234");
 295                 createSymbolicLink(link, file);
 296                 try {
 297                     assertCheckWrite(link);
 298                     assertCheckPermission(LinkPermission.class, "symbolic");
 299                 } finally {
 300                     delete(link);
 301                 }
 302             }
 303 
 304             // -- createLink --
 305 
 306             if (TestUtil.supportsLinks(testdir)) {
 307                 prepare();
 308                 Path link = testdir.resolve("entry234");
 309                 createLink(link, file);
 310                 try {
 311                     assertCheckWrite(link);
 312                     assertCheckPermission(LinkPermission.class, "hard");
 313                 } finally {
 314                     delete(link);
 315                 }
 316             }
 317 
 318             // -- createTempFile --
 319 
 320             prepare();
 321             Path tmpfile1 = createTempFile("foo", null);
 322             try {
 323                 assertCheckWriteToDirectory(tmpdir);
 324             } finally {
 325                 delete(tmpfile1);
 326             }
 327             prepare();
 328             Path tmpfile2 = createTempFile(testdir, "foo", ".tmp");
 329             try {
 330                 assertCheckWriteToDirectory(testdir);
 331             } finally {
 332                 delete(tmpfile2);
 333             }
 334 
 335             // -- createTempDirectory --
 336 
 337             prepare();
 338             Path tmpdir1 = createTempDirectory("foo");
 339             try {
 340                 assertCheckWriteToDirectory(tmpdir);
 341             } finally {
 342                 delete(tmpdir1);
 343             }
 344             prepare();
 345             Path tmpdir2 = createTempDirectory(testdir, "foo");
 346             try {
 347                 assertCheckWriteToDirectory(testdir);
 348             } finally {
 349                 delete(tmpdir2);
 350             }
 351 
 352             // -- delete/deleteIfExists --
 353 
 354             Path fileToDelete = testdir.resolve("file7890");
 355 
 356             createFile(fileToDelete);
 357             prepare();
 358             delete(fileToDelete);
 359             assertCheckDelete(fileToDelete);
 360 
 361             createFile(fileToDelete);
 362             prepare();
 363             deleteIfExists(fileToDelete);   // file exists
 364             assertCheckDelete(fileToDelete);
 365 
 366             prepare();
 367             deleteIfExists(fileToDelete);   // file does not exist
 368             assertCheckDelete(fileToDelete);
 369 
 370             // -- exists/notExists --
 371 
 372             prepare();
 373             exists(file);
 374             assertCheckRead(file);
 375 
 376             prepare();
 377             notExists(file);
 378             assertCheckRead(file);
 379 
 380             // -- getFileStore --
 381 
 382             prepare();
 383             getFileStore(file);
 384             assertCheckRead(file);
 385             assertCheckPermission(RuntimePermission.class, "getFileStoreAttributes");
 386 
 387             // -- isSameFile --
 388 
 389             prepare();
 390             isSameFile(file, testdir);
 391             assertCheckRead(file);
 392             assertCheckRead(testdir);
 393 
 394             // -- move --
 395 
 396             Path target2 = testdir.resolve("target1234");
 397             prepare();
 398             move(file, target2);
 399             try {
 400                 assertCheckWrite(file);
 401                 assertCheckWrite(target2);
 402             } finally {
 403                 // restore file
 404                 move(target2, file);
 405             }
 406 
 407             // -- newByteChannel --
 408 
 409             prepare();
 410             try (SeekableByteChannel sbc = newByteChannel(file)) {
 411                 assertCheckRead(file);
 412             }
 413             prepare();
 414             try (SeekableByteChannel sbc = newByteChannel(file, WRITE)) {
 415                 assertCheckWrite(file);
 416             }
 417             prepare();
 418             try (SeekableByteChannel sbc = newByteChannel(file, READ, WRITE)) {
 419                 assertCheckRead(file);
 420                 assertCheckWrite(file);
 421             }
 422 
 423             prepare();
 424             try (SeekableByteChannel sbc = newByteChannel(file, DELETE_ON_CLOSE)) {
 425                 assertCheckRead(file);
 426                 assertCheckDelete(file);
 427             }
 428             createFile(file); // restore file
 429 
 430 
 431             // -- newInputStream/newOutptuStream --
 432 
 433             prepare();
 434             try (InputStream in = newInputStream(file)) {
 435                 assertCheckRead(file);
 436             }
 437             prepare();
 438             try (OutputStream out = newOutputStream(file)) {
 439                 assertCheckWrite(file);
 440             }
 441 
 442             // -- newDirectoryStream --
 443 
 444             prepare();
 445             try (DirectoryStream<Path> stream = newDirectoryStream(testdir)) {
 446                 assertCheckRead(testdir);
 447 
 448                 if (stream instanceof SecureDirectoryStream<?>) {
 449                     Path entry;
 450                     SecureDirectoryStream<Path> sds =
 451                         (SecureDirectoryStream<Path>)stream;
 452 
 453                     // newByteChannel
 454                     entry = file.getFileName();
 455                     prepare();
 456                     try (SeekableByteChannel sbc = sds.newByteChannel(entry, EnumSet.of(READ))) {
 457                         assertCheckRead(file);
 458                     }
 459                     prepare();
 460                     try (SeekableByteChannel sbc = sds.newByteChannel(entry, EnumSet.of(WRITE))) {
 461                         assertCheckWrite(file);
 462                     }
 463 
 464                     // deleteFile
 465                     entry = file.getFileName();
 466                     prepare();
 467                     sds.deleteFile(entry);
 468                     assertCheckDelete(file);
 469                     createFile(testdir.resolve(entry));  // restore file
 470 
 471                     // deleteDirectory
 472                     entry = Paths.get("subdir1234");
 473                     createDirectory(testdir.resolve(entry));
 474                     prepare();
 475                     sds.deleteDirectory(entry);
 476                     assertCheckDelete(testdir.resolve(entry));
 477 
 478                     // move
 479                     entry = Paths.get("tempname1234");
 480                     prepare();
 481                     sds.move(file.getFileName(), sds, entry);
 482                     assertCheckWrite(file);
 483                     assertCheckWrite(testdir.resolve(entry));
 484                     sds.move(entry, sds, file.getFileName());  // restore file
 485 
 486                     // newDirectoryStream
 487                     entry = Paths.get("subdir1234");
 488                     createDirectory(testdir.resolve(entry));
 489                     try {
 490                         prepare();
 491                         sds.newDirectoryStream(entry).close();
 492                         assertCheckRead(testdir.resolve(entry));
 493                     } finally {
 494                         delete(testdir.resolve(entry));
 495                     }
 496 
 497                     // getFileAttributeView to access attributes of directory
 498                     testBasicFileAttributeView(sds
 499                         .getFileAttributeView(BasicFileAttributeView.class), testdir);
 500                     testPosixFileAttributeView(sds
 501                         .getFileAttributeView(PosixFileAttributeView.class), testdir);
 502 
 503                     // getFileAttributeView to access attributes of entry
 504                     entry = file.getFileName();
 505                     testBasicFileAttributeView(sds
 506                         .getFileAttributeView(entry, BasicFileAttributeView.class), file);
 507                     testPosixFileAttributeView(sds
 508                         .getFileAttributeView(entry, PosixFileAttributeView.class), file);
 509 
 510                 } else {
 511                     System.out.println("SecureDirectoryStream not tested");
 512                 }
 513             }
 514 
 515             // -- toAbsolutePath --
 516 
 517             prepare();
 518             file.getFileName().toAbsolutePath();
 519             assertCheckPropertyAccess("user.dir");
 520 
 521             // -- toRealPath --
 522 
 523             prepare();
 524             file.toRealPath(true);
 525             assertCheckRead(file);
 526 
 527             prepare();
 528             file.toRealPath(false);
 529             assertCheckRead(file);
 530 
 531             prepare();
 532             Paths.get(".").toRealPath(true);
 533             assertCheckPropertyAccess("user.dir");
 534 
 535             prepare();
 536             Paths.get(".").toRealPath(false);
 537             assertCheckPropertyAccess("user.dir");
 538 
 539             // -- register --
 540 
 541             try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
 542                 prepare();
 543                 testdir.register(watcher, StandardWatchEventKind.ENTRY_DELETE);
 544                 assertCheckRead(testdir);
 545             }
 546 
 547             // -- getAttribute/setAttribute/readAttributes --
 548 
 549             prepare();
 550             getAttribute(file, "size");
 551             assertCheckRead(file);
 552 
 553             prepare();
 554             setAttribute(file, "lastModifiedTime",
 555                 FileTime.fromMillis(System.currentTimeMillis()));
 556             assertCheckWrite(file);
 557 
 558             prepare();
 559             readAttributes(file, "*");
 560             assertCheckRead(file);
 561 
 562             // -- BasicFileAttributeView --
 563             testBasicFileAttributeView(
 564                 getFileAttributeView(file, BasicFileAttributeView.class), file);
 565 
 566             // -- PosixFileAttributeView --
 567 
 568             {
 569                 PosixFileAttributeView view =
 570                     getFileAttributeView(file, PosixFileAttributeView.class);
 571                 if (view != null &&
 572                     getFileStore(file).supportsFileAttributeView(PosixFileAttributeView.class))
 573                 {
 574                     testPosixFileAttributeView(view, file);
 575                 } else {
 576                     System.out.println("PosixFileAttributeView not tested");
 577                 }
 578             }
 579 
 580             // -- DosFileAttributeView --
 581 
 582             {
 583                 DosFileAttributeView view =
 584                     getFileAttributeView(file, DosFileAttributeView.class);
 585                 if (view != null &&
 586                     getFileStore(file).supportsFileAttributeView(DosFileAttributeView.class))
 587                 {
 588                     prepare();
 589                     view.readAttributes();
 590                     assertCheckRead(file);
 591 
 592                     prepare();
 593                     view.setArchive(false);
 594                     assertCheckWrite(file);
 595 
 596                     prepare();
 597                     view.setHidden(false);
 598                     assertCheckWrite(file);
 599 
 600                     prepare();
 601                     view.setReadOnly(false);
 602                     assertCheckWrite(file);
 603 
 604                     prepare();
 605                     view.setSystem(false);
 606                     assertCheckWrite(file);
 607                 } else {
 608                     System.out.println("DosFileAttributeView not tested");
 609                 }
 610             }
 611 
 612             // -- FileOwnerAttributeView --
 613 
 614             {
 615                 FileOwnerAttributeView view =
 616                     getFileAttributeView(file, FileOwnerAttributeView.class);
 617                 if (view != null &&
 618                     getFileStore(file).supportsFileAttributeView(FileOwnerAttributeView.class))
 619                 {
 620                     prepare();
 621                     UserPrincipal owner = view.getOwner();
 622                     assertCheckRead(file);
 623                     assertCheckPermission(RuntimePermission.class, "accessUserInformation");
 624 
 625                     prepare();
 626                     view.setOwner(owner);
 627                     assertCheckWrite(file);
 628                     assertCheckPermission(RuntimePermission.class, "accessUserInformation");
 629 
 630                 } else {
 631                     System.out.println("FileOwnerAttributeView not tested");
 632                 }
 633             }
 634 
 635             // -- UserDefinedFileAttributeView --
 636 
 637             {
 638                 UserDefinedFileAttributeView view =
 639                     getFileAttributeView(file, UserDefinedFileAttributeView.class);
 640                 if (view != null &&
 641                     getFileStore(file).supportsFileAttributeView(UserDefinedFileAttributeView.class))
 642                 {
 643                     prepare();
 644                     view.write("test", ByteBuffer.wrap(new byte[100]));
 645                     assertCheckWrite(file);
 646                     assertCheckPermission(RuntimePermission.class,
 647                                                "accessUserDefinedAttributes");
 648 
 649                     prepare();
 650                     view.read("test", ByteBuffer.allocate(100));
 651                     assertCheckRead(file);
 652                     assertCheckPermission(RuntimePermission.class,
 653                                                "accessUserDefinedAttributes");
 654 
 655                     prepare();
 656                     view.size("test");
 657                     assertCheckRead(file);
 658                     assertCheckPermission(RuntimePermission.class,
 659                                                "accessUserDefinedAttributes");
 660 
 661                     prepare();
 662                     view.list();
 663                     assertCheckRead(file);
 664                     assertCheckPermission(RuntimePermission.class,
 665                                                "accessUserDefinedAttributes");
 666 
 667                     prepare();
 668                     view.delete("test");
 669                     assertCheckWrite(file);
 670                     assertCheckPermission(RuntimePermission.class,
 671                                                "accessUserDefinedAttributes");
 672                 } else {
 673                     System.out.println("UserDefinedFileAttributeView not tested");
 674                 }
 675             }
 676 
 677             // -- AclFileAttributeView --
 678             {
 679                 AclFileAttributeView view =
 680                     getFileAttributeView(file, AclFileAttributeView.class);
 681                 if (view != null &&
 682                     getFileStore(file).supportsFileAttributeView(AclFileAttributeView.class))
 683                 {
 684                     prepare();
 685                     List<AclEntry> acl = view.getAcl();
 686                     assertCheckRead(file);
 687                     assertCheckPermission(RuntimePermission.class, "accessUserInformation");
 688                     prepare();
 689                     view.setAcl(acl);
 690                     assertCheckWrite(file);
 691                     assertCheckPermission(RuntimePermission.class, "accessUserInformation");
 692                 } else {
 693                     System.out.println("AclFileAttributeView not tested");
 694                 }
 695             }
 696 
 697             // -- UserPrincipalLookupService
 698 
 699             UserPrincipalLookupService lookupService =
 700                 FileSystems.getDefault().getUserPrincipalLookupService();
 701             UserPrincipal owner = getOwner(file);
 702 
 703             prepare();
 704             lookupService.lookupPrincipalByName(owner.getName());
 705             assertCheckPermission(RuntimePermission.class,
 706                                        "lookupUserInformation");
 707 
 708             try {
 709                 UserPrincipal group = readAttributes(file, PosixFileAttributes.class).group();
 710                 prepare();
 711                 lookupService.lookupPrincipalByGroupName(group.getName());
 712                 assertCheckPermission(RuntimePermission.class,
 713                                            "lookupUserInformation");
 714             } catch (UnsupportedOperationException ignore) {
 715                 System.out.println("lookupPrincipalByGroupName not tested");
 716             }
 717 
 718 
 719         } finally {
 720             deleteIfExists(file);
 721         }
 722     }
 723 }