1/*
2 * Copyright (c) 2009, 2015, 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 8028270 8065109
26 * @summary Unit test for java.nio.file.Files
27 * @library ..
28 * @build CheckPermissions
29 * @run main/othervm CheckPermissions
30 */
31
32import java.nio.ByteBuffer;
33import java.nio.file.*;
34import static java.nio.file.Files.*;
35import static java.nio.file.StandardOpenOption.*;
36import java.nio.file.attribute.*;
37import java.nio.channels.SeekableByteChannel;
38import java.security.Permission;
39import java.io.*;
40import java.nio.charset.StandardCharsets;
41import java.util.*;
42
43/**
44 * Checks each method that accesses the file system does the right permission
45 * check when there is a security manager set.
46 */
47
48public class CheckPermissions {
49
50    static class Checks {
51        private List<Permission> permissionsChecked = new ArrayList<>();
52        private Set<String>  propertiesChecked = new HashSet<>();
53        private List<String> readsChecked   = new ArrayList<>();
54        private List<String> writesChecked  = new ArrayList<>();
55        private List<String> deletesChecked = new ArrayList<>();
56        private List<String> execsChecked   = new ArrayList<>();
57
58        List<Permission> permissionsChecked()  { return permissionsChecked; }
59        Set<String> propertiesChecked()        { return propertiesChecked; }
60        List<String> readsChecked()            { return readsChecked; }
61        List<String> writesChecked()           { return writesChecked; }
62        List<String> deletesChecked()          { return deletesChecked; }
63        List<String> execsChecked()            { return execsChecked; }
64    }
65
66    static ThreadLocal<Checks> myChecks =
67        new ThreadLocal<Checks>() {
68            @Override protected Checks initialValue() {
69                return null;
70            }
71        };
72
73    static void prepare() {
74        myChecks.set(new Checks());
75    }
76
77    static void assertCheckPermission(Permission expected) {
78        if (!myChecks.get().permissionsChecked().contains(expected))
79          throw new RuntimeException(expected + " not checked");
80    }
81
82    static void assertCheckPropertyAccess(String key) {
83        if (!myChecks.get().propertiesChecked().contains(key))
84            throw new RuntimeException("Property " + key + " not checked");
85    }
86
87    static void assertChecked(Path file, List<String> list) {
88        String s = file.toString();
89        for (String f: list) {
90            if (f.endsWith(s))
91                return;
92        }
93        throw new RuntimeException("Access not checked");
94    }
95
96    static void assertCheckRead(Path file) {
97        assertChecked(file, myChecks.get().readsChecked());
98    }
99
100    static void assertCheckWrite(Path file) {
101        assertChecked(file, myChecks.get().writesChecked());
102    }
103
104    static void assertCheckWriteToDirectory(Path dir) {
105        String s = dir.toString();
106        List<String> list = myChecks.get().writesChecked();
107        for (String f: list) {
108            if (f.startsWith(s)) {
109                return;
110            }
111        }
112        throw new RuntimeException("Access not checked");
113    }
114
115    static void assertCheckDelete(Path file) {
116        assertChecked(file, myChecks.get().deletesChecked());
117    }
118
119    static void assertCheckExec(Path file) {
120        assertChecked(file, myChecks.get().execsChecked());
121    }
122
123    static class LoggingSecurityManager extends SecurityManager {
124        static void install() {
125            System.setSecurityManager(new LoggingSecurityManager());
126        }
127
128        @Override
129        public void checkPermission(Permission perm) {
130            Checks checks = myChecks.get();
131            if (checks != null)
132                checks.permissionsChecked().add(perm);
133        }
134
135        @Override
136        public void checkPropertyAccess(String key) {
137            Checks checks = myChecks.get();
138            if (checks != null)
139                checks.propertiesChecked().add(key);
140        }
141
142        @Override
143        public void checkRead(String file) {
144            Checks checks = myChecks.get();
145            if (checks != null)
146                checks.readsChecked().add(file);
147        }
148
149        @Override
150        public void checkWrite(String file) {
151            Checks checks = myChecks.get();
152            if (checks != null)
153                checks.writesChecked().add(file);
154        }
155
156        @Override
157        public void checkDelete(String file) {
158            Checks checks = myChecks.get();
159            if (checks != null)
160                checks.deletesChecked().add(file);
161        }
162
163        @Override
164        public void checkExec(String file) {
165            Checks checks = myChecks.get();
166            if (checks != null)
167                checks.execsChecked().add(file);
168        }
169    }
170
171    static void testBasicFileAttributeView(BasicFileAttributeView view, Path file)
172        throws IOException
173    {
174        prepare();
175        view.readAttributes();
176        assertCheckRead(file);
177
178        prepare();
179        FileTime now = FileTime.fromMillis(System.currentTimeMillis());
180        view.setTimes(null, now, now);
181        assertCheckWrite(file);
182    }
183
184    static void testPosixFileAttributeView(PosixFileAttributeView view, Path file)
185        throws IOException
186    {
187        prepare();
188        PosixFileAttributes attrs = view.readAttributes();
189        assertCheckRead(file);
190        assertCheckPermission(new RuntimePermission("accessUserInformation"));
191
192        prepare();
193        view.setPermissions(attrs.permissions());
194        assertCheckWrite(file);
195        assertCheckPermission(new RuntimePermission("accessUserInformation"));
196
197        prepare();
198        view.setOwner(attrs.owner());
199        assertCheckWrite(file);
200        assertCheckPermission(new RuntimePermission("accessUserInformation"));
201
202        prepare();
203        view.setOwner(attrs.owner());
204        assertCheckWrite(file);
205        assertCheckPermission(new RuntimePermission("accessUserInformation"));
206    }
207
208    public static void main(String[] args) throws IOException {
209        final Path testdir = Paths.get(System.getProperty("test.dir", ".")).toAbsolutePath();
210        final Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
211
212        Path file = createFile(testdir.resolve("file1234"));
213        try {
214            LoggingSecurityManager.install();
215
216            // -- check access --
217
218            prepare();
219            exists(file);
220            assertCheckRead(file);
221
222            prepare();
223            isReadable(file);
224            assertCheckRead(file);
225
226            prepare();
227            isWritable(file);
228            assertCheckWrite(file);
229
230            prepare();
231            isExecutable(file);
232            assertCheckExec(file);
233
234            // -- copy --
235
236            Path target = testdir.resolve("target1234");
237            prepare();
238            copy(file, target);
239            try {
240                assertCheckRead(file);
241                assertCheckWrite(target);
242            } finally {
243                delete(target);
244            }
245
246            if (TestUtil.supportsLinks(testdir)) {
247                Path link = testdir.resolve("link1234");
248                createSymbolicLink(link, file);
249                try {
250                    prepare();
251                    copy(link, target, LinkOption.NOFOLLOW_LINKS);
252                    try {
253                        assertCheckRead(link);
254                        assertCheckWrite(target);
255                        assertCheckPermission(new LinkPermission("symbolic"));
256                    } finally {
257                        delete(target);
258                    }
259
260                    prepare();
261                    readSymbolicLink(link);
262                    assertCheckPermission(new FilePermission(link.toString(), "readlink"));
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(new LinkPermission("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(new LinkPermission("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(new RuntimePermission("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            // -- newBufferedReader/newBufferedWriter --
431
432            prepare();
433            try (BufferedReader br = newBufferedReader(file)) {
434                assertCheckRead(file);
435            }
436
437            prepare();
438            try (BufferedWriter bw = newBufferedWriter(file, WRITE)) {
439                assertCheckWrite(file);
440            }
441
442            prepare();
443            try (BufferedWriter bw = newBufferedWriter(file, DELETE_ON_CLOSE)) {
444                assertCheckWrite(file);
445                assertCheckDelete(file);
446            }
447            createFile(file); // restore file
448
449            prepare();
450            try (BufferedWriter bw = newBufferedWriter(file,
451                StandardCharsets.UTF_16, WRITE)) {
452                assertCheckWrite(file);
453            }
454
455            prepare();
456            try (BufferedWriter bw = newBufferedWriter(file,
457                StandardCharsets.UTF_16, DELETE_ON_CLOSE)) {
458                assertCheckWrite(file);
459                assertCheckDelete(file);
460            }
461            createFile(file); // restore file
462
463            // -- newInputStream/newOutputStream --
464
465            prepare();
466            try (InputStream in = newInputStream(file)) {
467                assertCheckRead(file);
468            }
469            prepare();
470            try (OutputStream out = newOutputStream(file)) {
471                assertCheckWrite(file);
472            }
473
474            // -- write --
475
476            prepare();
477            Files.write(file, new byte[]{(byte) 42, (byte) 666}, WRITE);
478            assertCheckWrite(file);
479
480            prepare();
481            Files.write(file, new byte[]{(byte) 42, (byte) 666}, WRITE,
482                DELETE_ON_CLOSE);
483            assertCheckWrite(file);
484            assertCheckDelete(file);
485            createFile(file); // restore file
486
487            List<String> lines = Arrays.asList("42", "666");
488
489            prepare();
490            Files.write(file, lines, StandardCharsets.UTF_16, WRITE);
491            assertCheckWrite(file);
492
493            prepare();
494            Files.write(file, lines, StandardCharsets.UTF_16, WRITE,
495                DELETE_ON_CLOSE);
496            assertCheckWrite(file);
497            assertCheckDelete(file);
498            createFile(file); // restore file
499
500            prepare();
501            Files.write(file, lines, WRITE);
502            assertCheckWrite(file);
503
504            prepare();
505            Files.write(file, lines, WRITE, DELETE_ON_CLOSE);
506            assertCheckWrite(file);
507            assertCheckDelete(file);
508            createFile(file); // restore file
509
510            // -- newDirectoryStream --
511
512            prepare();
513            try (DirectoryStream<Path> stream = newDirectoryStream(testdir)) {
514                assertCheckRead(testdir);
515
516                if (stream instanceof SecureDirectoryStream<?>) {
517                    Path entry;
518                    SecureDirectoryStream<Path> sds =
519                        (SecureDirectoryStream<Path>)stream;
520
521                    // newByteChannel
522                    entry = file.getFileName();
523                    prepare();
524                    try (SeekableByteChannel sbc = sds.newByteChannel(entry, EnumSet.of(READ))) {
525                        assertCheckRead(file);
526                    }
527                    prepare();
528                    try (SeekableByteChannel sbc = sds.newByteChannel(entry, EnumSet.of(WRITE))) {
529                        assertCheckWrite(file);
530                    }
531
532                    // deleteFile
533                    entry = file.getFileName();
534                    prepare();
535                    sds.deleteFile(entry);
536                    assertCheckDelete(file);
537                    createFile(testdir.resolve(entry));  // restore file
538
539                    // deleteDirectory
540                    entry = Paths.get("subdir1234");
541                    createDirectory(testdir.resolve(entry));
542                    prepare();
543                    sds.deleteDirectory(entry);
544                    assertCheckDelete(testdir.resolve(entry));
545
546                    // move
547                    entry = Paths.get("tempname1234");
548                    prepare();
549                    sds.move(file.getFileName(), sds, entry);
550                    assertCheckWrite(file);
551                    assertCheckWrite(testdir.resolve(entry));
552                    sds.move(entry, sds, file.getFileName());  // restore file
553
554                    // newDirectoryStream
555                    entry = Paths.get("subdir1234");
556                    createDirectory(testdir.resolve(entry));
557                    try {
558                        prepare();
559                        sds.newDirectoryStream(entry).close();
560                        assertCheckRead(testdir.resolve(entry));
561                    } finally {
562                        delete(testdir.resolve(entry));
563                    }
564
565                    // getFileAttributeView to access attributes of directory
566                    testBasicFileAttributeView(sds
567                        .getFileAttributeView(BasicFileAttributeView.class), testdir);
568                    testPosixFileAttributeView(sds
569                        .getFileAttributeView(PosixFileAttributeView.class), testdir);
570
571                    // getFileAttributeView to access attributes of entry
572                    entry = file.getFileName();
573                    testBasicFileAttributeView(sds
574                        .getFileAttributeView(entry, BasicFileAttributeView.class), file);
575                    testPosixFileAttributeView(sds
576                        .getFileAttributeView(entry, PosixFileAttributeView.class), file);
577
578                } else {
579                    System.out.println("SecureDirectoryStream not tested");
580                }
581            }
582
583            // -- toAbsolutePath --
584
585            prepare();
586            file.getFileName().toAbsolutePath();
587            assertCheckPropertyAccess("user.dir");
588
589            // -- toRealPath --
590
591            prepare();
592            file.toRealPath();
593            assertCheckRead(file);
594
595            prepare();
596            file.toRealPath(LinkOption.NOFOLLOW_LINKS);
597            assertCheckRead(file);
598
599            prepare();
600            Paths.get(".").toRealPath();
601            assertCheckPropertyAccess("user.dir");
602
603            prepare();
604            Paths.get(".").toRealPath(LinkOption.NOFOLLOW_LINKS);
605            assertCheckPropertyAccess("user.dir");
606
607            // -- register --
608
609            try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
610                prepare();
611                testdir.register(watcher, StandardWatchEventKinds.ENTRY_DELETE);
612                assertCheckRead(testdir);
613            }
614
615            // -- getAttribute/setAttribute/readAttributes --
616
617            prepare();
618            getAttribute(file, "size");
619            assertCheckRead(file);
620
621            prepare();
622            setAttribute(file, "lastModifiedTime",
623                FileTime.fromMillis(System.currentTimeMillis()));
624            assertCheckWrite(file);
625
626            prepare();
627            readAttributes(file, "*");
628            assertCheckRead(file);
629
630            // -- BasicFileAttributeView --
631            testBasicFileAttributeView(
632                getFileAttributeView(file, BasicFileAttributeView.class), file);
633
634            // -- PosixFileAttributeView --
635
636            {
637                PosixFileAttributeView view =
638                    getFileAttributeView(file, PosixFileAttributeView.class);
639                if (view != null &&
640                    getFileStore(file).supportsFileAttributeView(PosixFileAttributeView.class))
641                {
642                    testPosixFileAttributeView(view, file);
643                } else {
644                    System.out.println("PosixFileAttributeView not tested");
645                }
646            }
647
648            // -- DosFileAttributeView --
649
650            {
651                DosFileAttributeView view =
652                    getFileAttributeView(file, DosFileAttributeView.class);
653                if (view != null &&
654                    getFileStore(file).supportsFileAttributeView(DosFileAttributeView.class))
655                {
656                    prepare();
657                    view.readAttributes();
658                    assertCheckRead(file);
659
660                    prepare();
661                    view.setArchive(false);
662                    assertCheckWrite(file);
663
664                    prepare();
665                    view.setHidden(false);
666                    assertCheckWrite(file);
667
668                    prepare();
669                    view.setReadOnly(false);
670                    assertCheckWrite(file);
671
672                    prepare();
673                    view.setSystem(false);
674                    assertCheckWrite(file);
675                } else {
676                    System.out.println("DosFileAttributeView not tested");
677                }
678            }
679
680            // -- FileOwnerAttributeView --
681
682            {
683                FileOwnerAttributeView view =
684                    getFileAttributeView(file, FileOwnerAttributeView.class);
685                if (view != null &&
686                    getFileStore(file).supportsFileAttributeView(FileOwnerAttributeView.class))
687                {
688                    prepare();
689                    UserPrincipal owner = view.getOwner();
690                    assertCheckRead(file);
691                    assertCheckPermission(new RuntimePermission("accessUserInformation"));
692
693                    prepare();
694                    view.setOwner(owner);
695                    assertCheckWrite(file);
696                    assertCheckPermission(new RuntimePermission("accessUserInformation"));
697
698                } else {
699                    System.out.println("FileOwnerAttributeView not tested");
700                }
701            }
702
703            // -- UserDefinedFileAttributeView --
704
705            {
706                UserDefinedFileAttributeView view =
707                    getFileAttributeView(file, UserDefinedFileAttributeView.class);
708                if (view != null &&
709                    getFileStore(file).supportsFileAttributeView(UserDefinedFileAttributeView.class))
710                {
711                    prepare();
712                    view.write("test", ByteBuffer.wrap(new byte[100]));
713                    assertCheckWrite(file);
714                    assertCheckPermission(new RuntimePermission("accessUserDefinedAttributes"));
715
716                    prepare();
717                    view.read("test", ByteBuffer.allocate(100));
718                    assertCheckRead(file);
719                    assertCheckPermission(new RuntimePermission("accessUserDefinedAttributes"));
720
721                    prepare();
722                    view.size("test");
723                    assertCheckRead(file);
724                    assertCheckPermission(new RuntimePermission("accessUserDefinedAttributes"));
725
726                    prepare();
727                    view.list();
728                    assertCheckRead(file);
729                    assertCheckPermission(new RuntimePermission("accessUserDefinedAttributes"));
730
731                    prepare();
732                    view.delete("test");
733                    assertCheckWrite(file);
734                    assertCheckPermission(new RuntimePermission("accessUserDefinedAttributes"));
735                } else {
736                    System.out.println("UserDefinedFileAttributeView not tested");
737                }
738            }
739
740            // -- AclFileAttributeView --
741            {
742                AclFileAttributeView view =
743                    getFileAttributeView(file, AclFileAttributeView.class);
744                if (view != null &&
745                    getFileStore(file).supportsFileAttributeView(AclFileAttributeView.class))
746                {
747                    prepare();
748                    List<AclEntry> acl = view.getAcl();
749                    assertCheckRead(file);
750                    assertCheckPermission(new RuntimePermission("accessUserInformation"));
751                    prepare();
752                    view.setAcl(acl);
753                    assertCheckWrite(file);
754                    assertCheckPermission(new RuntimePermission("accessUserInformation"));
755                } else {
756                    System.out.println("AclFileAttributeView not tested");
757                }
758            }
759
760            // -- UserPrincipalLookupService
761
762            UserPrincipalLookupService lookupService =
763                FileSystems.getDefault().getUserPrincipalLookupService();
764            UserPrincipal owner = getOwner(file);
765
766            prepare();
767            lookupService.lookupPrincipalByName(owner.getName());
768            assertCheckPermission(new RuntimePermission("lookupUserInformation"));
769
770            try {
771                UserPrincipal group = readAttributes(file, PosixFileAttributes.class).group();
772                prepare();
773                lookupService.lookupPrincipalByGroupName(group.getName());
774                assertCheckPermission(new RuntimePermission("lookupUserInformation"));
775            } catch (UnsupportedOperationException ignore) {
776                System.out.println("lookupPrincipalByGroupName not tested");
777            }
778
779
780        } finally {
781            deleteIfExists(file);
782        }
783    }
784}
785