ldapvi User Manual

ldapvi is an interactive LDAP client for Unix terminals. Using it, you can update LDAP entries with a text editor.

Think of it as vipw(1) for LDAP.

ldapvi was written by David Lichteblau and is available at http://www.lichteblau.com/ldapvi/.

Installing ldapvi

ldapvi uses autoconf and should be rather easy to install.

It used to work on Linux, Solaris, FreeBSD, IRIX, and Cygwin for me and seems to work on MacOS X and NetBSD for others. Current versions are only really tested on Linux though, so please send a bug report if a port is broken.

$ ./configure && make
# make install

Prerequisites. 

Note that binaries compiled for libldap 2.1 will crash when ran with libldap 2.2.

The choice of GnuTLS over OpenSSL affects only the use of hashing routines for the userPassword convenience encodings md5, smd5, sha, and ssha. GnuTLS support is offered because, according to Debian, OpenSSL is not GPL compatible.



Getting started

The quickest way to try ldapvi is using this:

$ ldapvi -d --host HOSTNAME

Explanation.  This will bind anonymously to hostname, read all entries the server has and open them in the editor.

--host is the one option you really need to give. It can be one of:

-d is short for --discover and lets ldapvi search all of the server's naming contexts. Without -d, you would have had to specify the base DN yourself using --base, and you know how inconvenient those LDAP DNs are to type.

Using a configuration file.  As easy as that was, you might want to put the hostname and other search options like the precise base DN to use into a configuration file.

To do that, you might like

$ ldapvi --config --discover --host HOSTNAME

This will ask the server for its naming contexts and print sample contents for ~/.ldaprc (or /etc/ldap.conf).

(Note that ldapvi also has its own configuration file format which supports multiple configuration profiles and all of its options.)

# ldap.conf(5)
# edit this as needed and paste into ~/.ldaprc

# server name
# (for parameterless operation, make sure to include at least this line)
HOST localhost

# default search base
### multiple namingcontexts found (uncomment one of these lines):
#BASE dc=lichteblau,dc=com
#BASE dc=acme,dc=com

# user to bind as
#BINDDN <dn>

# search parameters (uncomment as needed)
#DEREF never
#SIZELIMIT 0
#TIMELIMIT 0

Adjust to taste.



Interactive usage

After quitting from the editor, one of three things can happen:

If all is well, you are now in the main loop. Your options are:

Edit - diff - fail.  To continue, type y.

ldapvi will contact the LDAP server apply all changes. First, entries are processed in order of the changed file, then all entries missing from the file are deleted.

If any LDAP operation fails while processing the file, ldapvi will stop, report the error, and wait for your choice. To correct such an error, go back to the editor. Your will find all previously processed entries removed from the file, with the failing change at the top. After changing the file, you will be back at the prompt.

Action? [yYqQvVebB*rsf+?] y
ldap_modify: Strong(er) authentication required (8)
        additional info: modifications require authentication
Error at: cn=blub4,dc=lichteblau,dc=com
add: 0, rename: 0, modify: 1, delete: 0
Action? [yYqQvVebB*rsf+?] 

Apply all changes as if invoked with --continue ignoring all errors without further warning. (Make sure to save changes to an external file before using this option if they were important. Invalid changes will be lost otherwise.)

Reviewing changes.  Before applying the changes, you can inspect them in either LDIF syntax or ldapvi's special changerecord syntax.

LDIF syntax is useful if you want to copy and paste changes into a file for later processing with other LDAP tools. ldapvi syntax is usually easier to read (less Base 64) and can also be entered directly into the editor.

This will update the file to include schema comments and re-enter the editor afterwards. This works like the --may command line option, but is based on the current contents of the file rather than the original entries, useful when changing the class of an entry.

Note that this command will rewrite the entire file and wipe out all comments present before invoking it.

Logging in.  One way to bind to the LDAP server is to specify user name and credentials at startup using command line options or configuration files. The other is to simply start without authentication and login later.

