HP introduced LDAP support for password authentication in OpenVMS 8.3, which is fantastic. However, when looking for documentation about how it is configured and implemented, one comes up short – there is a dearth of information to be found.

Thanks to Hoffman Labs, this is no longer the case: their article on LDAP exposes the configuration details of ACME LDAP on OpenVMS quite nicely. They have the technical details as well as the README from the ACME LDAP add-on posted there; I’ll try to summarize installation and configuration concisely here.

ACME is the Authentication and Credential Management Extensions, which appear to be an architecture for creating plugins for authentication and so forth, like PAM (the Pluggable Authentication Modules) for UNIX. ACME appears to have been introduced in OpenVMS 8.3.

ACME LDAP is perhaps the most visible of the first of these extensions. This, perhaps, explains its dearth of publically accessible documentation. Currently, ACME LDAP has these features:

  • Support for TLS/SSL
  • Support for StartTLS
  • Support for Active Directory
  • Support for Netscape “expired password” mechanisms

ACME LDAP also has these restrictions:

  • Still requires local username; password only is checked against LDAP
  • Characters in usernames and passwords are restricted to ISO 8859-1 eight bit characters; UTF-8 support not present.
  • Characters in passwords used in Active Directory are restricted to ISO 8859-1 7-bit ASCII characters.

Each user account to be authenticated with LDAP must exist on the system (in the SYSUAF file) and must have the EXTAUTH flag set.

To use ACME LDAP, you must configure the SYS$STARTUP:LDAPACME$CONFIG-STD.INI file. The file can be started by copying the LDAPACME$CONFIG-STD.INI_TEMPLATE file:


An example LDAPACME$CONFIG-STD.INI may look like this:

server = roux.zko.hp.com
port = 636
port_security = ssl
bind_dn = uid=acme-admin,ou=people,dc=acme,dc=mycompany,dc=com
bind_password = swordfish
base_dn = ou=people,dc=acme,dc=mycompany,dc=com
login_attribute = uid
scope = sub
ca_file = sys$manager:acme_ca.crt

This example is suitable for the Red Hat Directory Server (also known as the Fedora Directory Server).

The LDAP Persona extension must also be loaded using the MCR utility:

SYSMAN> exit


Following the load of the LDAP Persona extension, the system must be rebooted:


If there are no errors during startup, then the LDAP Persona extension was loaded correctly.

Change the SYS$MANAGER:ACME$START.COM file to contain a pointer to the initialization file and to start the LDAP extension automatically.

Add the following definition line to ACME$START.COM:


To start the server at ACME load time, add this line:


Finally, configure the system to start the ACME subsystem by adding this line to SYS$MANAGER:SYSTART_VMS.COM:


The description from Hoffman Labs is a perfect example of how community support works!

Update: A nice description (from the VMS Help subsystem) of the ACME server can be found here; it describes SET SERVER ACME_SERVER.

Directory Sizes

Each directory in UNIX is just another file in UNIX like any other. Directories contain information about the names of files and their locations on disk. As more and more files are added to a directory, the directory itself grows larger and larger. However, the directory does not shrink when files are removed.

For example:

# ls -ld /tmp
drwxrwxrwt 14 root root 4096 2007-10-29 11:14 /tmp

This directory is 4096 bytes (4k) in size. There is no way to actually shrink this directory. To reduce its size, the directory must be moved (renamed) and its contents copied into a new directory.

This could be done this way:

# mv /tmp /tmp.old
# mkdir /tmp
# chmod 1777 /tmp

The chmod will change the /tmp directory permissions to the appropriate ones. Note that the “sticky” bit is set, which means that files may be created, accessed, and deleted by anyone, but that files may be deleted only by their owner.

In the case of the /tmp directory, it may be best to reboot before deleting the old directory to avoid problems with programs using /tmp.

Supporting Open Source with a Linux Credit Card? Think Twice…

This credit card from the LinuxFund seems like a good idea.  You and I would certainly like to support open source projects like Linux and KDE and so on.  Each purchase on this credit card results in a donation to a worthy open source cause, and you can send all of your cash-back rewards back as donations as well.

