LDAP-Benutzung mit
Java+Tomcat und Python+Zope

Holger Blasum, Andreas Meisl, 1.3.6.1.4.1.14212
image/siegel.png


(page 1)


Anwendung


Anwendungsfall:
image/browser.png

(page 2)


X.500 und LDAP


X.500

LDAP

(page 3)


RFC 1777

image/rfc1777.png

(page 4)


LDAP läuft über TCP


Schichten: TCP/IP->ASN.1/BER-Kodierung->LDAP-Anwendung
image/ldapethereal.png

(page 5)


Sandkasten

image/repview.png

Alternativ:
ldapsearch -vLx "ou=subldap, ou=user, o=novell"
-h www.nldap.com "(objectclass=*)" > subldap.ldif


(page 6)


LDIF-Datei



version: 1

#
# filter: (objectclass=*)
# requesting: ALL
#

# subldap, user, NOVELL
dn: ou=subldap,ou=user,o=NOVELL
equivalentToMe: cn=admin,ou=subldap,ou=user,o=NOVELL
ou: subldap
objectClass: organizationalUnit
objectClass: top
objectClass: ndsLoginProperties
objectClass: ndsContainerLoginProperties
ACL: 16#subtree#cn=admin,ou=subldap,ou=user,o=NOVELL#[Entry Rights]
ACL: 32#subtree#cn=admin,ou=subldap,ou=user,o=NOVELL#[All Attributes Rights]

# admin, subldap, user, NOVELL
dn: cn=admin,ou=subldap,ou=user,o=NOVELL
sn: subldap
securityEquals: ou=subldap,ou=user,o=NOVELL
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: ndsLoginProperties
networkAddress:: MSPAbGbX
networkAddress:: MSONVLBZ
loginTime: 20020517160451Z
cn: admin
ACL: 6#entry#cn=admin,ou=subldap,ou=user,o=NOVELL#loginScript
ACL: 6#entry#cn=admin,ou=subldap,ou=user,o=NOVELL#printJobConfiguration

# zoology, subldap, user, NOVELL
dn: ou=zoology,ou=subldap,ou=user,o=NOVELL
ou: zoology
objectClass: organizationalUnit
objectClass: top
objectClass: ndsLoginProperties
objectClass: ndsContainerLoginProperties

# students, zoology, subldap, user, NOVELL
dn: ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL
ou: students
objectClass: organizationalUnit
objectClass: top
objectClass: ndsLoginProperties
objectClass: ndsContainerLoginProperties

# student1, students, zoology, subldap, user, NOVELL
dn: cn=student1,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL
givenName: Louis
Language: English
sn: Agassiz
passwordRequired: FALSE
passwordAllowChange: TRUE
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: ndsLoginProperties
cn: student1
ACL: 6#entry#cn=student1,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL#lo
 ginScript
ACL: 6#entry#cn=student1,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL#pr
 intJobConfiguration

# student2, students, zoology, subldap, user, NOVELL
dn: cn=student2,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL
Language: English
sn: Buffon
passwordRequired: FALSE
passwordAllowChange: TRUE
ou: 2
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: ndsLoginProperties
cn: student2
ACL: 6#entry#cn=student2,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL#lo
 ginScript
ACL: 6#entry#cn=student2,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL#pr
 intJobConfiguration

# student3, students, zoology, subldap, user, NOVELL
dn: cn=student3,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL
givenName: Georges
Language: English
sn: Cuvier
passwordRequired: FALSE
passwordAllowChange: TRUE
ou: 4
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
objectClass: ndsLoginProperties
cn: student3
ACL: 6#entry#cn=student3,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL#lo
 ginScript
ACL: 6#entry#cn=student3,ou=students,ou=zoology,ou=subldap,ou=user,o=NOVELL#pr
 intJobConfiguration

# courses, zoology, subldap, user, NOVELL
dn: ou=courses,ou=zoology,ou=subldap,ou=user,o=NOVELL
ou: courses
objectClass: organizationalUnit
objectClass: top
objectClass: ndsLoginProperties
objectClass: ndsContainerLoginProperties

# 200201, courses, zoology, subldap, user, NOVELL
dn: ou=200201,ou=courses,ou=zoology,ou=subldap,ou=user,o=NOVELL
ou: 200201
objectClass: organizationalUnit
objectClass: top
objectClass: ndsLoginProperties
objectClass: ndsContainerLoginProperties

# Ant, 200201, courses, zoology, subldap, user, NOVELL
dn: cn=Ant,ou=200201,ou=courses,ou=zoology,ou=subldap,ou=user,o=NOVELL
ou: 2
objectClass: groupOfNames
objectClass: top
l: 40
description: An introduction to ant ecology
cn: Ant
cn: Ant ecology
ACL: 2#entry#[Root]#member