When relying on binding after editing, keep in mind that some information will not be returned by the LDAP server unless user authorization permits it in the first place. For example, a userPassword can usually only be displayed and edited if you are bound as that user or root upon startup.

This option will ask for your user name and password (in the case of simple authentication) or various SASL parameters (as requested by the SASL library).

For simple authentication, the user name can be either an DN or a search filter. In the latter case, it must be written with parentheses around it.

Action? [yYqQvVebB*rsf+?] b

--- Login
Type M-h for help on key bindings.

Filter or DN: (cn=admin)
    Password: ********
OK, bound as cn=admin,dc=lichteblau,dc=com.

Same example with SASL:

Action? [yYqQvVebB*rsf+?] b
SASL/DIGEST-MD5 authentication started

--- SASL login
Type M-h for help on key bindings.

 authorization name: 
authentication name: admin
           password: ********
SASL username: admin
SASL SSF: 128
SASL installing layers
Bound as authzid=, authcid=admin.

Note that all non-password values are saved into ~/.ldapvi_history, so after entering them once, "cursor up" or incremental search (C-r) will save you from having to type them again.

Use this key to switch between simple authentication and SASL at run time:

Action? [yYqQvVebB*rsf+?] B
SASL authentication enabled.
SASL mechanism: DIGEST-MD5 (use '*' to change)
Type 'b' to log in.

When the SASL dialog is shown, it is too late to switch the SASL mechanism. Type * to set it at run time.

Action? [yYqQvVebB*rsf+?] *
SASL mechanism: DIGEST-MD5
Type 'b' to log in.

"Oops".  You can skip one change to proceed with the rest.

Removes the topmost entry from the data file.

This is useful if you have deleted entries from the file accidentally (or intentionally) and still want to commit other change records in the same file.

This option does not affect explicit deletion records.

Bailing out.  There is a gentle way to quit and a hard one.

q will save your changes to a new file, print the file name, and quit only then. This way your changes do not get lost and you can feed them into ldapmodify at a later time.

Action? [yYqQvVebB*rsf+?] q
Your changes have been saved to ,ldapvi-xenon-20094.ldif.


Command line arguments

Normal ldapvi invocations look similar to ldapsearch(1), taking an optional search filter and zero or more attribute descriptions as unnamed arguments.

ldapvi [OPTION]... [FILTER] [AD]...

In addition, ldapvi can also simulate behaviour of other LDAP command line tools, e.g. as an interactive substitute for ldapmodify or even for a simple non-interactive usage. See below under command line tool compatibility.

Index of options. 

  -h   --host   LDAP server to connect to
    --bind   Disable or enable SASL
    --bind-dialog   Interactive login dialog
  -D   --user   User to bind as (simple bind)
  -w   --password   User's password
  -I   --sasl-interactive   Use SASL Interactive mode
  -Q   --sasl-quiet   Use SASL Quiet mode
  -O   --sasl-secprops   SASL security properties
  -R   --sasl-realm   SASL realm
  -U   --sasl-authcid   SASL authentication identity
  -X   --sasl-authzid   SASL authorization identity
  -Y   --sasl-mech   SASL mechanism
  -b   --base   Search base
  -s   --scope   Search scope
  -S   --sort   Search control
  -d   --discover   Auto-detect naming contexts
  -o   --class   Class to add
  -m   --may   Show schema comments.
    --add   Treat attrval records as new entries to add.
  -A   --empty   Start with empty file
  -a   --deref   Alias dereferencing mode
    --config   Print parameters in ldap.conf syntax
  -c   --continue   Ignore LDAP errors and continue
    --encoding   The encoding to allow
  -M   --managedsait   manageDsaIT control
  -Z   --starttls   Require startTLS.
    --tls   Level of TLS strictness
    --read   Read this entry
  -v   --verbose   Note every update
  -H   --help   Print usage information
    --deleteoldrdn   Delete the old RDN
    --ldif   Use LDIF syntax internally
    --ldapvi   Use ldapvi syntax externally
    --out   Print entries
    --in   Load change records
    --delete   Edit a delete record
    --rename   Edit a rename record
    --ldapsearch   Print entries noninteractively
    --ldapmodify   Apply change records noninteractively
    --ldapdelete   Delete an entry noninteractively
    --ldapmoddn   Rename an entry noninteractively