However, this turns out to be a lesson in reading the fine print.  This card has some very ominous conditions, which they don’t tell you except in the fine print:

  • The rate is not fixed, but variable: that means it can go up and down over time, with no changes in the terms.
  • The terms (including APR, fees, and conditions) may be changed at any time and without notice to you.
  • The default rate is (approximately) 12% over prime up to 21% over prime.
  • Cash advances are 24% over prime.
  • If you miss a payment by more than 15 days, your rate will skyrocket to 32% over prime.
  • If you miss a payment by more than 5 days twice in a year, your rate will skyrocket to 32% over prime.
  • If you miss any payment on any card you own they will raise your rate.

As you can see, there are a number of gotcha! features to this card.  However, it is not alone.  Here are some ways to avoid the gotchas:

  • Is the advertized rate an introductory rate?  When does it expire?
  • What is the rate for purchases?
  • What is the rate for cash advances?
  • Are there any other rates?
  • Are the rates fixed or variable?
  • Is there a grace period?  What happens if you miss a payment?
  • Are the rates dependent on other cards?

It has been said that consumer credit is the riskiest form of credit, and the terms on most cards suggest that the credit card companies think so.  Read the fine print carefully!

Researching the Dynamic Loader on Any System

In finding information about the dynamic loader and shared libraries in general, there are several places to look. The obvious Internet location is Google; however, the system itself has a lot of information about shared libraries if one only knows where to look.

The first place is the information on the dynamic loader’s man page. Unfortunately, most loaders have names that are unique among their UNIX peers (Linux is almost universal). You can start by looking at the /lib directory for a program containing the string “ld” (or perhaps, “dl”). On Linux, this produces:

# ls -d *ld*
ld-2.6.so ld-linux.so.2

The proper Linux loader is ld-linux.so.

On HP-UX, this produces:

# ls -d *ld*
dld.sl* libdld.2* libldap_send.1*
libdld.0@ libdld.sl@ libldap_send.sl@
libdld.1* libldap.sl@ libnss_ldap.1*

Here, the proper loader is dld.sl.

Looking at the man pages for ld-linux.so or dld.sl or whatever was found gives a vast amount of information directly related to the dynamic loader and how it loads shared libraries, as well as debugging tools to report on how the libraries are found and loaded.

This man page will also mention utilities that will help you manipulate shared libraries. For example, the Linux man page for ld-linux.so mentions ldconfig(8); the HP-UX man page for dld.sl mentions the utilities fastbind(8) and chatr(8).

There are other utilities that remain fairly generic and which can help, though these tend to be specific to machines that are configured for development. If the development tools are not loaded, these tools may be missing. These utilities may include:

  • ldd – list libraries used by a binary
  • nm – list symbols from program binaries and/or libraries
  • objdump – display information from binaries and/or libraries
  • readelf – display information from ELF-formatted binaries

Always look at the SEE ALSO section in order find more information.

Shared Libraries (Linux)

The loading of shared libraries in Linux is somewhat complicated (though not any more than other UNIX systems). Firstly, Linux has gone through tremendous growth; as a result, the method and format of loadable libraries has changed several times, necessitating a change in the library loader:

  • ld.so – for a.out formatted binaries
  • ld-linux.so.1 – for ELF binaries that used libc5
  • ld-linux.so.2 – for ELF binaries that use glibc

Nearly everything today will use ld-linux.so.2. All three use the same support files, configuration files, and so forth. The loaders ld-linux.so.1 and ld.so will not be discussed further.

The search for shared libraries goes in this order:

  • Use the binary’s internally stored RPATH (deprecated).
  • Use the environment variable LD_LIBRARY_PATH (except for suid and sgid binaries).
  • Use the binary’s internally stored RUNPATH.
  • Use the cache file /etc/ld.so.cache.
  • Search /lib then /usr/lib.

If the binary being loaded was linked with the -z nodeflib (that is, no default libraries) option then the last two steps are ignored.

Conveniently, the loader is an actual program which can be executed and with a variety of options. There are only two that will be of assistance when debugging the loading of system libraries. To use a specified path instead of LD_LIBRARY_PATH, use the loader this way:

/lib/ld-linux.so.2 --library-path path binary