# Bee, 200201, courses, zoology, subldap, user, NOVELL
dn: cn=Bee,ou=200201,ou=courses,ou=zoology,ou=subldap,ou=user,o=NOVELL
ou: 2
objectClass: groupOfNames
objectClass: top
l: 20
description: Practical course in apiculture
cn: Bee
cn: Bees and apiculture
ACL: 2#entry#[Root]#member

# Cow, 200201, courses, zoology, subldap, user, NOVELL
dn: cn=Cow,ou=200201,ou=courses,ou=zoology,ou=subldap,ou=user,o=NOVELL
ou: 4
objectClass: groupOfNames
objectClass: top
l: 40
description: Genetics of cows
cn: Cow
cn: Cow genetics
ACL: 2#entry#[Root]#member

# search result

# numResponses: 13
# numEntries: 12

(page 7)


LDAP-Klienten: Installation


Java:

Python:

OS:

(page 8)


Kurse anschauen: Python


#!/usr/bin/python

import ldap
l = ldap.initialize("ldap://www.nldap.com:389")
res = l.search_s("ou=200201, ou=courses, ou=zoology, " 
    + "ou=subldap, ou=user, o=novell", 
    ldap.SCOPE_ONELEVEL, "objectclass=*")

for r in res:
    print r[0]
l.unbind_s()

$ python ListCourses.py
cn=Ant,ou=200201,ou=courses,ou=zoology,ou=subldap,ou=user,o=NOVELL
cn=Bee,ou=200201,ou=courses,ou=zoology,ou=subldap,ou=user,o=NOVELL
cn=Cow,ou=200201,ou=courses,ou=zoology,ou=subldap,ou=user,o=NOVELL

(page 9)


Kurse anschauen: Java


import java.io.*;
import com.novell.ldap.*;

public class ListCourses {

    public static void main (String [] args) throws LDAPException {

        LDAPConnection c = new LDAPConnection ();
        c.connect ("www.nldap.com", 389);
        LDAPSearchResults res =c.search("ou=200201,"
            + "ou=courses, ou=zoology,ou=subldap, ou=user, "+
            + "o=novell", LDAPConnection.SCOPE_ONE,  
            null, null,false);
        while (res.hasMore()) {
            System.out.println(res.next().getDN());
        c.disconnect();
        }
    }
}

(page 10)


Kurse anschauen: Jython


from com.novell.ldap import *