Connection parameters

The host option specifies the LDAP server to connect to. It is required for startup (unless specified in a configuration file).

-h --host  hostname   LDAP server to connect to
Three styles of host name are recognized.
  • A domain name.
  • ldap://hostname[:port]
  • ldaps://hostname[:port]
To specify a port number or tunnelling through SSL, the URL form must be used.
 

Authentication

Note that you can also bind to the server interactively after performing the search using the b command.

--bind  simple|sasl   Disable or enable SASL

Initially, ldapvi defaults to simple authentication. If any SASL parameter is given, the mode is set to sasl. Conversely, -D sets it to simple.

This parameter sets it explicitly.

 
--bind-dialog  never|auto|always   Interactive login dialog

This option controls whether ldapvi will ask for authentication parameters interactively.

The default is auto, which means that simple binds will be done interactively if a user name is provided but no password, and similarly for SASL.

always forces display of a login dialog even if defaults are known. never skips the login dialog completely.

Note that this option has effect only for the initial bind operation. In the main loop, all binds are done interactively.

See also: -Q and -I.

 
-D --user  dn|filter   User to bind as (simple bind)
The user name can be specified as a distinguished name
uid=foo,ou=bar,dc=acme,dc=com
or as a search filter
(uid=foo)

Note the use of parenthesis, which can be omitted from search filters usually but are required here. For this searching bind to work, your client library must be configured with appropriate default search parameters.

Exactly one entry must match.

 
-w --password  secret   User's password
Beware that passwords in a simple bind are transmitted in clear text unless the connection is encrypted through SSL.

This option is valid for both simple authorization and SASL.

 

SASL authentication.  If any of the SASL arguments is specified, ldapvi uses SASL by default.

If you are unsure which SASL parameters to try for your server, start with -Y DIGEST-MD5 -U username.

-I --sasl-interactive     Use SASL Interactive mode
Always ask for SASL parameters interactively.

This option is an alias for --bind-dialog always and --bind sasl.

 
-Q --sasl-quiet     Use SASL Quiet mode
Never ask for SASL parameters interactively at all.

This option is an alias for --bind-dialog never and --bind sasl.

 
-O --sasl-secprops  properties   SASL security properties
OpenLDAP's slapd.conf(5) manual page has some information on these (search for sasl-secprops).
 
-R --sasl-realm  realm   SASL realm
The SASL realm [Cyrus SASL documentation].
 
-U --sasl-authcid  username   SASL authentication identity
The authentication ID [Cyrus SASL documentation].

(Basically, your username.)

 
-X --sasl-authzid  u:username|dn:dn   SASL authorization identity
The authorization ID [Cyrus SASL documentation].