…where path is the library path, and binary is the program binary to be loaded and executed. To keep the program binary’s preconfigured RPATH and RUNPATH from being used, use this invocation:

/lib/ld-linux.so.2 --inhibit-rpath binary

The loader also recognizes a lot of different environment variables; only a few are relevant for most purposes:

  • LD_LIBRARY_PATH: a path of directories to search for ELF libraries. Formatted like PATH.
  • LD_PRELOAD: a list of libraries (separated by whitespace) to be loaded before all others. For suid and sgid binaries, only libraries in standard search directories that are also suid will be loaded.
  • LD_BIND_NOW: bind (and load) all necessary libraries at startup instead of on demand. This is useful when using a debugger.
  • LD_TRACE_LOADED_OBJECTS: produces output like ldd(8).
  • LD_DEBUG: output debugging information related to the linker. If set to help will provide help for using this variable. If set to all, will provide full and detailed debugging of all portions of the dynamic loading process and of the dynamic loader.

The variable LD_DEBUG can be quite useful when debugging a missing library. The help for LD_DEBUG looks like this:

# LD_DEBUG=help nm --help
Valid options for the LD_DEBUG environment variable are:
libs display library search paths
reloc display relocation processing
files display progress for input file
symbols display symbol table processing
bindings display information about symbol binding
versions display version dependencies
all all previous options combined
statistics display relocation statistics
unused determined unused DSOs
help display this help message and exit
To direct the debugging output into a file instead of standard output
a filename can be specified using the LD_DEBUG_OUTPUT environment variable.

To debug a program’s shared libraries, try invoking the program with this environment variable set. As the program executes, each library search and library invocation will be reported. For example:

# LD_DEBUG=libs,versions ls -m
28927: find library=librt.so.1 [0]; searching
28927: search cache=/etc/ld.so.cache
28927: trying file=/lib/librt.so.1
28927: find library=libselinux.so.1 [0]; searching
28927: search cache=/etc/ld.so.cache
28927: trying file=/lib/libselinux.so.1
28927: find library=libacl.so.1 [0]; searching
28927: search cache=/etc/ld.so.cache
28927: trying file=/lib/libacl.so.1
28927: find library=libc.so.6 [0]; searching
28927: search cache=/etc/ld.so.cache
28927: trying file=/lib/libc.so.6
28927: find library=libpthread.so.0 [0]; searching
28927: search cache=/etc/ld.so.cache
28927: trying file=/lib/libpthread.so.0
28927: find library=libdl.so.2 [0]; searching
28927: search cache=/etc/ld.so.cache
28927: trying file=/lib/libdl.so.2
28927: find library=libsepol.so.1 [0]; searching
28927: search cache=/etc/ld.so.cache
28927: trying file=/lib/libsepol.so.1
28927: find library=libattr.so.1 [0]; searching
28927: search cache=/etc/ld.so.cache
28927: trying file=/lib/libattr.so.1
28927: checking for version `GLIBC_2.2' in file /lib/librt.so.1 [0] required by file ls [0]
28927: checking for version `ACL_1.0' in file /lib/libacl.so.1 [0] required by file ls [0]
28927: checking for version `GLIBC_2.2.3' in file /lib/libc.so.6 [0] required by file ls [0]
28927: checking for version `GLIBC_2.4' in file /lib/libc.so.6 [0] required by file ls [0]
28927: checking for version `GLIBC_2.3' in file /lib/libc.so.6 [0] required by file ls [0]
28927: checking for version `GLIBC_2.3.4' in file /lib/libc.so.6 [0] required by file ls [0]
28927: checking for version `GLIBC_2.1' in file /lib/libc.so.6 [0] required by file ls [0]
28927: checking for version `GLIBC_2.1.3' in file /lib/libc.so.6 [0] required by file ls [0]
28927: checking for version `GLIBC_2.2' in file /lib/libc.so.6 [0] required by file ls [0]
28927: checking for version `GLIBC_2.0' in file /lib/libc.so.6 [0] required by file ls [0]


The output can be quite verbose, but you can get the idea. This output can be most useful when a library is not being loaded by the loader (when you think it should be).

