private Envelope.GridFile findFile(String path, Envelope env) { for (Envelope.GridFile file : env.getFiles()) { if (path.equals(file.getLfn())) { return file; } } return null; }
@Override public String authorize( Subject subject, InetSocketAddress localAddress, InetSocketAddress remoteAddress, String path, Map<String, String> opaque, int request, FilePerm mode) throws XrootdException { if (path == null) { throw new IllegalArgumentException("The lfn string must not be null."); } String authzTokenString = opaque.get("authz"); if (authzTokenString == null) { if (request == XrootdProtocol.kXR_stat || request == XrootdProtocol.kXR_statx || request == XrootdProtocol.kXR_dirlist || request == XrootdProtocol.kXR_locate) { return path; } throw new XrootdException( kXR_NotAuthorized, "An authorization token is required for this request."); } // get the VO-specific keypair or the default keypair if VO // was not specified KeyPair keypair = getKeys(opaque.get("vo")); // decode the envelope from the token using the keypair // (Remote public key, local private key) Envelope env; try { env = decodeEnvelope(authzTokenString, keypair); } catch (CorruptedEnvelopeException | IllegalBlockSizeException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | SignatureException e) { throw new XrootdException( kXR_ArgInvalid, "Error parsing authorization token: " + e.getMessage()); } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { throw new XrootdException( kXR_ServerError, "Error parsing authorization token: " + e.getMessage()); } catch (CredentialException e) { throw new XrootdException( kXR_NotAuthorized, "Error parsing authorization token: " + e.getMessage()); } // loop through all files contained in the envelope and find // the one with the matching lfn if no match is found, the // token/envelope is possibly hijacked Envelope.GridFile file = findFile(path, env); if (file == null) { throw new XrootdException( kXR_NotAuthorized, "Authorization token doesn't contain any file permissions for lfn " + path + "."); } // check for hostname:port in the TURL. Must match the current // xrootd service endpoint. If this check fails, the token is // possibly hijacked try { if (!Arrays.asList(InetAddress.getAllByName(file.getTurl().getHost())) .contains(localAddress.getAddress())) { throw new XrootdException( kXR_NotAuthorized, "Hostname mismatch in authorization token (address=" + localAddress + " turl=" + file.getTurl() + ")."); } } catch (UnknownHostException e) { throw new XrootdException( kXR_NotAuthorized, "Hostname in authorization token is not resolvable (turl=" + file.getTurl() + ")."); } int turlPort = file.getTurl().getPort(); if (turlPort == -1) { turlPort = XrootdProtocol.DEFAULT_PORT; } if (turlPort != localAddress.getPort()) { throw new XrootdException( kXR_NotAuthorized, "Port mismatch in authorization token (address=" + localAddress + " turl=" + file.getTurl() + ")."); } // the authorization check. read access (lowest permission // required) is granted by default (file.getAccess() == 0), we // must check only in case of writing FilePerm grantedPermission = file.getAccess(); if (mode == FilePerm.WRITE) { if (grantedPermission.ordinal() < FilePerm.WRITE_ONCE.ordinal()) { throw new XrootdException( kXR_NotAuthorized, "Token lacks authorization for requested operation."); } } else if (mode == FilePerm.DELETE) { if (grantedPermission.ordinal() < FilePerm.DELETE.ordinal()) { throw new XrootdException( kXR_NotAuthorized, "Token lacks authorization for requested operation."); } } return file.getTurl().getPath(); }