[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: UNIX Disk Quote Control w/LDAP

Samson Luk wrote:
> How can this be controled without /etc/passwd but just LDAP database?
> Any replacement for the "quota" utility family?

Disk quotas are enforced in UNIX by UNIX UID.  I'll explain
this, and then give you three possible approaches to doing
what you want to do.

When a file is created, deleted, truncated, or extended,
the quota record for the UID performing the operation is
updated.  If the UID goes over quota, an error, EQUOTA,
is returned, and the requested operation fails.

This assumes that quotas are enabled on the file system
in question, and that they are being enforced against
the UID performing the operation.

As far as the UNIX kernel is concerned, there is no such
thing as a user name; there are only UIDs.

The kernel knows the UID performing the operation because
it looks at the credentials hung off the process structure,
which were established either at login time or later through
the setuid/setgid/seteuid/setegid family of system calls.
Either login calls these when you login as a user other than
"root", or your program in user space calls these to change
from one UID to another (this is generally done by making
your program setuid root, and then making it call the
seteuid/setegid calls, which will let it switch from user
to user; SAMBA does this, for example).

Depending on your application, you may be better off doing
quota enforcement in your program.  It sounds like you are
saying that you want quotas enforced on LDAP credentials
alone, and that the LDAP credentials would not map to real

If you are using this for email accounts, this is usually
enforced by the "deliver" program.  As an example of this,
"cyrus" quota enforcement is done via the "deliver" program.
If you wanted "cyrus" to use LDAP contents, you would have
to replace its own database references with LDAP lookups,
in both the "deliver" and "cyradm" programs.

If you are trying to do this with something that doesn't
already support non-UNIX UID based virtual users, like
SAMBA, your best bet would be to establish UNIX credentials
for these people during the SAMBA login, so that these
values are used, instead of the password file entries, for
looking up the UNIX UID.

You will want to make sure that you don't collide with any
valid UNIX UIDs, since if you did, this would give the user
of your program access to any of the files that that UNIX
UID would normally have access to.

If you do this, you should be aware that the the quota UID
space is usually limited to 0-65535 (2^16) by the use of a
short-word (uint16_t) in the quota record structure.

Another alternate approach would be to write libc wrapper
functions for all functions which could affect the quota
of a user, and maintain the quota from within these

This may not work on some systems, since not all libc
implementations declare their symbols "weak" in their
standard C library, which means that if you link first
with your wrapper library and then with the normal C
library, you might get the normal C library.

A rule of thumb on this is that, if your UNIX system works
with "runsocks" (a proxy which replaces the socket API with
a socket proxy API), then you should be safe.

Another potential pitfall is that, if your application is
threaded, and your UNIX system uses user space threads,
then your override will replace the threaded libc calls
with unthreaded ones, and your application will not work
(socks has this same problem).  The only fix for this is
to make your wrappers multithreaded by using the libc_r
source code to create your wrappers.

Finally, when wrapping system calls, you will have to
worry about signals.

Back in the good old pre-POSIX days, Berkeley signals
would automatically restart the interrupted system call
after the signal handler ran.

This meant that if you truly wanted to interrupt the
system call (e.g. via SIGALARM), you would have
to longjmp from within the handler.  But it also meant
that if you wanted to wrap system calls, you would not
have to deal with blocking and unblocking signals and
changing the behaviour of the code or adding "if" tests
for EINTR inside "while()" loops everywhere.  It's
really sad; Berkeley got this right, and then fell into
line with POSIX.  8-(.

In any case, wrapping is my least-recommended approach.

Hope this information helps you decide on an approach.

-- Terry Lambert
-- Whistle Communications, Inc., an I.B.M. Company
-- terry@whistle.com
This is formal notice under California Assembly Bill 1629, enacted
9/26/98 that any UCE sent to my email address will be billed $50
per incident to the legally allowed maximum of $25,000.