Warning: be aware, too, that the C compiler (gcc) as of version 4.0 requires a shared library for every program by default. If you are trying to create a static program, it will not truly be static until the gcc library is actually built into the binary. This requires a special gcc option for linking in addition to the standard -static option: -static-libgcc. The -static option alone is not enough. This library can be seen by using the -print-libgcc-file-name option:

# gcc -print-libgcc-file-name

Note, too, that any library required by a program has its own requirements: thus, if the library requires another library, and cannot find a static build version, then that library will be used as a shared library.

The program ldd can be used (as always) to find the libraries that a program requires:

# ldd $(which ls)
linux-gate.so.1 => (0x00ef8000)
librt.so.1 => /lib/librt.so.1 (0x0585b000)
libselinux.so.1 => /lib/libselinux.so.1 (0x004b2000)
libacl.so.1 => /lib/libacl.so.1 (0x05c0c000)
libc.so.6 => /lib/libc.so.6 (0x00101000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00282000)
/lib/ld-linux.so.2 (0x00dc2000)
libdl.so.2 => /lib/libdl.so.2 (0x00de1000)
libsepol.so.1 => /lib/libsepol.so.1 (0x0046a000)
libattr.so.1 => /lib/libattr.so.1 (0x05c05000)

The ldd program will also report if a library is missing.

Update: I forgot to mention these resources for further information about using (and creating) shared libraries in Linux:

In particular, I found Russ Allbery’s description most illuminating.

A “new” file pager: view

I, like most people I know, adore the file pager less. However, for whatever inconceivable reason, new UNIX systems (Linux doesn’t count here!) virtually never come with less. So… what to do when less is missing?

HP-UX, for one, comes with more and pg. Everything comes with more – but once you’ve used less you’ll never want to use a standard more again. The pager pg really isn’t any better.

Is there a solution? Yes – view.

What is view? The program view is a file pager which is included on virtually all UNIX and Linux systems. The view program is available, for example, in Solaris 9, HP-UX 11i v2, FreeBSD 6.2, Red Hat Linux 9, and more.

If you know vi, then you’ll know view. Why? Because view is actually vi in disguise, acting as a file pager with read-only access to the file.

The biggest drawback to view is that it does not handle stdin; that is, using view as the destination of a pipe gets very messy very fast (i.e., don’t do that!).

Apparently, vim handles this situation much better. Perhaps much better: there are ways to specify the use of vim with less keymappings, and to use view (i.e., vim) for general pager use! There are directions on how to make vim work as a man page viewer complete with syntax highlighting. Here is the quick and dirty instructions (for ksh):

export MANPAGER="col -b | view -c 'set ft=man nomod nolist' -"

For less key bindings, use (for ksh again):

export MANPAGER="col -b | /usr/share/vim/vim61/macros/less.sh -c 'set ft=man nomod nolist' -"

Be sure to use the right macro location for your version of vim. If you check out the original directions, be sure to read all of the comments: there are directions on how to properly configure the environment so reading man pages inside vim will work properly, and so that non-English locales can be handled properly, and more.

Next time you find yourself suffering without less – stop suffering through more and use view instead. You’ll be glad you did.

OpenVMS celebrates its 30th anniversary!

You may have noticed recently that VMS got mentioned a few times.  OpenVMS remains alive, despite people’s perceptions, because of a large (in numbers) user base and a proven track record for solid and stable performance and for security.  In fact, at DEFCON 9 (2001) a VMS system (in a “out of the box” configuration) proved unhackable.  The VAX, in comparison, is long gone (OpenVMS 8 does not support VAXes) and the Alpha was discontinued as of April 2007; OpenVMS on Itanium is the future (yes, OpenVMS 8 runs on Itanium!).

OpenVMS celebrates its 30th anniversary today.  In the future, as I start my journey towards becoming a VMS System Administrator, I’ll post some details here and there about VMS for new system administrators.

That won’t take away from the primary focus: UNIX and Linux.  However, UNIX does owe a lot to the VAX and to VMS: it was the VAX that the first UNIX virtual memory system was designed to take advantage of.  To this day, there are parts of UNIX that are a direct result of that first VAX implementation (of the memory management system).