Skip to content

Commit

Permalink
pol: update to oncrpc4j-3.1.0
Browse files Browse the repository at this point in the history
Motivation:
new major version update with improvements and breaking changes:

- Drop dependency on dcache-auth , which had incompatible license
- Experimental AUTH_TLS support
- Various javadoc improvements
- Improved code coverage
- removed direct dependency on grizzly-framework-monitoring

The result of removal of license incompatible dcache-auth in oncrpc4j is
migration from org.dcache.auth.GidPrincipal and org.dcache.auth.UidPrincipal
to com.sun.security.auth.UnixNumericGroupPrincipal and
com.sun.security.auth.UnixNumericUserPrincipa. This breaking change have
to be handled in nfs4j.

Modification:
Update pom to use oncrpc4j-3.1.0. Introduce UnixSubjects that provides
alternative to org.dcache.auth.Subjects. Update code base to match API
changes.

Result:
The nfs4j has no dependency with conflicting license. Support for
nfs-over-tls.

WARNING: this is a breaking change that requires changes in VirtualFileSystem
implementations.

Acked-by: Paul Millar
Target: master
  • Loading branch information
kofemann committed Oct 22, 2020
1 parent b1320d9 commit ed9a578
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 77 deletions.
3 changes: 3 additions & 0 deletions API-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

- removed deprecated CompoundContextBuilder#withExportFile
- removed interface org.dcache.nfs.v4.NfsLoginService
- drop dependency on org.dcache.auth package. Now only UnixNumericUserPrincipal and UnixNumericGroupPrincipal are used.
- this change is not backward compatible due to license incompatibility of org.dcache.auth package.
- added new class org.dcache.nfs.util.UnixSubjects that provides functionality used form org.dcache.auth package.Subjects

## 0.21

Expand Down
157 changes: 157 additions & 0 deletions core/src/main/java/org/dcache/nfs/util/UnixSubjects.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* Copyright (c) 2020 Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program (see the file COPYING.LIB for more
* details); if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.dcache.nfs.util;

import com.sun.security.auth.UnixNumericGroupPrincipal;
import com.sun.security.auth.UnixNumericUserPrincipal;

import javax.security.auth.Subject;
import java.util.Arrays;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
* A collection of utility methods to manipulate with Unix based subjects.
*/
public class UnixSubjects {

private UnixSubjects() {}

/**
* Returns true if and only if subjects contains UnixNumericUserPrincipal with uid 0 (zero).
* @param subject subject to evaluate.
* @return true if subjects contains UnixNumericUserPrincipal with uid 0.
*/
public static boolean isRootSubject(Subject subject) {
return hasUid(subject, 0);
}

/**
* Returns true if and only if subjects doesn't contain any UnixNumericUserPrincipal.
* @param subject subject to evaluate.
* @return true if subjects doesn't contain any UnixNumericUserPrincipal.
*/
public static boolean isNobodySubject(Subject subject) {
return subject.getPrincipals().stream()
.noneMatch(UnixNumericUserPrincipal.class::isInstance);
}
/**
* Returns true if and only if the subject has the given uid.
*
* @param subject
* @param uid
* @return true, if the subject has given uid..
*/
public static boolean hasUid(Subject subject, long uid) {

return subject.getPrincipals().stream()
.filter(UnixNumericUserPrincipal.class::isInstance)
.map(UnixNumericUserPrincipal.class::cast)
.anyMatch(p -> p.longValue() == uid);
}

/**
* Returns true if and only if the subject has as primary or secondary the given gid.
*
* @param subject
* @param gid
* @return true, if the subject has given gid.
*/
public static boolean hasGid(Subject subject, long gid) {
return subject.getPrincipals().stream()
.filter(UnixNumericGroupPrincipal.class::isInstance)
.map(UnixNumericGroupPrincipal.class::cast)
.anyMatch(p -> p.longValue() == gid);
}

/**
* Create subject with given uid and gid.
* @param uid users numeric id.
* @param gid users primary group numeric id.
* @return subject with given uid, gid.
*/
public static Subject toSubject(long uid, long gid) {
return new Subject(false,
Set.of(new UnixNumericUserPrincipal(uid), new UnixNumericGroupPrincipal(gid, true)),
Set.of(),
Set.of());
}

/**
* Create subject with given uid, primary gid and secondary gids.
* @param uid users numeric id.
* @param gid users primary group numeric id.
* @param gids array of users secondary group numeric ids.
* @return subject with given uid, gid and gids.
*/
public static Subject toSubject(long uid, long gid, long ... gids) {
Subject subject = toSubject(uid, gid);
subject.getPrincipals()
.addAll(
Arrays.stream(gids)
.mapToObj(l -> new UnixNumericGroupPrincipal(l, false))
.collect(Collectors.toSet())
);
return subject;
}

/**
* Returns the user ID represented by UnixNumericUserPrincipal.
* @param subject subject to evaluate.
* @return the user id.
*/

public static long getUid(Subject subject) {
return subject.getPrincipals().stream().filter(UnixNumericUserPrincipal.class::isInstance)
.map(UnixNumericUserPrincipal.class::cast)
.mapToLong(UnixNumericUserPrincipal::longValue)
.findFirst()
.getAsLong();
}

/**
* Returns the primary group ID of a subject represented by UnixNumericGroupPrincipal.
* @param subject subject to evaluate.
* @return the primary group ID.
*/
public static long getPrimaryGid(Subject subject) {
return subject.getPrincipals().stream().filter(UnixNumericGroupPrincipal.class::isInstance)
.map(UnixNumericGroupPrincipal.class::cast)
.filter(UnixNumericGroupPrincipal::isPrimaryGroup)
.mapToLong(UnixNumericGroupPrincipal::longValue)
.findFirst()
.getAsLong();
}

/**
* Returns the secondary group IDs of a subject represented by UnixNumericGroupPrincipal.
* @param subject subject to evaluate.
* @return an array with secondary group IDs, possibly empty.
*/
public static long[] getSecondaryGids(Subject subject) {
return subject.getPrincipals().stream().filter(UnixNumericGroupPrincipal.class::isInstance)
.map(UnixNumericGroupPrincipal.class::cast)
.filter(Predicate.not(UnixNumericGroupPrincipal::isPrimaryGroup))
.mapToLong(UnixNumericGroupPrincipal::longValue)
.toArray();
}

}
8 changes: 4 additions & 4 deletions core/src/main/java/org/dcache/nfs/v3/NfsServerV3.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 - 2018 Deutsches Elektronen-Synchroton,
* Copyright (c) 2009 - 2020 Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY
*
* This library is free software; you can redistribute it and/or modify
Expand All @@ -19,10 +19,10 @@
*/
package org.dcache.nfs.v3;

