Skip to content

Instantly share code, notes, and snippets.

@MikeN123
Created August 30, 2016 09:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MikeN123/e84191a6bdd1b257734850013f6c0129 to your computer and use it in GitHub Desktop.
Save MikeN123/e84191a6bdd1b257734850013f6c0129 to your computer and use it in GitHub Desktop.
/*
* Eveoh MyTimetable, Web interface for timetables.
*
* Copyright (c) 2010 - 2016 Eveoh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program, see src/main/webapp/license/gpl-3.0.txt.
* If not, see <http://www.gnu.org/licenses/>.
*/
package nl.eveoh.mytimetable.core.util;
import com.google.common.base.Splitter;
import com.sun.jna.platform.win32.COM.util.*;
import com.sun.jna.platform.win32.COM.util.annotation.ComInterface;
import com.sun.jna.platform.win32.COM.util.annotation.ComMethod;
import com.sun.jna.platform.win32.COM.util.annotation.ComObject;
import com.sun.jna.platform.win32.COM.util.annotation.ComProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Looks up an AD property of the current logged in user. Uses JNA, COM and ADSI, so only works from Windows servers.
*
* Only 1 of these readers should be active per process, as the ComThread is shared between threads.
*
* @author Mike Noordermeer
*/
public class JnaADAttributeReader implements ADAttributeReader, AutoCloseable {
protected static final Logger log = LoggerFactory.getLogger(JnaADAttributeReader.class);
private ComThread comThread;
public JnaADAttributeReader() {
this.comThread = new ComThread("Default Factory COM Thread", 5000, (t, e) -> {
//ignore
});
}
@Override
public Collection<String> getAttribute(Principal principal, String attributeName) {
List<String> parts = Splitter.on('\\').splitToList(principal.getName());
if (parts.size() != 2) {
log.warn("Could not find domain and username in principal name: {}", principal.getName());
return Collections.emptyList();
}
String domainname = parts.get(0);
String username = parts.get(1);
String ldapStr = "<LDAP://" + domainname + ">;(&(objectClass=user)(samAccountName=" + username + "));" +
attributeName + ";subtree";
log.debug("Executing LDAP query {}", ldapStr);
Factory factory = new Factory(comThread);
Connection conn = factory.createObject(Connection.class);
Recordset rs = factory.createObject(Recordset.class);
try {
conn.Open("Provider=ADsDSOObject", "", "", -1);
rs.Open(ldapStr, conn, CursorTypeEnum.adOpenUnspecified, LockTypeEnum.adLockUnspecified, -1);
Fields fs = rs.getFields();
if (rs.getEOF()) {
log.debug("No results found");
return Collections.emptyList();
}
rs.MoveFirst();
log.debug("Found a result");
Object value = fs.getItem(0).getValue();
if (value == null) {
log.debug("Result was null");
return Collections.emptyList();
} else {
log.debug("Result was non-null");
return Collections.singletonList(value.toString());
}
} finally {
rs.Close();
conn.Close();
factory.disposeAll();
}
}
@Override
public void close() throws Exception {
comThread.terminate(1000);
}
@ComObject(clsId = "{00000535-0000-0010-8000-00AA006D2EA4}", progId = "{00000300-0000-0010-8000-00AA006D2EA4}")
public static interface Recordset extends _Recordset {}
@ComObject(clsId = "{00000514-0000-0010-8000-00AA006D2EA4}", progId = "{B691E011-1797-432E-907A-4D8C69339129}")
public static interface Connection extends _Connection, IConnectionPoint, IUnknown {}
@ComInterface(iid = "{00000556-0000-0010-8000-00AA006D2EA4}")
public static interface _Recordset {
@ComProperty(name = "EOF")
Boolean getEOF();
@ComProperty(name = "Fields")
Fields getFields();
@ComMethod(name = "MoveFirst")
void MoveFirst();
@ComMethod(name = "Close")
void Close();
@ComMethod(name = "Open")
void Open(Object Source, Object ActiveConnection, CursorTypeEnum CursorType, LockTypeEnum LockType,
int Options);
}
@ComInterface(iid = "{00000564-0000-0010-8000-00AA006D2EA4}")
public static interface Fields {
@ComProperty(name = "Item")
Field getItem(int index);
}
@ComInterface(iid = "{00000569-0000-0010-8000-00AA006D2EA4}")
public static interface Field {
@ComProperty(name = "Value")
Object getValue();
}
@ComInterface(iid = "{00001550-0000-0010-8000-00AA006D2EA4}")
public static interface _Connection {
@ComMethod(name = "Close")
void Close();
@ComMethod(name = "Open")
void Open(String ConnectionString, String UserID, String Password, int Options);
}
public static enum LockTypeEnum implements IComEnum {
adLockUnspecified(-1),
adLockReadOnly(1),
adLockPessimistic(2),
adLockOptimistic(3),
adLockBatchOptimistic(4),;
private LockTypeEnum(long value) {
this.value = value;
}
private long value;
public long getValue() {
return this.value;
}
}
public static enum CursorTypeEnum implements IComEnum {
adOpenUnspecified(-1),
adOpenForwardOnly(0),
adOpenKeyset(1),
adOpenDynamic(2),
adOpenStatic(3),;
private CursorTypeEnum(long value) {
this.value = value;
}
private long value;
public long getValue() {
return this.value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment