Posts Tagged security
Assigning a Custom Password policy to a subTree
Posted by Ludo in Directory Services on 20 June 2012
OpenDJ supports defining password policies that are quite complete in term of security measures to reduce the risks associated with textual passwords. It also defines 2 default policies, one for the administrators such as “cn=Directory Manager”, and one for all other users : the “Default Password Policy”. But it is possible to define additional password policies and assign them to individual users or group of users. Today, we are considering how to assign a password policy to all users under a specific subtree. In the article below, I first define a new custom password policy and then I demonstrate 2 ways of assigning that password policy to all persons under the ou=people,dc=example,dc=com subtree.
Defining a custom password policy using dsconfig:
$ dsconfig create-password-policy \ --set default-password-storage-scheme:Salted\ SHA-256 \ --set password-attribute:userpassword \ --type generic \ --policy-name Custom\ PP \ --hostname lpmac.local \ --port 4444 \ --bindDN cn=Directory\ Manager \ --bindPassword ****** \ -X -n
1- Assigning the password policy through a Virtual Attribute.
$ dsconfig create-virtual-attribute \ --set attribute-type:ds-pwp-password-policy-dn \ --set enabled:true \ --set value:cn=Custom\ PP,cn=Password\ Policies,cn=config \ --set base-dn:ou=people,dc=example,dc=com \ --set filter:\(objectClass=person\) \ --type user-defined \ --name Custom\ PP\ Assignment \ --hostname lpmac.local \ --port 4444 \ --bindDN cn=Directory\ Manager \ --bindPassword ****** \ -X -n
Check that the password policy is assigned properly:
$ ldapsearch -D "cn=directory manager" -w secret12 -p 1389 -b "" 'uid=user.1' '+' userPassword
dn: uid=user.1,ou=People,dc=example,dc=com
userPassword: {SSHA}u+52Ld6iaTvFoNlQvqTHrn1BBW9IjjT2/I25hg==
numSubordinates: 0
ds-pwp-password-policy-dn: cn=Custom PP,cn=Password Policies,cn=config
structuralObjectClass: inetOrgPerson
pwdPolicySubentry: cn=Custom PP,cn=Password Policies,cn=config
subschemaSubentry: cn=schema
hasSubordinates: false
entryDN: uid=user.1,ou=people,dc=example,dc=com
entryUUID: 4e9b7847-edcb-3791-b11b-7505f4a55af4
Change the user password, the new password should be encoded with the scheme specified (SSHA-256)
$ ldappasswordmodify -p 1389 -D uid=user.1,ou=People,dc=example,dc=com -w password -A -n newPassword
The LDAP password modify operation was successful
$ ldapsearch -D "cn=directory manager" -w secret12 -p 1389 -b "" 'uid=user.1' userPassword
dn: uid=user.1,ou=People,dc=example,dc=com
userPassword: {SSHA256}vjIdZEtF1AIiM0EgY9unZUXXublwQwlOCoe4RYEIHtpzumW1hYyvNg==
2 – Assigning the password policy using Collective Attributes :
$ ldapmodify -D cn=directory\ manager -w secret12 -p 1389
dn: cn=Pwp for Users,dc=example,dc=com
changetype: add
objectclass: collectiveAttributeSubEntry
objectclass: extensibleObject
objectclass: subentry
objectclass: top
ds-pwp-password-policy-dn;collective: cn=Custom PP,cn=Password Policies,cn=config
subtreeSpecification: { base "ou=people", specificationFilter "(objectclass=person)"}
Processing ADD request for cn=Pwp for Users,dc=example,dc=com
ADD operation successful for DN cn=Pwp for Users,dc=example,dc=com
Now we can check that the password policy is well assigned, and that it’s used when changing password for example.
$ ldapsearch -D "cn=directory manager" -w secret12 -p 1389 -b "" 'uid=user.1' '+' userPassword
dn: uid=user.1,ou=People,dc=example,dc=com
userPassword: {SSHA}6tHBLHh2C25UpAsKX0eq0d6LEXYGX+Jcm4dh7g==
numSubordinates: 0
ds-pwp-password-policy-dn: cn=Custom PP,cn=Password Policies,cn=config
structuralObjectClass: inetOrgPerson
etag: 000000008211ac6a
pwdPolicySubentry: cn=Custom PP,cn=Password Policies,cn=config
subschemaSubentry: cn=schema
hasSubordinates: false
collectiveAttributeSubentries: cn=Pwp for Users,dc=example,dc=com
entryDN: uid=user.1,ou=people,dc=example,dc=com
entryUUID: 4e9b7847-edcb-3791-b11b-7505f4a55af4
$ ldappasswordmodify -p 1389 -D uid=user.1,ou=People,dc=example,dc=com -w password -A -n newPassword
The LDAP password modify operation was successful
$ ldapsearch -D "cn=directory manager" -w secret12 -p 1389 -b "" 'uid=user.1' userPassword
dn: uid=user.1,ou=People,dc=example,dc=com
userPassword: {SSHA256}WswyH9ANoKcxQWlSn/eL8h/dNk532K/e5zGlJcwiwMLsCQqw+cAX0Q==
So which method to assign a password policy to specific users is best ?
The first method should be preferred when the password policy is defined in the configuration (as we’ve done in the example). Both configuration entries, the password policy and its assignment, are under the “cn=config” tree, but need to be defined in all replicas.
The second method defines the assignment of a policy to users as an subentry collocated with the data, and will be replicated. It should be preferred if the password policy is also defined as a subEntry, along with its assignment. Such way of configuring a password policy is documented in the Administration Guide, Configuring Password Policies section, procedure 10.3 - To Create a Subentry Based Password Policy.
More secure passwords !
Posted by Ludo in Directory Services on 13 June 2012
I’ve received an intriguing request from a customer last week : he wanted to know if we’ve done benchmarks of the password hashing schemes that are available in OpenDJ, our LDAP directory service. Their fear was that with stronger schemes, they could not sustain a high authentication rate.
In light of the LinkedIn leak of several millions of passwords, hashed with a simple unsalted SHA1, I decided to run a quick and simple test.
SSHA1 is the default hashing scheme for password in OpenDJ. The salt is an 8 bytes (64-bit) random string and is used with the password to produce the 20 bytes message digest. But OpenDJ directory server supports a wide range of password hashing scheme and salted SHA512 is currently the most secure hashing algorithm we support (and the salt here is also an 8 bytes (64-bit) random octet string).
So for the test, I generated a sample directory data set with 10 000 users, and imported it in the OpenDJ directory (a 2.5 development build) with the default settings, on my laptop (MacBook Pro, 2.2 GHz intel Core i7).
$ ldapsearch -D "cn=directory manager" -w secret12 -p 1389 -b "dc=example,dc=com" 'uid=user.10' dn userPassword
dn: uid=user.10,ou=People,dc=example,dc=com
userPassword: {SSHA}cchzM+LrPCvbZdthOC8e62d4h7a4CfoNvl6d/w==
I then ran an “authrate” which is a small benchmark tool that allows to stress an LDAP server with a high number of authentications (LDAP Bind requests) and let it run to 5 minutes.
authrate -h localhost -p 1389 -g 'rand(0,10000)' -D "uid=user.%d,ou=people,dc=example,dc=com" -w password -c 32 -f ----------------------------------------------------------------- Throughput Response Time (ops/second) (milliseconds) recent average recent average 99.9% 99.99% 99.999% err/sec ----------------------------------------------------------------- ... 26558.0 26148.9 1.179 1.195 10.168 19.431 156.421 0.0
I then stopped the server, changed the import default password encryption scheme to Salted SHA512, and reimported the data.
$ ldapsearch -D "cn=directory manager" -w secret12 -p 1389 -b "dc=example,dc=com" 'uid=user.10' dn userPassword
dn: uid=user.10,ou=People,dc=example,dc=com
userPassword: {SSHA512}eTGiwtTM4niUKNkEBy/9t03UdbsyYTL1ZXhy6uFnw4X0T6Y9Zf5/dS7hDIdx3/UTlUQ/9JjNV9fOg2BkmVgBhWWu5WpWKPog
And then re-run the “authrate”
$ authrate -h localhost -p 1389 -g 'rand(0,10000)' -D "uid=user.,ou=people,dc=example,dc=com" -w password -c 32 -f ----------------------------------------------------------------- Throughput Response Time (ops/second) (milliseconds) recent average recent average 99.9% 99.99% 99.999% err/sec ----------------------------------------------------------------- ... 25481.7 25377.6 1.222 1.227 10.470 15.473 158.234 0.0
As you can see, there is not much of a difference in throughput or response time, when using the strongest algorithm to hash user password. So do not hesitate to change the default settings and make use of the strongest password hashing schemes with OpenDJ. It could save you from the embarrassment of, one day, contacting each of your users or customers to ask them to change their compromised password.
The default password hashing schemes are in 2 locations :
- The default password policy for all passwords that are changed online.
dn: cn=Default Password Policy,cn=Password Policies,cn=config ds-cfg-default-password-storage-scheme: cn=Salted SHA-512,cn=Password Storage Schemes,cn=config
- In the Import Password Policy
dn: cn=Password Policy Import,cn=Plugins,cn=config ds-cfg-default-user-password-storage-scheme: cn=Salted SHA-512,cn=Password Storage Schemes,cn=config
Both properties can be changed with dsconfig while the OpenDJ server is running, and the new scheme will be used for all subsequent operations.
OpenAM 10.0.0 is now available…
This is a big milestone for ForgeRock and the OpenAM project, an open source WebSSO, Authentication, Authorization, Federation and Entitlements solution. After months of development (a few more than we anticipated), we’ve finally released OpenAM 10.0.0, a major version of the product.
OpenAM 10 brings a set of new features, including support for OAuth 2.0 client authentication, the ForgeRock Identity Gateway (built out of project OpenIG), enhanced SAML 2 identity provider capabilities, a new Risk Based Authentication module, … It also now relies on OpenDJ 2.4.5, the latest stable release of OpenDJ the open source LDAP directory server, and supports the internet-draft based LDAP password policy. You can find more details in the press announcement, or the product release notes. The documentation of the OpenAM 10 release can be read at http://docs.forgerock.org/en/index.html?product=openam&version=10.0.0.
The OpenAM 10 release owes a lot to the OpenAM community, for the issues raised : a total of 41 issues fixed in OpenAM 10 were raised by 26 different persons, and for the generous patches offered to fix over a dozen of these issues.
To each and every contributor : THANK YOU !
OpenAM universal gateway presentation at RMLL 2011
Last month, just before the French national day, I was in Strasbourg to participate in the RMLL.
On the occasion, I did a presentation in the security track, about OpenAM Universal Gateway, another piece in the complex puzzle of Web Single Sign-On. The Universal Gateway solves an important problem in Access Management: allowing single sign-on for applications that are usually left out because they are based on legacy or non standard based technology.
The Universal Gateway comes from ApexIdentity, an acquisition that ForgeRock did in the spring. It’s been released in open source as part of the OpenAM source code repository.
The presentation I did was in French, and so are the slides.
You can find more about the Universal Gateway on ApexIdentity web site, and soon on OpenAM documentation.
Newbie help : How to reset the Directory Manager’s password ?
Posted by Ludo in Directory Services on 30 June 2011
We get this question quite often on IRC or mailling lists, from newbies who’ve installed OpenDJ (or OpenDS) for evaluation and forgot the Directory Manager’s password.
So here are the steps :
Make sure OpenDJ is stopped.
bin/stop-ds
Generate an encoded password for Directory Manager :
bin/encode-password -s SSHA512 -c AS3cur3PassW0rd
Encoded Password: "{SSHA512}G/knE0xkyW2Af3+1MFy+yPYxchGgLuqog71R4njPJcs9t5NDAadqLxU7pxZjZkrDquQeb5aq7tum1ZFC3uE+r4Nmuil4S46A"
Copy the string within quotes (without the quotes), and edit the config/config.ldif file.
Go down to the following entry
dn: cn=Directory Manager,cn=Root DNs,cn=config
Replace the value of userPassword with the newly generated one.
dn: cn=Directory Manager,cn=Root DNs,cn=config
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
objectClass: ds-cfg-root-dn-user
userpassword: {SSHA512}G/knE0xkyW2Af3+1MFy+yPYxchGgLuqog71R4njPJcs9t5NDAadqLxU7pxZjZkrDquQeb5aq7tum1ZFC3uE+r4Nmuil4S46A
...
You can now restart the server and administer it.
OpenDJ: Troubleshooting LDAP SSL connections
Posted by Ludo in Directory Services on 29 June 2011
Troubleshooting Secure Socket Layer (SSL, also now standardized as TLS) issues is not trivial and there is no secret sauce specific to OpenDJ.
Should an LDAP SSL connection fails due to the server, you should find a descriptive error message in the server’s errors log (in logs/errors). But sometime the connection is aborted by the client with some obscure message. Often we see a message ending with “ javax.net.ssl.SSLHandshakeException: no cipher suites in common“.
Java has some debugging capabilities embedded and they are pretty easy to use with the OpenDJ LDAP directory server, which just need to be restarted with some additional arguments: -Djavax.net.debug=all or -Djavax.net.debug=ssl.
There are two ways to add extra arguments to the OpenDJ server startup command, using an environment variable, or using the java.properties file.
Using env variable
- you define the OPENDS_JAVA_ARGS environment variable. And you restart the server. If you do so, make sure you include all previous arguments.
OPENDS_JAVA_ARGS='-server -Xms1G -Xmx1G -Djavax.net.debug=ssl,handshake,trustmanager' bin/start-ds
Using the java.properties file
Edit the java.properties file in the config directory.
Since you probably only want to track the OpenDS directory server SSL access, you should append the -Djavax.net.debug=ssl,handshake,trustmanager args to the start-ds line (rather than applying it to all commands).
start-ds.java-args=-Xms1G -Xmx1G -server -Djavax.net.debug=ssl,handshake,trustmanager
Save the file and run the dsjavaproperties command:
bin/dsjavaproperties
Now restart the server, using the start-ds command
Where is the output ?
All SSL related logs are output in the logs/server.out file.
To test, you can use ldapsearch :
bin/ldapsearch -Z -X -p 1636 -b "" -s base '(objectclass=*)'
And if you look into the logs/server.out file, you will see something similar to this:
Using SSLEngineImpl.
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
LDAP Request Handler 0 for connection handler LDAP Connection Handler 0.0.0.0 port 1636, READ: SSL v2, contentType = Handshake, translated length = 81
*** ClientHello, TLSv1
RandomCookie: GMT: 1287771875 bytes = { 68, 231, 5, 253, 105, 26, 137, 36, 38, 238, 12, 141, 110, 12, 59, 10, 192, 135, 113, 119, 108, 153, 10, 31, 127, 120, 110, 61 }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
...
This will help you to identify what part of the secure connection is failing and fix it.
Note that -Djavax.net.debug=ssl enables debug of the SSL connections, while -Djavax.net.debug=all enables full debugging including use of certificates, and more. You can also find more debug options by using -Djavax.net.debug=help.
LDAP Advanced Administration for Enterprises…
Posted by Ludo in Directory Services on 03 May 2011
OpenDJ directory server has one default administrator that can manage all aspects of the server.
In an earlier post, I’ve described how to create multiple administrative accounts in OpenDJ, and in another one, I’ve talked about the Privilege system and how it can be used to tailor the administrative roles of each account.
In most enterprises, administrators are usually employees and therefore have their own entries and password. For auditing purpose, security processes require that a change or an administrative task on the directory be done as the true person and not the administrative account. But often there are multiple administrators, and they can change role frequently. So what is the best practice for granting employees some administrative privileges ?
An efficient and manageable way is to create an Administrators’ group and grant the privileges to all members of that group. When an employee, is no longer administrator, simply remove him from the group and he will loose all privileges associated. Likewise, adding a new administrator is just adding a member in the group.
With OpenDJ, this can be done with 2 simple entries : a group and a privilege collective attribute subentry.
The Group :
dn: cn=Administrators,ou=Groups,dc=example,dc=com objectClass: groupOfNames objectClass: top description: LDAP Administrators Group cn: Administrators member: uid=ludo,ou=People,dc=example,dc=com member: uid=Matt,ou=people,dc=example,dc=com
The Collective Attribute Subentry :
dn: cn=Administrators Privilege,dc=example,dc=com
objectClass: extensibleObject
objectClass: collectiveAttributeSubentry
objectClass: top
objectClass: subentry
cn: Administrators Privilege
ds-privilege-name;collective: config-read
ds-privilege-name;collective: config-write
ds-privilege-name;collective: ldif-export
ds-privilege-name;collective: modify-acl
ds-privilege-name;collective: password-reset
ds-privilege-name;collective: proxied-auth
subtreeSpecification: {base "ou=people", specificationFilter
"(isMemberOf=cn=Administrators,ou=groups,dc=example,dc=com)" }
How does it work ?
Collective Attributes is a standard based LDAP functionality that allows to define attributes and value that are defined once and appear in all entries that match the subtreeSpecification. Collective Attributes are defined in RFC 3671. For those who are familiar with Sun Directory Server’s Class Of Service, Collective Attributes provide a similar function, but based on industry approved standard.
OpenDJ collective attributes feature supports a few extensions to facilitate their use.
First, the standard way to define a collective attribute is to define it in the schema with a “c–” prefix. With OpenDJ, any existing attribute can be defined as collective with the ;collective attribute option.
Second, the scope of a Collective Attribute subentry as defined by the standard is a subtree, but the only filter possible is to specify the object class it applies to. We’ve extended the specificationFilter to accept an arbitrary LDAP filter, allowing a finer grained control of which entries are targeted.
In the example above, the filter is used to restrict the Privilege Collective Attribute subentry to apply only to entries that have the isMemberOf attribute with the value “cn=Administrators,ou=Groups,dc=example,dc=com”.
IsMemberOf is an operational read-only attribute (virtual) that is a back-link to the groups a user belongs to. OpenDJ does support the isMemberOf attribute for static groups, nested static groups and dynamic groups.
The subtreeSpecification also contains a base “ou=people” to restrict the targeted entries to the ou=people subtree. There are additional field allowed in the subtreeSpecification to indicate a depth in the tree for example.
As a result, collective attribute subentries, combined with groups, provide a flexible way to “inject” attributes and values to a specified set of entries, either to grant them specific privileges like in our example, or to decorate entries based on some common properties.
This said, remember that privileges are set in addition to the Access Controls. So giving a user the password-reset privilege for example, will be useless if there is no ACI allowing him or her to modify the userPassword attribute of other users. Granting access through an ACI to a group is as simple as using groupdn=”ldap:///cn=Administrators,dc=example,dc=com”; to designate the authorized identities.
Linux and Unix LDAP clients and RFC2307 support
Posted by Ludo in Directory Services on 20 April 2011
Quite often when one tries to migrate data from a directory server to another, small differences are discovered that prevent a direct and smooth migration. One of the most common issues when migrating from OpenLDAP or other Linux centric directory server to OpenDJ is around the schema for NIS, or the RFC 2307.
Before we dive into the core of the problem, let’s describe the symptoms:
Part of migrating from one directory to another consist of exporting the data to a common textual format, most likely LDIF, and import it in the new server. If you try to import some data in OpenDJ and it rejects entries as invalid with messages like the one just below, then you’ve just hit a schema issue with RFC 2307.
LDAP: error code 65 – Entry cn=MyGroup,ou=groups,dc=example,dc=com violates the Directory Server schema configuration because it does not include a structural objectclass. All entries must contain a structural objectclass
Why a schema issue ?
Well, RFC 2307, “An Approach for Using LDAP as a Network Information Service” was published as an experimental RFC in 1998. As Unix vendors started to use it, they found a few issues which were addressed in an internet draft nicknamed rfc2307bis (the latest version can be found here). Solaris and HP-UX started to use this later schema, while Linux sticked to the official RFC.
One of the main difference between the RFC and the internet draft, is the PosixGroup object class definition that was changed from Structural to Auxiliary, hence the failure to import an entry defined with the RFC 2307 schema into a server supporting the rfc2307bis schema.
So what to do if I want to successfully import my data ?
There are 2 options : Fix the data to be compliant with rfc230bis schema or configure OpenDJ schema to be strictly RFC2307 compliant.
Fixing the data is quite simple, but requires basic knowledge of LDIF.
Since in rfc2307bis the posixGroup is Auxiliary, the entries are missing a Structural object class to be valid. The simplest way to fix that is to add the namedObject Structural object class.
dn: cn=MyGroup,ou=Groups,dc=example,dc=com
cn: MyGroup
objectClass: top
objectClass: posixGroup
objectClass: namedObject
gidNumber: 1001
description: My Group
memberUid: 1
memberUid: 10
Make sure you change all group definition and you can now import the data to OpenDJ.
Linux pam_ldap has full support for RFC2307bis. You just need to update the /etc/pam_ldap.conf file with the following line :
nss_schema rfc2307bis
Now, if you prefer to remain strictly compliant with RFC 2307, you need to change the schema of the OpenDJ server. Basically, you just need to stop the server, remove the 04-rfc2307bis.ldif file from the config/schema/ directory (save it in case you need it later) and add in the config/schema/ directory, the 04-rfc2307.ldif file. You can now import the data in OpenDJ.
This 04-rfc2307.ldif file is not part of the current distribution of OpenDJ, but we will add it pretty soon, however not as the default schema.
OpenAM – The Book
For many years, I’ve been working in collaboration with the Sun access management product team, as it started working on the Directory Server Access Management Edition (DSAME) product that years later became Sun Access Manager and OpenSSO. And now that I’m at ForgeRock, I have the pleasure to keep working with some members of that team, on OpenAM, the continuation of the OpenSSO open source project.
My knowledge of the product is rather shallow as I’ve worked on several case studies or issues related to customers and LDAP directory servers, but I never had a chance to deploy a service for production use or even extensive testing.
So when I learnt that Packt Publishing was releasing a book on “OpenAM”, writen by Indira Thangasamy, an ex-colleague of mine and manager of the Quality Assurance team, I asked if I could get a copy for review, which Packt kindly agreed to.
I haven’t finished the book yet, as it’s over 250 pages of content, covering all aspects of the OpenAM software, from its history, its components and services, to its integration with Google Apps or SalesForce… But from what I’ve read (about 2/3 of the book), I can say that the book is easy to read and well organized. It helps a beginner to grasp the concepts and starts using the product, thanks to the detailed explanations and diagrams. As the chapters advance and dive into specific technical areas, Indira uses real-world examples and simple code or commands, followed by detailed description to illustrate what OpenAM does or does not, giving a comprehensive picture of the fully featured product.
Some of the features of OpenAM are not covered in the book, like Federation or the most recent Entitlement Services or Secure Token Services. I hope they will be covered in a revised edition or may be another book, as these features are becoming more used and important to enterprise security and access management.
In summary, if you’re about to, or have just started to engage on a project with OpenAM, this book will help you understand the technology and ease your ramping up. But even for the more experienced users of OpenAM, the book contains full of details, tips and example that will save you time and make you more efficient.
You can find the book on Pack-Publishing web site or Amazon.
Securing JBoss JMX console with OpenDS
Posted by Ludo in Directory Services on 07 December 2009
Steve Millidge, founder of C2B2, has just published a nice and illustrated step by step tutorial for securing JBoss JMX console with LDAP and more specifically the OpenDS directory server. Similar steps could be used to secure all the different subsystems in JBoss, as illustrated in this already 2 years old tutorial about JBoss Portal, OpenSSO and OpenDS.
Technorati Tags: directory-server, java, JBoss, ldap, opends, opensource, security


