package com.constellio.app.modules.es.connectors.smb.security;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class TrusteeManager {
private static final String TRUSTEE_FOLDER = "._NETWARE";
private static final String TRUSTEE_ELEMENT = "trustee";
private static final String INHERITED_RIGHTS_MASKS_ELEMENT = "inherited_rights_mask";
private static final String PATH_ATTRIBUTE = "path";
private static final String NAME_ELEMENT = "name";
private static final String RIGHTS_ELEMENT = "rights";
private Map<String, ReadTrustees> shareTrustees = new HashMap<String, ReadTrustees>();
private Set<String> readMasks = new HashSet<String>();
private boolean isTrusteeFilePresent = true;
public TrusteeManager() {
}
private ReadTrustees getTrusteesForFile(SmbFile smbFile)
throws ParserConfigurationException, SAXException, IOException {
String share = smbFile.getShare();
if (share != null) {
ReadTrustees readTrustees = shareTrustees.get(share);
if (readTrustees == null) {
// Load a new trustee
readTrustees = new ReadTrustees();
shareTrustees.put(share, readTrustees);
// SmbFile trusteeDatabaseFile = new SmbFile(smbFile, "/" + share + "/._NETWARE/.trustee_database.xml");
SmbFile trusteeDatabaseFile = new SmbFile(smbFile, "/" + share + "/" + TRUSTEE_FOLDER + "/.trustee_database.xml");
if (trusteeDatabaseFile.exists()) {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = null;
InputStream trusteeIs = null;
try {
doc = dBuilder.parse(trusteeDatabaseFile.getInputStream());
} finally {
IOUtils.closeQuietly(trusteeIs);
}
doc.getDocumentElement().normalize();
NodeList trusteeList = doc.getElementsByTagName(TRUSTEE_ELEMENT);
for (int temp = 0; temp < trusteeList.getLength(); temp++) {
Node nNode = trusteeList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
String path = eElement.getAttribute(PATH_ATTRIBUTE);
String name = eElement.getElementsByTagName(NAME_ELEMENT).item(0).getTextContent();
// String simpleName = StringUtils.substringBetween(name, ".");
// if (StringUtils.startsWith(name, ".") && simpleName == null) {
// //Case where the whole domain can access the path
// simpleName = "Everyone";
// }
if (StringUtils.isNotBlank(name)) {
String rights = eElement.getElementsByTagName(RIGHTS_ELEMENT).item(0).getTextContent();
// R = read, S = admin
if (StringUtils.contains(rights, "R") || StringUtils.contains(rights, "S")) {
readTrustees.add(path, name);
}
}
}
}
NodeList masksList = doc.getElementsByTagName(INHERITED_RIGHTS_MASKS_ELEMENT);
for (int temp = 0; temp < masksList.getLength(); temp++) {
Node nNode = masksList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
String path = eElement.getAttribute(PATH_ATTRIBUTE);
String rights = eElement.getElementsByTagName(RIGHTS_ELEMENT).item(0).getTextContent();
// R = read, S = admin
if (StringUtils.contains(rights, "R") || StringUtils.contains(rights, "S")) {
readMasks.add(path);
}
}
}
} else {
isTrusteeFilePresent = false;
}
}
return readTrustees;
}
return null;
}
public Set<String> getNames(SmbFile smbFile) {
Set<String> names = new TreeSet<String>();
try {
if (!isTrusteeFilePresent) {
return names;
}
ReadTrustees readTrustees = getTrusteesForFile(smbFile);
String canonicalPath = smbFile.getCanonicalPath();
String pathAfterProtocol = StringUtils.substringAfter(canonicalPath, "smb://");
String contextPath = StringUtils.substringAfter(pathAfterProtocol, "/");
String shareContextPath = "/" + StringUtils.substringAfter(contextPath, "/");
String shareContextPathNoTrailing = StringUtils.removeEnd(shareContextPath, "/");
Collection<String> pathTrustees = readTrustees.get(shareContextPathNoTrailing);
if (pathTrustees != null) {
names.addAll(pathTrustees);
}
if (!this.readMasks.contains(shareContextPathNoTrailing)) {
// No mask, retrieve parent rights
SmbFile parent;
if (smbFile.isDirectory()) {
parent = new SmbFile(smbFile, "..");
} else {
parent = new SmbFile(smbFile, ".");
}
if (parent.exists() && !parent.getCanonicalPath().equals(smbFile.getCanonicalPath())) {
// Recursive
names.addAll(getNames(parent));
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
return names;
}
private static class ReadTrustees {
private Map<String, Collection<String>> trusteesMap = new HashMap<String, Collection<String>>();
public Collection<String> get(String path) {
return trusteesMap.get(path);
}
public void add(String path, String name) {
Collection<String> names = trusteesMap.get(path);
if (names == null) {
names = new TreeSet<String>();
trusteesMap.put(path, names);
}
names.add(name.toLowerCase());
}
}
public static void main(String[] args)
throws SAXException, IOException, ParserConfigurationException {
String user = "";
String pass = "";
String domain = "";
String sharedFolder = "tmp";
String path = "smb://WIN-87DVRU8DGM1/" + sharedFolder + "/ME/COM_SAGIR/Agent multiplicateur/test.rtf";
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain, user, pass);
SmbFile smbFile = new SmbFile(path, auth);
TrusteeManager trustee = new TrusteeManager();
for (String name : trustee.getNames(smbFile)) {
System.out.println(name);
}
}
}