зеркало из https://github.com/mozilla/pjs.git
Updtates for LDAPJDK 4.17
This commit is contained in:
Родитель
939b8670f9
Коммит
aa729f7d11
|
@ -168,9 +168,9 @@ public interface LDAPAsynchronousConnection {
|
|||
|
||||
|
||||
/**
|
||||
* Makes a single change to an existing entry in the directory (for
|
||||
* example, changes the value of an attribute, adds a new attribute
|
||||
* value, or removes an existing attribute value).<BR>
|
||||
* Makes a single change to an existing entry in the directory.
|
||||
* For example, changes the value of an attribute, adds a new attribute
|
||||
* value, or removes an existing attribute value.<BR>
|
||||
* The LDAPModification object specifies both the change to be made and
|
||||
* the LDAPAttribute value to be changed.
|
||||
*
|
||||
|
@ -190,9 +190,9 @@ public interface LDAPAsynchronousConnection {
|
|||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Makes a single change to an existing entry in the directory (for
|
||||
* example, changes the value of an attribute, adds a new attribute
|
||||
* value, or removes an existing attribute value).<BR>
|
||||
* Makes a single change to an existing entry in the directory.
|
||||
* For example, changes the value of an attribute, adds a new attribute
|
||||
* value, or removes an existing attribute value.<BR>
|
||||
* The LDAPModification object specifies both the change to be made and
|
||||
* the LDAPAttribute value to be changed.
|
||||
*
|
||||
|
@ -215,9 +215,9 @@ public interface LDAPAsynchronousConnection {
|
|||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Makes a set of changes to an existing entry in the directory (for
|
||||
* example, changes attribute values, adds new attribute values, or
|
||||
* removes existing attribute values).
|
||||
* Makes a set of changes to an existing entry in the directory.
|
||||
* For example, changes attribute values, adds new attribute values, or
|
||||
* removes existing attribute values.
|
||||
* <P>
|
||||
* @param dn distinguished name of the entry to modify
|
||||
* @param mods a set of modifications to make to the entry
|
||||
|
@ -235,9 +235,9 @@ public interface LDAPAsynchronousConnection {
|
|||
throws LDAPException;
|
||||
|
||||
/**
|
||||
* Makes a set of changes to an existing entry in the directory (for
|
||||
* example, changes attribute values, adds new attribute values, or
|
||||
* removes existing attribute values).
|
||||
* Makes a set of changes to an existing entry in the directory.
|
||||
* For example, changes attribute values, adds new attribute values, or
|
||||
* removes existing attribute values.
|
||||
*
|
||||
* @param dn distinguished name of the entry to modify
|
||||
* @param mods a set of modifications to make to the entry
|
||||
|
|
|
@ -38,12 +38,12 @@ import java.net.*;
|
|||
* When a connection is successfully created, a socket is opened. The socket
|
||||
* is passed to the LDAPConnThread. The LDAPConnThread must call
|
||||
* invalidateConnection() if the connection is lost due to a network or
|
||||
* server error, or disconnect() if the connection is deliberately terminated
|
||||
* server error, or closeConnection() if the connection is deliberately terminated
|
||||
* by the user.
|
||||
*/
|
||||
class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
||||
class LDAPConnSetupMgr implements java.io.Serializable {
|
||||
|
||||
static final long serialVersionUID = 1519402748245755306L;
|
||||
static final long serialVersionUID = 1519402748245755307L;
|
||||
/**
|
||||
* Policy for opening a connection when multiple servers are used
|
||||
*/
|
||||
|
@ -65,28 +65,32 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
* Representation for a server in the server list.
|
||||
*/
|
||||
class ServerEntry {
|
||||
String host;
|
||||
int port;
|
||||
LDAPUrl url;
|
||||
int connSetupStatus;
|
||||
Thread connSetupThread;
|
||||
|
||||
ServerEntry(String host, int port, int status) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
ServerEntry(LDAPUrl url, int status) {
|
||||
this.url = url;
|
||||
connSetupStatus = status;
|
||||
connSetupThread = null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "{" +host+":"+port + " status="+connSetupStatus+"}";
|
||||
return "{" + url + " status="+connSetupStatus+"}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Socket to the connected server
|
||||
*/
|
||||
private Socket m_socket = null;
|
||||
|
||||
/**
|
||||
* Original, underlying socket to the server, see layerSocket()
|
||||
*/
|
||||
private Socket m_origSocket = null;
|
||||
|
||||
|
||||
/**
|
||||
* Last exception occured during connection setup
|
||||
*/
|
||||
|
@ -128,25 +132,50 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
*/
|
||||
private transient int m_attemptCnt = 0;
|
||||
|
||||
/**
|
||||
* Connection IDs for ldap trace messages
|
||||
*/
|
||||
private static int m_nextId;
|
||||
private int m_id;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param host list of host names to which to connect
|
||||
* @param port list of port numbers corresponding to the host list
|
||||
* @param factory socket factory for SSL connections
|
||||
*/
|
||||
LDAPConnSetupMgr(String[] hosts, int[] ports, LDAPSocketFactory factory) {
|
||||
LDAPConnSetupMgr(String[] hosts, int[] ports, LDAPSocketFactory factory) throws LDAPException{
|
||||
m_dsList = new ServerEntry[hosts.length];
|
||||
boolean secure = (factory != null);
|
||||
for (int i=0; i < hosts.length; i++) {
|
||||
m_dsList[i] = new ServerEntry(hosts[i], ports[i], NEVER_USED);
|
||||
String url = secure ? "ldaps://" : "ldap://";
|
||||
url += hosts[i] + ":" + ports[i];
|
||||
try {
|
||||
m_dsList[i] = new ServerEntry(new LDAPUrl(url), NEVER_USED);
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new LDAPException("Invalid host:port " + hosts[i]+":"+ports[i],
|
||||
LDAPException.PARAM_ERROR);
|
||||
}
|
||||
}
|
||||
m_factory = factory;
|
||||
}
|
||||
|
||||
LDAPConnSetupMgr(String[] urls, LDAPSocketFactory factory) throws LDAPException{
|
||||
m_dsList = new ServerEntry[urls.length];
|
||||
for (int i=0; i < urls.length; i++) {
|
||||
try {
|
||||
LDAPUrl url = new LDAPUrl(urls[i]);
|
||||
m_dsList[i] = new ServerEntry(url, NEVER_USED);
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new LDAPException("Malformed LDAP URL " + urls[i],
|
||||
LDAPException.PARAM_ERROR);
|
||||
}
|
||||
}
|
||||
m_factory = factory;
|
||||
}
|
||||
|
||||
LDAPConnSetupMgr(LDAPUrl[] urls, LDAPSocketFactory factory) throws LDAPException{
|
||||
m_dsList = new ServerEntry[urls.length];
|
||||
for (int i=0; i < urls.length; i++) {
|
||||
m_dsList[i] = new ServerEntry(urls[i], NEVER_USED);
|
||||
}
|
||||
m_factory = factory;
|
||||
m_id = m_nextId++;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,7 +233,7 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
th.interrupt();
|
||||
cleanup();
|
||||
throw new LDAPException(
|
||||
"connect timeout, " + getServerList() + " might be unreachable",
|
||||
"Connect timeout, " + getServerList() + " might be unreachable",
|
||||
LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
|
||||
|
@ -213,12 +242,13 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
}
|
||||
|
||||
throw new LDAPException(
|
||||
"failed to connect to server " + getServerList(),
|
||||
"Failed to connect to server " + getServerList(),
|
||||
LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
m_socket = null;
|
||||
m_origSocket = null;
|
||||
m_connException = null;
|
||||
m_attemptCnt = 0;
|
||||
|
||||
|
@ -231,9 +261,9 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
StringBuffer sb = new StringBuffer();
|
||||
for (int i=0; i < m_dsList.length; i++) {
|
||||
sb.append(i==0 ? "" : " ");
|
||||
sb.append(m_dsList[i].host);
|
||||
sb.append(m_dsList[i].url.getHost());
|
||||
sb.append(":");
|
||||
sb.append(m_dsList[i].port);
|
||||
sb.append(m_dsList[i].url.getPort());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -268,9 +298,25 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
newDsList[j] = m_dsList[m_dsIdx];
|
||||
m_dsList = newDsList;
|
||||
m_dsIdx = j;
|
||||
|
||||
try {
|
||||
m_socket.close();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_socket = null;
|
||||
}
|
||||
|
||||
m_socket = null;
|
||||
}
|
||||
|
||||
if (m_origSocket != null) {
|
||||
|
||||
try {
|
||||
m_origSocket.close();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_origSocket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,30 +324,69 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
* Mark the connected server status as DISCONNECTED. This will
|
||||
* put it at top of the server list for the next connect attempt.
|
||||
*/
|
||||
void disconnect() {
|
||||
void closeConnection() {
|
||||
if (m_socket != null) {
|
||||
|
||||
m_dsList[m_dsIdx].connSetupStatus = DISCONNECTED;
|
||||
|
||||
try {
|
||||
m_socket.close();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_socket = null;
|
||||
}
|
||||
}
|
||||
|
||||
m_socket = null;
|
||||
if (m_origSocket != null) {
|
||||
|
||||
try {
|
||||
m_origSocket.close();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_origSocket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Socket getSocket() {
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layer a new socket over the existing one (used by startTLS)
|
||||
*/
|
||||
void layerSocket(LDAPTLSSocketFactory factory) throws LDAPException{
|
||||
Socket s = factory.makeSocket(m_socket);
|
||||
m_origSocket = m_socket;
|
||||
m_socket = s;
|
||||
}
|
||||
|
||||
String getHost() {
|
||||
if (m_dsIdx >= 0) {
|
||||
return m_dsList[m_dsIdx].host;
|
||||
return m_dsList[m_dsIdx].url.getHost();
|
||||
}
|
||||
return m_dsList[0].host;
|
||||
return m_dsList[0].url.getHost();
|
||||
}
|
||||
|
||||
int getPort() {
|
||||
if (m_dsIdx >= 0) {
|
||||
return m_dsList[m_dsIdx].port;
|
||||
return m_dsList[m_dsIdx].url.getPort();
|
||||
}
|
||||
return m_dsList[0].port;
|
||||
return m_dsList[0].url.getPort();
|
||||
}
|
||||
|
||||
boolean isSecure() {
|
||||
if (m_dsIdx >= 0) {
|
||||
return m_dsList[m_dsIdx].url.isSecure();
|
||||
}
|
||||
return m_dsList[0].url.isSecure();
|
||||
}
|
||||
|
||||
LDAPUrl getLDAPUrl() {
|
||||
if (m_dsIdx >= 0) {
|
||||
return m_dsList[m_dsIdx].url;
|
||||
}
|
||||
return m_dsList[0].url;
|
||||
}
|
||||
|
||||
int getConnSetupDelay() {
|
||||
|
@ -363,8 +448,7 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
|
||||
//Create a Thread to execute connectSetver()
|
||||
final int dsIdx = i;
|
||||
String threadName = "ConnSetupMgr " +
|
||||
m_dsList[dsIdx].host + ":" + m_dsList[dsIdx].port;
|
||||
String threadName = "ConnSetupMgr " + m_dsList[dsIdx].url;
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
connectServer(dsIdx);
|
||||
|
@ -411,16 +495,25 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
try {
|
||||
/* If we are to create a socket ourselves, make sure it has
|
||||
sufficient privileges to connect to the desired host */
|
||||
if (m_factory == null) {
|
||||
sock = new Socket (entry.host, entry.port);
|
||||
//s.setSoLinger( false, -1 );
|
||||
if (!entry.url.isSecure()) {
|
||||
sock = new Socket (entry.url.getHost(), entry.url.getPort());
|
||||
} else {
|
||||
sock = m_factory.makeSocket(entry.host, entry.port);
|
||||
LDAPSocketFactory factory = m_factory;
|
||||
if (factory == null) {
|
||||
factory = entry.url.getSocketFactory();
|
||||
}
|
||||
if (factory == null) {
|
||||
throw new LDAPException("Can not connect, no socket factory " + entry.url,
|
||||
LDAPException.OTHER);
|
||||
}
|
||||
sock = factory.makeSocket(entry.url.getHost(), entry.url.getPort());
|
||||
}
|
||||
|
||||
sock.setTcpNoDelay( true );
|
||||
}
|
||||
catch (IOException e) {
|
||||
conex = new LDAPException("failed to connect to server "
|
||||
+ entry.host+":"+entry.port, LDAPException.CONNECT_ERROR);
|
||||
+ entry.url, LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
catch (LDAPException e) {
|
||||
conex = e;
|
||||
|
@ -515,28 +608,4 @@ class LDAPConnSetupMgr implements Cloneable, java.io.Serializable {
|
|||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
int getID() {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
String getLDAPUrl() {
|
||||
return ((m_factory == null) ? "ldap" : "ldaps") +
|
||||
"://" + getHost() + ":" + getPort();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
try {
|
||||
LDAPConnSetupMgr cloneMgr = (LDAPConnSetupMgr) super.clone();
|
||||
cloneMgr.m_dsList = new ServerEntry[m_dsList.length];
|
||||
for (int i=0; i<m_dsList.length; i++) {
|
||||
ServerEntry e = m_dsList[i];
|
||||
cloneMgr.m_dsList[i] = new ServerEntry(e.host, e.port, e.connSetupStatus);
|
||||
}
|
||||
return cloneMgr;
|
||||
}
|
||||
catch (CloneNotSupportedException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ import java.text.SimpleDateFormat;
|
|||
* All LDAPConnections send requests and get responses from
|
||||
* LDAPConnThread (a thread).
|
||||
*/
|
||||
class LDAPConnThread extends Thread {
|
||||
class LDAPConnThread implements Runnable {
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
@ -61,20 +61,24 @@ class LDAPConnThread extends Thread {
|
|||
* Internal variables
|
||||
*/
|
||||
transient private static int m_highMsgId;
|
||||
transient private InputStream m_serverInput;
|
||||
transient private OutputStream m_serverOutput;
|
||||
transient private InputStream m_serverInput, m_origServerInput;
|
||||
transient private OutputStream m_serverOutput, m_origServerOutput;
|
||||
transient private Hashtable m_requests;
|
||||
transient private Hashtable m_messages = null;
|
||||
transient private Vector m_registered;
|
||||
transient private boolean m_disconnected = false;
|
||||
transient private LDAPCache m_cache = null;
|
||||
transient private boolean m_doRun = true;
|
||||
private Socket m_socket = null;
|
||||
transient private Thread m_thread = null;
|
||||
transient Object m_sendRequestLock = new Object();
|
||||
transient LDAPConnSetupMgr m_connMgr = null;
|
||||
transient Object m_traceOutput = null;
|
||||
transient private Object m_sendRequestLock = new Object();
|
||||
transient private LDAPConnSetupMgr m_connMgr = null;
|
||||
transient private Object m_traceOutput = null;
|
||||
transient private int m_backlogCheckCounter = BACKLOG_CHKCNT;
|
||||
transient private boolean m_bound;
|
||||
|
||||
/**
|
||||
* Connection IDs for ldap trace messages
|
||||
*/
|
||||
transient private static int m_nextId;
|
||||
transient private int m_id;
|
||||
|
||||
|
||||
// Time Stemp format Hour(0-23):Minute:Second.Milliseconds used for trace msgs
|
||||
|
@ -83,47 +87,82 @@ class LDAPConnThread extends Thread {
|
|||
/**
|
||||
* Constructs a connection thread that maintains connection to the
|
||||
* LDAP server.
|
||||
* @param host LDAP host name
|
||||
* @param port LDAP port number
|
||||
* @param factory LDAP socket factory
|
||||
* @param connMgr the connection setup manager
|
||||
* @param cache cache object or null
|
||||
* @param traceOutput trace object or null
|
||||
*/
|
||||
public LDAPConnThread(LDAPConnSetupMgr connMgr, LDAPCache cache, Object traceOutput)
|
||||
throws LDAPException {
|
||||
super("LDAPConnThread " + connMgr.getHost() +":"+ connMgr.getPort());
|
||||
public LDAPConnThread(LDAPConnSetupMgr connMgr, LDAPCache cache, Object traceOutput) {
|
||||
m_requests = new Hashtable ();
|
||||
m_registered = new Vector ();
|
||||
m_connMgr = connMgr;
|
||||
m_socket = connMgr.getSocket();
|
||||
setCache( cache );
|
||||
setTraceOutput(traceOutput);
|
||||
}
|
||||
|
||||
setDaemon(true);
|
||||
synchronized void connect(LDAPConnection ldc) throws LDAPException{
|
||||
|
||||
if (m_thread != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
m_serverInput = new BufferedInputStream (m_socket.getInputStream());
|
||||
m_serverOutput = new BufferedOutputStream (m_socket.getOutputStream());
|
||||
|
||||
m_connMgr.openConnection();
|
||||
m_serverInput = new BufferedInputStream (m_connMgr.getSocket().getInputStream());
|
||||
m_serverOutput = new BufferedOutputStream(m_connMgr.getSocket().getOutputStream());
|
||||
register(ldc);
|
||||
} catch (IOException e) {
|
||||
|
||||
// a kludge to make the thread go away. Since the thread has already
|
||||
// been created, the only way to clean up the thread is to call the
|
||||
// start() method. Otherwise, the exit method will be never called
|
||||
// because the start() was never called. In the run method, the stop
|
||||
// method calls right away if the m_doRun is set to false.
|
||||
m_doRun = false;
|
||||
start();
|
||||
throw new LDAPException ( "failed to connect to server " +
|
||||
m_connMgr.getHost(), LDAPException.CONNECT_ERROR );
|
||||
}
|
||||
|
||||
if (traceOutput != null) {
|
||||
StringBuffer sb = new StringBuffer(" connected to ");
|
||||
sb.append(m_connMgr.getLDAPUrl());
|
||||
m_id = m_nextId++;
|
||||
String url = m_connMgr.getLDAPUrl().getServerUrl();
|
||||
|
||||
if (m_traceOutput != null) {
|
||||
StringBuffer sb = new StringBuffer(" Connected to ");
|
||||
sb.append(url);
|
||||
logTraceMessage(sb);
|
||||
}
|
||||
|
||||
start(); /* start the thread */
|
||||
String threadID = "LDAPConnThread-" + m_id + " " + url;
|
||||
m_thread = new Thread(this, threadID);
|
||||
m_thread.setDaemon(true);
|
||||
m_thread.start();
|
||||
}
|
||||
|
||||
public synchronized String toString() {
|
||||
if (m_thread != null) {
|
||||
return m_thread.getName();
|
||||
}
|
||||
else {
|
||||
return "LDAPConnThread-" + m_id + " <disconnected>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Layer a SSL socket over the current non-SSL one
|
||||
*/
|
||||
void layerSocket(LDAPTLSSocketFactory factory) throws Exception {
|
||||
synchronized (m_sendRequestLock) {
|
||||
try {
|
||||
m_connMgr.layerSocket(factory);
|
||||
setInputStream(m_connMgr.getSocket().getInputStream());
|
||||
setOutputStream(m_connMgr.getSocket().getOutputStream());
|
||||
}
|
||||
catch (Exception e) {
|
||||
m_serverInput = m_origServerInput;
|
||||
m_serverOutput = m_origServerOutput;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setBound(boolean bound) {
|
||||
m_bound = bound;
|
||||
}
|
||||
|
||||
boolean isBound() {
|
||||
return (m_thread != null) && m_bound;
|
||||
}
|
||||
|
||||
InputStream getInputStream() {
|
||||
|
@ -142,6 +181,10 @@ class LDAPConnThread extends Thread {
|
|||
m_serverOutput = os;
|
||||
}
|
||||
|
||||
int getRequestCount() {
|
||||
return m_requests.size();
|
||||
}
|
||||
|
||||
void setTraceOutput(Object traceOutput) {
|
||||
synchronized (m_sendRequestLock) {
|
||||
if (traceOutput == null) {
|
||||
|
@ -161,7 +204,7 @@ class LDAPConnThread extends Thread {
|
|||
String timeStamp = m_timeFormat.format(new Date());
|
||||
StringBuffer sb = new StringBuffer(timeStamp);
|
||||
sb.append(" ldc=");
|
||||
sb.append(m_connMgr.getID());
|
||||
sb.append(m_id);
|
||||
|
||||
synchronized( m_sendRequestLock ) {
|
||||
if (m_traceOutput instanceof PrintWriter) {
|
||||
|
@ -207,36 +250,69 @@ class LDAPConnThread extends Thread {
|
|||
void sendRequest (LDAPConnection conn, JDAPProtocolOp request,
|
||||
LDAPMessageQueue toNotify, LDAPConstraints cons)
|
||||
throws LDAPException {
|
||||
if (!m_doRun) {
|
||||
throw new LDAPException ( "not connected to a server",
|
||||
|
||||
if (m_thread == null) {
|
||||
throw new LDAPException ( "Not connected to a server",
|
||||
LDAPException.SERVER_DOWN );
|
||||
}
|
||||
|
||||
LDAPMessage msg =
|
||||
new LDAPMessage(allocateId(), request, cons.getServerControls());
|
||||
|
||||
if ( toNotify != null ) {
|
||||
if (!(request instanceof JDAPAbandonRequest ||
|
||||
request instanceof JDAPUnbindRequest)) {
|
||||
/* Only worry about toNotify if we expect a response... */
|
||||
this.m_requests.put (new Integer (msg.getMessageID()), toNotify);
|
||||
m_requests.put (new Integer (msg.getMessageID()), toNotify);
|
||||
|
||||
/* Notify the backlog checker that there may be another outstanding
|
||||
request */
|
||||
resultRetrieved();
|
||||
}
|
||||
|
||||
toNotify.addRequest(msg.getMessageID(), conn, this, cons.getTimeLimit());
|
||||
}
|
||||
|
||||
if (!sendRequest(msg, /*ignoreErrors=*/false)) {
|
||||
throw new LDAPException("Server or network error",
|
||||
LDAPException.SERVER_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendRequest (LDAPMessage msg, boolean ignoreErrors) {
|
||||
synchronized( m_sendRequestLock ) {
|
||||
try {
|
||||
if (m_traceOutput != null) {
|
||||
logTraceMessage(msg.toTraceString());
|
||||
}
|
||||
msg.write (m_serverOutput);
|
||||
m_serverOutput.flush ();
|
||||
} catch (IOException e) {
|
||||
m_serverOutput.flush();
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (!ignoreErrors) {
|
||||
networkError(e);
|
||||
}
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
// m_serverOutput is null bacause of network error
|
||||
if (!ignoreErrors) {
|
||||
if (m_thread != null) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendUnbindRequest(LDAPControl[] ctrls) {
|
||||
LDAPMessage msg =
|
||||
new LDAPMessage(allocateId(), new JDAPUnbindRequest(), ctrls);
|
||||
sendRequest(msg, /*ignoreErrors=*/true);
|
||||
}
|
||||
|
||||
private void sendAbandonRequest(int id, LDAPControl[] ctrls) {
|
||||
LDAPMessage msg =
|
||||
new LDAPMessage(allocateId(), new JDAPAbandonRequest(id), ctrls);
|
||||
sendRequest(msg, /*ignoreErrors=*/true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -252,8 +328,8 @@ class LDAPConnThread extends Thread {
|
|||
return m_registered.size();
|
||||
}
|
||||
|
||||
boolean isRunning() {
|
||||
return m_doRun;
|
||||
boolean isConnected() {
|
||||
return m_thread != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,47 +337,54 @@ class LDAPConnThread extends Thread {
|
|||
* is deregistered. Then, this thread should be killed.
|
||||
* @param conn LDAP connection
|
||||
*/
|
||||
public synchronized void deregister(LDAPConnection conn) {
|
||||
/**
|
||||
* De-Register with this connection thread. If all the connection
|
||||
* is deregistered. Then, this thread should be killed.
|
||||
* @param conn LDAP connection
|
||||
*/
|
||||
synchronized void deregister(LDAPConnection conn) {
|
||||
|
||||
if (m_thread == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_registered.removeElement(conn);
|
||||
if (m_registered.size() == 0) {
|
||||
|
||||
// No more request processing
|
||||
Thread t = m_thread;
|
||||
m_thread = null;
|
||||
|
||||
try {
|
||||
// Notify the server
|
||||
sendUnbindRequest(conn.getConstraints().getServerControls());
|
||||
|
||||
if (!m_disconnected) {
|
||||
LDAPSearchConstraints cons = conn.getSearchConstraints();
|
||||
sendRequest (null, new JDAPUnbindRequest (), null, cons);
|
||||
}
|
||||
|
||||
// must be set after the call to sendRequest
|
||||
m_doRun =false;
|
||||
|
||||
if ( m_thread != null && m_thread != Thread.currentThread()) {
|
||||
|
||||
m_thread.interrupt();
|
||||
|
||||
// Wait up to 1 sec for thread to accept disconnect
|
||||
// notification. When the interrupt is accepted,
|
||||
// m_thread is set to null. See run() method.
|
||||
// interrupt the thread
|
||||
try {
|
||||
wait(1000);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
}
|
||||
t.interrupt();
|
||||
wait(500);
|
||||
}
|
||||
catch (InterruptedException ignore) {}
|
||||
|
||||
} catch (Exception e) {
|
||||
LDAPConnection.printDebug(e.toString());
|
||||
}
|
||||
finally {
|
||||
cleanUp();
|
||||
cleanUp(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clean ups before shutdown the thread.
|
||||
* Clean up after the thread shutdown.
|
||||
* The list of registered clients m_registered is left in the current state
|
||||
* to enable the clients to recover the connection.
|
||||
*/
|
||||
private void cleanUp() {
|
||||
if (!m_disconnected) {
|
||||
private void cleanUp(LDAPException ex) {
|
||||
|
||||
resultRetrieved();
|
||||
|
||||
try {
|
||||
m_serverOutput.close ();
|
||||
} catch (Exception e) {
|
||||
|
@ -316,56 +399,56 @@ class LDAPConnThread extends Thread {
|
|||
m_serverInput = null;
|
||||
}
|
||||
|
||||
if (m_origServerInput != null) {
|
||||
try {
|
||||
m_socket.close ();
|
||||
m_origServerInput.close ();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_socket = null;
|
||||
m_origServerInput = null;
|
||||
}
|
||||
}
|
||||
|
||||
m_disconnected = true;
|
||||
if (m_origServerOutput != null) {
|
||||
try {
|
||||
m_origServerOutput.close ();
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
m_origServerOutput = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the Connection Setup Manager that the connection was
|
||||
* terminated by the user
|
||||
*/
|
||||
m_connMgr.disconnect();
|
||||
// Notify the Connection Manager
|
||||
if (ex != null) {
|
||||
// the connection is lost
|
||||
m_connMgr.invalidateConnection();
|
||||
}
|
||||
else {
|
||||
// the connection is closed
|
||||
m_connMgr.closeConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel all outstanding requests
|
||||
*/
|
||||
if (m_requests != null) {
|
||||
// Set the status for all outstanding requests
|
||||
Enumeration requests = m_requests.elements();
|
||||
while (requests.hasMoreElements()) {
|
||||
try {
|
||||
LDAPMessageQueue listener =
|
||||
(LDAPMessageQueue)requests.nextElement();
|
||||
if (ex != null) {
|
||||
listener.setException(this, ex);
|
||||
}
|
||||
else {
|
||||
listener.removeAllRequests(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all the registered about this bad moment.
|
||||
* IMPORTANT: This needs to be done at last. Otherwise, the socket
|
||||
* input stream and output stream might never get closed and the whole
|
||||
* task will get stuck in the stop method when we tried to stop the
|
||||
* LDAPConnThread.
|
||||
*/
|
||||
|
||||
if (m_registered != null) {
|
||||
Vector registerCopy = (Vector)m_registered.clone();
|
||||
|
||||
Enumeration cancelled = registerCopy.elements();
|
||||
|
||||
while (cancelled.hasMoreElements ()) {
|
||||
LDAPConnection c = (LDAPConnection)cancelled.nextElement();
|
||||
c.deregisterConnection();
|
||||
catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
m_registered.removeAllElements();
|
||||
m_requests.clear();
|
||||
m_messages = null;
|
||||
m_cache = null;
|
||||
|
||||
if (m_messages != null) {
|
||||
m_messages.clear();
|
||||
}
|
||||
|
||||
m_bound = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -383,8 +466,8 @@ class LDAPConnThread extends Thread {
|
|||
while( listeners.hasMoreElements() ) {
|
||||
LDAPMessageQueue l = (LDAPMessageQueue)listeners.nextElement();
|
||||
|
||||
// If there are any threads waiting for a regular response
|
||||
// message, we have to go read the next incoming message
|
||||
// If there are clients waiting for a regular response
|
||||
// message, skip backlog checking
|
||||
if ( !(l instanceof LDAPSearchListener) ) {
|
||||
return;
|
||||
}
|
||||
|
@ -438,28 +521,20 @@ class LDAPConnThread extends Thread {
|
|||
*/
|
||||
public void run() {
|
||||
|
||||
// if there is a problem of establishing connection to the server,
|
||||
// stop the thread right away...
|
||||
if (!m_doRun) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_thread = Thread.currentThread();
|
||||
LDAPMessage msg = null;
|
||||
JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
|
||||
|
||||
while (m_doRun) {
|
||||
yield();
|
||||
int[] nread = new int[1];
|
||||
nread[0] = 0;
|
||||
|
||||
while (Thread.currentThread() == m_thread) {
|
||||
try {
|
||||
|
||||
// Check after every BACKLOG_CHKCNT messages if the backlog is not too high
|
||||
// Check every BACKLOG_CHKCNT messages if the backlog is not too high
|
||||
if (--m_backlogCheckCounter <= 0) {
|
||||
m_backlogCheckCounter = BACKLOG_CHKCNT;
|
||||
checkBacklog();
|
||||
}
|
||||
|
||||
nread[0] = 0;
|
||||
BERElement element = BERElement.getElement(decoder,
|
||||
m_serverInput,
|
||||
nread);
|
||||
|
@ -473,17 +548,14 @@ class LDAPConnThread extends Thread {
|
|||
// entry, thereby avoiding serialization of the entry stored in the
|
||||
// cache
|
||||
processResponse (msg, nread[0]);
|
||||
Thread.yield();
|
||||
|
||||
} catch (Exception e) {
|
||||
if (m_doRun) {
|
||||
if (Thread.currentThread() == m_thread) {
|
||||
networkError(e);
|
||||
}
|
||||
else {
|
||||
// interrupted from deregister()
|
||||
synchronized (this) {
|
||||
m_thread = null;
|
||||
notifyAll();
|
||||
}
|
||||
resultRetrieved();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -502,24 +574,6 @@ class LDAPConnThread extends Thread {
|
|||
return; /* nobody is waiting for this response (!) */
|
||||
}
|
||||
|
||||
// For asynch operations controls are to be read from the LDAPMessage
|
||||
// For synch operations controls are copied into the LDAPConnection
|
||||
// For synch search operations, controls are also copied into
|
||||
// LDAPSearchResults (see LDAPConnection.checkSearchMsg())
|
||||
if ( ! l.isAsynchOp()) {
|
||||
|
||||
/* Were there any controls for this client? */
|
||||
LDAPControl[] con = msg.getControls();
|
||||
if (con != null) {
|
||||
int msgid = msg.getMessageID();
|
||||
LDAPConnection ldc = l.getConnection(msgid);
|
||||
if (ldc != null) {
|
||||
ldc.setResponseControls( this,
|
||||
new LDAPResponseControl(ldc, msgid, con));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_cache != null && (l instanceof LDAPSearchListener)) {
|
||||
cacheSearchResult((LDAPSearchListener)l, msg, size);
|
||||
}
|
||||
|
@ -531,8 +585,40 @@ class LDAPConnThread extends Thread {
|
|||
if (m_requests.size() == 0) {
|
||||
m_backlogCheckCounter = BACKLOG_CHKCNT;
|
||||
}
|
||||
|
||||
// Change IO streams if startTLS extended op completed
|
||||
if (msg instanceof LDAPExtendedResponse) {
|
||||
LDAPExtendedResponse extrsp = (LDAPExtendedResponse) msg;
|
||||
String extid = extrsp.getID();
|
||||
if (extrsp.getResultCode() == 0 && extid != null &&
|
||||
extid.equals(LDAPConnection.OID_startTLS)) {
|
||||
|
||||
changeIOStreams();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void changeIOStreams() {
|
||||
|
||||
// Note: For the startTLS, the new streams are layered over the
|
||||
// existing ones so current IO streams as well as the socket MUST
|
||||
// not be closed.
|
||||
m_origServerInput = m_serverInput;
|
||||
m_origServerOutput = m_serverOutput;
|
||||
m_serverInput = null;
|
||||
m_serverOutput = null;
|
||||
|
||||
while (m_serverInput == null || m_serverOutput == null) {
|
||||
try {
|
||||
if (Thread.currentThread() != m_thread) {
|
||||
return; // user disconnected
|
||||
}
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collect search results to be added to the LDAPCache. Search results are
|
||||
|
@ -629,12 +715,13 @@ class LDAPConnThread extends Thread {
|
|||
}
|
||||
|
||||
/**
|
||||
* Stop dispatching responses for a particular message ID.
|
||||
* Stop dispatching responses for a particular message ID and send
|
||||
* the abandon request.
|
||||
* @param id Message ID for which to discard responses.
|
||||
*/
|
||||
void abandon (int id ) {
|
||||
void abandon (int id, LDAPControl[] ctrls) {
|
||||
|
||||
if (!m_doRun) {
|
||||
if (m_thread == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -647,6 +734,8 @@ class LDAPConnThread extends Thread {
|
|||
l.removeRequest(id);
|
||||
}
|
||||
resultRetrieved(); // If LDAPConnThread is blocked in checkBacklog()
|
||||
|
||||
sendAbandonRequest(id, ctrls);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -657,7 +746,7 @@ class LDAPConnThread extends Thread {
|
|||
*/
|
||||
LDAPMessageQueue changeListener (int id, LDAPMessageQueue toNotify) {
|
||||
|
||||
if (!m_doRun) {
|
||||
if (m_thread == null) {
|
||||
toNotify.setException(this, new LDAPException("Server or network error",
|
||||
LDAPException.SERVER_DOWN));
|
||||
return null;
|
||||
|
@ -672,26 +761,11 @@ class LDAPConnThread extends Thread {
|
|||
*/
|
||||
private synchronized void networkError (Exception e) {
|
||||
|
||||
m_doRun =false;
|
||||
|
||||
// notify the Connection Setup Manager that the connection is lost
|
||||
m_connMgr.invalidateConnection();
|
||||
|
||||
try {
|
||||
|
||||
// notify each listener that the server is down.
|
||||
Enumeration requests = m_requests.elements();
|
||||
while (requests.hasMoreElements()) {
|
||||
LDAPMessageQueue listener =
|
||||
(LDAPMessageQueue)requests.nextElement();
|
||||
listener.setException(this, new LDAPException("Server or network error",
|
||||
if (m_thread == null) {
|
||||
return;
|
||||
}
|
||||
m_thread = null; // No more request processing
|
||||
cleanUp(new LDAPException("Server or network error",
|
||||
LDAPException.SERVER_DOWN));
|
||||
}
|
||||
|
||||
} catch (NullPointerException ee) {
|
||||
System.err.println("Exception: "+ee.toString());
|
||||
}
|
||||
|
||||
cleanUp();
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -360,16 +360,12 @@ public class LDAPConstraints implements Cloneable, java.io.Serializable {
|
|||
|
||||
/**
|
||||
* Makes a copy of an existing set of constraints.
|
||||
* @returns a copy of an existing set of constraints
|
||||
* @return a copy of an existing set of constraints
|
||||
*/
|
||||
public Object clone() {
|
||||
LDAPConstraints o = new LDAPConstraints();
|
||||
try {
|
||||
LDAPConstraints o = (LDAPConstraints) super.clone();
|
||||
|
||||
o.m_time_limit = this.m_time_limit;
|
||||
o.referrals = this.referrals;
|
||||
o.m_bind_proc = this.m_bind_proc;
|
||||
o.m_rebind_proc = this.m_rebind_proc;
|
||||
o.m_hop_limit = this.m_hop_limit;
|
||||
if ( (this.m_clientControls != null) &&
|
||||
(this.m_clientControls.length > 0) ) {
|
||||
o.m_clientControls = new LDAPControl[this.m_clientControls.length];
|
||||
|
@ -386,4 +382,9 @@ public class LDAPConstraints implements Cloneable, java.io.Serializable {
|
|||
}
|
||||
return o;
|
||||
}
|
||||
catch (CloneNotSupportedException ex) {
|
||||
// shold never happen, the class is Cloneable
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ import java.io.*;
|
|||
* 95 <A HREF="#MORE_RESULTS_TO_RETURN">MORE_RESULTS_TO_RETURN</A>
|
||||
* 96 <A HREF="#CLIENT_LOOP">CLIENT_LOOP</A>
|
||||
* 97 <A HREF="#REFERRAL_LIMIT_EXCEEDED">REFERRAL_LIMIT_EXCEEDED</A>
|
||||
* 112 <A HREF="#TLS_NOT_SUPPORTED">TLS_NOT_SUPPORTED</A> (LDAP v3)
|
||||
* </PRE>
|
||||
* <P>
|
||||
*
|
||||
|
@ -132,7 +133,7 @@ import java.io.*;
|
|||
public class LDAPException extends java.lang.Exception
|
||||
implements java.io.Serializable {
|
||||
|
||||
static final long serialVersionUID = -9215007872184847924L;
|
||||
static final long serialVersionUID = -9215007872184847925L;
|
||||
|
||||
/**
|
||||
* (0) The operation completed successfully.
|
||||
|
@ -556,11 +557,21 @@ public class LDAPException extends java.lang.Exception
|
|||
*/
|
||||
public final static int REFERRAL_LIMIT_EXCEEDED = 0x61;
|
||||
|
||||
/**
|
||||
* (112) The socket factory of the connection is not capable
|
||||
* of initiating a TLS session.
|
||||
* <P>
|
||||
*
|
||||
* @see netscape.ldap.LDAPConnection#startTLS
|
||||
*/
|
||||
public final static int TLS_NOT_SUPPORTED = 0x70;
|
||||
|
||||
/**
|
||||
* Internal variables
|
||||
*/
|
||||
private int resultCode = -1;
|
||||
private String errorMessage = null;
|
||||
private String extraMessage = null;
|
||||
private String matchedDN = null;
|
||||
private Locale m_locale = Locale.getDefault();
|
||||
private static Hashtable cacheResource = new Hashtable();
|
||||
|
@ -734,16 +745,31 @@ public class LDAPException extends java.lang.Exception
|
|||
return errorMessage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds additional explanation to the error message
|
||||
*/
|
||||
void setExtraMessage (String msg) {
|
||||
if (extraMessage == null) {
|
||||
extraMessage = msg;
|
||||
}
|
||||
else {
|
||||
extraMessage += "; " + msg;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximal subset of a DN which could be matched by the
|
||||
* server, if the server returned one of the following errors:
|
||||
* server.
|
||||
*
|
||||
* The method should be used if the server returned one of the
|
||||
* following errors:
|
||||
* <UL>
|
||||
* <LI><CODE>NO_SUCH_OBJECT</CODE>
|
||||
* <LI><CODE>ALIAS_PROBLEM</CODE>
|
||||
* <LI><CODE>INVALID_DN_SYNTAX</CODE>
|
||||
* <LI><CODE>ALIAS_DEREFERENCING_PROBLEM</CODE>
|
||||
* </UL>
|
||||
* </PRE>
|
||||
* For example, if the DN <CODE>cn=Babs Jensen, o=People, c=Airius.com</CODE>
|
||||
* could not be found by the DN <CODE>o=People, c=Airius.com</CODE>
|
||||
* could be found, the matched DN is
|
||||
|
@ -791,14 +817,19 @@ public class LDAPException extends java.lang.Exception
|
|||
*/
|
||||
public String toString() {
|
||||
String str = super.toString() + " (" + resultCode + ")" ;
|
||||
if ( (errorMessage != null) && (errorMessage.length() > 0) )
|
||||
if ( (errorMessage != null) && (errorMessage.length() > 0) ) {
|
||||
str += "; " + errorMessage;
|
||||
if ( (matchedDN != null) && (matchedDN.length() > 0) )
|
||||
}
|
||||
if ( (matchedDN != null) && (matchedDN.length() > 0) ) {
|
||||
str += "; matchedDN = " + matchedDN;
|
||||
String errorStr = null;
|
||||
if (((errorStr = errorCodeToString(m_locale)) != null) &&
|
||||
(errorStr.length() > 0))
|
||||
}
|
||||
String errorStr = errorCodeToString(m_locale);
|
||||
if ((errorStr != null) && (errorStr.length() > 0)) {
|
||||
str += "; " + errorStr;
|
||||
}
|
||||
if (extraMessage != null) {
|
||||
str += "; " + extraMessage;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.Vector;
|
|||
*/
|
||||
class LDAPMessageQueue implements java.io.Serializable {
|
||||
|
||||
static final long serialVersionUID = -7163312406176592277L;
|
||||
static final long serialVersionUID = -7163312406176592278L;
|
||||
|
||||
/**
|
||||
* Request entry encapsulates request parameters
|
||||
|
@ -88,6 +88,27 @@ class LDAPMessageQueue implements java.io.Serializable {
|
|||
return m_asynchOp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks until a response is available.
|
||||
* Used by LDAPConnection.sendRequest (synch ops) to test if the server
|
||||
* is really available after a request had been sent.
|
||||
* @exception LDAPException Network error exception
|
||||
* @exception LDAPInterruptedException The invoking thread was interrupted
|
||||
*/
|
||||
synchronized void waitFirstMessage () throws LDAPException {
|
||||
|
||||
while(m_requestList.size() != 0 && m_exception == null && m_messageQueue.size() == 0) {
|
||||
waitForMessage();
|
||||
}
|
||||
|
||||
// Network exception occurred ?
|
||||
if (m_exception != null) {
|
||||
LDAPException ex = m_exception;
|
||||
m_exception = null;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks until a response is available or until all operations
|
||||
* associated with the object have completed or been canceled.
|
||||
|
@ -287,7 +308,7 @@ class LDAPMessageQueue implements java.io.Serializable {
|
|||
// Mark conn as bound for asych bind operations
|
||||
if (isAsynchOp() && msg.getType() == msg.BIND_RESPONSE) {
|
||||
if (((LDAPResponse) msg).getResultCode() == 0) {
|
||||
getConnection(msg.getMessageID()).markConnAsBound();
|
||||
getConnection(msg.getMessageID()).setBound(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ public class LDAPSSLSocketFactory
|
|||
|
||||
|
||||
/**
|
||||
* <B>This method is currently not implemented.</B>
|
||||
* <B>This method is currently not implemented</B>.
|
||||
* Enables client authentication for an application that uses
|
||||
* an external (file-based) certificate database.
|
||||
* Call this method before you call <CODE>makeSocket</CODE>.
|
||||
|
|
|
@ -225,7 +225,7 @@ public class LDAPSaslBind implements LDAPBind, java.io.Serializable {
|
|||
_saslClient,
|
||||
className, "getOutputStream", args, argNames);
|
||||
ldc.setOutputStream(os);
|
||||
ldc.markConnAsBound();
|
||||
ldc.setBound(true);
|
||||
} catch (LDAPException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -34,11 +34,25 @@ package netscape.ldap;
|
|||
public class LDAPSearchConstraints extends LDAPConstraints
|
||||
implements Cloneable {
|
||||
|
||||
|
||||
// Constants for behavior when a search continuation reference cannot
|
||||
// be followed
|
||||
/**
|
||||
* Continue processing if there is an error following a search continuation
|
||||
* reference
|
||||
*/
|
||||
public static final int REFERRAL_ERROR_CONTINUE = 0;
|
||||
/**
|
||||
* Throw exception if there is an error following a search continuation
|
||||
* reference
|
||||
*/
|
||||
public static final int REFERRAL_ERROR_EXCEPTION = 1;
|
||||
private int deref;
|
||||
private int maxRes;
|
||||
private int batch;
|
||||
private int serverTimeLimit;
|
||||
private int maxBacklog = 100;
|
||||
private int referralErrors = REFERRAL_ERROR_CONTINUE;
|
||||
|
||||
/**
|
||||
* Constructs an <CODE>LDAPSearchConstraints</CODE> object that specifies
|
||||
|
@ -81,8 +95,10 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
|||
* @param hop_limit maximum number of referrals to follow in a
|
||||
* sequence when attempting to resolve a request
|
||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
|
||||
netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String,
|
||||
java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
*/
|
||||
public LDAPSearchConstraints( int msLimit, int dereference,
|
||||
int maxResults, boolean doReferrals, int batchSize,
|
||||
|
@ -125,8 +141,10 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
|||
* @param hop_limit maximum number of referrals to follow in a
|
||||
* sequence when attempting to resolve a request
|
||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
|
||||
netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String,
|
||||
java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
*/
|
||||
public LDAPSearchConstraints( int msLimit, int timeLimit,
|
||||
int dereference,
|
||||
|
@ -171,8 +189,10 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
|||
* @param hop_limit maximum number of referrals to follow in a
|
||||
* sequence when attempting to resolve a request
|
||||
* @see netscape.ldap.LDAPConnection#setOption(int, java.lang.Object)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String, java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(netscape.ldap.LDAPUrl,
|
||||
netscape.ldap.LDAPSearchConstraints)
|
||||
* @see netscape.ldap.LDAPConnection#search(java.lang.String, int, java.lang.String,
|
||||
java.lang.String[], boolean, netscape.ldap.LDAPSearchConstraints)
|
||||
*/
|
||||
public LDAPSearchConstraints( int msLimit, int timeLimit,
|
||||
int dereference,
|
||||
|
@ -296,51 +316,101 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
|||
return maxBacklog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports if errors when following search continuation references are
|
||||
* to cause processing of the remaining results to be aborted.
|
||||
* <p>
|
||||
* If an LDAP server does not contain an entry at the base DN for a search,
|
||||
* it may be configured to return a referral. If it contains an entry at
|
||||
* the base DN of a subtree search, one or more of the child entries may
|
||||
* contain search continuation references. The search continuation
|
||||
* references are returned to the client, which may follow them by issuing
|
||||
* a search request to the host indicated in the search reference.
|
||||
* <p>
|
||||
* If the <CODE>LDAPConnection</CODE> object has been configured to follow
|
||||
* referrals automatically, it may fail when issuing a search request to
|
||||
* the host indicated in a search reference, e.g. because there is no
|
||||
* entry there, because it does not have credentials, because it does not
|
||||
* have sufficient permissions, etc. If the client aborts evaluation of the
|
||||
* search results (obtained through <CODE>LDAPSearchResults</CODE>) when a
|
||||
* search reference cannot be followed, any remaining results are discarded.
|
||||
* <p>
|
||||
* Up to version 4.17 of the Java LDAP SDK, the SDK printed an error
|
||||
* message but continued to process the remaining search results and search
|
||||
* continuation references.
|
||||
* <p>
|
||||
* As of SDK version 4.17, the default behavior is still to continue
|
||||
* processing any remaining search results and search continuation
|
||||
* references if there is an error following a referral, but the behavior
|
||||
* may be changed with <CODE>setReferralErrors</CODE> to throw an exception
|
||||
* instead.
|
||||
*
|
||||
* @return <CODE>REFERRAL_ERROR_CONTINUE</CODE> if remaining results are
|
||||
* to be processed when there is an error following a search continuation
|
||||
* reference, <CODE>REFERRAL_ERROR_EXCEPTION</CODE> if such an error is to
|
||||
* cause an <CODE>LDAPException</CODE>.
|
||||
*
|
||||
* @see netscape.ldap.LDAPConstraints#setReferrals
|
||||
* @since LDAPJDK 4.17
|
||||
*/
|
||||
public int getReferralErrors() {
|
||||
return referralErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies if errors when following search continuation references are
|
||||
* to cause processing of the remaining results to be aborted.
|
||||
* <p>
|
||||
* If an LDAP server does not contain an entry at the base DN for a search,
|
||||
* it may be configured to return a referral. If it contains an entry at
|
||||
* the base DN of a subtree search, one or more of the child entries may
|
||||
* contain search continuation references. The search continuation
|
||||
* references are returned to the client, which may follow them by issuing
|
||||
* a search request to the host indicated in the search reference.
|
||||
* <p>
|
||||
* If the <CODE>LDAPConnection</CODE> object has been configured to follow
|
||||
* referrals automatically, it may fail when issuing a search request to
|
||||
* the host indicated in a search reference, e.g. because there is no
|
||||
* entry there, because it does not have credentials, because it does not
|
||||
* have sufficient permissions, etc. If the client aborts evaluation of the
|
||||
* search results (obtained through <CODE>LDAPSearchResults</CODE>) when a
|
||||
* search reference cannot be followed, any remaining results are discarded.
|
||||
* <p>
|
||||
* Up to version 4.17 of the Java LDAP SDK, the SDK printed an error
|
||||
* message but continued to process the remaining search results and search
|
||||
* continuation references.
|
||||
* <p>
|
||||
* As of SDK version 4.17, the default behavior is still to continue
|
||||
* processing any remaining search results and search continuation
|
||||
* references if there is an error following a referral, but the behavior
|
||||
* may be changed with <CODE>setReferralErrors</CODE> to throw an exception
|
||||
* instead.
|
||||
*
|
||||
* @param errorBehavior Either <CODE>REFERRAL_ERROR_CONTINUE</CODE> if
|
||||
* remaining results are to be processed when there is an error following a
|
||||
* search continuation reference or <CODE>REFERRAL_ERROR_EXCEPTION</CODE>
|
||||
* if such an error is to cause an <CODE>LDAPException</CODE>.
|
||||
*
|
||||
* @see netscape.ldap.LDAPSearchConstraints#getReferralErrors
|
||||
* @see netscape.ldap.LDAPSearchResults#next
|
||||
* @see netscape.ldap.LDAPSearchResults#nextElement
|
||||
* @since LDAPJDK 4.17
|
||||
*/
|
||||
public void setReferralErrors(int errorBehavior) {
|
||||
if ( (errorBehavior != REFERRAL_ERROR_CONTINUE) &&
|
||||
(errorBehavior != REFERRAL_ERROR_EXCEPTION) ) {
|
||||
throw new IllegalArgumentException( "Invalid error behavior: " +
|
||||
errorBehavior );
|
||||
}
|
||||
referralErrors = errorBehavior;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a copy of an existing set of search constraints.
|
||||
* @return a copy of an existing set of search constraints.
|
||||
*/
|
||||
public Object clone() {
|
||||
LDAPSearchConstraints o = new LDAPSearchConstraints();
|
||||
|
||||
o.serverTimeLimit = this.serverTimeLimit;
|
||||
o.deref = this.deref;
|
||||
o.maxRes = this.maxRes;
|
||||
o.batch = this.batch;
|
||||
o.maxBacklog = this.maxBacklog;
|
||||
|
||||
o.setHopLimit(this.getHopLimit());
|
||||
o.setReferrals(this.getReferrals());
|
||||
o.setTimeLimit(this.getTimeLimit());
|
||||
|
||||
if (this.getBindProc() != null) {
|
||||
o.setBindProc(this.getBindProc());
|
||||
} else {
|
||||
o.setRebindProc(this.getRebindProc());
|
||||
}
|
||||
|
||||
LDAPControl[] tClientControls = this.getClientControls();
|
||||
LDAPControl[] oClientControls;
|
||||
|
||||
if ( (tClientControls != null) &&
|
||||
(tClientControls.length > 0) ) {
|
||||
oClientControls = new LDAPControl[tClientControls.length];
|
||||
for( int i = 0; i < tClientControls.length; i++ )
|
||||
oClientControls[i] = (LDAPControl)tClientControls[i].clone();
|
||||
o.setClientControls(oClientControls);
|
||||
}
|
||||
|
||||
LDAPControl[] tServerControls = this.getServerControls();
|
||||
LDAPControl[] oServerControls;
|
||||
|
||||
if ( (tServerControls != null) &&
|
||||
(tServerControls.length > 0) ) {
|
||||
oServerControls = new LDAPControl[tServerControls.length];
|
||||
for( int i = 0; i < tServerControls.length; i++ )
|
||||
oServerControls[i] = (LDAPControl)tServerControls[i].clone();
|
||||
o.setServerControls(oServerControls);
|
||||
}
|
||||
|
||||
LDAPSearchConstraints o = (LDAPSearchConstraints) super.clone();
|
||||
return o;
|
||||
}
|
||||
|
||||
|
@ -356,7 +426,8 @@ public class LDAPSearchConstraints extends LDAPConstraints
|
|||
sb.append("server time limit " + serverTimeLimit + ", ");
|
||||
sb.append("aliases " + deref + ", ");
|
||||
sb.append("batch size " + batch + ", ");
|
||||
sb.append("max backlog " + maxBacklog);
|
||||
sb.append("max backlog " + maxBacklog + ", ");
|
||||
sb.append("referralErrors " + referralErrors);
|
||||
sb.append('}');
|
||||
|
||||
return sb.toString();
|
||||
|
|
|
@ -549,7 +549,7 @@ public class LDAPSearchResults implements Enumeration, java.io.Serializable {
|
|||
currBase, currScope, currFilter,
|
||||
currAttrs, currAttrsOnly);
|
||||
} catch (LDAPException e) {
|
||||
System.err.println("LDAPSearchResults.fetchResult: "+e);
|
||||
add(e);
|
||||
} finally {
|
||||
currConn.releaseSearchListener(resultSource);
|
||||
}
|
||||
|
@ -567,7 +567,7 @@ public class LDAPSearchResults implements Enumeration, java.io.Serializable {
|
|||
currConn.checkSearchMsg(this, msg, currCons,
|
||||
currBase, currScope, currFilter, currAttrs, currAttrsOnly);
|
||||
} catch (LDAPException e) {
|
||||
System.err.println("Exception: "+e);
|
||||
add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (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.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2002 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package netscape.ldap;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* A socket factory interface for supporting the start TLS LDAPv3
|
||||
* extension (RFC 2830).
|
||||
* <P>
|
||||
*
|
||||
* @version 1.0
|
||||
* @since LDAPJDK 4.17
|
||||
*/
|
||||
public interface LDAPTLSSocketFactory extends LDAPSocketFactory {
|
||||
/**
|
||||
* Creates an SSL socket layered over an existing socket.
|
||||
*
|
||||
* Used for the start TLS operations (RFC2830).
|
||||
*
|
||||
* @param s An existing non-SSL socket
|
||||
* @return A SSL socket layered over the input socket
|
||||
* @exception LDAPException on error creating socket
|
||||
* @see LDAPConnection#startTLS
|
||||
*/
|
||||
public Socket makeSocket(Socket s) throws LDAPException;
|
||||
}
|
|
@ -24,7 +24,6 @@ package netscape.ldap;
|
|||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import netscape.ldap.factory.*;
|
||||
|
||||
/**
|
||||
* Represents an LDAP URL. The complete specification for LDAP URLs is in
|
||||
|
@ -81,7 +80,7 @@ import netscape.ldap.factory.*;
|
|||
*/
|
||||
public class LDAPUrl implements java.io.Serializable {
|
||||
|
||||
static final long serialVersionUID = -3245440798565713640L;
|
||||
static final long serialVersionUID = -3245440798565713641L;
|
||||
public static String defaultFilter = "(objectClass=*)";
|
||||
|
||||
private String m_hostName;
|
||||
|
@ -371,7 +370,7 @@ public class LDAPUrl implements java.io.Serializable {
|
|||
} else
|
||||
m_attributes = null;
|
||||
|
||||
StringBuffer url = new StringBuffer (secure ? "LDAPS://" :"LDAP://");
|
||||
StringBuffer url = new StringBuffer (secure ? "ldaps://" :"ldap://");
|
||||
|
||||
if (host != null) {
|
||||
url.append (host);
|
||||
|
@ -444,6 +443,15 @@ public class LDAPUrl implements java.io.Serializable {
|
|||
return m_DN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server part of the ldap url, ldap://host:port
|
||||
* @return server url.
|
||||
*/
|
||||
String getServerUrl() {
|
||||
return (m_secure ? "ldaps://" : "ldap://") +
|
||||
m_hostName + ":" + m_portNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the collection of attributes specified in the URL, or null
|
||||
* for "every attribute"
|
||||
|
@ -545,10 +553,10 @@ public class LDAPUrl implements java.io.Serializable {
|
|||
|
||||
if (m_factory == null) {
|
||||
|
||||
// No factory explicity set, try to determine
|
||||
// No factory explicitly set, try to determine
|
||||
// the default one.
|
||||
try {
|
||||
// First try iPlanet JSSSocketFactory
|
||||
// First try Mozilla JSSSocketFactory
|
||||
Class c = Class.forName("netscape.ldap.factory.JSSSocketFactory");
|
||||
m_factory = (LDAPSocketFactory) c.newInstance();
|
||||
}
|
||||
|
@ -561,7 +569,8 @@ public class LDAPUrl implements java.io.Serializable {
|
|||
|
||||
try {
|
||||
// then try Sun JSSESocketFactory
|
||||
m_factory = new JSSESocketFactory(null);
|
||||
Class c = Class.forName("netscape.ldap.factory.JSSESocketFactory");
|
||||
m_factory = (LDAPSocketFactory) c.newInstance();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
}
|
||||
|
|
|
@ -49,3 +49,4 @@
|
|||
95=More results to return
|
||||
96=Client detected loop
|
||||
97=Referral hop limit exceeded
|
||||
112=Cannot start TLS
|
||||
|
|
|
@ -49,3 +49,4 @@
|
|||
95=Es stehen noch weitere Ergebnisse zur Verfügung
|
||||
96=Client stellte Schleife fest
|
||||
97=Beschränkung für Zwischenschritte bei Referenz überschritten
|
||||
112=TLS kann nicht activiert werden
|
||||
|
|
|
@ -49,3 +49,4 @@
|
|||
95=Autres résultats à venir
|
||||
96=Client a détecté la boucle
|
||||
97=Nombre de rebonds sur référence trop grand
|
||||
112=Impossible d'activer TLS
|
||||
|
|
|
@ -49,3 +49,4 @@
|
|||
95=\u3055\u3089\u306B\u7D50\u679C\u304C\u8FD4\u3055\u308C\u307E\u3059\u3002
|
||||
96=\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u304C\u30EB\u30FC\u30D7\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002
|
||||
97=\u30EC\u30D5\u30A7\u30E9\u30EB \u30DB\u30C3\u30D7 \u30EA\u30DF\u30C3\u30C8\u3092\u8D85\u904E\u3057\u307E\u3057\u305F\u3002
|
||||
112=TLS\u3092\u-6a75\u59cb\u3067\u304d\u307e\u305b\u3093\u3002
|
||||
|
|
|
@ -37,15 +37,22 @@ import netscape.ldap.*;
|
|||
* @see LDAPSocketFactory
|
||||
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
||||
*/
|
||||
public class JSSESocketFactory
|
||||
implements LDAPSocketFactory, java.io.Serializable {
|
||||
public class JSSESocketFactory implements LDAPTLSSocketFactory,
|
||||
java.io.Serializable {
|
||||
|
||||
static final long serialVersionUID = 6834205777733266609L;
|
||||
static final long serialVersionUID = 6834205777733266610L;
|
||||
|
||||
// Optional explicit cipher suites to use
|
||||
private String[] suites;
|
||||
protected String[] suites;
|
||||
// The socket factory
|
||||
private SSLSocketFactory factory;
|
||||
protected SSLSocketFactory factory;
|
||||
|
||||
/**
|
||||
* Default factory constructor
|
||||
*/
|
||||
public JSSESocketFactory() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory constructor that uses the default JSSE SSLSocketFactory
|
||||
|
@ -73,7 +80,7 @@ public class JSSESocketFactory
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an SSL socket
|
||||
* Creates an SSL socket.
|
||||
*
|
||||
* @param host Host name or IP address of SSL server
|
||||
* @param port Port numbers of SSL server
|
||||
|
@ -98,16 +105,49 @@ public class JSSESocketFactory
|
|||
sock.startHandshake();
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
throw new LDAPException("SSL connection to " + host +
|
||||
":" + port + ", " + e.getMessage(),
|
||||
throw new LDAPException("JSSESocketFactory.makeSocket - Unknown host: " + host,
|
||||
LDAPException.CONNECT_ERROR);
|
||||
} catch (IOException f) {
|
||||
throw new LDAPException("SSL connection to " + host +
|
||||
":" + port + ", " + f.getMessage(),
|
||||
throw new LDAPException("JSSESocketFactory.makeSocket " +
|
||||
host + ":" + port + ", " + f.getMessage(),
|
||||
LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SSL socket layered over an existing socket.
|
||||
*
|
||||
* Used for the startTLS implementation (RFC2830).
|
||||
*
|
||||
* @param s An existing non-SSL socket
|
||||
* @return A SSL socket layered over the input socket
|
||||
* @exception LDAPException on error creating socket
|
||||
* @since LDAPJDK 4.17
|
||||
*/
|
||||
public Socket makeSocket(Socket s)
|
||||
throws LDAPException {
|
||||
|
||||
SSLSocket sock = null;
|
||||
String host = s.getInetAddress().getHostName();
|
||||
int port = s.getPort();
|
||||
|
||||
try {
|
||||
sock = (SSLSocket)factory.createSocket(s, host, port, /*autoClose=*/ true);
|
||||
|
||||
if (suites != null) {
|
||||
sock.setEnabledCipherSuites(suites);
|
||||
}
|
||||
|
||||
sock.startHandshake();
|
||||
|
||||
} catch (IOException f) {
|
||||
throw new LDAPException("JSSESocketFactory - start TLS, " + f.getMessage(),
|
||||
LDAPException.TLS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (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.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package netscape.ldap.factory;
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
import netscape.ldap.*;
|
||||
|
||||
import org.mozilla.jss.ssl.SSLSocket;
|
||||
import org.mozilla.jss.ssl.SSLCertificateApprovalCallback.ValidityStatus;
|
||||
import org.mozilla.jss.ssl.SSLCertificateApprovalCallback;
|
||||
import org.mozilla.jss.crypto.X509Certificate;
|
||||
import org.mozilla.jss.crypto.AlreadyInitializedException;
|
||||
import org.mozilla.jss.CryptoManager;
|
||||
|
||||
/**
|
||||
* Creates an SSL socket connection to a server, using the Netscape/Mozilla
|
||||
* JSS package.
|
||||
* This class implements the <CODE>LDAPSocketFactory</CODE>
|
||||
* interface.
|
||||
* <P>
|
||||
* <B>NOTE: This class is internal to Netscape and is distributed only with
|
||||
* Netscape products</B>.
|
||||
* <P>
|
||||
* By default, the factory uses "secmod.db", "key3.db" and "cert7.db"
|
||||
* databases in the current directory. If you need to override this default
|
||||
* setting, then you should call the static <CODE>initialize</CODE> method
|
||||
* before creating the first instance of <CODE>JSSSocketFactory</CODE>.
|
||||
* <P>
|
||||
* <PRE>
|
||||
* ...
|
||||
* JSSSocketFactory.initialize("../certDir");
|
||||
* LDAPConnection ld = new LDAPConnection(new JSSSocketFactory());
|
||||
* ...
|
||||
* </PRE>
|
||||
* @version 1.1
|
||||
* @see LDAPSocketFactory
|
||||
* @see LDAPConnection#LDAPConnection(netscape.ldap.LDAPSocketFactory)
|
||||
*/
|
||||
|
||||
public class JSSSocketFactory implements Serializable,
|
||||
LDAPTLSSocketFactory,
|
||||
SSLCertificateApprovalCallback
|
||||
{
|
||||
|
||||
static final long serialVersionUID = -6926469178017736903L;
|
||||
|
||||
/**
|
||||
* Default security module database path "secmod.db".
|
||||
*/
|
||||
public static final String defaultModDB = "secmod.db";
|
||||
|
||||
/**
|
||||
* Default key database path "key3.db".
|
||||
*/
|
||||
public static final String defaultKeyDB = "key3.db";
|
||||
|
||||
/**
|
||||
* Default certificate database path "cert7.db".
|
||||
*/
|
||||
public static final String defaultCertDB = "cert7.db";
|
||||
|
||||
private static String moddb;
|
||||
private static String keydb;
|
||||
private static String certdb;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>JSSSocketFactory</CODE>.
|
||||
* <CODE>CryptoManager.initialize(certdbDir)</CODE> or
|
||||
* JSSSocketFactory.initialize(certdbDir)</CODE> must be called once in the
|
||||
* application before using the object.
|
||||
*
|
||||
* @exception LDAPException on initialization error
|
||||
* @see netscape.ldap.factory.JSSSocketFactory#JSSSocketFactory(java.lang.String)
|
||||
*/
|
||||
public JSSSocketFactory() throws LDAPException{
|
||||
initialize(".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <CODE>JSSSocketFactory</CODE>, initializing the
|
||||
* JSS security system if it has not already been initialized
|
||||
*
|
||||
* @param certdbDir The full path, relative or absolute, of the certificate
|
||||
* database directory
|
||||
* @exception LDAPException on initialization error
|
||||
*/
|
||||
public JSSSocketFactory( String certdbDir ) throws LDAPException{
|
||||
initialize( certdbDir );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the JSS security subsystem.
|
||||
* <P>
|
||||
* This method allows you to override the current directory as the
|
||||
* default certificate database directory. The directory is expected
|
||||
* to contain <CODE>secmod.db</CODE>, <CODE>key3.db</CODE> and
|
||||
* <CODE>cert7.db</CODE> files as the security module database, key database
|
||||
* and certificate database respectively.
|
||||
* <P>
|
||||
* The method may be called only once, before the first instance of
|
||||
* <CODE>JSSSocketFactory</CODE> is created. When creating the first
|
||||
* instance, the constructor will automatically initialize the JSS
|
||||
* security subsystem using the defaults, unless it is already initialized.
|
||||
* <P>
|
||||
* @param certdbDir The full path, relative or absolute, of the certificate
|
||||
* database directory.
|
||||
* @exception LDAPException on initialization error
|
||||
* @see netscape.ldap.factory.JSSSocketFactory#JSSSocketFactory(String)
|
||||
*/
|
||||
public static void initialize( String certdbDir ) throws LDAPException {
|
||||
moddb = certdbDir + File.separator + JSSSocketFactory.defaultModDB;
|
||||
keydb = certdbDir + File.separator + JSSSocketFactory.defaultKeyDB;
|
||||
certdb = certdbDir + File.separator + JSSSocketFactory.defaultCertDB;
|
||||
try {
|
||||
CryptoManager.initialize( certdbDir );
|
||||
} catch (AlreadyInitializedException e) {
|
||||
// This is ok
|
||||
} catch (Exception e) {
|
||||
throw new LDAPException("Failed to initialize JSSSocketFactory: "
|
||||
+ e.getMessage(), LDAPException.OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the JSS security subsystem.
|
||||
* <P>
|
||||
* This method allows you to override the default name and location of
|
||||
* the security module database, key database and certificate databases.
|
||||
* <P>
|
||||
* The method may be called only once, before the first instance of
|
||||
* <CODE>JSSSocketFactory</CODE> is created. When creating the first
|
||||
* instance, the constructor will automatically initialize the JSS
|
||||
* security subsystem using the defaults, unless it is already initialized.
|
||||
* <P>
|
||||
* @param moddb The full path, relative or absolute, of the security
|
||||
* module database.
|
||||
* @param keydb The full path, relative or absolute, of the key database.
|
||||
* @param keydb The full path, relative or absolute, of the certificate
|
||||
* database.
|
||||
* @see netscape.ldap.factory.JSSSocketFactory#JSSSocketFactory
|
||||
* @see netscape.ldap.factory.JSSSocketFactory#initialize(java.lang.String)
|
||||
* @exception LDAPException on initialization error
|
||||
* @deprecated Please call <CODE>JSSSocketFactory(String certDir)</CODE> instead
|
||||
*/
|
||||
public static void initialize( String moddb, String keydb, String certdb )
|
||||
throws LDAPException {
|
||||
JSSSocketFactory.moddb = moddb;
|
||||
JSSSocketFactory.keydb = keydb;
|
||||
JSSSocketFactory.certdb = certdb;
|
||||
int ind = certdb.lastIndexOf( File.separator );
|
||||
String certdbDir = ( ind == 0 ) ? File.separator :
|
||||
( ind > 0 ) ? certdb.substring( 0, ind ) : ".";
|
||||
initialize( certdbDir );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path of the security module
|
||||
* database
|
||||
*
|
||||
* @return The full path, relative or absolute, of the security module database
|
||||
*/
|
||||
public static String getModDB() {
|
||||
return moddb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path of the key database
|
||||
*
|
||||
* @return The full path, relative or absolute, of the key database
|
||||
*/
|
||||
public static String getKeyDB() {
|
||||
return keydb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path of the certificate database
|
||||
*
|
||||
* @return The full path, relative or absolute, of the certificate database
|
||||
*/
|
||||
public static String getCertDB() {
|
||||
return certdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SSL socket
|
||||
*
|
||||
* @param host Host name or IP address of SSL server
|
||||
* @param port Port numbers of SSL server
|
||||
* @return A socket for an encrypted session
|
||||
* @exception LDAPException on error creating socket
|
||||
*/
|
||||
public Socket makeSocket( String host, int port ) throws LDAPException {
|
||||
SSLSocket socket = null;
|
||||
try {
|
||||
|
||||
socket = new SSLSocket( host, // address
|
||||
port, // port
|
||||
null, // localAddress
|
||||
0, // localPort
|
||||
this, // certApprovalCallback
|
||||
null // clientCertSelectionCallback
|
||||
);
|
||||
|
||||
socket.forceHandshake();
|
||||
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
throw new LDAPException("JSSSocketFactory.makeSocket - Unknown host: " + host,
|
||||
LDAPException.CONNECT_ERROR);
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new LDAPException("JSSSocketFactory.makeSocket " +
|
||||
host + ":" + port + ", " + e.getMessage(),
|
||||
LDAPException.CONNECT_ERROR);
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation of the SSLCertificateApprovalCallback
|
||||
* interface.
|
||||
* <P>
|
||||
* This default implementation always returns true. If you need to
|
||||
* verify the server certificate validity, then you should override
|
||||
* this method.
|
||||
* <P>
|
||||
* @param serverCert X509 Certificate
|
||||
* @param status The validity of the server certificate
|
||||
* @return <CODE>true</CODE>, by default we trust the certificate
|
||||
*/
|
||||
public boolean approve(X509Certificate serverCert,
|
||||
ValidityStatus status) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SSL socket layered over an existing socket.
|
||||
*
|
||||
* Used for the startTLS implementation (RFC2830).
|
||||
*
|
||||
* @param s An existing non-SSL socket
|
||||
* @return A SSL socket layered over the input socket
|
||||
* @exception LDAPException on error creating socket
|
||||
* @since LDAPJDK 4.17
|
||||
*/
|
||||
public Socket makeSocket(Socket s) throws LDAPException {
|
||||
SSLSocket socket = null;
|
||||
String host = s.getInetAddress().getHostName();
|
||||
int port = s.getPort();
|
||||
try {
|
||||
socket = new SSLSocket( s,
|
||||
host,
|
||||
this, // certApprovalCallback
|
||||
null // clientCertSelectionCallback
|
||||
);
|
||||
|
||||
socket.forceHandshake();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new LDAPException("JSSSocketFactory - start TLS, " + e.getMessage(),
|
||||
LDAPException.TLS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче