summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
Diffstat (limited to 'base')
-rw-r--r--base/common/python/pki/key.py102
-rw-r--r--base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java22
-rw-r--r--base/common/src/com/netscape/certsrv/request/IRequest.java1
-rw-r--r--base/kra/functional/drmtest.py26
-rw-r--r--base/kra/src/CMakeLists.txt9
-rw-r--r--base/kra/src/com/netscape/kra/SymKeyGenService.java4
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java29
7 files changed, 159 insertions, 34 deletions
diff --git a/base/common/python/pki/key.py b/base/common/python/pki/key.py
index 7d93e783a..3fa5952db 100644
--- a/base/common/python/pki/key.py
+++ b/base/common/python/pki/key.py
@@ -94,7 +94,7 @@ class KeyInfo(object):
def get_key_id(self):
''' Return the key ID as parsed from key URL '''
- if self.keyURL != None:
+ if self.keyURL is not None:
indx = str(self.keyURL).rfind("/") + 1
return str(self.keyURL)[indx:]
return None
@@ -146,14 +146,14 @@ class KeyRequestInfo(object):
def get_request_id(self):
''' Return the request ID by parsing the request URL. '''
- if self.requestURL != None:
+ if self.requestURL is not None:
indx = str(self.requestURL).rfind("/") + 1
return str(self.requestURL)[indx:]
return None
def get_key_id(self):
''' Return the ID of the secret referred to by this request. '''
- if self.keyURL != None:
+ if self.keyURL is not None:
indx = str(self.keyURL).rfind("/") + 1
return str(self.keyURL)[indx:]
return None
@@ -268,7 +268,7 @@ class SymKeyGenerationRequest(pki.ResourceMessage):
ENCRYPT_USAGE = "encrypt"
def __init__(self, client_key_id=None, key_size=None, key_algorithm=None,
- key_usages=None):
+ key_usages=None, trans_wrapped_session_key=None):
''' Constructor '''
pki.ResourceMessage.__init__(self,
"com.netscape.certsrv.key.SymKeyGenerationRequest")
@@ -277,6 +277,7 @@ class SymKeyGenerationRequest(pki.ResourceMessage):
self.add_attribute("keySize", key_size)
self.add_attribute("keyAlgorithm", key_algorithm)
self.add_attribute("keyUsage", ','.join(key_usages))
+ self.add_attribute("transWrappedSessionKey", trans_wrapped_session_key)
class KeyClient(object):
'''
@@ -288,6 +289,9 @@ class KeyClient(object):
PASS_PHRASE_TYPE = "passPhrase"
ASYMMETRIC_KEY_TYPE = "asymmetricKey"
+ KEY_STATUS_ACTIVE = "active"
+ KEY_STATUS_INACTIVE = "inactive"
+
def __init__(self, connection, crypto, transport_cert_nick=None):
''' Constructor '''
self.connection = connection
@@ -297,7 +301,7 @@ class KeyClient(object):
self.keyRequestsURL = '/rest/agent/keyrequests'
self.crypto = crypto
- if transport_cert_nick != None:
+ if transport_cert_nick is not None:
self.crypto.initialize()
self.transport_cert = crypto.get_cert(transport_cert_nick)
else:
@@ -305,6 +309,8 @@ class KeyClient(object):
def set_transport_cert(self, transport_cert_nick):
''' Set the transport certificate for crypto operations '''
+ if transport_cert_nick is None:
+ raise ValueError("Transport cert nickname must be specified.")
self.transport_cert = self.crypto.get_cert(transport_cert_nick)
@pki.handle_exceptions()
@@ -339,6 +345,9 @@ class KeyClient(object):
@pki.handle_exceptions()
def get_request_info(self, request_id):
''' Return a KeyRequestInfo object for a specific request. '''
+ if request_id is None:
+ raise ValueError("request_id must be specified")
+
url = self.keyRequestsURL + '/' + request_id
response = self.connection.get(url, self.headers)
return KeyRequestInfo.from_json(response.json())
@@ -346,6 +355,9 @@ class KeyClient(object):
@pki.handle_exceptions()
def get_key_info(self, key_id):
''' Get the info in the KeyRecord for a specific secret in the DRM. '''
+ if key_id is None:
+ raise ValueError("key_id must be specified")
+
url = self.keyURL + '/' + key_id
response = self.connection.get(url, headers=self.headers)
return KeyInfo.from_json(response.json())
@@ -353,6 +365,9 @@ class KeyClient(object):
@pki.handle_exceptions()
def get_active_key_info(self, client_key_id):
''' Get the info in the KeyRecord for the active secret in the DRM. '''
+ if client_key_id is None:
+ raise ValueError("client_key_id must be specified")
+
url = self.keyURL + '/active/' + urllib.quote_plus(client_key_id)
response = self.connection.get(url, headers=self.headers)
return KeyInfo.from_json(response.json())
@@ -360,6 +375,9 @@ class KeyClient(object):
@pki.handle_exceptions()
def modify_key_status(self, key_id, status):
''' Modify the status of a key '''
+ if (key_id is None) or (status is None):
+ raise ValueError("key_id and status must be specified")
+
url = self.keyURL + '/' + key_id
params = {'status':status}
self.connection.post(url, None, headers=self.headers, params=params)
@@ -367,18 +385,27 @@ class KeyClient(object):
@pki.handle_exceptions()
def approve_request(self, request_id):
''' Approve a secret recovery request '''
+ if request_id is None:
+ raise ValueError("request_id must be specified")
+
url = self.keyRequestsURL + '/' + request_id + '/approve'
self.connection.post(url, self.headers)
@pki.handle_exceptions()
def reject_request(self, request_id):
''' Reject a secret recovery request. '''
+ if request_id is None:
+ raise ValueError("request_id must be specified")
+
url = self.keyRequestsURL + '/' + request_id + '/reject'
self.connection.post(url, self.headers)
@pki.handle_exceptions()
def cancel_request(self, request_id):
''' Cancel a secret recovery request '''
+ if request_id is None:
+ raise ValueError("request_id must be specified")
+
url = self.keyRequestsURL + '/' + request_id + '/cancel'
self.connection.post(url, self.headers)
@@ -403,6 +430,9 @@ class KeyClient(object):
This method expects initialize_nss() to have been called previously.
'''
+ if secret is None:
+ raise ValueError("secret must be specified")
+
session_key = self.crypto.generate_symmetric_key()
trans_wrapped_session_key = self.crypto.asymmetric_wrap(session_key, self.transport_cert)
wrapped_secret = self.crypto.symmetric_wrap(secret, session_key)
@@ -419,22 +449,42 @@ class KeyClient(object):
returns a KeyRequestResponse object.
'''
+ if request is None:
+ raise ValueError("request must be specified")
+
url = self.keyRequestsURL
key_request = json.dumps(request, cls=encoder.CustomTypeEncoder, sort_keys=True)
response = self.connection.post(url, key_request, self.headers)
return KeyRequestResponse.from_json(response.json())
@pki.handle_exceptions()
- def generate_symmetric_key(self, client_key_id, algorithm, size, usages):
+ def generate_symmetric_key(self, client_key_id, algorithm=None, size=None, usages=None,
+ trans_wrapped_session_key=None):
''' Generate and archive a symmetric key on the DRM.
Return a KeyRequestResponse which contains a KeyRequestInfo
object that describes the URL for the request and generated key.
+
'''
- request = SymKeyGenerationRequest(client_key_id=client_key_id,
- key_size=size,
- key_algorithm=algorithm,
- key_usages=usages)
+ if client_key_id is None:
+ raise ValueError("Must specify client_key_id")
+
+ if trans_wrapped_session_key is not None:
+ twsk = base64.encodestring(trans_wrapped_session_key)
+ request = SymKeyGenerationRequest(
+ client_key_id=client_key_id,
+ key_size=size,
+ key_algorithm=algorithm,
+ key_usages=usages,
+ trans_wrapped_session_key=twsk)
+ raise NotImplementedError(
+ "Returning the symmetric key in the same call is not yet implemented.")
+ else:
+ request = SymKeyGenerationRequest(
+ client_key_id=client_key_id,
+ key_size=size,
+ key_algorithm=algorithm,
+ key_usages=usages)
return self.create_request(request)
@pki.handle_exceptions()
@@ -448,9 +498,9 @@ class KeyClient(object):
key exists, a BadRequestException is thrown.
data_type can be one of the following:
- KeyRequestResource.SYMMETRIC_KEY_TYPE,
- KeyRequestResource.ASYMMETRIC_KEY_TYPE,
- KeyRequestResource.PASS_PHRASE_TYPE
+ KeyClient.SYMMETRIC_KEY_TYPE,
+ KeyClient.ASYMMETRIC_KEY_TYPE,
+ KeyClient.PASS_PHRASE_TYPE
key_algorithm and key_size are applicable to symmetric keys only.
If a symmetric key is being archived, these parameters are required.
@@ -469,8 +519,16 @@ class KeyClient(object):
The function returns a KeyRequestResponse object containing a KeyRequestInfo
object with details about the archival request and key archived.
'''
- if wrapped_private_data == None:
- if private_data == None:
+ if (client_key_id is None) or (data_type is None):
+ raise ValueError("client_key_id and data_type must be specified")
+
+ if data_type == KeyClient.SYMMETRIC_KEY_TYPE:
+ if (key_algorithm is None) or (key_size is None):
+ raise ValueError(
+ "For symmetric keys, key algorithm and key_size must be specified")
+
+ if wrapped_private_data is None:
+ if private_data is None:
raise ValueError("No data provided to be archived")
wrapped_private_data = self.generate_archive_options(private_data)
@@ -494,6 +552,9 @@ class KeyClient(object):
To retrieve an asymmetric key, the keyId and the the base-64 encoded certificate
is required.
'''
+ if key_id is None:
+ raise ValueError("key_id must be defined")
+
request = KeyRecoveryRequest(key_id=key_id,
request_id=request_id,
trans_wrapped_session_key=trans_wrapped_session_key,
@@ -513,6 +574,9 @@ class KeyClient(object):
Returns a KeyData object containing the wrapped secret.
'''
+ if data is None:
+ raise ValueError("KeyRecoveryRequest must be specified")
+
url = self.keyURL + '/retrieve'
keyRequest = json.dumps(data, cls=encoder.CustomTypeEncoder, sort_keys=True)
response = self.connection.post(url, keyRequest, self.headers)
@@ -546,8 +610,11 @@ class KeyClient(object):
The function will return the tuple (KeyData, None), where the KeyData structure includes the
wrapped secret and some nonce data to be used as a salt when unwrapping.
'''
+ if key_id is None:
+ raise ValueError("key_id must be specified")
+
key_provided = True
- if (trans_wrapped_session_key == None):
+ if trans_wrapped_session_key is None:
key_provided = False
session_key = self.crypto.generate_symmetric_key()
trans_wrapped_session_key = self.crypto.asymmetric_wrap(session_key,
@@ -629,6 +696,9 @@ class KeyClient(object):
The function returns a KeyData object.
'''
+ if (key_id is None) or (certificate is None) or (passphrase is None):
+ raise ValueError("key_id, certificate and passphrase must all be specified")
+
response = self.recover_key(key_id, b64certificate=certificate)
request_id = response.get_request_id()
self.approve_request(request_id)
diff --git a/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java b/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
index 01326442f..27dc69fd5 100644
--- a/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
+++ b/base/common/src/com/netscape/certsrv/key/SymKeyGenerationRequest.java
@@ -25,6 +25,7 @@ public class SymKeyGenerationRequest extends ResourceMessage {
private static final String KEY_SIZE = "keySize";
private static final String KEY_ALGORITHM = "keyAlgorithm";
private static final String KEY_USAGE = "keyUsage";
+ private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey";
/* Symmetric Key usages */
public static final String UWRAP_USAGE = "unwrap";
@@ -65,6 +66,7 @@ public class SymKeyGenerationRequest extends ResourceMessage {
attributes.put(KEY_SIZE, form.getFirst(KEY_SIZE));
attributes.put(KEY_ALGORITHM, form.getFirst(KEY_ALGORITHM));
attributes.put(KEY_USAGE, form.getFirst(KEY_USAGE));
+ attributes.put(TRANS_WRAPPED_SESSION_KEY, form.getFirst(TRANS_WRAPPED_SESSION_KEY));
String usageString = attributes.get(KEY_USAGE);
if (! StringUtils.isBlank(usageString)) {
@@ -96,7 +98,11 @@ public class SymKeyGenerationRequest extends ResourceMessage {
* @return the keySize
*/
public Integer getKeySize() {
- return new Integer(attributes.get(KEY_SIZE));
+ try {
+ return new Integer(attributes.get(KEY_SIZE));
+ } catch (NumberFormatException e) {
+ return null;
+ }
}
/**
@@ -120,6 +126,20 @@ public class SymKeyGenerationRequest extends ResourceMessage {
attributes.put(KEY_ALGORITHM, keyAlgorithm);
}
+ /**
+ * @return the transWrappedSessionKey
+ */
+ public String getTransWrappedSessionKey() {
+ return attributes.get(TRANS_WRAPPED_SESSION_KEY);
+ }
+
+ /**
+ * @param transWrappedSessionKey the wrapped seesion key to set
+ */
+ public void setTransWrappedSessionKey(String transWrappedSessionKey) {
+ attributes.put(TRANS_WRAPPED_SESSION_KEY, transWrappedSessionKey);
+ }
+
public String toString() {
try {
return ResourceMessage.marshal(this, SymKeyGenerationRequest.class);
diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java
index e77a2e2b8..f9c442754 100644
--- a/base/common/src/com/netscape/certsrv/request/IRequest.java
+++ b/base/common/src/com/netscape/certsrv/request/IRequest.java
@@ -174,6 +174,7 @@ public interface IRequest extends Serializable {
public static final String SYMKEY_GEN_ALGORITHM = "symkeyGenAlgorithm";
public static final String SYMKEY_GEN_SIZE = "symkeyGenSize";
public static final String SYMKEY_GEN_USAGES = "symkeyGenUsages";
+ public static final String SYMKEY_TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey";
// requestor type values.
public static final String REQUESTOR_EE = "EE";
diff --git a/base/kra/functional/drmtest.py b/base/kra/functional/drmtest.py
index a1db60c55..b53c5569a 100644
--- a/base/kra/functional/drmtest.py
+++ b/base/kra/functional/drmtest.py
@@ -106,18 +106,21 @@ def main():
# Test 4: generate symkey -- same as barbican_encode()
print "Now generating symkey on KRA"
#client_key_id = "Vek #1" + time.strftime('%X %x %Z')
- client_key_id = "vek1234567"
+ client_key_id = "veka6"
algorithm = "AES"
key_size = 128
usages = [key.SymKeyGenerationRequest.DECRYPT_USAGE, key.SymKeyGenerationRequest.ENCRYPT_USAGE]
- response = keyclient.generate_symmetric_key(client_key_id, algorithm, key_size, usages)
+ response = keyclient.generate_symmetric_key(client_key_id,
+ algorithm=algorithm,
+ size=key_size,
+ usages=usages)
print_key_request(response.requestInfo)
print "Request ID is " + response.requestInfo.get_request_id()
key_id = response.get_key_id()
# Test 5: Confirm the key_id matches
print "Now getting key ID for clientKeyID=\"" + client_key_id + "\""
- key_infos = keyclient.list_keys(client_key_id=client_key_id, status="active")
+ key_infos = keyclient.list_keys(client_key_id=client_key_id, status=keyclient.KEY_STATUS_ACTIVE)
for key_info in key_infos.key_infos:
print_key_info(key_info)
key_id2 = key_info.get_key_id()
@@ -152,7 +155,10 @@ def main():
# Test 10 = test BadRequestException on create()
print "Trying to generate a new symkey with the same client ID"
try:
- response = keyclient.generate_symmetric_key(client_key_id, algorithm, key_size, usages)
+ response = keyclient.generate_symmetric_key(client_key_id,
+ algorithm=algorithm,
+ size=key_size,
+ usages=usages)
except pki.BadRequestException as exc:
print "BadRequestException thrown - Code:" + exc.code + " Message: " + exc.message
@@ -169,10 +175,6 @@ def main():
key_data, unwrapped_key = keyclient.retrieve_key('2000003434')
except pki.KeyNotFoundException as exc:
print "KeyNotFoundException thrown - Code:" + exc.code + " Message: " + exc.message
- except pki.PKIException as exc:
- # note: this is broken - we should be sending KeyNotFoundException here before the recovery
- # request is created - to be fixed in next patch
- print "PKIException thrown - Code:" + exc.code + " Message: " + exc.message
#Test 13 = getKeyInfo
print "Get key info for existing key"
@@ -186,7 +188,7 @@ def main():
#Test 15: change the key status
print "Change the key status"
- keyclient.modify_key_status(key_id, "inactive")
+ keyclient.modify_key_status(key_id, keyclient.KEY_STATUS_INACTIVE)
print_key_info(keyclient.get_key_info(key_id))
# Test 16: Get key info for non-existent key
@@ -200,8 +202,14 @@ def main():
print "Get non-existent active key"
try:
key_info = keyclient.get_active_key_info(client_key_id)
+ print_key_info(key_info)
except pki.ResourceNotFoundException as exc:
print "ResourceNotFoundException thrown - Code: " + exc.code + "Message: " + exc.message
+ #Test 18: Generate a symmetric key with default parameters
+ client_key_id = "Vek #3" + time.strftime('%X %x %Z')
+ response = keyclient.generate_symmetric_key(client_key_id)
+ print_key_request(response.requestInfo)
+
if __name__ == "__main__":
main()
diff --git a/base/kra/src/CMakeLists.txt b/base/kra/src/CMakeLists.txt
index 99088ce06..ccbc6a6c3 100644
--- a/base/kra/src/CMakeLists.txt
+++ b/base/kra/src/CMakeLists.txt
@@ -75,6 +75,13 @@ find_file(SYMKEY_JAR
${JAVA_LIB_INSTALL_DIR}
)
+find_file(COMMONS_LANG_JAR
+ NAMES
+ commons-lang.jar
+ PATHS
+ /usr/share/java
+)
+
# build pki-kra
javac(pki-kra-classes
@@ -84,7 +91,7 @@ javac(pki-kra-classes
${PKI_CERTSRV_JAR} ${PKI_CMS_JAR} ${PKI_CMSCORE_JAR}
${PKI_CMSUTIL_JAR} ${PKI_NSUTIL_JAR}
${LDAPJDK_JAR} ${JAXRS_API_JAR}
- ${JSS_JAR} ${COMMONS_CODEC_JAR} ${SYMKEY_JAR}
+ ${JSS_JAR} ${COMMONS_CODEC_JAR} ${COMMONS_LANG_JAR} ${SYMKEY_JAR}
OUTPUT_DIR
${CMAKE_BINARY_DIR}/classes
DEPENDS
diff --git a/base/kra/src/com/netscape/kra/SymKeyGenService.java b/base/kra/src/com/netscape/kra/SymKeyGenService.java
index 99c57b8d9..d1e60fa70 100644
--- a/base/kra/src/com/netscape/kra/SymKeyGenService.java
+++ b/base/kra/src/com/netscape/kra/SymKeyGenService.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.apache.commons.lang.StringUtils;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyGenerator;
@@ -92,7 +93,8 @@ public class SymKeyGenService implements IService {
String algorithm = request.getExtDataInString(IRequest.SYMKEY_GEN_ALGORITHM);
String usageStr = request.getExtDataInString(IRequest.SYMKEY_GEN_USAGES);
- List<String> usages = new ArrayList<String>(Arrays.asList(usageStr.split(",")));
+ List<String> usages = new ArrayList<String>(
+ Arrays.asList(StringUtils.split(usageStr, ",")));
String keySizeStr = request.getExtDataInString(IRequest.SYMKEY_GEN_SIZE);
int keySize = Integer.parseInt(keySizeStr);
diff --git a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
index 308d3daf8..d84bbd013 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/key/KeyRequestDAO.java
@@ -32,11 +32,13 @@ import org.mozilla.jss.crypto.KeyGenAlgorithm;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.BadRequestException;
import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.EDBRecordNotFoundException;
import com.netscape.certsrv.dbs.keydb.IKeyRecord;
import com.netscape.certsrv.dbs.keydb.IKeyRepository;
import com.netscape.certsrv.dbs.keydb.KeyId;
import com.netscape.certsrv.key.KeyArchivalRequest;
import com.netscape.certsrv.key.KeyData;
+import com.netscape.certsrv.key.KeyNotFoundException;
import com.netscape.certsrv.key.KeyRecoveryRequest;
import com.netscape.certsrv.key.KeyRequestInfo;
import com.netscape.certsrv.key.KeyRequestInfoCollection;
@@ -142,7 +144,7 @@ public class KeyRequestDAO extends CMSRequestDAO {
String keyAlgorithm = data.getKeyAlgorithm();
int keyStrength = data.getKeySize();
- boolean keyExists = doesKeyExist(clientKeyId, "active", uriInfo);
+ boolean keyExists = doesKeyExist(clientKeyId, "active");
if (keyExists == true) {
throw new EBaseException("Can not archive already active existing key!");
@@ -184,6 +186,11 @@ public class KeyRequestDAO extends CMSRequestDAO {
IRequest request = queue.newRequest(IRequest.SECURITY_DATA_RECOVERY_REQUEST);
KeyId keyId = data.getKeyId();
+ try {
+ repo.readKeyRecord(keyId.toBigInteger());
+ } catch (EDBRecordNotFoundException e) {
+ throw new KeyNotFoundException(keyId);
+ }
Hashtable<String, Object> requestParams;
@@ -219,12 +226,13 @@ public class KeyRequestDAO extends CMSRequestDAO {
String algName = data.getKeyAlgorithm();
Integer keySize = data.getKeySize();
List<String> usages = data.getUsages();
+ String transWrappedSessionKey = data.getTransWrappedSessionKey();
if (StringUtils.isBlank(clientKeyId)) {
throw new BadRequestException("Invalid key generation request. Missing client ID");
}
- boolean keyExists = doesKeyExist(clientKeyId, "active", uriInfo);
+ boolean keyExists = doesKeyExist(clientKeyId, "active");
if (keyExists == true) {
throw new BadRequestException("Can not archive already active existing key!");
}
@@ -261,6 +269,11 @@ public class KeyRequestDAO extends CMSRequestDAO {
request.setExtData(IRequest.SYMKEY_GEN_USAGES, StringUtils.join(usages, ","));
request.setExtData(IRequest.SECURITY_DATA_CLIENT_KEY_ID, clientKeyId);
+ if (transWrappedSessionKey != null) {
+ request.setExtData(IRequest.SYMKEY_TRANS_WRAPPED_SESSION_KEY,
+ transWrappedSessionKey);
+ }
+
queue.processRequest(request);
queue.markAsServiced(request);
@@ -331,10 +344,14 @@ public class KeyRequestDAO extends CMSRequestDAO {
}
//We only care if the key exists or not
- private boolean doesKeyExist(String clientKeyId, String keyStatus, UriInfo uriInfo) {
- String state = "active";
- String filter = "(&(" + IRequest.SECURITY_DATA_CLIENT_KEY_ID + "=" + clientKeyId + ")"
- + "(" + IRequest.SECURITY_DATA_STATUS + "=" + state + "))";
+ private boolean doesKeyExist(String clientKeyId, String keyStatus) {
+ String filter = null;
+ if (keyStatus == null) {
+ filter = "(" + IKeyRecord.ATTR_CLIENT_ID + "=" + clientKeyId + ")";
+ } else {
+ filter = "(&(" + IKeyRecord.ATTR_CLIENT_ID + "=" + clientKeyId + ")"
+ + "(" + IKeyRecord.ATTR_STATUS + "=" + keyStatus + "))";
+ }
try {
Enumeration<IKeyRecord> existingKeys = null;