(See SASL Proxy Authorization [openldap.org] in the OpenLDAP Administrator's Guide.)

 
-Y --sasl-mech  mechanism   SASL mechanism

The SASL mechanism to use. Possible values depend on the server, but DIGEST-MD5 support is mandated by RFC 2829 for all servers using passwords.

 

Search parameters

Where and how to look for entries.

-b --base  dn   Search base
The entry at which to start the search.

Conflicts with --discover.

 
-s --scope  base|one|sub   Search scope
  • base: Retrieve at most the entry at base.
  • one: Search for entries exactly one level below base.
  • sub: Search the entire subtree starting at base.
 
-S --sort  keys   Search control
Use the search control to instruct the server to sort results on keys. ldapvi will fail if the server does not support the control. Unfortunately, few servers do.
 

Handy parameters

-d --discover     Auto-detect naming contexts
With this option, ldapvi will first read the root DSE, then repeat the search for each naming context found and present the concatenation of all search results.

Conflicts with --base.

With --config, show a BASE configuration line for each context.

 
-o --class  objectClass   Class to add
Read the server's schema for the specified objectclass to find out which attributes an entry of this class must have and can have. Then open the editor with an entry template containing one line for each such attribute the user needs to fill out. Optional attributes are included as comments.

The option can be repeated to include additional, auxiliary classes.

A distinguished name for the entry template can be specified using --base.

 
-m --may     Show schema comments.
Show schema comments for existing entries. Specificially, show optional attributes as comments, if not present.
 

Miscellaneous options

--add     Treat attrval records as new entries to add.

This option applies only to the --in/--ldapmodify mode:

Add new entries (default would be to replace existing attributes).

 
-A --empty     Start with empty file
Do not search, start with an empty file instead.

This is the little brother of the --class parameter, which is more interesting for the original use case of this option, adding new entries.

However, it is still useful because allows the interactive entry of delete, modify, or rename changerecords.

 
-a --deref  never|searching|finding|always   Alias dereferencing mode
Default is never.
 
--config     Print parameters in ldap.conf syntax
Print a configuration file in standard ldap.conf syntax which reflects current command line arguments. The file is written to standard output. Use this option to create an initial configuration file after experimenting with search parameters. Useful in conjunction with --discover.
 
-c --continue     Ignore LDAP errors and continue
When LDAP errors occur while applying changes, print the messages but continue processing. This mode can also be specified interactively using the 'Y' key.
 
--encoding  ASCII|UTF-8|binary   The encoding to allow
This option controls how ldapvi deals with non-ASCII bytes in attribute values.
  • ASCII: If an attribute value contains any non-ASCII character, use Base 64 encoding for this value
  • UTF-8: Use auto-detection. If an attribute value parses as correct UTF-8, pass it through to the file or terminal unchanged. Otherwise, fall back to Base 64. Mark the file's encoding as UTF-8 for Emacs and VIM.
  • binary: Do not inspect attribute values at all, let arbitrary data through, including zero bytes. Do not use Base 64.

The default is UTF-8.

 
-M --managedsait     manageDsaIT control
Use this option to edit referral entries.
 
-Z --starttls     Require startTLS.
After opening an unencrypted LDAP connection, use startTLS to enable SSL. (This is an alternative to LDAP connections tunnelled through SSL, specified using ldaps:// URLs.)
 
--tls  never|allow|try|strict   Level of TLS strictness
This option controls the level of certificate checking strictness. Default is try.

fixme: If anyone has a concise description of what these values mean rather than the wishy-washy explanations I can find right now, please tell. Thanks.

(Basically, if you want to use SSL but your certificate is self-signed, you might want to experiment with something less than try.)

 
--read  DN   Read this entry
A rather trivial option. It means the same as:
-b DN -s base '(objectclass=*)' + *
 
-v --verbose     Note every update
Print the distinguished name of every entry as it is being processed.
 
-H --help     Print usage information
Print help on command line arguments.
 
--deleteoldrdn     Delete the old RDN
When changing the relative distinguished name to a new attribute value, delete the old attribute value instead of keeping it.

This option applies only to the --rename mode.

 
--ldif     Use LDIF syntax internally
Use standard LDIF syntax in the editor. The default is to use ldapvi syntax.
 
--ldapvi     Use ldapvi syntax externally
Use ldapvi syntax when reading and writing files. The default is to use LDIF syntax.
 

Command line tool compatibility

ldapvi invocation modes inspired by LDAP command line tools:

  ldapvi --out [OPTION]... [FILTER] [AD]...     Print LDIF, similar to ldapsearch
  ldapvi --in [OPTION]... [FILENAME]     Load LDIF change records, similar to ldapmodify
  ldapvi --delete [OPTION]... DN...     Edit delete records, similar to ldapdelete
  ldapvi --rename [OPTION]... DN1 DN2     Edit rename records, similar to ldapmodrdn

All of these are more verbose and interactive than the standard command line tools. There are additional aliases for closer compatibility:

  --ldapsearch     Short for --quiet --out
  --ldapmodify     Short for --noninteractive --in
  --ldapdelete     Short for --noninteractive --delete
  --ldapmoddn     Short for --noninteractive --rename

Please keep in mind that all these invocation modes are only meant to imitate LDAP command line tools as far as possible while still working within the design of ldapvi. An option-by-option emulation of the OpenLDAP command line tools is not a goal, and minor differences in look and feel are to be expected.

Format conversion. 

  ldapvi --in | cat     Convert LDIF on stdin to ldapvi format on stdout
  ldapvi --in --ldif --ldapvi | cat     Convert ldapvi format on stdin to LDIF on stdout



Configuration file format

The are two ways to configure ldapvi. It has its own configuration files ~/.ldapvirc (or /etc/ldapvi.conf) which support multiple configuration profiles and all of its custom options. Alternatively, it can fall back to libldap's standard configuration files, /etc/ldap.conf and ~/.ldaprc.

Files and profiles.  On startup, ldapvi will first look for ~/.ldapvirc, or /etc/ldapvi.conf if the former does not exist.

Environment variables.  The choice of text editor is made using environment variables. $VISUAL and $EDITOR are looked up in this order. If neither is set, ldapvi falls back to vi.

Profile syntax.  The configuration file has ldapvi syntax, except with header lines of the form profile name.

Every configuration file option corresponds to a command line parameter.

For the named command line parameters, the long name is used in the configuration. For details, refer to the documentation of each parameter:  ➙ host  ➙ bind  ➙ bind-dialog  ➙ user  ➙ password  ➙ sasl-interactive  ➙ sasl-quiet  ➙ sasl-secprops  ➙ sasl-realm  ➙ sasl-authcid  ➙ sasl-authzid  ➙ sasl-mech  ➙ base  ➙ scope  ➙ sort  ➙ discover  ➙ class  ➙ may  ➙ add  ➙ empty  ➙ deref  ➙ continue  ➙ encoding  ➙ managedsait  ➙ starttls  ➙ tls  ➙ read  ➙ verbose  ➙ deleteoldrdn  ➙ ldif  ➙ ldapvi  ➙ out  ➙ in  ➙ delete  ➙ rename  ➙ ldapsearch  ➙ ldapmodify  ➙ ldapdelete  ➙ ldapmoddn

The two unnamed kinds of command line arguments are the search filter and the list of attribute descriptions to be returned. The former is named ➙ filter in the configuration file. The latter are given as ➙ ad, one line each.

For boolean flags, given without a value at the command line, use yes as their value in the configuration file. (no is also allowed and has no effect.)

Example.  With the following configuration file, ldapvi ignores libldap configuration, because a default profile is given.

profile default
ldaprc: yes
may: yes

profile otherhost
host: ldap://otherhost
discover: yes

profile adduser
host: ldap://localhost
base: uid=FILLMEIN,ou=passwd,dc=lichteblau,dc=com
class: person
class: posixAccount

profile root
host: ldap://localhost
base: 
scope: base
filter: (objectclass=*)
ad: +


ldapvi syntax explained

ldapvi syntax is somewhat LDIF-like, but not the same as standard LDIF. This chapter includes examples explaining the difference between the two formats. (A precise, technical definition of ldapvi syntax is given in the next section.)

➙ In interactive editing, the default is ldapvi syntax, explained below, unless overridden using --ldif.

➙ For external input and output (see --in, --out), the default is standard LDIF syntax, unless overridden using --ldapvi.

Basics

Comments are lines starting with a sharpsign:

# like this

They are allowed both between entries and in the middle of entries (but not in the middle of an attribute value).

Empty lines are used to separate entries:

0 dc=lichteblau,dc=com
# don't touch the number!
objectClass: top
objectClass: dcObject
objectClass: organization
o: lichteblau
dc: lichteblau

# more than one empty line would be OK here, too
add cn=admin,dc=lichteblau,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator

So far this looks pretty much like LDIF, except for the record key that appears instead of the dn: LDIF uses to start an entry.

First though, more on low-level syntax issues.


Value encodings

All non-empty, non-comment "lines" have the same base syntax: A left-hand and a right-hand side, separated by an optional encoding marker and a space. (Depending on the encoding used, a such a logical line may include newline characters.)

The syntax of the right-hand side depends on the encoding marker. For simple ASCII text without special characters, there are multiple valid encodings that can be used.

This includes the first line of a record with the distinguished name, its base syntax is the same as for the attribute lines. For traditional reasons, ldapvi prints this line without a colon, but that is not a requirement:

# rather than writing this:
add cn=admin,dc=lichteblau,dc=com

# we could have included a colon:
add: cn=admin,dc=lichteblau,dc=com

# or actually, this:
add:; cn=admin,dc=lichteblau,dc=com

Or, vice versa, we could have omitted the colon from those attribute values. ldapvi prints it only so that entries looks for familiar to eyes used to LDIF.

Value encodings are:

LDIF-compatible encoding.  Lines with just a colon and a space are parsed according to normal LDIF rules. Values must be ASCII-only and must not contain zero bytes, LF, or CR. In addition, they must not start with a space, a colon, or a less-than sign.

This encoding allows LDIF-style line folding: If a line ends, and the first character of the next line, if any, is a space, the nextline and the space are elided and parsing continues on the next line.

Note: The language for attribute value lines described above is the common subset of LDIF's attrval-spec and the actual syntax accepted by ldapvi for this value encoding. ldapvi will only ever print out values in this encoding if they follow these rules and hence are valid LDIF, but is more liberal in parsing them. It accepts space, colon, or less-than sign as the first character. It can allow them without ambiguity because, in contrast to LDIF, it does not ignore an arbitrary number of space characters after the colon.

Examples of valid LDIF values:

# normally, one would write:
objectClass: posixAccount

# but with line folding, the same value can be broken into two lines:
objectClass: posix
 Account

# in contrast to ldapvi backslashed format, this encoding does not
# interpret backslashes specially at all:
cn: this is a value containing a backslash\
 but no newline

Examples of attribute values not representable in LDIF-compatible encoding:

# must not start with '<':
# [accepted by ldapvi but not LDIF]
document: <?xml version="1.0" encoding="UTF-8"><foo/>

# cannot start with a space:
# [LDIF would ignore the space]
foo:  ...

# must not start with a colon:
# [accepted by ldapvi but not LDIF]
foo: ::::::::

# must not contain non-ASCII bytes:
surname: Müller

# cannot represent newlines:
mail: From david@lichteblau.com Mon Apr  1 00:11:22 2006
Return-path: <david@lichteblau.com>
Envelope-to: lists@mail.askja.de

Base 64 encoding.  Base 64 can be used just as in LDIF.

# This is what the XML from above looks like in strict LDIF:
document:: PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPjxmb28vPg==

ldapvi backslashed encoding.  This is the format ldapvi falls back to if a value cannot be represented in LDIF-compatible encoding without resorting to Base 64. Any character is valid in this encoding, except for two characters with a special meaning:

Examples of valid backslashed attributes:

# any funny characters are OK
document:; <?xml version="1.0" encoding="UTF-8">
foo:;  ...
foo:; ::::::::
surname:; Müller

# backslash escapes newline
mail:; From david@lichteblau.com Mon Apr  1 00:11:22 2006\
Return-path: <david@lichteblau.com>\
Envelope-to: lists@mail.askja.de

# No LDIF line folding, however, so this value contains a space:
cn:; David\
 Lichteblau

Counter-example:

# Parsable first line, followed by garbage on the second:
cn:; David
 Lichteblau

Finally, in most situations :; can be omitted, leaving just a space between the left-hand and right-hand side of the line. The only exception is a line with an empty left-hand side, which occurs in modify records.

foo:; bar
# is the same as:
foo bar

Binary encoding.  Decimal numbers are valid as encoding markers and specify the number of bytes to read after the separating space. No special characters exist in this syntax. This encoding is not meant for interactive use, but for the sake of completeness, here is an example:

# This entry has two attributes, givenname and cn:
add cn=admin,ou=passwd,dc=blubba
givenname:5 Davidcn: admin

File inclusion.  The less-than sign tells LDAP to read the contents of another file and use them as the attribute value. This is another LDIF compatibility feature.

# oops
add cn=haxor,ou=passwd,dc=blubba
comment:< file:///etc/passwd

userPassword encodings.  The encodings crypt, cryptmd5, md5, smd5, sha, and ssha are designed for the userPassword attribute. ldapvi takes the right-hand side as the password, hashes it, and prepends {ENCODING} as appropriate.

userPassword:crypt foo
# ...could result in:
userPassword: {CRYPT}KgJTUDs14z57Q
# ...or:
userPassword: {CRYPT}UoILyHlM1bPYU

# cryptmd5 gives $1$ notation
userPassword:cryptmd5 foo
userPassword: {CRYPT}$1$iKeAY9mQ$vmo/m/6EoDqRuVtjSqLPr0

# while the other encodings prepend the marker of the same name:
userPassword:md5 foo
userPassword: {MD5}AQ3GmMeoPXozyRU4wsEDXA==

Change records

Aside from the obvious add records mentioned above, there are three change record formats: rename, modify, and delete.

rename records.  Like every other record, rename states the (original) distinguished name of the name in the header line. Next is one additional line stating the new distinguished name.

The complication is that LDAP's moddn operation needs to be told what to do with the old relative DN if there is a new one. The old one can be kept as an additional attribute value or deleted in favour of the new one.

In ldapvi, this choice is made using the left-hand side of the second line. It is either "add" or "replace".

# example for "deleteoldrdn" behaviour:
rename: cn=blub4,dc=lichteblau,dc=com
replace: cn=blub3,dc=neu,dc=com

# alternatively, the old RDN can be kept:
rename: cn=blub3,dc=lichteblau,dc=com
add: cn=blub4,dc=neu,dc=com

In LDIF, the same changes would be written as:

# this is LDIF, not ldapvi syntax!
dn: cn=blub4,dc=lichteblau,dc=com
changetype: modrdn
newrdn: cn=blub3
deleteoldrdn: 1
newsuperior: dc=neu,dc=com

dn: cn=blub3,dc=lichteblau,dc=com
changetype: modrdn
newrdn: cn=blub4
deleteoldrdn: 0
newsuperior: dc=neu,dc=com

modify records.  These records state changes to attributes, processed in order. Attributes can be changed by replacing their existing values with a new set of values, adding those values to the existing ones, or removing only selected old values.

Example:

# Let's add classes, delete a comment and remove cn entirely:
modify: dc=bar,dc=lichteblau,dc=com
add: objectClass
: posixAccount
: specialAccount
delete: comment
: dummy user
replace: cn

In LDIF, this would be:

# this is LDIF, not ldapvi syntax!
dn: dc=bar,dc=lichteblau,dc=com
changetype: modify
add: objectClass
objectClass: posixAccount
objectClass: specialAccount
-
delete: comment
comment: dummy user
-
replace: cn
-

delete records.  These are rather simple, they consist just of the header line.

delete: dc=acme,dc=com

In LDIF, this would be:

# this is LDIF, not ldapvi syntax!
dn: dc=acme,dc=com
changetype: delete

Using LDIF syntax

When invoked using --ldif, ldapvi will use RFC 2849 syntax instead of its own special syntax.

However, there is a special marker in each entry:

Existing entries are presented for editing with an additional marker on the second line, just after the dn: line. This line states the (numeric) key that would appear in the header line if the entry had been printed in ldapvi syntax.

(New entries can have the same line, with add as their key, but records with neither ldapvi-key nor changetype are automatically assumed to be new entries to add.)

Also, control: is not supported.

Examples:

# Existing entry
dn: dc=lichteblau,dc=com
ldapvi-key: 0
objectClass: top
objectClass: dcObject
objectClass: organization
o: lichteblau
dc: lichteblau

# New entry
dn: cn=admin,dc=lichteblau,dc=com
# next line is optional
ldapvi-key: add
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator

# Changerecord (standard LDIF syntax)
dn: cn=blub4,dc=lichteblau,dc=com
changetype: modify
delete: seeAlso
seeAlso: cn=dort
-



ldapvi syntax (BNF)

As explained above, ldapvi has its own, vaguely LDIF-inspired syntax. For a precise definition, see ldapvi-file below.

LDIF is defined in RFC 2849.

RFC 2849 modifies the language generated by its BNF grammar with the "Notes on LDIF Syntax" (2) and (3) presented there. These notes do not apply to ldapvi syntax as stated: Line folding and comments can be used, but are allowed specificially by our modified BNF, not hacked into the rules later. Line folding is allowed only in LDIF-compatible attribute values and comments. ldapvi files cannot be read line-by-line without knowing the encoding of those lines, since newlines are permitted in certain attribute value representations.

The following rules are used as defined in RFC 2849 and not reproduced here: AttributeDescription, SAFE-STRING, BASE64-STRING, SPACE.

Changes to the RFC 2849 BNF grammar. 

ldapvi-file = vspace ldapvi-record
              *(vspace SEP vspace ldapvi-record) vspace
ldapvi-record = ldapvi-attrval-record
	        / ldapvi-rename-record
		/ ldapvi-modify-record
ldapvi-attrval-record = *(comment) dn-spec 1*(*(comment) attrval-spec)
ldapvi-rename-record = *(comment)
                       "rename" distinguishedName SEP
		       ("add" / "replace") value-spec SEP
ldapvi-modify-record = *(comment)
                       "modify" distinguishedName SEP
		       1*(*(comment) mod-spec)
mod-spec = ("delete" / "add" / "replace") ad-value SEP
	   *(value-enc SEP)

vspace = *(comment / sep)
comment = "#" *(ldif-char) *(SEP " " *(ldif-char)) SEP

dn-spec = key distinguishedName SEP
key = number / "add"
distinguishedName = value-spec                  ;encoding an RFC 2253 DN

attrval-spec = AttributeDescription value-spec SEP
value-spec = value-simple / value-enc
value-simple = SPACE escaped-string             ;escape CR/LF with '\\\\'
value-enc = (":;" SPACE escaped-string /        ;ditto
             ":" SPACE 0*1(SAFE-STRING          ;LDIF compatible
                           *(SEP " " *SAFE-CHAR)) /
             "::" SPACE BASE64-STRING /         ;ditto
             ":" number SPACE 0*1(octet) /      ;exactly `number' octets
             ":<" SPACE url /                   ;only file:// supported
             ":crypt" SPACE password /          ;for userPassword
             ":cryptmd5" SPACE password /
             ":md5" SPACE password /
             ":smd5" SPACE password /
             ":sha" SPACE password /
             ":ssha" SPACE password /
             ;; other encoding markers reserved
            )

octet = %x00-ff
number = 1*(%x30-39)                            ;any decimal number
ldif-char = unescaped-char / %5c                ;any except for CR/LF.
unescaped-char = %x00-%x09 / %x0a-%x0c / %x0d-%5b / %x5d-%ff
escaped-string = *(unescaped-char / %x5c %x0a / %x5c %x0d / %x5c %x5c)
password = 0*ldif-char
SEP = LF                                        ;this is a unix program!

ad-value = value-spec  ;parsing as an AttributeDescription


Reporting bugs

Please report bugs to the ldapvi mailing list for archival purposes.

Address: ldapvi@lists.askja.de