Samba-PDC LDAP howto

20010730.01

Ignacio Coupeau
CTI, University of Navarra


I hope this document can help: express our personal experience at University of Navarra using Samba and LDAP together.

This howto runs for HEAD pre-2.1 (1999/10/15); NT-WS-4-SP3/SP5; linux RH5.2, RH6.1, Kernel 2.2.x and Openldap 1.2.x (x>6). Please, remember that the Openldap 2.x, requires a different schema codification (OID); in the new releases of Samba, theses schemas will be used. If you are in a hurry, this patch for ldap v3 may help: provides a provisional schema and a small patch for the code.
The ldap stuff in the actual HEAD and SAMBA_2_2 branches are under development.
The other project with the PDC-LDAP functionality, SAMBA_TNG, needs a different approach.
 

Table of contents

  1. Preliminary notes
  2. Most recent changes
  3. How to download
  4. How to compile
  5. Ldap server configuration slap.conf
  6. An optinonal schema: ldap+posix accounts (LCFIB, Laboratori de Calcul, UPC)
  7. Ldap server configuration sldap.oc.conf
  8. Ldap basic entries
  9. Ldap "builtin" and "group" entries
  10. Configuring smb server
  11. Adding accounts with smbpasswd
  12. Refine the ldap account entries
  13. Adding members to a group
  14. A complex and real example: several domains(PDC), several share servers (no PDC), two ldap (master/slave) servers.
  15. Some useful (crude) perl scripts: [tar ball]
  16. A note about roaming/mandatory profiles (by Inge-Håvard Hunstad )
  17. Passwd synchronization
  18. A very useful site for PDC stuff, (by David Bannon)