c = LDAPConnection ()
c.connect ("www.nldap.com", 389)
res = c.search("ou=200201, ou=courses, ou=zoology, ou=subldap, 
     ou=user, o=novell", LDAPConnection.SCOPE_ONE, None, None, 0)

while res.hasMore():
     print res.next().getDN()

(page 11)


Performance


$ cat /proc/cpuinfo
cpu MHz         : 399.327
model name      : Pentium II (Deschutes)
bogomips        : 796.26

$ time java ListCourses
real    0m2.415s
user    0m1.150s
sys     0m0.030s

$ time python ListCourses.py
real    0m1.067s
user    0m0.100s
sys     0m0.020s

$ time jython ListCourses.jy
real    0m7.408s
user    0m4.540s
sys     0m0.140s


(page 12)


Einschreibungsdaten ändern


#!/usr/bin/python

import ldap
import sys

if len (sys.argv) != 3:
    print "Usage: Register.py course student"
    print "Eg: Register.py ant student1"
    sys.exit(1)

ldap.set_option (ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)
c = ldap.initialize ("ldap://www.nldap.com:389")
c.simple_bind_s("cn=admin, ou=subldap, ou=user, o=novell","secret")
c.modify_s ("cn=" + sys.argv[1] + ", " + "ou=200201, ou=courses, " 
   + "ou=zoology, ou=subldap, ou=user, o=novell", 
   [(ldap.MOD_ADD, "member", "cn=" + sys.argv[2] + "," + 
   "ou=students, ou=zoology, ou=subldap, ou=user, o=novell")])
c.unbind_s()


Gegenstück: Ersetze MOD_ADD durch MOD_DEL

(page 13)


Abstraktionsebene


ChangeManager.py
>>> import ChangeManager
>>> c = ChangeManager.ChangeManager()
>>> couses = c.getCourseList()

(page 14)


Präsentationsschicht


Zope (2.5.1)
image/zopewahl.png


index.html ruft doGet auf.

(page 15)


Tomcat


Version (4.1.18 von jakarta.apache.org)
Verwendet als Servlet Container

Konfiguration in:

(page 16)


TLS/SSL

image/ssl1.png


Protokoll

(page 17)


TLS Handshake (1)
image/ssl2.png


(page 18)


TLS Handshake (2)


$  ssldump -A -N > ssldumpraw.txt
New TCP connection #1: www.vetmed.uni-muenchen.de(2916) 
   <-> devsup-news3.Novell.COM(636)
1 1  0.2432 (0.2432)  C>S SSLv2 compatible client hello
  Version 3.1 
  cipher suites
  TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA  
  TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA  
  TLS_RSA_WITH_3DES_EDE_CBC_SHA  
  [ 35 more lines ] 
  SSL2_CK_RC4_EXPORT40  
1 2  0.4228 (0.1795)  S>CV3.1(74)  Handshake
      ServerHello
        Version 3.1 
        random[32]=
          3e 63 b7 f7 98 02 54 54 55 49 ba 45 c0 db fd d2 
        session_id[32]=
          a1 18 8e 06 5d 0e 42 9c 01 37 3c 8d 4a c0 01 d8 
        cipherSuite         TLS_RSA_WITH_3DES_EDE_CBC_SHA
        compressionMethod                   NULL
        certificate[1377]=
          30 82 05 5d 30 82 04 45 a0 03 02 01 02 02 1b 02 
		  [...]

(page 19)


TLS Handshake (3)


1 5  0.6462 (0.0450)  C>SV3.1(262)  Handshake
      ClientKeyExchange
        EncryptedPreMasterSecret[256]=
          02 ba 95 91 0e c4 f0 3f 79 5c b9 e1 ef 8a b6 24 
		  [...]
1 6  0.6462 (0.0000)  C>SV3.1(1)  ChangeCipherSpec
1 7  0.6462 (0.0000)  C>SV3.1(40)  Handshake
1 8  0.8985 (0.2523)  S>CV3.1(1)  ChangeCipherSpec
1 9  0.8985 (0.0000)  S>CV3.1(40)  Handshake
1 10 0.8995 (0.0009)  C>SV3.1(24)  application_data
[...]
1    1.2949 (0.0000)  C>S  TCP FIN
1    1.4711 (0.1762)  S>C  TCP FIN

(page 20)


LDAP-Server-Zertifikat

image/cert.png


(page 21)


$ openssl x509 -noout -text -in ldapservercert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            02:14:11:e9:81:65:28:a6:1f:50:10:cf:02:c7:62[...]
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: OU=Organizational CA, O=VETMED
        Validity
            Not Before: Sep 25 07:08:00 2000 GMT
            Not After : Sep 25 09:08:00 2010 GMT
        Subject: CN=cippie.vetmed.uni-muenchen.de,OU=vetmed
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
                    00:bc:04:67:e4:35:83:c8:ac:ac:04:b2:ce:39:2f:
					[...]
		        Exponent: 65537 (0x10001)
  		Signature Algorithm: sha1WithRSAEncryption
        	81:6f:dc:32:8d:58:9e:e0:65:04:22:f9:43:ae:97:9f:5d:66:
			[...]



(page 22)


CA-Zertifikat-Export

image/instca.png


(page 23)


Client: Python


#!/usr/bin/python
import ldap
import sys

if len (sys.argv) != 3:
    print "Usage: RegisterSSL.py course student"
    print "Eg: RegisterSSL.py ant student1"
    sys.exit(1)
ldap.set_option (ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)
ldap.set_option (ldap.OPT_X_TLS_CACERTFILE, "nldapcacert.pem")
#alternative: TLS_CACERT /etc/certs/nldapcacert.pem 
#in /etc/openldap/ldap.conf 
c = ldap.initialize ("ldaps://www.nldap.com:636")
c.simple_bind_s("cn=admin, ou=subldap, ou=user, o=novell",
  "secret")
c.modify_s ("cn=" + sys.argv[1] + ", " + "ou=200201," +   
   "ou=courses, ou=zoology, ou=subldap, ou=user, o=novell",
   [(ldap.MOD_ADD, "member", "cn=" + sys.argv[2] + "," +
   "ou=students, ou=zoology, ou=subldap, ou=user, o=novell")])
c.unbind_s()

Beachte: python: openldap-tls, java: keystore

(page 24)


Ergebnisse


Zugänglichkeit von eDir / NDS

(page 25)


Java vs Python


Apache (ohne LDAP): 25-35 Transaktionen/Sek.
Apache+Java+Tomcat (ohne SSL): 10-12 Transaktionen/Sek.
Apache+Zope+Python (ohne SSL): 10-12 Transaktionen/Sek.
Apache+Java+Tomcat (mit SSL): 3,2 Transaktionen/Sek.
Apache+Zope+Python (mit SSL): 3,2 Transaktionen/Sek.
Apache+Zope+Python (mit SSL, als Prod)10-12 Transaktionen/Sek.


Performance, gemessen mit siege (400 gleichz Nutzer für 60 Sek.)

Interface search

(page 26)


TLS/SSL Schnittstelle für Python und Zope


TLS/SSL kann via python-ldap von Zope-Produkten
benutzt werden

(page 27)


Verzeichnisse vs Datenbanken


Unsere Anwendung ist Grenzfall:

-> Verzeichnisimplementation möglich

(page 28)


Vielen Dank !


URL: http://www.blasum.net/wri/comp/net/7appl/ldap/

(page 29)


LDAP-Patente (petition.eurolinux.org)

image/pat.png

(page 30)