Author: mturk Date: Sat May 23 15:14:50 2009 New Revision: 777940 URL: http://svn.apache.org/viewvc?rev=777940&view=rev Log: Implement file protection setter
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java?rev=777940&r1=777939&r2=777940&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java Sat May 23 15:14:50 2009 @@ -36,6 +36,8 @@ throws IOException, SecurityException; private static native int fprot0(String pathname) throws IOException, SecurityException; + private static native boolean fprot1(String pathname, int prot) + throws IOException, SecurityException; private static native boolean mkslink0(String target, String link) throws IOException, SecurityException, UnsupportedOperationException; @@ -185,6 +187,12 @@ return FileProtection.valueOf(mode); } + public boolean setFileProtection(EnumSet<FileProtection> prot) + throws IOException, SecurityException + { + return fprot1(getPath(), FileProtection.bitmapOf(prot)); + } + /** * Returns {...@code true} if the file denoted by this abstract * pathname is symbolic link. Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h?rev=777940&r1=777939&r2=777940&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/acr_file.h Sat May 23 15:14:50 2009 @@ -42,7 +42,7 @@ #define ACR_FT_UNKFILE 127 /**< a file of some other unknown type */ /** - * @defgroup apr_file_permissions File Permissions flags + * @defgroup apr_file_permissions File Permissions flags * @{ */ @@ -135,10 +135,28 @@ * @param env JNI environment to use. If NULL no exception will be thrown * if stat fails. * @param fname File name for which to get the type. - * @return One of the ACR_FT_* types or -1 of error + * @return One of the ACR_FT_* types or -1 on error */ ACR_DECLARE(int) ACR_FileTypeGet(JNIEnv *_E, const acr_pchar_t *fname); +/** Set File protection mode + * @param env JNI environment to use. If NULL no exception will be thrown + * if stat fails. + * @param fname File name for which to set the protection. + * @param prot Combination of ACR_FPROT_* flags. + * @return ACR_ERROR code on failure + */ +ACR_DECLARE(int) ACR_FileProtectionSet(JNIEnv *_E, acr_pchar_t *fname, + int prot); + +/** Get File protection mode + * @param env JNI environment to use. If NULL no exception will be thrown + * if stat fails. + * @param fname File name for which to set the protection. + * @return Combination of ACR_FPROT_* flags or -1 on error. + */ +ACR_DECLARE(int) ACR_FileProtectionGet(JNIEnv *_E, acr_pchar_t *fname); + /** Create new File object with FileType set. * @param env JNI environment to use. If NULL no exception will be thrown * if stat fails. Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c?rev=777940&r1=777939&r2=777940&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c Sat May 23 15:14:50 2009 @@ -91,12 +91,12 @@ * include files, APR cannot report a good reason why the stat() * of the file failed; there are cases where it can fail even though * the file exists. This opens holes in Apache, for example, because - * it becomes possible for someone to get a directory listing of a - * directory even though there is an index (eg. index.html) file in - * it. If you do not have a problem with this, delete the above + * it becomes possible for someone to get a directory listing of a + * directory even though there is an index (eg. index.html) file in + * it. If you do not have a problem with this, delete the above * #error lines and start the compile again. If you need to do this, * please submit a bug report to http://www.apache.org/bug_report.html - * letting us know that you needed to do this. Please be sure to + * letting us know that you needed to do this. Please be sure to * include the operating system you are using. */ #endif @@ -288,6 +288,23 @@ return -1; } +ACR_DECLARE(int) ACR_FileProtectionSet(JNIEnv *_E, const char *fname, int prot) +{ + struct_stat info; + + /* Always use a real target */ + if (chown(fname, ACR_UnixPermsToMode(prot)) == 0) { + return 0; + } + else if (_E) { + if (errno == EACCES) + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0); + else + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, errno); + } + return errno; +} + ACR_IO_EXPORT_DECLARE(int, File, fprot0)(ACR_JNISTDARGS, jstring pathname) { int prot = 0; @@ -299,3 +316,20 @@ return prot; } + +ACR_IO_EXPORT_DECLARE(jboolean, File, fprot1)(ACR_JNISTDARGS, jstring pathname, + jint prot) +{ + int rc = -1; + + UNREFERENCED_O; + + WITH_WSTR(pathname) { + rc = ACR_FileProtectionSet(_E, J2W(pathname), prot); + } END_WITH_WSTR(pathname); + + if (rc) + return JNI_FALSE; + else + return JNI_TRUE; +} Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c?rev=777940&r1=777939&r2=777940&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c Sat May 23 15:14:50 2009 @@ -358,6 +358,23 @@ return (prot << scope); } +static ACCESS_MASK convert_acc(int prot, prot_scope_e scope) +{ + /* These choices are based on the single filesystem bit that controls + * the given behavior. They are -not- recommended for any set protection + * function, such a function should -set- use GENERIC_READ/WRITE/EXECUTE + */ + ACCESS_MASK acc = 0; + prot = (prot >> scope) & 0x0F; + if (prot & ACR_FPROT_WEXECUTE) + acc |= FILE_EXECUTE; + if (prot & ACR_FPROT_WWRITE) + acc |= FILE_WRITE_DATA; + if (prot & ACR_FPROT_WREAD) + acc |= FILE_READ_DATA; + return acc; +} + static int resolve_prot(PSID user, PSID group, PACL dacl) { TRUSTEE_W ident = { NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID }; @@ -405,16 +422,23 @@ int protection = 0; PSID user = NULL, group = NULL; PACL dacl = NULL; - PSECURITY_DESCRIPTOR pdesc = NULL; + PSECURITY_DESCRIPTOR ppsd = NULL; int fix = 0; int rc; if (wcsncmp(fname, L"\\\\?\\", 4) == 0) { fname += 4; if (wcsncmp(fname, L"UNC\\", 4) == 0) { + /* TODO: Do not modify in fname in-place. + */ fname += 2; *fname = L'\\'; } + else if (wcsncmp(fname, L"UN\\\\", 4) == 0) { + /* Already modified in-place. + */ + fname += 2; + } } rc = GetNamedSecurityInfoW(fname, SE_FILE_OBJECT, @@ -423,7 +447,7 @@ &group, &dacl, NULL, - &pdesc); + &ppsd); if (rc == ERROR_SUCCESS) { return resolve_prot(user, group, dacl); } @@ -437,6 +461,137 @@ return 0; } +static PACL update_prot(PSID user, PSID group, PACL dacl, int prot) +{ + PACL eacl = NULL; + EXPLICIT_ACCESS_W eacc[3]; + ACCESS_MASK acc; + TRUSTEE_W ident = { NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID }; + int tc = 0; + DWORD rc; + + /* + * This function is only invoked for WinNT, + * there is no reason for os_level testing here. + */ + acc = convert_acc(prot, prot_scope_user); + if (user && acc) { + ZeroMemory(&eacc[tc], sizeof(EXPLICIT_ACCESS)); + eacc[tc].Trustee = ident; + eacc[tc].Trustee.TrusteeType = TRUSTEE_IS_USER; + eacc[tc].Trustee.ptstrName = user; + eacc[tc].grfAccessPermissions = acc; + eacc[tc].grfAccessMode = SET_ACCESS; + eacc[tc].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; + + ++tc; + } + /* Windows NT: did not return group rights. + * Windows 2000 returns group rights information. + * Since WinNT kernels don't follow the unix model of + * group associations, this all all pretty mute. + */ + acc = convert_acc(prot, prot_scope_group); + if (group && acc) { + ZeroMemory(&eacc[tc], sizeof(EXPLICIT_ACCESS)); + eacc[tc].Trustee = ident; + eacc[tc].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + eacc[tc].Trustee.ptstrName = group; + eacc[tc].grfAccessPermissions = acc; + eacc[tc].grfAccessMode = SET_ACCESS; + eacc[tc].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; + + ++tc; + } + acc = convert_acc(prot, prot_scope_world); + if (acr_everyone_sid && acc) { + ZeroMemory(&eacc[tc], sizeof(EXPLICIT_ACCESS)); + eacc[tc].Trustee = ident; + eacc[tc].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + eacc[tc].Trustee.ptstrName = acr_everyone_sid; + eacc[tc].grfAccessPermissions = acc; + eacc[tc].grfAccessMode = SET_ACCESS; + eacc[tc].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; + + ++tc; + } + rc = SetEntriesInAclW(tc, &eacc[0], dacl, &eacl); + if (rc != ERROR_SUCCESS) { + SetLastError(rc); + return NULL; + } + else { + return eacl; + } +} + +ACR_DECLARE(int) ACR_FileProtectionSet(JNIEnv *_E, wchar_t *fname, int prot) +{ + int protection = 0; + PSID user = NULL, group = NULL; + PACL dacl = NULL; + PACL eacl = NULL; + PSECURITY_DESCRIPTOR ppsd = NULL; + int fix = 0; + int rc; + + if (wcsncmp(fname, L"\\\\?\\", 4) == 0) { + fname += 4; + if (wcsncmp(fname, L"UNC\\", 4) == 0) { + fname += 2; + *fname = L'\\'; + } + else if (wcsncmp(fname, L"UN\\\\", 4) == 0) { + /* Already modified in-place. + */ + fname += 2; + } + } + rc = GetNamedSecurityInfoW(fname, + SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + &user, + &group, + &dacl, + NULL, + &ppsd); + if (rc != ERROR_SUCCESS) { + goto failed; + } + + eacl = update_prot(user, group, dacl, prot); + if (!eacl) { + rc = GetLastError(); + goto failed; + } + rc = SetNamedSecurityInfoW(fname, + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, + NULL, + NULL, + eacl, + NULL); + + if (rc != ERROR_SUCCESS) { + goto failed; + } + LocalFree((HLOCAL)eacl); + return 0; + +failed: + rc = ACR_FROM_OS_ERROR(rc); + if (_E) { + if (ACR_STATUS_IS_EACCES(rc)) + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0); + else + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, rc); + } + if (eacl) { + LocalFree((HLOCAL)eacl); + } + return rc; +} + ACR_IO_EXPORT_DECLARE(int, File, fprot0)(ACR_JNISTDARGS, jstring pathname) { int prot = 0; @@ -448,3 +603,20 @@ return prot; } + +ACR_IO_EXPORT_DECLARE(jboolean, File, fprot1)(ACR_JNISTDARGS, jstring pathname, + jint prot) +{ + int rc = -1; + + UNREFERENCED_O; + + WITH_WSTR(pathname) { + rc = ACR_FileProtectionSet(_E, J2W(pathname), prot); + } END_WITH_WSTR(pathname); + + if (rc) + return JNI_FALSE; + else + return JNI_TRUE; +} Modified: commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java?rev=777940&r1=777939&r2=777940&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java (original) +++ commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java Sat May 23 15:14:50 2009 @@ -99,10 +99,10 @@ File second = new File("foo"); File link2 = second.createSymbolicLink("bar"); assertEquals("Name", "bar", link2.getPath()); - + symlnk.delete(); } catch (UnsupportedOperationException u) { - // fail("Unsupported Operating system"); + // fail("Unsupported Operating system"); } } @@ -121,12 +121,12 @@ File link2 = second.createSymbolicLink("bar"); fail("Exception not thrown"); } catch (Exception ex) { - // This is expected - } finally { + // This is expected + } finally { symlnk.delete(); } } catch (UnsupportedOperationException u) { - // fail("Unsupported Operating system"); + // fail("Unsupported Operating system"); } } @@ -141,10 +141,10 @@ assertEquals("Type", FileType.LNK, t); File target = symlnk.getTargetFile(); assertEquals("Target", source.getPath(), target.getPath()); - + symlnk.delete(); } catch (UnsupportedOperationException u) { - // fail("Unsupported Operating system"); + // fail("Unsupported Operating system"); } } @@ -167,7 +167,7 @@ } } - public void testProtection() + public void testGetProtection() throws Exception { File f = new File("ffoo"); @@ -176,5 +176,20 @@ System.out.println("Protection " + fp); assertTrue("UWRITE", fp.contains(FileProtection.UWRITE)); f.delete(); - } + } + + public void testSetProtection() + throws Exception + { + File f = new File("ffoo"); + f.createNewFile(); + EnumSet <FileProtection> fp = f.getFileProtection(); + System.out.println("Org Protection " + fp); + f.setFileProtection(EnumSet.of(FileProtection.GWRITE)); + EnumSet <FileProtection> np = f.getFileProtection(); + System.out.println("Set Protection " + np); + assertTrue("GWRITE", np.contains(FileProtection.GWRITE)); + f.delete(); + } + }