How to download    [toc]


  • You can found the Openldap 1.2.x (x>6) sources at: http://www.openldap.org/.
  • To download the Samba sources (via CVS) for the old (HEAD) stable release: type cvs as passwd, and then:


    Recent changes    [toc]


  • The "ldap basic entries" section has been revised (00.08.04).
  • Also the scripts has been revised (00.08.04).
  • The "root" acount is necessary only in the slapd.conf  (00.08.04).
  • Some indexes added to slapd.conf (00.08.05)
  • grouprid/gidnumber added to nobody record (00.08.07)
  • a optional schema: ldap+posix accounts (00.08.11)
  • minor fixes in the download section (00.10.27)
  • passwd sync note (00.11.13)
     


     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     


    How to download    [toc]


  • You can found the Openldap 1.2.x sources at: http://www.openldap.org/. Take care: don't use the 1.2.6 without patches.
  • To download the Samba sources (via CVS) for the old (HEAD) stable release:


    How to complile    [toc]



    In this example, I assume: You need (step #1) copy the includes and libraries to the default places and -occasionally- do a minor changes in the Makefile.in; also you need (step #2) con figure with the ldap switch.

    Step #1:
    Before run the configure script you need make a copy of the ldap includes and libraries to the default places (for example, in linux /usr/include/ and /usr/lib):

    cp -p /usr/local/etc/openldap/include/* /usr/include/
    cp -p /usr/local/etc/openldap/lib/* /usr/lib

    or the place where the libs/includes are:
    <openldap_source>/configure --prefix=/usr/local/etc/openldap
    as you can decide in the openldap configure step.

    Step #2:
    Compile... "with-ldap", for example:
    ./configure --prefix=/usr/local/etc/samba --with-ldap
    make
    make install


    If this fails, perhaps you need edit the Makefile.in and add some adds/changes:

    add a new line before the FLAGS1 line (the place where the libs/includes are):
    LDAPFLAGS = -I/usr/local/etc/openldap/include -L/usr/local/etc/openldap/lib

    Add the $(LDAPFLAGS) to FLAGS1  line:
    FLAGS1 = $(CFLAGS) $(LDAPFLAGS) -L-Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/smbwrapper $(CPPFLAGS) -DSMBLOGFILE=\"$(SMBLOGFILE)\" -DNMBLOGFILE=\"$(NMBLOGFILE)\"
     


    Ldap server configuration slap.conf   [toc]



    Create a ldap entry in slap.conf:

    ------ snip ------
    #
    database        ldbm
    suffix          "o=SMB-Universidad de Navarra, c=ES"
    rootdn          "uid=root, o=SMB-Universidad de Navarra, c=ES"
    rootpw          <a_secret_word>
    replogfile      /usr/tmp/slurpd-smb.replog
    directory       /usr/local/etc/openldap/samba-slapd
    #
    index           cn
    index           sn,uid,rid,objectclass,ntuid      pres,sub,eq
    index           default         sub
    #
    defaultaccess   read
    access  to dn=".*, o=SMB-Universidad de Navarra, c=ES"
            by self         write
            by *            search
    ----


    Ldap server configuration sldap.oc.conf    [toc]



    Add the schema to sldap.oc.conf:

    ------ snip --------
    objectclass sambaAccount
            requires
                    ObjectClass,
                    uid,
                    uidNumber,
                    ntuid,
                    rid
            allows
               cn
                    gidNumber,
                    grouprid,
                    nickname,
                    userpassword,
                    ou,
                    description,
                    lmPassword,
                    ntPassword,
                    pwdLastSet,
                    smbHome,
                    homeDrive,
                    script,
                    profile,
                    workstations,
                    acctFlags,
                    pwdCanChange,
                    pwdMustChange
     

    objectclass sambaGroup
            requires
                    cn,
                    rid
            allows
                    ntuid,
                    member,
                    description
     

    objectclass sambaBuiltin
            requires
                    cn,
                    sid
            allows
                    ntuid,
                    rid,
                    member,
                    description
    -------------

    Note 1:
            samba creates _by itself_, a sambaConfig structure like:
            ---
            dn: id=root, o=SMB-Universidad de Navarra, c=ES
            objectclass: sambaConfig
            id: root
            nextrid: 3f2
            ---

    The very first account you add to the ldap makes a warning like "object not found", to avoid this,
    Robert Brooks <elvis@gracelands.com> (Mon, 30 Aug 1999) suggest an addition to the slapd.oc.conf:
    ------ snip --------
    objectclass sambaConfig
            requires
                    id
            allows
                    nextrid
    -------------
    perhaps (I no tested it yet), an "requires/objectclass" will be also added...

    Note 2: Matt Chapman suggest me remove these old and unused entries:
                    logonTime,
                    logoffTime,
                    kickoffTime


    Ldap basic entries    [toc]



    Create basic ldap records; with the ldapadd, add these 3 records (the uid=root is not necessary because "root" is managed via slapd.conf); note that gidnumber and uidnumber must be the same that in /etc/passwd/etc/group files:

    --------- snip -------------
    dn: o=SMB-Universidad de Navarra, c=ES
    o: SMB-Universidad de Navarra
    objectclass: organization

    dn: id=root, o=SMB-Universidad de Navarra, c=ES
    id: root
    objectclass: sambaConfig
    nextrid: 3e9

    dn: uid=Administrator, o=SMB-Universidad de Navarra, c=ES
    objectclass: sambaAccount
    uid: Administrator
    lmpassword: 19331995431739EDF9393D97E7A1873C
    ntpassword: CE9F79F52D5AEEDB398A8E07C82CA20F
    pwdlastset: 3982F885
    grouprid: 200
    pwdmustchange: ffffffff
    ntuid: Administrator
    acctflags: [U          ]
    gidnumber: 0
    uidnumber: 522
    rid: 1f4

    dn: uid=nobody, o=SMB-Universidad de Navarra, c=ES
    objectclass: sambaAccount
    uid: nobody
    uidnumber: 99
    ntuid: nobody
    rid: 1f5
    grouprid: 202
    gidnumber: 99
    acctflags: [NU         ]
    lmpassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
    ntpassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX

    ---------- eof -----------------

    Note:

    Keep in mind that an account for login needs the equivalent /etc/passwd entry.
    When you add an user account with bin/smbpasswd, the /etc/passwd account entry is tested, the rid is incremented (+1) and asigned; but with the administrative accounts (ie well know RIDs) the insertion is manual, so you must check the rid is ok AND the /etc/passwd; for example:

    Administrator:*:522:0:Linux samba Administrator:/home/administrador:/dev/null



    LDAP Create "builtin" and "group" records    [toc]



    This step is required for  interdomain  functionality; see Adding members to a group. Follows the
    RID and SID stuff from docs/textdocs/cifsntdomain.txt (A2):
    A2) SIDs and RIDs
    -----------------
    SIDs and RIDs are well documented elsewhere.
    A SID is an NT Security ID (see DOM_SID structure).  They are of the form:

            S-revision-NN-SubAuth1-SubAuth2-SubAuth3...
            S-revision-0xNNNNNNNNNNNN-SubAuth1-SubAuth2-SubAuth3...

    currently, the SID revision is 1.
    The Sub-Authorities are known as Relative IDs (RIDs).

    A2.1) Well-known SIDs
    ---------------------

    A2.1.1) Universal well-known SIDs
    ---------------------------------
            Null SID                     S-1-0-0
            World                        S-1-1-0
            Local                        S-1-2-0
            Creator Owner ID             S-1-3-0
            Creator Group ID             S-1-3-1
            Creator Owner Server ID      S-1-3-2
            Creator Group Server ID      S-1-3-3
            (Non-unique IDs)             S-1-4

    A2.1.2) NT well-known SIDs
    --------------------------

            NT Authority          S-1-5
            Dialup                S-1-5-1

            Network               S-1-5-2
            Batch                 S-1-5-3
            Interactive           S-1-5-4
            Service               S-1-5-6
            AnonymousLogon        S-1-5-7       (aka null logon session)
            Proxy                 S-1-5-8
            ServerLogon           S-1-5-8       (aka domain controller account)
            (Logon IDs)           S-1-5-5-X-Y
            (NT non-unique IDs)   S-1-5-0x15-...
            (Built-in domain)     s-1-5-0x20

    A2.2) Well-known RIDS
    ---------------------

    A RID is a sub-authority value, as part of either a SID, or in the case
    of Group RIDs, part of the DOM_GID structure, in the USER_INFO_1
    structure, in the LSA SAM Logon response.

    A2.2.1) Well-known RID users
    ----------------------------
            DOMAIN_USER_RID_ADMIN          0x0000 01F4
            DOMAIN_USER_RID_GUEST          0x0000 01F5

    A2.2.2) Well-known RID groups
    ----------------------------
            DOMAIN_GROUP_RID_ADMINS        0x0000 0200
            DOMAIN_GROUP_RID_USERS         0x0000 0201
            DOMAIN_GROUP_RID_GUESTS        0x0000 0202

    A2.2.3) Well-known RID aliases
    ------------------------------
            DOMAIN_ALIAS_RID_ADMINS        0x0000 0220
            DOMAIN_ALIAS_RID_USERS         0x0000 0221
            DOMAIN_ALIAS_RID_GUESTS        0x0000 0222
            DOMAIN_ALIAS_RID_POWER_USERS   0x0000 0223

            DOMAIN_ALIAS_RID_ACCOUNT_OPS   0x0000 0224
            DOMAIN_ALIAS_RID_SYSTEM_OPS    0x0000 0225
            DOMAIN_ALIAS_RID_PRINT_OPS     0x0000 0226
            DOMAIN_ALIAS_RID_BACKUP_OPS    0x0000 0227

            DOMAIN_ALIAS_RID_REPLICATOR    0x0000 0228
     

    So, you can import several internals records. Look at sambaBuiltin and sambaAlias entries in some entries:

    ---- snip ----
    dn: cn=Domain Admins,  o=SMB-Universidad de Navarra, c=ES
    member: Administrator,1f4,1
    objectclass: sambaGroup
    ntuid: Domain Admins
    rid: 200
    cn: Domain Admins

    dn: cn=Domain Users,  o=SMB-Universidad de Navarra, c=ES
    objectclass: sambaGroup
    ntuid: Domain Users
    rid: 201
    cn: Domain Users

    dn: cn=Domain Guests,  o=SMB-Universidad de Navarra, c=ES
    objectclass: sambaGroup
    ntuid: Domain Guests
    rid: 202
    cn: Domain Guests

    dn: cn=Administrators,  o=SMB-Universidad de Navarra, c=ES
    description: Members can fully administer the computer/domain
    sid: S-1-5-32-544
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Administrators
    rid: 220
    cn: Administrators
    gidnumber: 0

    dn: cn=Users,  o=SMB-Universidad de Navarra, c=ES
    sid: S-1-5-32-545
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Users
    rid: 221
    cn: Users
    gidnumber: 200

    dn: cn=Guests,  o=SMB-Universidad de Navarra, c=ES
    sid: S-1-5-32-546
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Guests
    rid: 222
    cn: Guests
    gidnumber: 99
    member: nobody,1f5,1

    dn: cn=Account Operators,  o=SMB-Universidad de Navarra, c=ES
    sid: S-1-5-32-548
    objectclass: sambaBuiltin
    ntuid: Account Operators
    rid: 224
    cn: Account Operators

    dn: cn=Server Operators,  o=SMB-Universidad de Navarra, c=ES
    sid: S-1-5-32-549
    objectclass: sambaBuiltin
    ntuid: Server Operators
    rid: 225
    cn: Server Operators

    dn: cn=Print Operators,  o=SMB-Universidad de Navarra, c=ES
    sid: S-1-5-32-550
    objectclass: sambaBuiltin
    ntuid: Print Operators
    rid: 226
    cn: Print Operators

    dn: cn=Backup Operators,  o=SMB-Universidad de Navarra, c=ES
    sid: S-1-5-32-551
    objectclass: sambaBuiltin
    ntuid: Backup Operators
    rid: 227
    cn: Backup Operators

    dn: cn=Replicator,  o=SMB-Universidad de Navarra, c=ES
    sid: S-1-5-32-552
    objectclass: sambaBuiltin
    ntuid: Replicator
    rid: 228
    cn: Replicator

    --------- eof ------------
     


    Configuring smb server    [toc]


    Modify the smb.conf file:

    ------ snip ------
    [global]
    ldap suffix = "o=SMB-Universidad de Navarra, c=ES"
    ldap bind as = "uid=root, o=SMB-Universidad de Navarra, c=ES"
    ldap passwd file = /usr/local/etc/samba/private/ldappasswd
    # if the ldap server resides in the same machine you can use localhost
    # ldap server = localhost
    ldap server = LDAP-SMB1
    ldap port = 389

    workgroup = CTI-SMB
    netbios name = bilbo
    comment = Linux RedHat Samba Server
    security = user
    null passwords = Yes
    encrypt passwords = yes

    #The ldap params are overwritting by smb.conf params
    #logon path = \\bilbo\profiles\%G
    #logon script = %U.bat
    #logon drive = U:

    domain master = yes
    domain logons = yes

    #The ldap internals/groups/builtin are overwritting by smb.conf map files
    #domain group map = /usr/local/etc/samba/lib/domain_group.map
    #domain user map = /usr/local/etc/samba/lib/domain_user.map
    #local group map = /usr/local/etc/samba/lib/local_group.map

    ...
    [netlogon]
    path = /usr/local/etc/samba/netlogon
    locking = no
    writeable = yes
    guest ok = no
    browseable = yes
    --------- eof -----------
     

    Note about LDAP-smb.conf params:


    Note about ldap root passwd:
    The ldap rootdn in the slapd.conf file contains a line like:

    rootpw          <a_secret_word>
    and the smb.conf file contains a line like:
    ldap passwd file = /usr/local/etc/samba/private/ldappasswd
    ... this is the file that contains the passwd <a_secret_word>.


    Adding accounts with smbpasswd    [toc]



    Run the ./bin/smbpasswd to add new entries, WS or people,... of course, you
    need the /etc/passwd /etc/groups contains the accounts and groups....

    do:
    ./bin/smbpasswd -a -m <machine_name> -D 255
    ./bin/smbpasswd -a <user_name> -D 255

    the -D provides debug; is a "-D" not a "-d"


    Refine the ldap account entries    [toc]


    With ldapmodify, you can add/replace some attributes as the "homeDrive",
    "script" and "profile"...

    You need only specify the relative "logon script" name (in this example
    037148.bat); this scrip will be searched in the [netlogon] share.

    For our classrooms I found the "pwdMustChange: FFFFFFFF" very useful,
    because overrides the dialog box for passwd replacement.

    ------- snip-----------
    dn: uid=037148, o=SMB-Universidad de Navarra, c=ES
    changetype: modify
    replace: profile
    profile: \\bilbo\profiles\prn1
    -
    replace: script
    script: 037148.bat
    -
    replace: homeDrive
    homeDrive: U:
    -
    replace: gidnumber
    gidnumber: 201
    -
    replace: grouprid
    grouprid: 202
    -
    replace: pwdCanChange
    pwdCanChange: 00000000
    -
    replace: pwdMustChange
    pwdMustChange: FFFFFFFF
    -
    ------EOF------

    Note:
    The syntax:
        profile: \\bilbo\profiles\prn1
    runs, but
        profile: \\%L\profiles\%U
    or similar may not. I posted a possible patch:

    diff -u ./passdb/sampassldap.c-DIST ./passdb/sampassldap.c
    --- ./passdb/sampassldap.c-DIST Fri Jan 15 06:00:26 1999
    +++ ./passdb/sampassldap.c      Sat Sep  4 20:14:44 1999
    @@ -149,8 +149,10 @@
            else
                    sam21->logon_script = NULL;

    -       if(ldap_get_attribute("profile", profile_path))
    +       if(ldap_get_attribute("profile", profile_path)){
    +               standard_sub_basic(profile_path);
                    sam21->profile_path = profile_path;
    +       }
            else
                    sam21->profile_path = NULL;



    Adding members to a group (by hand, from ldap)    [toc]


    This section follows http://us1.samba.org/listproc/samba-technical/2536.html (M. Chapman):

     objectclass sambaGroup
        requires
            cn, /* group name */
            rid
        allows
            description,
            member /* repeated for each member, in format "name,rid,type" */
                                /* e.g. member=matty,0x600,1 */


    The aim of this section is implement the smb.conf's maps functionality:

    #The smb.conf map files are overriding by ldap internals/groups/builtin
    #domain group map = /usr/local/etc/samba/lib/domain_group.map
    #domain user map = /usr/local/etc/samba/lib/domain_user.map
    #local group map = /usr/local/etc/samba/lib/local_group.map
    in the the ldap database instead.

    For example, assume now that you need to grant administrative privileges to a existent user called "admin". To do this, you need compliments two steps:

    Step #1
    To get the "rid" you can perform a search like:
    ./ldapsearch -L  -b "o=SMB-Universidad de Navarra, c=ES" "uid=*"  rid -h bilbo

    the output is  something like:

    dn: uid=icoupeau, o=SMB-Universidad de Navarra, c=ES
    rid: 3e9

    dn: uid=www, o=SMB-Universidad de Navarra, c=ES
    rid: 3eb

    dn: uid=nobody, o=SMB-Universidad de Navarra, c=ES
    rid: 3ec
    ...

    dn: uid=admin, o=SMB-Universidad de Navarra, c=ES
    rid: 3f5

    So, to add member "admin" to the group "Domain Admins" run the command
    ./ldapmodify -f <file> ... "
    where <file> contains:
    ------ snip ------
    dn: cn=Domain Admins,  o=SMB-Universidad de Navarra, c=ES
    changetype: modify
    add: member
    member: admin,3f5,1
    -
    ------EOF------
    the type "1" say that the group memeber is a "user".


    Step #2

    you need add the grouprid for "Domain Admins" and the unix gidnumber (0,root) to user admin:
    for this, run the command
    ./ldapmodify -f <file> ... "
    where <file> contains:
    ------ snip ------
    dn: uid=admin, o=SMB-Universidad de Navarra, c=ES
    changetype: modify
    replace: gidnumber
    gidnumber: 0
    -
    replace: grouprid
    grouprid: 200
    -
    ------EOF------



    A complex example    [toc]


    This example assume that you have several PDC, several shares distributed on several Samba servers, and two (or more) LDAP synchronized servers.
     

    Scenario

    An user record in ldif format

    dn: uid=037183, o=SMB-Universidad de Navarra, c=ES
    objectclass: sambaAccount
    uid: 037183
    uidnumber: 19233
    ntuid: 037183
    rid: 43dd
    acctflags: [U          ]
    profile: \\%L\profiles\prn1
    homedrive: U:
    smbhome: \\saco1\bag1\037183
    pwdcanchange: 00000000
    pwdmustchange: FFFFFFFF
    lmpassword: 2D8ACB8EA60FF445AAD3B435B51404EE
    ntpassword: A48AB840D44FF7C6F6B4AC4165B585B1
    pwdlastset: 361BAF8E
    gidnumber: 201
    grouprid: 20

     

    The process

    At login time, the user send the credentials (user:passwd) to the PDC from the NT's login window; if they're OK, then the PDC grants the access to the NT-WS, sent the profile and other params to the NT: smbhome, pwd*, *id, etc.
    In the second stage, the NT-WS connects to the samba pointed by smbhome, sent - again - the credentials and the samba server mount the share if the credentials are OK.

    PDC's configuration files

     
    [global]
    ldap suffix = "o=SMB-Universidad de Navarra, c=ES"
    ldap bind as = "uid=root, o=SMB-Universidad de Navarra, c=ES"
    ldap passwd file = /usr/local/etc/samba/private/ldappasswd
    ldap server = LDAP-SMB1 LDAP-SMB2
    ldap port = 389

    workgroup = CTI-SMB-D1
    netbios name = pdc2
    comment = Linux RedHat Samba Server
    security = user
    null passwords = Yes
    encrypt passwords = yes

    logon drive = U:
    domain master = yes
    domain logons = yes

    preferred master = yes
    os level = 255
    wins support = yes
    wins proxy = yes

    log file = /usr/local/etc/samba/logs
    public = No
    browseable = No
    writable = No

    [netlogon]
    path = /usr/local/etc/samba/netlogon
    locking = no
    writeable = yes
    guest ok = no
    browseable = yes
     

    [profiles]
    path = /usr/local/etc/samba/profiles
    writeable = no
    guest ok = yes
    browseable = yes
    create mode = 0777

    [global]
    ldap suffix = "o=SMB-Universidad de Navarra, c=ES"
    ldap bind as = "uid=root, o=SMB-Universidad de Navarra, c=ES"
    ldap passwd file = /usr/local/etc/samba/private/ldappasswd
    ldap server = LDAP-SMB1 LDAP-SMB2
    ldap port = 389

    workgroup = CTI-SMB-C1
    netbios name = pdc1
    comment = Linux RedHat Samba Server
    security = user
    null passwords = Yes
    encrypt passwords = yes

    logon drive = U:
    domain master = yes
    domain logons = yes

    preferred master = yes
    os level = 255
    wins support = yes
    wins proxy = yes

    log file = /usr/local/etc/samba/logs
    public = No
    browseable = No
    writable = No

    [netlogon]
    path = /usr/local/etc/samba/netlogon
    locking = no
    writeable = yes
    guest ok = no
    browseable = yes
     

    [profiles]
    path = /usr/local/etc/samba/profiles
    writeable = no
    guest ok = yes
    browseable = yes
    create mode = 0777


     

    LDAP's configuration files

    You need a strong background in the ldap (slapd, slurpd and slapd.conf) proceedings. The documentation about the replication of LDAP directories are poor. For Samba the problem is strong because we have things so similar (but not equals) as:
    access  to dn="uid=.*,o=SMB-Universidad de Navarra,c=ES"
    access  to dn="id=.*,o=SMB-Universidad de Navarra,c=ES"
    access  to dn="cn=*.,o=SMB-Universidad de Navarra,c=ES"
    so, at las very tired, i found the key for replication is (I hope):
    access  to dn="o=SMB-Universidad de Navarra,c=ES"
    Look a the bold lines:
     
    #       master LDAP configuration file
    #       CTI, Universidad de Navarra
    #       Ignacio Coupeau 990830
    #
    include         /usr/local/etc/openldap/etc/openldap/slapd.at.conf
    include         /usr/local/etc/openldap/etc/openldap/slapd.oc.conf
    schemacheck     on

    #------------------------------------------------------
    # UNAV SMB
    #------------------------------------------------------
    database        ldbm
    suffix          "o=SMB-Universidad de Navarra, c=ES"
    rootdn          "uid=root, o=SMB-Universidad de Navarra, c=ES"
    rootpw          <a_secret>
    directory       /usr/local/etc/openldap/samba-slapd
    #
    replogfile      /usr/tmp/slurpd.replog
    replica         host=ldap-smb2.cti.unav.es
                    binddn="uid=replicator,o=SMB-Universidad de Navarra,c=ES"
                    bindmethod=simple
                    credentials=<a_secret>
    #
    index           cn
    index           sn,uid,mail     pres,sub,eq
    index           default         sub
    #
    access  to dn="o=SMB-Universidad de Navarra,c=ES"
            by dn="uid=replicator,o=SMB-Universidad de Navarra,c=ES" write
            by self                         write
            by *                            search
     


    #       slave LDAP configuration file
    #       CTI, Universidad de Navarra
    #       Ignacio Coupeau 990830

    include         /usr/local/etc/openldap/etc/openldap/slapd.at.conf
    include         /usr/local/etc/openldap/etc/openldap/slapd.oc.conf
    schemacheck     on
    referral        ldap://ldap-smb1.cti.unav.es

    #------------------------------------------------------
    # UNAV SMB
    #------------------------------------------------------
    database        ldbm
    suffix          "o=SMB-Universidad de Navarra, c=ES"
    rootdn          "uid=root, o=SMB-Universidad de Navarra, c=ES"
    rootpw          <a_secret>
    directory       /usr/local/etc/openldap/samba-slapd
    updatedn        "uid=replicator,o=SMB-Universidad de Navarra,c=ES"
    #
    index           cn
    index           sn,uid      pres,sub,eq
    index           default         sub
    #
    access  to dn="o=SMB-Universidad de Navarra,c=ES"
            by dn="uid=replicator,o=SMB-Universidad de Navarra,c=ES" write
            by self                 write
            by *                    search


     

    Samba servers' configuration files

    The servers (saco1 and saco2) have two shares: bag1 and bag2
     
    #
    #       CTI, Universidad de Navarra
    #       Ignacio Coupeau 990825, ldap= LDAP-SMB1 LDAP-SMB2
    #

    [global]
            ldap suffix = "o=SMB-Universidad de Navarra, c=ES"
            ldap bind as = "uid=root, o=SMB-Universidad de Navarra, c=ES"
            ldap passwd file = /usr/local/etc/samba/private/ldappasswd
            ldap server = LDAP-SMB1 LDAP-SMB2
            ldap port = 389

            comment = Linux RedHat Samba Server  Saco1
            workgroup = CTI-SMB
            netbios name = SACO1
            security = user

            null passwords = Yes
            encrypt passwords = yes

            log file = /usr/local/etc/samba/logs
            shared mem size = 5242880

    [bag1]
            comment = Home Directories
            path = /disco1/%u
            read only = No
            create mask = 0700

    #
    #       CTI, Universidad de Navarra
    #       Ignacio Coupeau 990825, ldap= LDAP-SMB1 LDAP-SMB2
    #

    [global]
            ldap suffix = "o=SMB-Universidad de Navarra, c=ES"
            ldap bind as = "uid=root, o=SMB-Universidad de Navarra, c=ES"
            ldap passwd file = /usr/local/etc/samba/private/ldappasswd
            ldap server = LDAP-SMB1 LDAP-SMB2
            ldap port = 389

            comment = Linux RedHat Samba Server  Saco2
            workgroup = CTI-SMB
            netbios name = SACO2
            security = user

            null passwords = Yes
            encrypt passwords = yes

            log file = /usr/local/etc/samba/logs
            shared mem size = 5242880

    [bag2]
            comment = Home Directories
            path = /disco1/%u
            read only = No
            create mask = 0700

    Note: I strong recommend you, test the replication. With Linux RH 5.2 kernel 2.2.10 I need runs the slurpd in one shot mode every 1-2 hours; as demon not runs fine at all.
     


    Import builtin accounts from the scratch    [toc]


    This example assume that you have the  PDC and LDAP running. You need ONLY the slapd.conf and the slapd.oc.conf well configured: the administrative accounts concerns to this script ;-)

    #!/usr/bin/perl
    #
    #       Ignacio Coupeau, 000727
    #
    #       Populates a ldap-samba database from the scratch
    #       - you need a ldap database created, with a_password, a slapd.conf well defined and so.
    #
    #
    $ldap_pass = "a_secret";
    $ldap_base = "o=SMB-Universidad de Navarra, c=ES";
    $ldap_organization = "SMB-Universidad de Navarra";
    $ldap_host = "enigma.cti.unav.es";
    $ldapmodify_cmd = "/usr/local/etc/openldap/bin/ldapadd -crf a_ldif -D \"uid=root, $ldap_base\" -w $ldap_pass -h $ldap_host  ";
    $root_share = "\\\\bilbo\\homes";
    #
    #
    #

    print "$ldapmodify_cmd \n";
    create_ldif_buitin();
    system ("$ldapmodify_cmd -f a_ldif");

    exit(0);
     

    sub create_ldif_buitin {
            open (LDIF, ">a_ldif");

    print LDIF <<pagina;
    dn: $ldap_base
    o: $ldap_organization
    objectclass: organization

    dn: id=root, $ldap_base
    id: root
    objectclass: sambaConfig
    nextrid: 3e9

    dn: uid=Administrator, $ldap_base
    objectclass: sambaAccount
    uid: Administrator
    lmpassword: 19331995431739EDF9393D97E7A1873C
    ntpassword: CE9F79F52D5AEEDB398A8E07C82CA20F
    pwdlastset: 3982F885
    grouprid: 200
    pwdmustchange: ffffffff
    ntuid: Administrator
    acctflags: [U          ]
    gidnumber: 0
    uidnumber: 522
    rid: 1f4

    dn: uid=nobody, $ldap_base
    objectclass: sambaAccount
    uid: nobody
    uidnumber: 99
    grouprid: 202
    gidnumber: 99
    ntuid: nobody
    rid: 1f5
    pwdlastset: 39856D06
    acctflags: [U          ]
    lmpassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
    ntpassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX

    dn: cn=Domain Admins, $ldap_base
    objectclass: sambaGroup
    ntuid: Domain Admins
    rid: 200
    cn: Domain Admins
    member: Administrator,1f4,1

    dn: cn=Domain Users, $ldap_base
    objectclass: sambaGroup
    ntuid: Domain Users
    rid: 201
    cn: Domain Users

    dn: cn=Domain Guests, $ldap_base
    objectclass: sambaGroup
    ntuid: Domain Guests
    rid: 202
    cn: Domain Guests
    member: nobody,1f5,1

    dn: cn=Administrators, $ldap_base
    description: Members can fully administer the computer/domain
    sid: S-1-5-32-544
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Administrators
    rid: 220
    cn: Administrators

    dn: cn=Users, $ldap_base
    sid: S-1-5-32-545
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Users
    rid: 221
    cn: Users

    dn: cn=Guests, $ldap_base
    sid: S-1-5-32-546
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Guests
    rid: 222
    cn: Guests

    dn: cn=Account Operators, $ldap_base
    sid: S-1-5-32-548
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Account Operators
    rid: 224
    cn: Account Operators

    dn: cn=Server Operators, $ldap_base
    sid: S-1-5-32-549
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Server Operators
    rid: 225
    cn: Server Operators

    dn: cn=Print Operators, $ldap_base
    sid: S-1-5-32-550
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Print Operators
    rid: 226
    cn: Print Operators

    dn: cn=Backup Operators, $ldap_base
    sid: S-1-5-32-551
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Backup Operators
    rid: 227
    cn: Backup Operators

    dn: cn=Replicator, $ldap_base
    sid: S-1-5-32-552
    objectclass: sambaBuiltin
    objectclass: sambaAlias
    ntuid: Replicator
    rid: 228
    cn: Replicator

    pagina

            close (LDIF);
     

    # Are these useful???

    <<pagina2;
    dn: cn=Everyone, $ldap_base
    sid: S-1-1-0
    objectclass: sambaBuiltin
    ntuid: Everyone
    cn: Everyone

    dn: cn=Local, $ldap_base
    sid: S-1-2-0
    objectclass: sambaBuiltin
    ntuid: Local
    cn: Local

    dn: cn=Network, $ldap_base
    sid: S-1-5-2
    objectclass: sambaBuiltin
    ntuid: Network
    cn: Network

    dn: cn=Interactive, $ldap_base
    sid: S-1-5-4
    objectclass: sambaBuiltin
    ntuid: Interactive
    cn: Interactive

    dn: cn=Authenticated Users, $ldap_base
    sid: S-1-5-11
    objectclass: sambaBuiltin
    ntuid: Authenticated Users
    cn: Authenticated Users

    pagina2

    }
     


    Import from /etc/passwd    [toc]


    This example assume that you have the  PDC and LDAP running. This add users, not  machines (-m option may be added).

    #!/usr/bin/perl
    #
    #       Ignacio Coupeau, 000714
    #
    #       Populates a ldap-samba database from /etc/passwd from the scratch
    #       - from $uid_min to $uid_max users
    #       - all users by default has "Password" passwd.
    #       - for machines you must add a "$<uid>" filter and a "-m" option to smbpasswd
    #
    #
    $ldap_pass = "a_secret";
    $ldap_base = "o=SMB-Universidad de Navarra, c=ES";
    $ldap_host = "enigma.cti.unav.es";
    $ldapmodify_cmd = "/usr/local/etc/openldap/bin/ldapmodify -D \"uid=root, $ldap_base\" -w $ldap_pass -h $ldap_host  ";
    #
    #
    $uid_min = 100;
    $uid_max = 105;
    #
    #
    $profile_path_default = "\\\\%L\\profiles";
    $nt_grouprid_default = "2000";
    $nt_group_default = "prn1";
    $homeDrive_default = "U:";
    $smbpasswd_cmd = "/usr/local/etc/samba/bin/smbpasswd ";
    $samba_usr_passwd_default = "Password";
     
     

    for ($i=$uid_min; $i < $uid_max+1; $i++) {

            ($uid, $upasswd, $uidnumber, $gidnumber, $quota, $comment, $gecos, $homedrive, $ushell) = getpwuid($i);
            print "$uid, $upasswd, $uidnumber, $gidnumber, $quota, $comment, $gecos, $homedrive, $ushell \n";

            if ($uid ne "") {

                    # create samba account in the ldap
                    system ("$smbpasswd_cmd -a $uid $samba_usr_passwd_default");

                    # default values
                    $nt_grouprid = $nt_grouprid_default;
                    $nt_group = $nt_group_default;
                    $profile_path = "$profile_path_default\\$uid";
                    $homeDrive = $homeDrive_default;

                    # your unix - NT maps
                    # for example the users with gidnumber 201 in Unix are mappeed to group prn1 in NT

                    if ($gidnumber eq "201") {
                            $nt_grouprid = "201";
                            $nt_group = "prn1";
                            $profile_path = "$profile_path_default\\$nt_group";

                    } elsif ($gidnumber eq "202") {
                            $nt_grouprid = "201";
                           $nt_group = "prn2";
                            $profile_path = "$profile_path_default\\$nt_group";
                    }
                    &update_ldap();

            }
    }

    exit;
     
     
     

    sub update_ldap {

            open (LDIF, ">a_ldif");
            print LDIF "dn: uid=$uid, $ldap_base\n";
            print LDIF "changetype: modify\n";
            print LDIF "replace: profile\nprofile: $profile_path\n-\n";
            print LDIF "replace: homeDrive\nhomedrive: $homeDrive\n-\n";
            print LDIF "replace: pwdCanChange\npwdCanChange: 00000000\n-\n";
            print LDIF "replace: pwdMustChange\npwdMustChange: FFFFFFFF\n-\n";
            print LDIF "replace: gidnumber\ngidnumber:  $gidnumber\n-\n";
            print LDIF "replace: grouprid\ngrouprid: $nt_grouprid\n-\n";
            close (LDIF);

            print "$ldapmodify_cmd \n";
            system ("$ldapmodify_cmd -f a_ldif");
    }
     


    Migrating from smbpasswd    [toc]


    This example assume that you have the  PDC and LDAP running.
    #!/usr/bin/perl
    #
    #       Ignacio Coupeau, 000714
    #
    #       Migrates an smbpasswd database to ldap-samba
    #       - all users/machines from smbpasswd file
    #       - all users/machines mantains the smbpasswd passwd.
    #
    #
    $ldap_pass = "a_secret";
    $ldap_base = "o=SMB-Universidad de Navarra, c=ES";
    $ldap_host = "enigma.cti.unav.es";
    $ldapmodify_cmd = "/usr/local/etc/openldap/bin/ldapmodify -D \"uid=root, $ldap_base\" -w $ldap_pass -h $ldap_host  ";
    #
    #
    #
    $profile_path_default = "\\\\%L\\profiles";
    $nt_grouprid_default = "201";
    $nt_group_default = "prn1";
    $homedrive_default = "U:";
    #
    $smbpasswd_cmd = "/usr/local/etc/samba/bin/smbpasswd ";
    $smbpasswd_file = "/usr/local/etc/samba/private/smbpasswd";
     

    open (LECTURA, "$smbpasswd_file");
    while (<LECTURA>) {
            chop;
            $linea = $_;
            $uid = "";
            $smb_uid = "";
            ($smb_uid, $smb_uidnumber, $lmpassword, $ntpassword, $class, $pwdlastset, $dummy) = split(/:/, $linea);
            $pwdlastset =~ s/LCT-//;
            print "smb_uid: $smb_uid, $smb_uidnumber, $lmpassword, $ntpassword, $class, $pwdlastset\n";
            ($uid, $upasswd, $uidnumber, $gidnumber, $quota, $comment, $gecos, $homedrive, $ushell) = getpwnam($smb_uid);
            print "uid: $uid, $upasswd, $uidnumber, $gidnumber, $quota, $comment, $gecos, $homedrive, $ushell\n";

            if ($uid ne "") {

                    $ws = "";
                    $_ = $uid;
                    $ws = "-m" if (/\$/);
     

                    # create a new samba account in the ldap server
                    system ("$smbpasswd_cmd -a $ws $uid $samba_usr_passwd_default");

                    # default values
                    $nt_grouprid = $nt_grouprid_default;
                    $nt_group = $nt_group_default;
                    $profile_path = "$profile_path_default\\$uid";
                    $homedrive = $homedrive_default;

                    # your unix - NT maps come here...
                    # for example the users with gidnumber 201 in Unix are mappeed to group prn1 in NT.
                    #
                    # In this example, we are using gid (unix groups) 201 and 202 and the NT group 201
                    # but DON'T have any reason for these identity: it's casual.

                    if ($ws eq "-m") {
                            &update_ldap_ws();
                    } else {
                            if ($gidnumber eq "201") {
                                    $nt_grouprid = "201";
                                    $nt_group = "prn1";
                                    $profile_path = "$profile_path_default\\$nt_group";

                            } elsif ($gidnumber eq "202") {
                                    $nt_grouprid = "201";
                                   $nt_group = "prn2";
                                    $profile_path = "$profile_path_default\\$nt_group";
                            }
                            &update_ldap_user();
                    }

            }
    }
    close (LECTURA);

    exit;
     
     

    sub update_ldap_user {

            open (LDIF, ">a_ldif");
            print LDIF "dn: uid=$uid, $ldap_base\n";
            print LDIF "changetype: modify\n";
            print LDIF "replace: profile\nprofile: $profile_path\n-\n";
            print LDIF "replace: homedrive\nhomedrive: $homedrive\n-\n";
            print LDIF "replace: pwdCanChange\npwdCanChange: 00000000\n-\n";
            print LDIF "replace: pwdMustChange\npwdMustChange: FFFFFFFF\n-\n";
            print LDIF "replace: gidnumber\ngidnumber:  $gidnumber\n-\n";
            print LDIF "replace: grouprid\ngrouprid: $nt_grouprid\n-\n";
            print LDIF "replace: lmpassword\nlmpassword: $lmpassword\n-\n";
            print LDIF "replace: ntpassword\nntpassword: $ntpassword\n-\n";
            print LDIF "replace: pwdlastset\npwdlastset: $pwdlastset\n-\n";
            close (LDIF);

            print "$ldapmodify_cmd \n";
            system ("$ldapmodify_cmd -f a_ldif");
    }
     

    sub update_ldap_ws {

            open (LDIF, ">a_ldif");
            print LDIF "dn: uid=$uid, $ldap_base\n";
            print LDIF "changetype: modify\n";
            print LDIF "replace: pwdCanChange\npwdCanChange: 00000000\n-\n";
            print LDIF "replace: pwdMustChange\npwdMustChange: FFFFFFFF\n-\n";
            print LDIF "replace: lmpassword\nlmpassword: $lmpassword\n-\n";
            print LDIF "replace: ntpassword\nntpassword: $ntpassword\n-\n";
            print LDIF "replace: pwdlastset\npwdlastset: $pwdlastset\n-\n";
            close (LDIF);

            print "$ldapmodify_cmd \n";
            system ("$ldapmodify_cmd -f a_ldif");
    }
     
     


    A note about mandatory profiles   [toc]



    Subject:  Re: Working on LDAP support in HEAD
    Date:   Tue, 16 May 2000 05:43:51 +1000
    From:  Inge-Håvard Hunstad <inge@cc.uit.no>
    To:      Multiple recipients of list SAMBA-DOCS <samba-docs@samba.org>
    References: 1 , 2 , 3 , 4 , 5
     

    David Collier-Brown wrote:
    >
    > Inge-Håvard Hunstad wrote Re: Working on LDAP support in HEAD
    >
    > > I just wanted to say that those who where using my setup where *lucky*
    > > because they didn't have to worry, because I did a lot of this. But I
    > > see the point that those who have users with local files on the NTws,
    > > and roaming profiles have a problem if the rid is changed.
    >
    >         Could you write a short message to samba-docs@samba.org
    >         describing your profile setup, so we'll have it
    >         available when we rewrite textdocs/PROFILES.txt
    >         (which is getting out of date).
    >
    Hi,

    Thanks for asking David.

    We have a sever running samba ver 2.1prealpha from October 15. with
    support for LDAP, but this description should work for everyone using NT
    clients. This server serves only NT4ws clients. Our users are students
    in computer labs so we wanted a uniform setup for all the machines.
    Therefor we use a mandatory profile that all the users in our domain
    gets. Our users also doesn't use the same machine every time so to avoid
    having 6000 profiles stored on every machine in the domain we delete the
    profile when the users log out using this reg. hack:
    Add this REG_DWORD value key:
       HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\
       Winlogon\DeleteRoamingCache
    the Value should be 1.

    To create the mandatory profile you have to start from scratch with a
    brand new user to keep the profile size down. Then you have to configure
    the user as you want all your users should have it. Then you logout and
    login as a administrator and use "Control Panel->System->User Profiles"
    to copy the profile to the profile server. Make sure that "everyone" is
    able to use the profile. When you have done this you have to go to the
    profile server to change the name of Ntuser.dat in the profile to
    Ntuser.man and change the permission on the directory so that it's only
    readable by "world". Here you also have the possibility to change the
    extension of the directory containing the profile so that it has a .man
    extension but this is not necessary. If you do this then your users are
    kicked out to the logon screen if the profile server is not available. I
    have noted that if the user have logged on to an NT box before and then
    the user is removed from the server he can still log on if the server is
    unavailable. You prevent this if you are having the .man extension on
    the profile directory. The configuration I did of samba was this:

    smb.conf
    [global]
            logon path = \\%L\Profiles\users.man

    [Profiles]
            path = /opt/samba-pdc/profiles
            browseable = yes
            read only = Yes
            write list = @staff
            guest ok = yes
            locking = no

    Note that this is a setup without LDAP. If you use ldap the logon path
    is controlled by this entry in the record for the user:

    profile: \\ProfileServerNetbiosName\Profiles\users.man

    You can't use the normal variable substitution in the LDAP directory.
    I'm not sure why, but I haven't been able to get it to work properly.

    Also if you are using Internet Explorer (we are not) you have to do this
    reg. edit:
    Delete the Loadwc.exe from the BrowserWebCheck value from this registry
    key:
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run

    I would also recommend this reg. edit that I got from Martin
    Kuppinger(Samba-NTDOM mailing list):

    I believe this one turns off the slow link connection:
    ---> CUT HERE <---
    REGEDIT4
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon]
    "SlowLinkDetectEnabled"=dword:00000000

    ---> END CUT <---

    [>]  It turns off the message displayed. There is another parameter
    SlowLinkTimeOut
    which you could use to set the time in milliseconds. Default is 2000,
    maximum
    in system policy is 20000, in registry i've read about 120.000

    Here is some links to MS Knowlegebase:
    Q168476 - How to Create Mandatory Profiles with Windows NT 4.0
    http://support.microsoft.com/support/kb/articles/Q168/4/76.ASP
    Q236436 - "Setting Up Personalized Settings" Message at Every Boot
    http://support.microsoft.com/support/kb/articles/Q236/4/36.ASP

    Yes I've been cheating, shame on me:)

    People that have helped me setting this up so that it worked is Dejan
    Ilic (Samba-NTDOM) and John Terje Hunstad(NT administrator).

    Cheers,

    Inge-Håvard Hunstad

    PS. David please feel free to edit this text if it suits the samba
    community. I also hope that there is some sense in the text somewhere.
    Sorry that it is so long. I couldn't help myself:-)
     
     


    An optional schema: ldap+posix accounts   [toc]



    From the LCFIB of the UPC tell me this schema was tested with Netscape Directory server:

    Subject:  samba-ldap (2)
    Date:  Wed, 19 Jul 2000 09:48:07 +0200
    From:  Antonia Gomez <antonia@fib.upc.es>

    --

    objectclass sambaaccount
            oid sambaaccount-oid
            superior top
            requires
                   homedirectory,
                    ntuid,
                    rid,
                    uid,
                    uidnumber
            allows
                    acctFlags,
                    description,
                    gecos,
                    gidnumber,
                    grouprid,
                    homeDrive,
                    lmPassword,
                    loginshell,
                    nickname,
                    ntPassword,
                    ou,
                    profile,
                    pwdChange,
                    pwdLastSet,
                    pwdMustChange,
                    script,
                    smbHome,
                    userpassword,
                    workstations
    --
     


    Password sync    [toc]



    Subject:Samba-tng PDC- OpenLDAP - Password sync Working
       Date:Tue, 19 Sep 2000 12:29:04 -0400
       From:Jody Haynes <Jody.Haynes@isunnetworks.com>
         To:samba-ntdom@us4.samba.org

    I just wanted to post this to let everyone know that I got the following working:

    1)  Samba-TNG-2.6 as a PDC for Win2K, WinNT and Win98 clients
    2)  Password sync with Samba using OpenLDAP
    3)  Linux clients authenticating off of OpenLDAP using pam_ldap and nss_ldap.
    4)  pam_ldap/nss_ldap encrypted with the use of stunnel

    Here is the following configuration information:

    smb.conf file:

    ldap suffix = "<LDAP Suffix>"
    ldap bind as = "<LDAP Bind Info>"
    ldap port = 389
    .
    .
    .
    unix password sync = yes
    passwd program = /usr/local/samba/bin/ldapsync %u
    passwd chat = *New*Password* %n\n *modifying*

    My ldap sync perl script called ldapsync %u:

    #!/usr/bin/perl -w

     $user=$ARGV[0];
     print "New Password:  ";
     $pass=<STDIN>;
     chomp $pass;

     $salt=join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64];

     $pass=crypt($pass,$salt);

     $FILE="|ldapmodify -D '<LDAP Bind>' -w <LDAP Password>";

     open FILE or die;

     print FILE <<EOF;
     dn: uid=$user, ...ldap suffix...
     changetype: modify
     replace: userPassword
     userPassword: {crypt}$pass

     EOF
     close FILE;

     exit 0;
     

    The best reference material to go by is the following URL for samba as a PDC and ldap:

    http://www.unav.es/cti/ldap-smb-howto.html
     

    --
              Jody Haynes

    Also you can use this one (also from Jody Haynes and Mirko Manea).