/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.constellio.app.modules.es.connectors.smb.security;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import jcifs.smb.ACE;
import jcifs.smb.SmbFile;
import org.apache.commons.codec.binary.Base64;
/**
* http://svn.apache.org/repos/asf/manifoldcf/trunk/connectors/jcifs/connector/src/main/java/org/apache/manifoldcf/crawler/
* connectors/sharedrive/SharedDriveConnector.java
*
* @author Benoit, Nicolas
*
*/
public class WindowsPermissions {
private static final Logger LOG = Logger.getLogger(WindowsPermissions.class.getName());
private List<String> allowTokenShare = new ArrayList<String>();
private List<String> denyTokenShare = new ArrayList<String>();
private List<String> allowTokenDocument = new ArrayList<String>();
private List<String> denyTokenDocument = new ArrayList<String>();
private String permissionsHash = null;
private SmbFile file;
private TrusteeManager trusteeManager;
private boolean skipSharePermissions;
private Set<String> errors = new HashSet<>();
public WindowsPermissions(SmbFile file, TrusteeManager trusteeManager, boolean skipSharePermissions) {
this.file = file;
this.trusteeManager = trusteeManager;
this.skipSharePermissions = skipSharePermissions;
}
public void process() {
boolean foundNovellPermissions = processNovellPermissions(file, trusteeManager);
if (!foundNovellPermissions){
processNTFSPermissions(file);
if (!skipSharePermissions) {
processSharePermissions(file);
}
}
computePermissionsHash();
}
private void computePermissionsHash() {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
update(md, allowTokenDocument);
update(md, denyTokenDocument);
update(md, allowTokenShare);
update(md, denyTokenShare);
permissionsHash = Base64.encodeBase64String(md.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
private void update(MessageDigest md, List<String> tokens) {
for (String token : tokens) {
md.update(token.getBytes());
}
}
public List<String> getAllowTokenDocument() {
return allowTokenDocument;
}
public List<String> getAllowTokenShare() {
return allowTokenShare;
}
public List<String> getDenyTokenDocument() {
return denyTokenDocument;
}
public List<String> getDenyTokenShare() {
return denyTokenShare;
}
public String getPermissionsHash() {
return permissionsHash;
}
protected boolean processNTFSPermissions(SmbFile file) {
ACE[] documentAces = null;
for (int tries = 5; tries >= 0; tries--) {
try {
documentAces = file.getSecurity(true);
break;
} catch (IOException ioe) {
if (tries == 0) {
LOG.warning("Exception (NTFS PERMISSIONS)) : " + file.getCanonicalPath() + " (" + ioe.getClass()
.getCanonicalName() + ": " + ioe.getMessage());
errors.add("Exception (NTFS PERMISSIONS) :" + ioe.getMessage());
}
}
}
updateACE(documentAces, allowTokenDocument, denyTokenDocument);
if (documentAces != null) {
return true;
} else {
return false;
}
}
protected boolean processNovellPermissions(SmbFile file, TrusteeManager trusteeManager) {
Set<String> names = trusteeManager.getNames(file);
for (String name : names) {
allowTokenDocument.add(name);
}
return !names.isEmpty();
}
protected void processSharePermissions(SmbFile file) {
ACE[] shareAces = null;
for (int tries = 5; tries >= 0; tries--) {
try {
shareAces = file.getShareSecurity(true);
// Success, exit try-loop
break;
} catch (IOException ioe) {
if (tries == 0) {
LOG.warning("Exception (SHARE PERMISSIONS)) : " + file.getCanonicalPath() + " (" + ioe.getClass()
.getCanonicalName() + ": " + ioe.getMessage());
errors.add("Exception (SHARE PERMISSIONS) :" + ioe.getMessage());
}
}
}
updateACE(shareAces, allowTokenShare, denyTokenShare);
}
private void updateACE(ACE[] aces, List<String> allow, List<String> deny) {
if (aces == null) {
allow.add("S-1-1-0");
} else {
for (ACE ace : aces) {
if ((ace.getAccessMask() & ACE.FILE_READ_DATA) != 0) {
String aceSid = ace.getSID()
.toString();
if (ace.isAllow()) {
allow.add(aceSid);
} else {
deny.add(aceSid);
}
}
}
}
if (deny.isEmpty()) {
deny.add("DEAD_AUTHORITY");
}
}
public String getErrors() {
String result = "";
for (String error : errors) {
result += error + ", ";
}
return result;
}
}