import org.dcache.auth.Subjects;
import org.dcache.nfs.ExportTable;
import org.dcache.nfs.nfsstat;
import org.dcache.nfs.ChimeraNFSException;
import org.dcache.nfs.util.UnixSubjects;
import org.dcache.nfs.v3.xdr.LOOKUP3res;
import org.dcache.nfs.v3.xdr.WRITE3resfail;
import org.dcache.nfs.v3.xdr.RMDIR3resok;
Expand Down Expand Up @@ -300,7 +300,7 @@ public CREATE3res NFSPROC3_CREATE_3(RpcCall call$, CREATE3args arg1) {
if (newAttr != null) {
fmode = newAttr.mode.mode.value.value | Stat.S_IFREG;
if( newAttr.uid.set_it || newAttr.gid.set_it) {
actualSubject = Subjects.of(newAttr.uid.uid.value.value, newAttr.gid.gid.value.value);
actualSubject = UnixSubjects.toSubject(newAttr.uid.uid.value.value, newAttr.gid.gid.value.value);
}
}
inode = fs.create(parent, Stat.Type.REGULAR, path, actualSubject, fmode);
Expand Down Expand Up @@ -600,7 +600,7 @@ public MKDIR3res NFSPROC3_MKDIR_3(RpcCall call$, MKDIR3args arg1) {
if (attr != null) {
mode = attr.mode.mode.value.value | Stat.S_IFDIR;
if( attr.uid.set_it || attr.gid.set_it) {
actualSubject = Subjects.of(attr.uid.uid.value.value, attr.gid.gid.value.value);
actualSubject = UnixSubjects.toSubject(attr.uid.uid.value.value, attr.gid.gid.value.value);
}
}

Expand Down
5 changes: 3 additions & 2 deletions core/src/main/java/org/dcache/nfs/v4/CompoundContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import java.net.InetSocketAddress;
import java.security.Principal;

import com.sun.security.auth.UnixNumericUserPrincipal;
import org.dcache.nfs.ChimeraNFSException;
import org.dcache.nfs.ExportTable;
import org.dcache.nfs.v4.xdr.nfs_resop4;
Expand All @@ -32,7 +34,6 @@
import java.util.Optional;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
import org.dcache.auth.UidPrincipal;
import org.dcache.nfs.vfs.Inode;
import org.dcache.nfs.status.BadStateidException;
import org.dcache.nfs.status.NoFileHandleException;
Expand Down Expand Up @@ -320,7 +321,7 @@ private Principal principalOf(final RpcCall call) {
if(call.getCredential().type() == RpcAuthType.RPCGSS_SEC) {
type = KerberosPrincipal.class;
} else {
type = UidPrincipal.class;
type = UnixNumericUserPrincipal.class;
}

return call.getCredential().getSubject().getPrincipals().stream()
Expand Down
26 changes: 14 additions & 12 deletions core/src/main/java/org/dcache/nfs/vfs/PseudoFs.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import java.util.Set;
import java.util.function.Function;
import javax.security.auth.Subject;
import org.dcache.auth.Subjects;

import org.dcache.nfs.ChimeraNFSException;
import org.dcache.nfs.ExportTable;
import org.dcache.nfs.FsExport;
Expand All @@ -53,6 +53,8 @@

import static com.google.common.collect.Lists.newArrayList;
import static org.dcache.nfs.vfs.AclCheckable.Access;
import static org.dcache.nfs.util.UnixSubjects.*;

/**
* A decorated {@code VirtualFileSystem} that builds a Pseudo file system
* on top of an other file system based on export rules.
Expand Down Expand Up @@ -176,13 +178,13 @@ public int access(Inode inode, int mode) throws IOException {
public Inode create(Inode parent, Stat.Type type, String path, Subject subject, int mode) throws IOException {
Subject effectiveSubject = checkAccess(parent, ACE4_ADD_FILE);

if (subject != null && Subjects.isRoot(effectiveSubject)) {
if (subject != null && isRootSubject(effectiveSubject)) {
effectiveSubject = subject;
}

if (inheritUidGid(parent)) {
Stat s = _inner.getattr(parent);
effectiveSubject = Subjects.of(s.getUid(), s.getGid());
effectiveSubject = toSubject(s.getUid(), s.getGid());
}

return pushExportIndex(parent, _inner.create(parent, type, path, effectiveSubject, mode));
Expand Down Expand Up @@ -229,7 +231,7 @@ public Inode link(Inode parent, Inode link, String path, Subject subject) throws
Subject effectiveSubject = checkAccess(parent, ACE4_ADD_FILE);
if (inheritUidGid(parent)) {
Stat s = _inner.getattr(parent);
effectiveSubject = Subjects.of(s.getUid(), s.getGid());
effectiveSubject = toSubject(s.getUid(), s.getGid());
}
return pushExportIndex(parent, _inner.link(parent, link, path, effectiveSubject));
}
Expand All @@ -247,13 +249,13 @@ public DirectoryStream list(Inode inode, byte[] verifier, long cookie) throws IO
@Override
public Inode mkdir(Inode parent, String path, Subject subject, int mode) throws IOException {
Subject effectiveSubject = checkAccess(parent, ACE4_ADD_SUBDIRECTORY);
if (subject != null && Subjects.isRoot(effectiveSubject)) {
if (subject != null && isRootSubject(effectiveSubject)) {
effectiveSubject = subject;
}

if (inheritUidGid(parent)) {
Stat s = _inner.getattr(parent);
effectiveSubject = Subjects.of(s.getUid(), s.getGid());
effectiveSubject = toSubject(s.getUid(), s.getGid());
}
return pushExportIndex(parent, _inner.mkdir(parent, path, effectiveSubject, mode));
}
Expand Down Expand Up @@ -318,7 +320,7 @@ public Inode symlink(Inode parent, String path, String link, Subject subject, in
Subject effectiveSubject = checkAccess(parent, ACE4_ADD_FILE);
if (inheritUidGid(parent)) {
Stat s = _inner.getattr(parent);
effectiveSubject = Subjects.of(s.getUid(), s.getGid());
effectiveSubject = toSubject(s.getUid(), s.getGid());
}
return pushExportIndex(parent, _inner.symlink(parent, path, link, effectiveSubject, mode));
}
Expand Down Expand Up @@ -460,8 +462,8 @@ private Subject checkAccess(Inode inode, Stat stat, int requestedMask, boolean s
return effectiveSubject;
}

if (Subjects.isNobody(_subject) || export.hasAllSquash() || (!export.isTrusted() && Subjects.isRoot(_subject))) {
effectiveSubject = Subjects.of(export.getAnonUid(), export.getAnonGid());
if (isNobodySubject(_subject) || export.hasAllSquash() || (!export.isTrusted() && isRootSubject(_subject))) {
effectiveSubject = toSubject(export.getAnonUid(), export.getAnonGid());
}

if (export.checkAcls()) {
Expand Down Expand Up @@ -508,12 +510,12 @@ private int unixToAccessmask(Subject subject, Stat stat) {
boolean isDir = (mode & Stat.S_IFDIR) == Stat.S_IFDIR;
int fromUnixMask;

if (Subjects.isRoot(subject)) {
if (isRootSubject(subject)) {
fromUnixMask = Acls.toAccessMask(Acls.RBIT | Acls.WBIT | Acls.XBIT, isDir, true);
fromUnixMask |= ACE4_WRITE_OWNER;
} else if (Subjects.hasUid(subject, stat.getUid())) {
} else if (hasUid(subject, stat.getUid())) {
fromUnixMask = Acls.toAccessMask(mode >> BIT_MASK_OWNER_OFFSET, isDir, true);
} else if (Subjects.hasGid(subject, stat.getGid())) {
} else if (hasGid(subject, stat.getGid())) {
fromUnixMask = Acls.toAccessMask(mode >> BIT_MASK_GROUP_OFFSET, isDir, false);
} else {
fromUnixMask = Acls.toAccessMask(mode >> BIT_MASK_OTHER_OFFSET, isDir, false);
Expand Down
Loading

0 comments on commit ed9a578

Please sign in to comment.